/* * Copyright 2014 by SCSK Corporation. * * This file is part of PrimeCloud Controller(TM). * * PrimeCloud Controller(TM) is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * PrimeCloud Controller(TM) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with PrimeCloud Controller(TM). If not, see <http://www.gnu.org/licenses/>. */ package jp.primecloud.auto.process.vmware; import java.net.Inet4Address; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import jp.primecloud.auto.common.constant.PCCConstant; import jp.primecloud.auto.entity.crud.Farm; import jp.primecloud.auto.entity.crud.ImageVmware; import jp.primecloud.auto.entity.crud.Instance; import jp.primecloud.auto.entity.crud.Platform; import jp.primecloud.auto.entity.crud.PlatformVmware; import jp.primecloud.auto.entity.crud.PlatformVmwareInstanceType; import jp.primecloud.auto.entity.crud.User; import jp.primecloud.auto.entity.crud.VmwareInstance; import jp.primecloud.auto.entity.crud.VmwareNetwork; import jp.primecloud.auto.exception.AutoException; import jp.primecloud.auto.process.ProcessLogger; import jp.primecloud.auto.service.ServiceSupport; import jp.primecloud.auto.util.MessageUtils; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import com.vmware.vim25.CustomFieldDef; import com.vmware.vim25.DatastoreSummary; import com.vmware.vim25.GuestNicInfo; import com.vmware.vim25.NetIpConfigInfoIpAddress; import com.vmware.vim25.mo.Datastore; import com.vmware.vim25.mo.Folder; import com.vmware.vim25.mo.ManagedEntity; import com.vmware.vim25.mo.VirtualMachine; /** * <p> * TODO: クラスコメントを記述 * </p> * */ public class VmwareMachineProcess extends ServiceSupport { protected String fieldUserName = "UserName"; protected ProcessLogger processLogger; /** * TODO: メソッドコメントを記述 * * @param vmwareProcessClient * @param instanceNo * @return */ public boolean cloneVM(VmwareProcessClient vmwareProcessClient, Long instanceNo) { VmwareInstance vmwareInstance = vmwareInstanceDao.read(instanceNo); if (StringUtils.isNotEmpty(vmwareInstance.getDatastore())) { // データストアが設定されている場合はクローン済みとしてスキップ return false; } Instance instance = instanceDao.read(instanceNo); ImageVmware imageVmware = imageVmwareDao.read(instance.getImageNo()); // データストアの選択 String datastoreName = selectDatastore(vmwareProcessClient, vmwareInstance); // イベントログ出力 Platform platform = platformDao.read(vmwareProcessClient.getPlatformNo()); processLogger.debug(null, instance, "VmwareInstanceCreate", new Object[] { platform.getPlatformName(), vmwareInstance.getMachineName() }); // 仮想マシンをクローン vmwareProcessClient.cloneVM(vmwareInstance.getMachineName(), imageVmware.getTemplateName(), vmwareInstance.getComputeResource(), vmwareInstance.getResourcePool(), datastoreName); // 仮想マシンのルートサイズを拡張 if (vmwareInstance.getRootSize() != null) { vmwareProcessClient.extendRootDisk(vmwareInstance.getMachineName(), vmwareInstance.getRootSize()); } // イベントログ出力 processLogger.debug(null, instance, "VmwareInstanceCreateFinish", new Object[] { platform.getPlatformName(), vmwareInstance.getMachineName() }); // データベース更新 vmwareInstance = vmwareInstanceDao.read(instanceNo); vmwareInstance.setDatastore(datastoreName); vmwareInstanceDao.update(vmwareInstance); return true; } protected String selectDatastore(VmwareProcessClient vmwareProcessClient, VmwareInstance vmwareInstance) { // データストアフォルダ内のデータストアのうち、アクセス可能で空き容量が最も大きいものを用いる Datastore datastore = null; long freeSpace = 0L; // ComputeResourceごとのフォルダがあれば、その中のデータストアを用いる String datastoreFolderName = vmwareInstance.getComputeResource() + "-storage"; Folder datastoreFolder = vmwareProcessClient.getVmwareClient().search(Folder.class, datastoreFolderName); if (datastoreFolder == null) { // ComputeResourceごとのフォルダがなければ、"storage"フォルダの中のデータストアを用いる datastoreFolder = vmwareProcessClient.getVmwareClient().search(Folder.class, "storage"); } if (datastoreFolder != null) { ManagedEntity[] entities = vmwareProcessClient.getVmwareClient().searchByType(datastoreFolder, Datastore.class); for (ManagedEntity entity : entities) { Datastore datastore2 = Datastore.class.cast(entity); DatastoreSummary summary2 = datastore2.getSummary(); if (summary2.isAccessible() && freeSpace < summary2.getFreeSpace()) { datastore = datastore2; freeSpace = summary2.getFreeSpace(); } } } if (datastore == null) { // 利用可能なデータストアがない場合 throw new AutoException("EPROCESS-000528", vmwareInstance.getComputeResource()); } return datastore.getName(); } /** * TODO: メソッドコメントを記述 * * @param vmwareProcessClient * @param instanceNo */ public void powerOnVM(VmwareProcessClient vmwareProcessClient, Long instanceNo) { VmwareInstance vmwareInstance = vmwareInstanceDao.read(instanceNo); // イベントログ出力 Instance instance = instanceDao.read(instanceNo); Platform platform = platformDao.read(vmwareProcessClient.getPlatformNo()); processLogger.debug(null, instance, "VmwareInstanceStart", new Object[] { platform.getPlatformName(), vmwareInstance.getMachineName() }); // 仮想マシンをパワーオン vmwareProcessClient.powerOnVM(vmwareInstance.getMachineName()); } /** * TODO: メソッドコメントを記述 * * @param vmwareProcessClient * @param instanceNo */ public void powerOffVM(VmwareProcessClient vmwareProcessClient, Long instanceNo) { VmwareInstance vmwareInstance = vmwareInstanceDao.read(instanceNo); // イベントログ出力 Instance instance = instanceDao.read(instanceNo); Platform platform = platformDao.read(vmwareProcessClient.getPlatformNo()); processLogger.debug(null, instance, "VmwareInstanceStop", new Object[] { platform.getPlatformName(), vmwareInstance.getMachineName() }); // 仮想マシンをパワーオフ vmwareProcessClient.powerOffVM(vmwareInstance.getMachineName()); // イベントログ出力 processLogger.debug(null, instance, "VmwareInstanceStopFinish", new Object[] { platform.getPlatformName(), vmwareInstance.getMachineName() }); // データベースを更新 vmwareInstance = vmwareInstanceDao.read(instanceNo); vmwareInstance.setIpAddress(null); vmwareInstance.setPrivateIpAddress(null); vmwareInstanceDao.update(vmwareInstance); } /** * TODO: メソッドコメントを記述 * * @param vmwareProcessClient * @param instanceNo */ public void shutdownGuest(VmwareProcessClient vmwareProcessClient, Long instanceNo) { VmwareInstance vmwareInstance = vmwareInstanceDao.read(instanceNo); // イベントログ出力 Instance instance = instanceDao.read(instanceNo); Platform platform = platformDao.read(vmwareProcessClient.getPlatformNo()); processLogger.debug(null, instance, "VmwareInstanceStop", new Object[] { platform.getPlatformName(), vmwareInstance.getMachineName() }); // 仮想マシンのゲストをシャットダウン vmwareProcessClient.shutdownGuest(vmwareInstance.getMachineName()); // イベントログ出力 processLogger.debug(null, instance, "VmwareInstanceStopFinish", new Object[] { platform.getPlatformName(), vmwareInstance.getMachineName() }); // データベースを更新 vmwareInstance = vmwareInstanceDao.read(instanceNo); vmwareInstance.setIpAddress(null); vmwareInstance.setPrivateIpAddress(null); vmwareInstanceDao.update(vmwareInstance); } /** * TODO: メソッドコメントを記述 * * @param vmwareProcessClient * @param instanceNo */ public void destroy(VmwareProcessClient vmwareProcessClient, Long instanceNo) { VmwareInstance vmwareInstance = vmwareInstanceDao.read(instanceNo); // イベントログ出力 Instance instance = instanceDao.read(instanceNo); Platform platform = platformDao.read(vmwareProcessClient.getPlatformNo()); processLogger.debug(null, instance, "VmwareInstanceDelete", new Object[] { platform.getPlatformName(), vmwareInstance.getMachineName() }); // 仮想マシンを削除 vmwareProcessClient.destroyVM(vmwareInstance.getMachineName()); // イベントログ出力 processLogger.debug(null, instance, "VmwareInstanceDeleteFinish", new Object[] { platform.getPlatformName(), vmwareInstance.getMachineName() }); } /** * TODO: メソッドコメントを記述 * * @param vmwareProcessClient * @param instanceNo */ public void waitForRunning(VmwareProcessClient vmwareProcessClient, Long instanceNo) { Instance instance = instanceDao.read(instanceNo); VmwareInstance vmwareInstance = vmwareInstanceDao.read(instanceNo); // ネットワーク名の取得 PlatformVmware platformVmware = platformVmwareDao.read(instance.getPlatformNo()); String publicNetworkName = platformVmware.getPublicNetwork(); String privateNetworkName = platformVmware.getPrivateNetwork(); List<VmwareNetwork> vmwareNetworks = vmwareNetworkDao.readByFarmNo(instance.getFarmNo()); for (VmwareNetwork vmwareNetwork : vmwareNetworks) { if (BooleanUtils.isTrue(vmwareNetwork.getPublicNetwork())) { publicNetworkName = vmwareNetwork.getNetworkName(); } else { privateNetworkName = vmwareNetwork.getNetworkName(); } } List<String> networkNames = new ArrayList<String>(); if (StringUtils.isNotEmpty(publicNetworkName)) { networkNames.add(publicNetworkName); } if (StringUtils.isNotEmpty(privateNetworkName)) { networkNames.add(privateNetworkName); } // ゲストの起動完了待ち vmwareProcessClient.waitForRunning(vmwareInstance.getMachineName(), networkNames); } /** * TODO: メソッドコメントを記述 * * @param vmwareProcessClient * @param instanceNo */ public void getGuestInfo(VmwareProcessClient vmwareProcessClient, Long instanceNo) { Instance instance = instanceDao.read(instanceNo); VmwareInstance vmwareInstance = vmwareInstanceDao.read(instanceNo); List<VmwareNetwork> vmwareNetworks = vmwareNetworkDao.readByFarmNo(instance.getFarmNo()); // ネットワーク名の取得 Platform platform = platformDao.read(instance.getPlatformNo()); PlatformVmware platformVmware = platformVmwareDao.read(instance.getPlatformNo()); String publicNetworkName = platformVmware.getPublicNetwork(); String privateNetworkName = platformVmware.getPrivateNetwork(); for (VmwareNetwork vmwareNetwork : vmwareNetworks) { if (BooleanUtils.isTrue(vmwareNetwork.getPublicNetwork())) { publicNetworkName = vmwareNetwork.getNetworkName(); } else { privateNetworkName = vmwareNetwork.getNetworkName(); } } String publicIpAddress = null; String privateIpAddress = null; VirtualMachine machine = vmwareProcessClient.getVirtualMachine(vmwareInstance.getMachineName()); for (GuestNicInfo nicInfo : machine.getGuest().getNet()) { // NIC情報からIPv4のアドレスを取得 NetIpConfigInfoIpAddress[] tmpAddresses = nicInfo.getIpConfig().getIpAddress(); if (tmpAddresses == null) { continue; } String ipAddress = null; for (NetIpConfigInfoIpAddress tmpAdress : tmpAddresses) { try { InetAddress inetAddress = InetAddress.getByName(tmpAdress.getIpAddress()); if (inetAddress instanceof Inet4Address) { ipAddress = tmpAdress.getIpAddress(); break; } } catch (UnknownHostException ignore) { } } // NIC情報がPublicかPrivateかの判定 if (StringUtils.isNotEmpty(publicNetworkName) && publicNetworkName.equals(nicInfo.getNetwork())) { publicIpAddress = ipAddress; } else if (privateNetworkName.equals(nicInfo.getNetwork())) { privateIpAddress = ipAddress; } } if (StringUtils.isNotEmpty(publicNetworkName) && publicIpAddress == null) { // パブリックIPを取得できない場合 throw new AutoException("EPROCESS-000510", vmwareInstance.getMachineName()); } else if (privateIpAddress == null) { // プライベートIPを取得できない場合 throw new AutoException("EPROCESS-000511", vmwareInstance.getMachineName()); } // イベントログ出力 processLogger.debug(null, instance, "VmwareInstanceStartFinish", new Object[] { platform.getPlatformName(), vmwareInstance.getMachineName() }); // データベースに格納 vmwareInstance = vmwareInstanceDao.read(instanceNo); vmwareInstance.setIpAddress(publicIpAddress); vmwareInstance.setPrivateIpAddress(privateIpAddress); vmwareInstanceDao.update(vmwareInstance); if (log.isInfoEnabled()) { log.info(MessageUtils.getMessage("IPROCESS-100432", vmwareInstance.getMachineName())); } } /** * TODO: メソッドコメントを記述 * * @param vmwareProcessClient * @param instanceNo */ public void changeResource(VmwareProcessClient vmwareProcessClient, Long instanceNo) { Instance instance = instanceDao.read(instanceNo); VmwareInstance vmwareInstance = vmwareInstanceDao.read(instanceNo); // InstanceTypeの取得 PlatformVmwareInstanceType instanceType = null; Platform platform = platformDao.read(instance.getPlatformNo()); if (platform != null && (PCCConstant.PLATFORM_TYPE_VMWARE.equals(platform.getPlatformType()))) { PlatformVmware platformVmware = platformVmwareDao.read(instance.getPlatformNo()); List<PlatformVmwareInstanceType> instanceTypes = platformVmwareInstanceTypeDao.readByPlatformNo(instance .getPlatformNo()); if (platformVmware != null && instanceTypes.isEmpty() == false) { for (PlatformVmwareInstanceType instanceType2 : instanceTypes) { if (StringUtils.equals(vmwareInstance.getInstanceType(), instanceType2.getInstanceTypeName())) { instanceType = instanceType2; break; } } } } if (instanceType == null) { // InstanceTypeが見つからない場合 throw new AutoException("EPROCESS-000512", vmwareInstance.getInstanceType()); } // 仮想マシンのリソースを変更 vmwareProcessClient.changeResourceVM(vmwareInstance.getMachineName(), instanceType.getCpu(), instanceType.getMemory()); } /** * TODO: メソッドコメントを記述 * * @param vmwareProcessClient * @param instanceNo */ public void updateCustomValue(VmwareProcessClient vmwareProcessClient, Long instanceNo) { // カスタムフィールドがない場合は作成 CustomFieldDef customFieldDef = vmwareProcessClient.getCustomFieldDef(fieldUserName, VirtualMachine.class); if (customFieldDef == null) { vmwareProcessClient.addCustomFieldDef(fieldUserName, VirtualMachine.class); } VmwareInstance vmwareInstance = vmwareInstanceDao.read(instanceNo); Instance instance = instanceDao.read(instanceNo); Farm farm = farmDao.read(instance.getFarmNo()); User user = userDao.read(farm.getUserNo()); // カスタムフィールドの値を設定 vmwareProcessClient.setCustomValue(vmwareInstance.getMachineName(), fieldUserName, user.getUsername()); } /** * fieldUserNameを設定します。 * * @param fieldUserName fieldUserName */ public void setFieldUserName(String fieldUserName) { this.fieldUserName = fieldUserName; } /** * processLoggerを設定します。 * * @param processLogger processLogger */ public void setProcessLogger(ProcessLogger processLogger) { this.processLogger = processLogger; } }