mirror of https://github.com/apache/cloudstack.git
Move VMware/Premium Secondary storage VM to opensource
This commit is contained in:
parent
38e858e38d
commit
98212299b5
|
|
@ -111,6 +111,8 @@
|
|||
<property name="meld.home" location="/usr/local/bin" />
|
||||
<property name="assertion" value="-da" />
|
||||
|
||||
<!-- directory for vmware-base library -->
|
||||
<property name="vmware-base.dir" location="${base.dir}/vmware-base" />
|
||||
|
||||
<!-- directories for testing -->
|
||||
<property name="test.target.dir" location="${target.dir}/test" />
|
||||
|
|
@ -126,6 +128,7 @@
|
|||
<property name="console-common.jar" value="cloud-console-common.jar" />
|
||||
<property name="console-proxy.jar" value="cloud-console-proxy.jar" />
|
||||
<property name="api.jar" value="cloud-api.jar"/>
|
||||
<property name="vmware-base.jar" value="cloud-vmware-base.jar" />
|
||||
|
||||
<!--
|
||||
Import information about the build version and company information
|
||||
|
|
@ -199,10 +202,18 @@
|
|||
<path refid="deps.classpath" />
|
||||
<path refid="dist.classpath" />
|
||||
</path>
|
||||
<target name="compile-core" depends="-init, compile-utils, compile-api" description="Compile the core business logic.">
|
||||
<target name="compile-core" depends="-init, compile-utils, compile-api, compile-vmware-base" description="Compile the core business logic.">
|
||||
<compile-java jar.name="${core.jar}" top.dir="${core.dir}" classpath="core.classpath" />
|
||||
</target>
|
||||
|
||||
<path id="vmware-base.classpath">
|
||||
<path refid="thirdparty.classpath" />
|
||||
<path refid="dist.classpath" />
|
||||
</path>
|
||||
<target name="compile-vmware-base" depends="-init, compile-utils" description="Compile the VMware support library">
|
||||
<compile-java jar.name="${vmware-base.jar}" top.dir="${vmware-base.dir}" classpath="vmware-base.classpath" />
|
||||
</target>
|
||||
|
||||
<path id="server.classpath">
|
||||
<path refid="deps.classpath" />
|
||||
<path refid="dist.classpath" />
|
||||
|
|
|
|||
|
|
@ -185,12 +185,33 @@
|
|||
<include name="cloud-commons-codec-1.4.jar" />
|
||||
<include name="cloud-commons-pool-1.4.jar" />
|
||||
<include name="cloud-cglib.jar" />
|
||||
<include name="cloud-axis.jar" />
|
||||
<include name="cloud-commons-discovery.jar" />
|
||||
<include name="cloud-wsdl4j.jar" />
|
||||
<include name="vmware-apputils.jar" />
|
||||
<include name="vmware-lib-jaxen-core.jar" />
|
||||
<include name="vmware-lib-jdom.jar" />
|
||||
<include name="vmware-lib-smtp.jar" />
|
||||
<include name="vmware-lib-xerces.jar" />
|
||||
<include name="vmware-vim.jar" />
|
||||
<include name="vmware-credstore.jar" />
|
||||
<include name="vmware-lib-jaxen-jdom.jar" />
|
||||
<include name="vmware-lib-mailapi.jar" />
|
||||
<include name="vmware-lib-wbem.jar" />
|
||||
<include name="vmware-lib-xml-apis.jar" />
|
||||
<include name="vmware-lib-activation.jar" />
|
||||
<include name="vmware-lib-jaxrpc.jar" />
|
||||
<include name="vmware-lib-saxpath.jar" />
|
||||
<include name="vmware-lib-xalan.jar" />
|
||||
<include name="vmware-vim25.jar" />
|
||||
<include name="vmware-vim.jar" />
|
||||
</zipfileset>
|
||||
<zipfileset dir="${jar.dir}">
|
||||
<include name="${agent.jar}" />
|
||||
<include name="${utils.jar}" />
|
||||
<include name="${core.jar}" />
|
||||
<include name="${api.jar}" />
|
||||
<include name="${vmware-base.jar}" />
|
||||
</zipfileset>
|
||||
<zipfileset dir="${console-proxy.dist.dir}" filemode="555">
|
||||
</zipfileset>
|
||||
|
|
|
|||
|
|
@ -7,5 +7,6 @@
|
|||
<classpathentry combineaccessrules="false" kind="src" path="/api"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/deps"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/tools"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/vmware-base"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.manager;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
|
||||
public interface VmwareHostService {
|
||||
VmwareContext getServiceContext(Command cmd);
|
||||
void invalidateServiceContext(VmwareContext context);
|
||||
VmwareHypervisorHost getHyperHost(VmwareContext context, Command cmd);
|
||||
|
||||
String getWorkerName(VmwareContext context, Command cmd);
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.manager;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
//import com.cloud.cluster.CheckPointManager;
|
||||
import com.cloud.hypervisor.vmware.mo.HostMO;
|
||||
import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
|
||||
public interface VmwareManager {
|
||||
public final String CONTEXT_STOCK_NAME = "vmwareMgr";
|
||||
|
||||
// this limitation comes from the fact that we are using linked clone on shared VMFS storage,
|
||||
// we need to limit the size of vCenter cluster, http://en.wikipedia.org/wiki/VMware_VMFS
|
||||
public final int MAX_HOSTS_PER_CLUSTER = 8;
|
||||
|
||||
String composeWorkerName();
|
||||
|
||||
String getSystemVMIsoFileNameOnDatastore();
|
||||
void prepareSecondaryStorageStore(String strStorageUrl);
|
||||
|
||||
void setupResourceStartupParams(Map<String, Object> params);
|
||||
List<ManagedObjectReference> addHostToPodCluster(VmwareContext serviceContext, long dcId, Long podId, Long clusterId,
|
||||
String hostInventoryPath) throws Exception;
|
||||
|
||||
String getManagementPortGroupByHost(HostMO hostMo) throws Exception;
|
||||
String getServiceConsolePortGroupName();
|
||||
String getManagementPortGroupName();
|
||||
|
||||
String getSecondaryStorageStoreUrl(long dcId);
|
||||
|
||||
File getSystemVMKeyFile();
|
||||
|
||||
VmwareStorageManager getStorageManager();
|
||||
long pushCleanupCheckpoint(String hostGuid, String vmName);
|
||||
void popCleanupCheckpoint(long checkpiont);
|
||||
void gcLeftOverVMs(VmwareContext context);
|
||||
|
||||
Pair<Integer, Integer> getAddiionalVncPortRange();
|
||||
VirtualEthernetCardType getGuestNicDeviceType();
|
||||
|
||||
int getMaxHostsPerCluster();
|
||||
|
||||
boolean beginExclusiveOperation(int timeOutSeconds);
|
||||
void endExclusiveOperation();
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.manager;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.BackupSnapshotCommand;
|
||||
import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
|
||||
import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
|
||||
import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
|
||||
import com.cloud.agent.api.DeleteSnapshotBackupCommand;
|
||||
import com.cloud.agent.api.DeleteSnapshotsDirCommand;
|
||||
import com.cloud.agent.api.storage.CopyVolumeCommand;
|
||||
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
|
||||
|
||||
public interface VmwareStorageManager {
|
||||
Answer execute(VmwareHostService hostService, PrimaryStorageDownloadCommand cmd);
|
||||
Answer execute(VmwareHostService hostService, BackupSnapshotCommand cmd);
|
||||
Answer execute(VmwareHostService hostService, DeleteSnapshotsDirCommand cmd);
|
||||
Answer execute(VmwareHostService hostService, DeleteSnapshotBackupCommand cmd);
|
||||
Answer execute(VmwareHostService hostService, CreatePrivateTemplateFromVolumeCommand cmd);
|
||||
Answer execute(VmwareHostService hostService, CreatePrivateTemplateFromSnapshotCommand cmd);
|
||||
Answer execute(VmwareHostService hostService, CopyVolumeCommand cmd);
|
||||
Answer execute(VmwareHostService hostService, CreateVolumeFromSnapshotCommand cmd);
|
||||
}
|
||||
|
|
@ -0,0 +1,905 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.manager;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.BackupSnapshotAnswer;
|
||||
import com.cloud.agent.api.BackupSnapshotCommand;
|
||||
import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
|
||||
import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
|
||||
import com.cloud.agent.api.CreateVolumeFromSnapshotAnswer;
|
||||
import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
|
||||
import com.cloud.agent.api.DeleteSnapshotBackupAnswer;
|
||||
import com.cloud.agent.api.DeleteSnapshotBackupCommand;
|
||||
import com.cloud.agent.api.DeleteSnapshotsDirCommand;
|
||||
import com.cloud.agent.api.storage.CopyVolumeAnswer;
|
||||
import com.cloud.agent.api.storage.CopyVolumeCommand;
|
||||
import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
|
||||
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
|
||||
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
|
||||
import com.cloud.agent.api.to.StorageFilerTO;
|
||||
import com.cloud.hypervisor.vmware.mo.CustomFieldConstants;
|
||||
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
|
||||
import com.cloud.hypervisor.vmware.mo.DatastoreMO;
|
||||
import com.cloud.hypervisor.vmware.mo.HostMO;
|
||||
import com.cloud.hypervisor.vmware.mo.HypervisorHostHelper;
|
||||
import com.cloud.hypervisor.vmware.mo.VirtualMachineMO;
|
||||
import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpec;
|
||||
import com.vmware.vim25.VirtualLsiLogicController;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareHelper;
|
||||
import com.cloud.storage.JavaStorageLayer;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.StorageLayer;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.StringUtils;
|
||||
import com.cloud.utils.Ternary;
|
||||
import com.cloud.utils.script.Script;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.VirtualDisk;
|
||||
import com.vmware.vim25.VirtualMachineConfigSpec;
|
||||
import com.vmware.vim25.VirtualMachineFileInfo;
|
||||
import com.vmware.vim25.VirtualMachineGuestOsIdentifier;
|
||||
import com.vmware.vim25.VirtualSCSISharing;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpec;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
|
||||
|
||||
public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
||||
private static final Logger s_logger = Logger.getLogger(VmwareStorageManagerImpl.class);
|
||||
|
||||
private final VmwareStorageMount _mountService;
|
||||
private final StorageLayer _storage = new JavaStorageLayer();
|
||||
|
||||
private int _timeout;
|
||||
|
||||
public VmwareStorageManagerImpl(VmwareStorageMount mountService) {
|
||||
assert(mountService != null);
|
||||
_mountService = mountService;
|
||||
}
|
||||
|
||||
public void configure(Map<String, Object> params) {
|
||||
s_logger.info("Configure VmwareStorageManagerImpl");
|
||||
|
||||
String value = (String)params.get("scripts.timeout");
|
||||
_timeout = NumbersUtil.parseInt(value, 1440) * 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer execute(VmwareHostService hostService, PrimaryStorageDownloadCommand cmd) {
|
||||
String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
|
||||
assert (secondaryStorageUrl != null);
|
||||
|
||||
String templateUrl = cmd.getUrl();
|
||||
|
||||
String templateName = null;
|
||||
String mountPoint = null;
|
||||
if (templateUrl.endsWith(".ova")) {
|
||||
int index = templateUrl.lastIndexOf("/");
|
||||
mountPoint = templateUrl.substring(0, index);
|
||||
mountPoint = mountPoint.substring(secondaryStorageUrl.length() + 1);
|
||||
if (!mountPoint.endsWith("/")) {
|
||||
mountPoint = mountPoint + "/";
|
||||
}
|
||||
|
||||
templateName = templateUrl.substring(index + 1).replace("." + ImageFormat.OVA.getFileExtension(), "");
|
||||
|
||||
if (templateName == null || templateName.isEmpty()) {
|
||||
templateName = cmd.getName();
|
||||
}
|
||||
} else {
|
||||
mountPoint = templateUrl.substring(secondaryStorageUrl.length() + 1);
|
||||
if (!mountPoint.endsWith("/")) {
|
||||
mountPoint = mountPoint + "/";
|
||||
}
|
||||
templateName = cmd.getName();
|
||||
}
|
||||
|
||||
VmwareContext context = hostService.getServiceContext(cmd);
|
||||
try {
|
||||
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
|
||||
|
||||
String templateUuidName = UUID.nameUUIDFromBytes((templateName + "@" + cmd.getPoolUuid() + "-" + hyperHost.getMor().get_value()).getBytes()).toString();
|
||||
|
||||
DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
|
||||
VirtualMachineMO templateMo = VmwareHelper.pickOneVmOnRunningHost(dcMo.findVmByNameAndLabel(templateUuidName), true);
|
||||
|
||||
if (templateMo == null) {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("Template " + templateName + " is not setup yet, setup template from secondary storage with uuid name: " + templateUuidName);
|
||||
ManagedObjectReference morDs = hyperHost.findDatastore(cmd.getPoolUuid());
|
||||
assert (morDs != null);
|
||||
DatastoreMO primaryStorageDatastoreMo = new DatastoreMO(context, morDs);
|
||||
|
||||
copyTemplateFromSecondaryToPrimary(hyperHost,
|
||||
primaryStorageDatastoreMo, secondaryStorageUrl,
|
||||
mountPoint, templateUuidName);
|
||||
} else {
|
||||
s_logger.info("Template " + templateName + " has already been setup, skip the template setup process in primary storage");
|
||||
}
|
||||
|
||||
return new PrimaryStorageDownloadAnswer(templateUuidName, 0);
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof RemoteException) {
|
||||
hostService.invalidateServiceContext(context);
|
||||
}
|
||||
|
||||
String msg = "Unable to execute PrimaryStorageDownloadCommand due to exception";
|
||||
s_logger.error(msg, e);
|
||||
return new PrimaryStorageDownloadAnswer(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer execute(VmwareHostService hostService, BackupSnapshotCommand cmd) {
|
||||
Long accountId = cmd.getAccountId();
|
||||
Long volumeId = cmd.getVolumeId();
|
||||
String secondaryStoragePoolURL = cmd.getSecondaryStoragePoolURL();
|
||||
String snapshotUuid = cmd.getSnapshotUuid(); // not null: Precondition.
|
||||
String prevSnapshotUuid = cmd.getPrevSnapshotUuid();
|
||||
String prevBackupUuid = cmd.getPrevBackupUuid();
|
||||
VirtualMachineMO workerVm=null;
|
||||
String workerVMName = null;
|
||||
String volumePath = cmd.getVolumePath();
|
||||
ManagedObjectReference morDs = null;
|
||||
String snapshotUUID = null;
|
||||
DatastoreMO dsMo=null;
|
||||
|
||||
// By default assume failure
|
||||
String details = null;
|
||||
boolean success = false;
|
||||
String snapshotBackupUuid = null;
|
||||
|
||||
VmwareContext context = hostService.getServiceContext(cmd);
|
||||
try {
|
||||
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
|
||||
morDs = hyperHost.findDatastore(cmd.getPool().getUuid());
|
||||
|
||||
VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(cmd.getVmName());
|
||||
if (vmMo == null) {
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("Unable to find owner VM for BackupSnapshotCommand on host " + hyperHost.getHyperHostName() + ", will try within datacenter");
|
||||
|
||||
vmMo = hyperHost.findVmOnPeerHyperHost(cmd.getVmName());
|
||||
if(vmMo == null) {
|
||||
dsMo = new DatastoreMO(hyperHost.getContext(), morDs);
|
||||
//restrict VM name to 32 chars, (else snapshot descriptor file name will be truncated to 32 chars of vm name)
|
||||
workerVMName = UUID.randomUUID().toString().replaceAll("-", "");
|
||||
|
||||
//attach a volume to dummay wrapper VM for taking snapshot and exporting the VM for backup
|
||||
if (!hyperHost.createBlankVm(workerVMName, 1, 512, 0, false, 4, VirtualMachineGuestOsIdentifier._otherGuest.toString(), morDs, false)) {
|
||||
String msg = "Unable to create worker VM to execute BackupSnapshotCommand";
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
vmMo = hyperHost.findVmOnHyperHost(workerVMName);
|
||||
if (vmMo == null) {
|
||||
throw new Exception("Failed to find the newly create or relocated VM. vmName: " + workerVMName);
|
||||
}
|
||||
workerVm = vmMo;
|
||||
|
||||
//attach volume to worker VM
|
||||
String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumePath);
|
||||
vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs);
|
||||
snapshotUUID = UUID.randomUUID().toString();
|
||||
if (!vmMo.createSnapshot(snapshotUUID, "Snapshot taken for " + cmd.getSnapshotName(), false, false)) {
|
||||
throw new Exception("Failed to take snapshot " + cmd.getSnapshotName() + " on vm: " + cmd.getVmName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snapshotBackupUuid = backupSnapshotToSecondaryStorage(vmMo, accountId,
|
||||
volumeId, cmd.getVolumePath(), snapshotUuid,
|
||||
secondaryStoragePoolURL, prevSnapshotUuid,
|
||||
prevBackupUuid,
|
||||
hostService.getWorkerName(context, cmd));
|
||||
|
||||
success = (snapshotBackupUuid != null);
|
||||
|
||||
if (success) {
|
||||
details = "Successfully backedUp the snapshotUuid: " + snapshotUuid + " to secondary storage.";
|
||||
vmMo.removeAllSnapshots();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof RemoteException) {
|
||||
hostService.invalidateServiceContext(context);
|
||||
}
|
||||
|
||||
s_logger.error("Unexpecpted exception ", e);
|
||||
|
||||
details = "BackupSnapshotCommand exception: " + StringUtils.getExceptionStackInfo(e);
|
||||
return new BackupSnapshotAnswer(cmd, false, details, snapshotBackupUuid, true);
|
||||
} finally {
|
||||
try {
|
||||
if (workerVm != null) {
|
||||
//detach volume and destroy worker vm
|
||||
workerVm.moveAllVmDiskFiles(dsMo, "", false);
|
||||
workerVm.detachAllDisks();
|
||||
workerVm.destroy();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
s_logger.warn("Failed to destroy worker VM: " + workerVMName);
|
||||
}
|
||||
}
|
||||
|
||||
return new BackupSnapshotAnswer(cmd, success, details, snapshotBackupUuid, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer execute(VmwareHostService hostService, DeleteSnapshotsDirCommand cmd) {
|
||||
Long accountId = cmd.getAccountId();
|
||||
Long volumeId = cmd.getVolumeId();
|
||||
String secondaryStoragePoolURL = cmd.getSecondaryStoragePoolURL();
|
||||
|
||||
String details = null;
|
||||
boolean success = false;
|
||||
|
||||
VmwareContext context = hostService.getServiceContext(cmd);
|
||||
try {
|
||||
details = deleteSnapshotDirOnSecondaryStorage(accountId, volumeId, secondaryStoragePoolURL);
|
||||
if (details == null) {
|
||||
success = true;
|
||||
}
|
||||
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof RemoteException) {
|
||||
hostService.invalidateServiceContext(context);
|
||||
}
|
||||
|
||||
s_logger.error("Unexpecpted exception ", e);
|
||||
|
||||
details = "DeleteSnapshotDirCommand exception: " + StringUtils.getExceptionStackInfo(e);
|
||||
return new Answer(cmd, false, details);
|
||||
}
|
||||
|
||||
return new Answer(cmd, success, details);
|
||||
}
|
||||
|
||||
public Answer execute(VmwareHostService hostService, DeleteSnapshotBackupCommand cmd) {
|
||||
Long accountId = cmd.getAccountId();
|
||||
Long volumeId = cmd.getVolumeId();
|
||||
String secStorageUrl = cmd.getSecondaryStoragePoolURL();
|
||||
String backupUUID = cmd.getSnapshotUuid();
|
||||
String details = null;
|
||||
boolean success = false;
|
||||
|
||||
VmwareContext context = hostService.getServiceContext(cmd);
|
||||
try {
|
||||
details = deleteSnapshotOnSecondaryStorge(accountId, volumeId, secStorageUrl, backupUUID);
|
||||
if (details == null) {
|
||||
success = true;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof RemoteException) {
|
||||
hostService.invalidateServiceContext(context);
|
||||
}
|
||||
|
||||
s_logger.error("Unexpecpted exception ", e);
|
||||
details = "DeleteSnapshotBackupCommand exception: " + StringUtils.getExceptionStackInfo(e);
|
||||
return new DeleteSnapshotBackupAnswer(cmd, false, details);
|
||||
}
|
||||
|
||||
return new DeleteSnapshotBackupAnswer(cmd, success, details);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer execute(VmwareHostService hostService, CreatePrivateTemplateFromVolumeCommand cmd) {
|
||||
String secondaryStoragePoolURL = cmd.getSecondaryStorageURL();
|
||||
String volumePath = cmd.getVolumePath();
|
||||
Long accountId = cmd.getAccountId();
|
||||
Long templateId = cmd.getTemplateId();
|
||||
String details = null;
|
||||
|
||||
VmwareContext context = hostService.getServiceContext(cmd);
|
||||
try {
|
||||
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
|
||||
|
||||
VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(cmd.getVmName());
|
||||
if (vmMo == null) {
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("Unable to find the owner VM for CreatePrivateTemplateFromVolumeCommand on host " + hyperHost.getHyperHostName() + ", try within datacenter");
|
||||
vmMo = hyperHost.findVmOnPeerHyperHost(cmd.getVmName());
|
||||
|
||||
if(vmMo == null) {
|
||||
String msg = "Unable to find the owner VM for volume operation. vm: " + cmd.getVmName();
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
}
|
||||
|
||||
Ternary<String, Long, Long> result = createTemplateFromVolume(vmMo,
|
||||
accountId, templateId, cmd.getTemplateName(),
|
||||
secondaryStoragePoolURL, volumePath,
|
||||
hostService.getWorkerName(context, cmd));
|
||||
|
||||
return new CreatePrivateTemplateAnswer(cmd, true, null,
|
||||
result.first(), result.third(), result.second(),
|
||||
cmd.getTemplateName(), ImageFormat.OVA);
|
||||
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof RemoteException) {
|
||||
hostService.invalidateServiceContext(context);
|
||||
}
|
||||
|
||||
s_logger.error("Unexpecpted exception ", e);
|
||||
|
||||
details = "CreatePrivateTemplateFromVolumeCommand exception: " + StringUtils.getExceptionStackInfo(e);
|
||||
return new CreatePrivateTemplateAnswer(cmd, false, details);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer execute(VmwareHostService hostService, CreatePrivateTemplateFromSnapshotCommand cmd) {
|
||||
Long accountId = cmd.getAccountId();
|
||||
Long volumeId = cmd.getVolumeId();
|
||||
String secondaryStoragePoolURL = cmd.getSecondaryStoragePoolURL();
|
||||
String backedUpSnapshotUuid = cmd.getSnapshotUuid();
|
||||
Long newTemplateId = cmd.getNewTemplateId();
|
||||
String details;
|
||||
String uniqeName = UUID.randomUUID().toString();
|
||||
|
||||
VmwareContext context = hostService.getServiceContext(cmd);
|
||||
try {
|
||||
Ternary<String, Long, Long> result = createTemplateFromSnapshot(accountId,
|
||||
newTemplateId, uniqeName,
|
||||
secondaryStoragePoolURL, volumeId,
|
||||
backedUpSnapshotUuid);
|
||||
|
||||
return new CreatePrivateTemplateAnswer(cmd, true, null,
|
||||
result.first(), result.third(), result.second(),
|
||||
uniqeName, ImageFormat.OVA);
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof RemoteException) {
|
||||
hostService.invalidateServiceContext(context);
|
||||
}
|
||||
|
||||
s_logger.error("Unexpecpted exception ", e);
|
||||
|
||||
details = "CreatePrivateTemplateFromSnapshotCommand exception: " + StringUtils.getExceptionStackInfo(e);
|
||||
return new CreatePrivateTemplateAnswer(cmd, false, details);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer execute(VmwareHostService hostService, CopyVolumeCommand cmd) {
|
||||
Long volumeId = cmd.getVolumeId();
|
||||
String volumePath = cmd.getVolumePath();
|
||||
String secondaryStorageURL = cmd.getSecondaryStorageURL();
|
||||
String vmName = cmd.getVmName();
|
||||
|
||||
VmwareContext context = hostService.getServiceContext(cmd);
|
||||
try {
|
||||
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
|
||||
|
||||
Pair<String, String> result;
|
||||
if (cmd.toSecondaryStorage()) {
|
||||
result = copyVolumeToSecStorage(
|
||||
hyperHost, vmName, volumeId, cmd.getPool().getUuid(), volumePath,
|
||||
secondaryStorageURL,
|
||||
hostService.getWorkerName(context, cmd));
|
||||
} else {
|
||||
StorageFilerTO poolTO = cmd.getPool();
|
||||
|
||||
ManagedObjectReference morDatastore = hyperHost.findDatastore(poolTO.getUuid());
|
||||
if (morDatastore == null) {
|
||||
morDatastore = hyperHost.mountDatastore(
|
||||
false,
|
||||
poolTO.getHost(), 0, poolTO.getPath(),
|
||||
poolTO.getUuid());
|
||||
|
||||
if (morDatastore == null) {
|
||||
throw new Exception("Unable to mount storage pool on host. storeUrl: " + poolTO.getHost() + ":/" + poolTO.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
result = copyVolumeFromSecStorage(
|
||||
hyperHost, volumeId,
|
||||
new DatastoreMO(context, morDatastore),
|
||||
secondaryStorageURL, volumePath);
|
||||
}
|
||||
return new CopyVolumeAnswer(cmd, true, null, result.first(), result.second());
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof RemoteException) {
|
||||
hostService.invalidateServiceContext(context);
|
||||
}
|
||||
|
||||
String msg = "Unable to execute CopyVolumeCommand due to exception";
|
||||
s_logger.error(msg, e);
|
||||
return new CopyVolumeAnswer(cmd, false, "CopyVolumeCommand failed due to exception: " + StringUtils.getExceptionStackInfo(e), null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer execute(VmwareHostService hostService, CreateVolumeFromSnapshotCommand cmd) {
|
||||
|
||||
String primaryStorageNameLabel = cmd.getPrimaryStoragePoolNameLabel();
|
||||
Long accountId = cmd.getAccountId();
|
||||
Long volumeId = cmd.getVolumeId();
|
||||
String secondaryStoragePoolURL = cmd.getSecondaryStoragePoolURL();
|
||||
String backedUpSnapshotUuid = cmd.getSnapshotUuid();
|
||||
|
||||
String details = null;
|
||||
boolean success = false;
|
||||
String newVolumeName = UUID.randomUUID().toString().replaceAll("-", "");
|
||||
|
||||
VmwareContext context = hostService.getServiceContext(cmd);
|
||||
try {
|
||||
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
|
||||
|
||||
ManagedObjectReference morPrimaryDs = hyperHost.findDatastore(primaryStorageNameLabel);
|
||||
if (morPrimaryDs == null) {
|
||||
String msg = "Unable to find datastore: " + primaryStorageNameLabel;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
DatastoreMO primaryDsMo = new DatastoreMO(hyperHost.getContext(), morPrimaryDs);
|
||||
details = createVolumeFromSnapshot(hyperHost, primaryDsMo,
|
||||
newVolumeName, accountId, volumeId,
|
||||
secondaryStoragePoolURL, backedUpSnapshotUuid);
|
||||
if (details == null) {
|
||||
success = true;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof RemoteException) {
|
||||
hostService.invalidateServiceContext(context);
|
||||
}
|
||||
|
||||
s_logger.error("Unexpecpted exception ", e);
|
||||
details = "CreateVolumeFromSnapshotCommand exception: " + StringUtils.getExceptionStackInfo(e);
|
||||
}
|
||||
|
||||
return new CreateVolumeFromSnapshotAnswer(cmd, success, details, newVolumeName);
|
||||
}
|
||||
|
||||
private void copyTemplateFromSecondaryToPrimary(VmwareHypervisorHost hyperHost, DatastoreMO datastoreMo, String secondaryStorageUrl,
|
||||
String templatePathAtSecondaryStorage, String templateName) throws Exception {
|
||||
|
||||
s_logger.info("Executing copyTemplateFromSecondaryToPrimary. secondaryStorage: "
|
||||
+ secondaryStorageUrl + ", templatePathAtSecondaryStorage: " + templatePathAtSecondaryStorage
|
||||
+ ", templateName: " + templateName);
|
||||
|
||||
String secondaryMountPoint = _mountService.getMountPoint(secondaryStorageUrl);
|
||||
s_logger.info("Secondary storage mount point: " + secondaryMountPoint);
|
||||
|
||||
String srcOVAFileName = secondaryMountPoint + "/" + templatePathAtSecondaryStorage +
|
||||
templateName + "." + ImageFormat.OVA.getFileExtension();
|
||||
|
||||
String srcFileName = getOVFFilePath(srcOVAFileName);
|
||||
if(srcFileName == null) {
|
||||
String msg = "Unable to locate OVF file in template package directory: " + srcOVAFileName;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
String vmName = templateName;
|
||||
hyperHost.importVmFromOVF(srcFileName, vmName, datastoreMo, "thin");
|
||||
|
||||
VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
|
||||
if(vmMo == null) {
|
||||
String msg = "Failed to import OVA template. secondaryStorage: "
|
||||
+ secondaryStorageUrl + ", templatePathAtSecondaryStorage: " + templatePathAtSecondaryStorage
|
||||
+ ", templateName: " + templateName;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
if(vmMo.createSnapshot("cloud.template.base", "Base snapshot", false, false)) {
|
||||
vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_UUID, templateName);
|
||||
vmMo.markAsTemplate();
|
||||
} else {
|
||||
vmMo.destroy();
|
||||
String msg = "Unable to create base snapshot for template: " + templateName;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private Ternary<String, Long, Long> createTemplateFromVolume(VirtualMachineMO vmMo, long accountId, long templateId, String templateName,
|
||||
String secStorageUrl, String volumePath, String workerVmName) throws Exception {
|
||||
|
||||
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
|
||||
String installPath = getTemplateRelativeDirInSecStorage(accountId, templateId);
|
||||
String installFullPath = secondaryMountPoint + "/" + installPath;
|
||||
synchronized(installPath.intern()) {
|
||||
Script command = new Script(false, "mkdir", _timeout, s_logger);
|
||||
command.add("-p");
|
||||
command.add(installFullPath);
|
||||
|
||||
String result = command.execute();
|
||||
if(result != null) {
|
||||
String msg = "unable to prepare template directory: "
|
||||
+ installPath + ", storage: " + secStorageUrl + ", error msg: " + result;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
}
|
||||
|
||||
String tmpSnapshotName = UUID.randomUUID().toString();
|
||||
VirtualMachineMO clonedVm = null;
|
||||
try {
|
||||
Pair<VirtualDisk, String> volumeDeviceInfo = vmMo.getDiskDevice(volumePath, false);
|
||||
if(volumeDeviceInfo == null) {
|
||||
String msg = "Unable to find related disk device for volume. volume path: " + volumePath;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
if(!vmMo.createSnapshot(tmpSnapshotName, "Temporary snapshot for template creation", false, false)) {
|
||||
String msg = "Unable to take snapshot for creating template from volume. volume path: " + volumePath;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
// 4 MB is the minimum requirement for VM memory in VMware
|
||||
vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(),
|
||||
VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()));
|
||||
clonedVm = vmMo.getRunningHost().findVmOnHyperHost(workerVmName);
|
||||
if(clonedVm == null) {
|
||||
String msg = "Unable to create dummy VM to export volume. volume path: " + volumePath;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
clonedVm.exportVm(secondaryMountPoint + "/" + installPath, templateName, true, false);
|
||||
|
||||
// TODO, need to find out virtual size and physical size
|
||||
long size = new File(installFullPath + "/" + templateName + ".ova").length();
|
||||
postCreatePrivateTemplate(installFullPath, templateId, templateName, size, size);
|
||||
|
||||
return new Ternary<String, Long, Long>(installPath + "/" + templateName + ".ova", size, size);
|
||||
|
||||
} finally {
|
||||
if(clonedVm != null)
|
||||
clonedVm.destroy();
|
||||
|
||||
vmMo.removeSnapshot(tmpSnapshotName, false);
|
||||
}
|
||||
}
|
||||
|
||||
private Ternary<String, Long, Long> createTemplateFromSnapshot(long accountId, long templateId, String templateName,
|
||||
String secStorageUrl, long volumeId, String backedUpSnapshotUuid) throws Exception {
|
||||
|
||||
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
|
||||
String installPath = getTemplateRelativeDirInSecStorage(accountId, templateId);
|
||||
String installFullPath = secondaryMountPoint + "/" + installPath;
|
||||
String installFullName = installFullPath + "/" + templateName + ".ova";
|
||||
String snapshotFullName = secondaryMountPoint + "/" + getSnapshotRelativeDirInSecStorage(accountId, volumeId)
|
||||
+ "/" + backedUpSnapshotUuid + ".ova";
|
||||
String result;
|
||||
Script command;
|
||||
|
||||
synchronized(installPath.intern()) {
|
||||
command = new Script(false, "mkdir", _timeout, s_logger);
|
||||
command.add("-p");
|
||||
command.add(installFullPath);
|
||||
|
||||
result = command.execute();
|
||||
if(result != null) {
|
||||
String msg = "unable to prepare template directory: "
|
||||
+ installPath + ", storage: " + secStorageUrl + ", error msg: " + result;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
command = new Script(false, "cp", _timeout, s_logger);
|
||||
command.add(snapshotFullName);
|
||||
command.add(installFullName);
|
||||
result = command.execute();
|
||||
if(result != null) {
|
||||
String msg = "unable to copy snapshot " + snapshotFullName + " to " + installFullPath;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
// untar OVA file at template directory
|
||||
command = new Script("tar", 0, s_logger);
|
||||
command.add("-xf", installFullName);
|
||||
command.setWorkDir(installFullPath);
|
||||
result = command.execute();
|
||||
if(result != null) {
|
||||
String msg = "unable to copy snapshot " + snapshotFullName + " to " + installFullPath;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
long size = new File(installFullName).length();
|
||||
postCreatePrivateTemplate(installFullPath, templateId, templateName, size, size);
|
||||
return new Ternary<String, Long, Long>(installPath + "/" + templateName + ".ova", size, size);
|
||||
|
||||
} catch(Exception e) {
|
||||
// TODO, clean up left over files
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private void postCreatePrivateTemplate(String installFullPath, long templateId,
|
||||
String templateName, long size, long virtualSize) throws Exception {
|
||||
|
||||
// TODO a bit ugly here
|
||||
BufferedWriter out = null;
|
||||
try {
|
||||
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(installFullPath + "/template.properties")));
|
||||
out.write("filename=" + templateName + ".ova");
|
||||
out.newLine();
|
||||
out.write("description=");
|
||||
out.newLine();
|
||||
out.write("checksum=");
|
||||
out.newLine();
|
||||
out.write("hvm=false");
|
||||
out.newLine();
|
||||
out.write("size=" + size);
|
||||
out.newLine();
|
||||
out.write("ova=true");
|
||||
out.newLine();
|
||||
out.write("id=" + templateId);
|
||||
out.newLine();
|
||||
out.write("public=false");
|
||||
out.newLine();
|
||||
out.write("ova.filename=" + templateName + ".ova");
|
||||
out.newLine();
|
||||
out.write("uniquename=" + templateName);
|
||||
out.newLine();
|
||||
out.write("ova.virtualsize=" + virtualSize);
|
||||
out.newLine();
|
||||
out.write("virtualsize=" + virtualSize);
|
||||
out.newLine();
|
||||
out.write("ova.size=" + size);
|
||||
out.newLine();
|
||||
} finally {
|
||||
if(out != null)
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
private String createVolumeFromSnapshot(VmwareHypervisorHost hyperHost, DatastoreMO primaryDsMo, String newVolumeName,
|
||||
long accountId, long volumeId, String secStorageUrl, String snapshotBackupUuid) throws Exception {
|
||||
|
||||
restoreVolumeFromSecStorage(hyperHost, primaryDsMo, newVolumeName,
|
||||
secStorageUrl, getSnapshotRelativeDirInSecStorage(accountId, volumeId), snapshotBackupUuid);
|
||||
return null;
|
||||
}
|
||||
|
||||
private void restoreVolumeFromSecStorage(VmwareHypervisorHost hyperHost, DatastoreMO primaryDsMo, String newVolumeName,
|
||||
String secStorageUrl, String secStorageDir, String backupName) throws Exception {
|
||||
|
||||
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
|
||||
String srcOVAFileName = secondaryMountPoint + "/" + secStorageDir + "/"
|
||||
+ backupName + "." + ImageFormat.OVA.getFileExtension();
|
||||
|
||||
String srcFileName = getOVFFilePath(srcOVAFileName);
|
||||
if(srcFileName == null) {
|
||||
Script command = new Script("tar", 0, s_logger);
|
||||
command.add("-xf", srcOVAFileName);
|
||||
command.setWorkDir(secondaryMountPoint + "/" + secStorageDir);
|
||||
String result = command.execute();
|
||||
if(result != null) {
|
||||
String msg = "Unable to unpack snapshot OVA file at: " + srcOVAFileName;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
}
|
||||
|
||||
srcFileName = getOVFFilePath(srcOVAFileName);
|
||||
if(srcFileName == null) {
|
||||
String msg = "Unable to locate OVF file in template package directory: " + srcOVAFileName;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
VirtualMachineMO clonedVm = null;
|
||||
try {
|
||||
hyperHost.importVmFromOVF(srcFileName, newVolumeName, primaryDsMo, "thin");
|
||||
clonedVm = hyperHost.findVmOnHyperHost(newVolumeName);
|
||||
if(clonedVm == null)
|
||||
throw new Exception("Unable to create container VM for volume creation");
|
||||
|
||||
clonedVm.moveAllVmDiskFiles(primaryDsMo, "", false);
|
||||
clonedVm.detachAllDisks();
|
||||
} finally {
|
||||
if(clonedVm != null)
|
||||
clonedVm.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
private String backupSnapshotToSecondaryStorage(VirtualMachineMO vmMo, long accountId, long volumeId,
|
||||
String volumePath, String snapshotUuid, String secStorageUrl,
|
||||
String prevSnapshotUuid, String prevBackupUuid, String workerVmName) throws Exception {
|
||||
|
||||
String backupUuid = UUID.randomUUID().toString();
|
||||
exportVolumeToSecondaryStroage(vmMo, volumePath, secStorageUrl,
|
||||
getSnapshotRelativeDirInSecStorage(accountId, volumeId), backupUuid, workerVmName);
|
||||
return backupUuid;
|
||||
}
|
||||
|
||||
private void exportVolumeToSecondaryStroage(VirtualMachineMO vmMo, String volumePath,
|
||||
String secStorageUrl, String secStorageDir, String exportName,
|
||||
String workerVmName) throws Exception {
|
||||
|
||||
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
|
||||
String exportPath = secondaryMountPoint + "/" + secStorageDir;
|
||||
|
||||
synchronized(exportPath.intern()) {
|
||||
if(!new File(exportPath).exists()) {
|
||||
Script command = new Script(false, "mkdir", _timeout, s_logger);
|
||||
command.add("-p");
|
||||
command.add(exportPath);
|
||||
if(command.execute() != null)
|
||||
throw new Exception("unable to prepare snapshot backup directory");
|
||||
}
|
||||
}
|
||||
|
||||
VirtualMachineMO clonedVm = null;
|
||||
try {
|
||||
|
||||
Pair<VirtualDisk, String> volumeDeviceInfo = vmMo.getDiskDevice(volumePath, false);
|
||||
if(volumeDeviceInfo == null) {
|
||||
String msg = "Unable to find related disk device for volume. volume path: " + volumePath;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
// 4 MB is the minimum requirement for VM memory in VMware
|
||||
vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(),
|
||||
VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()));
|
||||
clonedVm = vmMo.getRunningHost().findVmOnHyperHost(workerVmName);
|
||||
if(clonedVm == null) {
|
||||
String msg = "Unable to create dummy VM to export volume. volume path: " + volumePath;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
clonedVm.exportVm(exportPath, exportName, true, true);
|
||||
} finally {
|
||||
if(clonedVm != null)
|
||||
clonedVm.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
private String deleteSnapshotOnSecondaryStorge(long accountId, long volumeId, String secStorageUrl, String backupUuid) throws Exception {
|
||||
|
||||
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
|
||||
String snapshotMountRoot = secondaryMountPoint + "/" + getSnapshotRelativeDirInSecStorage(accountId, volumeId);
|
||||
File file = new File(snapshotMountRoot + "/" + backupUuid + ".ova");
|
||||
if(file.exists()) {
|
||||
if(file.delete())
|
||||
return null;
|
||||
|
||||
} else {
|
||||
return "Backup file does not exist. backupUuid: " + backupUuid;
|
||||
}
|
||||
|
||||
return "Failed to delete snapshot backup file, backupUuid: " + backupUuid;
|
||||
}
|
||||
|
||||
private String deleteSnapshotDirOnSecondaryStorage(long accountId, long volumeId, String secStorageUrl) throws Exception {
|
||||
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
|
||||
String snapshotMountRoot = secondaryMountPoint + "/" + getSnapshotRelativeDirInSecStorage(accountId, volumeId);
|
||||
|
||||
synchronized(snapshotMountRoot.intern()) {
|
||||
Script command = new Script(false, "rm", _timeout, s_logger);
|
||||
command.add("-rf");
|
||||
command.add(snapshotMountRoot);
|
||||
return command.execute();
|
||||
}
|
||||
}
|
||||
|
||||
private Pair<String, String> copyVolumeToSecStorage(VmwareHypervisorHost hyperHost, String vmName, long volumeId, String poolId, String volumePath,
|
||||
String secStorageUrl, String workerVmName) throws Exception {
|
||||
String volumeFolder = String.valueOf(volumeId) + "/";
|
||||
VirtualMachineMO workerVm=null;
|
||||
VirtualMachineMO vmMo=null;
|
||||
String exportName = UUID.randomUUID().toString();
|
||||
|
||||
try {
|
||||
ManagedObjectReference morDs = hyperHost.findDatastore(poolId);
|
||||
|
||||
if (morDs == null) {
|
||||
String msg = "Unable to find volumes's storage pool for copy volume operation";
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
vmMo = hyperHost.findVmOnHyperHost(vmName);
|
||||
if (vmMo == null) {
|
||||
//create a dummy worker vm for attaching the volume
|
||||
DatastoreMO dsMo = new DatastoreMO(hyperHost.getContext(), morDs);
|
||||
//restrict VM name to 32 chars, (else snapshot descriptor file name will be truncated to 32 chars of vm name)
|
||||
String workerVMName = UUID.randomUUID().toString().replaceAll("-", "");
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
vmConfig.setName(workerVMName);
|
||||
vmConfig.setMemoryMB((long) 4);
|
||||
vmConfig.setNumCPUs(1);
|
||||
vmConfig.setGuestId(VirtualMachineGuestOsIdentifier._otherGuest.toString());
|
||||
VirtualMachineFileInfo fileInfo = new VirtualMachineFileInfo();
|
||||
fileInfo.setVmPathName(String.format("[%s]", dsMo.getName()));
|
||||
vmConfig.setFiles(fileInfo);
|
||||
|
||||
// Scsi controller
|
||||
VirtualLsiLogicController scsiController = new VirtualLsiLogicController();
|
||||
scsiController.setSharedBus(VirtualSCSISharing.noSharing);
|
||||
scsiController.setBusNumber(0);
|
||||
scsiController.setKey(1);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.add);
|
||||
vmConfig.setDeviceChange(new VirtualDeviceConfigSpec[] { scsiControllerSpec });
|
||||
|
||||
hyperHost.createVm(vmConfig);
|
||||
workerVm = hyperHost.findVmOnHyperHost(workerVMName);
|
||||
if (workerVm == null) {
|
||||
String msg = "Unable to create worker VM to execute CopyVolumeCommand";
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
//attach volume to worker VM
|
||||
String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumePath);
|
||||
workerVm.attachDisk(new String[] { datastoreVolumePath }, morDs);
|
||||
vmMo = workerVm;
|
||||
}
|
||||
|
||||
vmMo.createSnapshot(exportName, "Temporary snapshot for copy-volume command", false, false);
|
||||
|
||||
exportVolumeToSecondaryStroage(vmMo, volumePath, secStorageUrl, "volumes/" + volumeFolder, exportName, workerVmName);
|
||||
return new Pair<String, String>(volumeFolder, exportName);
|
||||
|
||||
} finally {
|
||||
vmMo.removeSnapshot(exportName, false);
|
||||
if (workerVm != null) {
|
||||
//detach volume and destroy worker vm
|
||||
workerVm.detachAllDisks();
|
||||
workerVm.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Pair<String, String> copyVolumeFromSecStorage(VmwareHypervisorHost hyperHost, long volumeId,
|
||||
DatastoreMO dsMo, String secStorageUrl, String exportName) throws Exception {
|
||||
|
||||
String volumeFolder = String.valueOf(volumeId) + "/";
|
||||
String newVolume = UUID.randomUUID().toString().replaceAll("-", "");
|
||||
restoreVolumeFromSecStorage(hyperHost, dsMo, newVolume, secStorageUrl, "volumes/" + volumeFolder, exportName);
|
||||
|
||||
return new Pair<String, String>(volumeFolder, newVolume);
|
||||
}
|
||||
|
||||
private String getOVFFilePath(String srcOVAFileName) {
|
||||
File file = new File(srcOVAFileName);
|
||||
assert(_storage != null);
|
||||
String[] files = _storage.listFiles(file.getParent());
|
||||
if(files != null) {
|
||||
for(String fileName : files) {
|
||||
if(fileName.toLowerCase().endsWith(".ovf")) {
|
||||
File ovfFile = new File(fileName);
|
||||
return file.getParent() + File.separator + ovfFile.getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String getTemplateRelativeDirInSecStorage(long accountId, long templateId) {
|
||||
return "template/tmpl/" + accountId + "/" + templateId;
|
||||
}
|
||||
|
||||
private static String getSnapshotRelativeDirInSecStorage(long accountId, long volumeId) {
|
||||
return "snapshots/" + accountId + "/" + volumeId;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.manager;
|
||||
|
||||
public interface VmwareStorageMount {
|
||||
String getMountPoint(String storageUrl);
|
||||
}
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.resource;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.trilead.ssh2.ChannelCondition;
|
||||
|
||||
public class SshHelper {
|
||||
private static int DEFAULT_CONNECT_TIMEOUT = 60000;
|
||||
private static int DEFAULT_KEX_TIMEOUT = 60000;
|
||||
|
||||
private static final Logger s_logger = Logger.getLogger(SshHelper.class);
|
||||
|
||||
public static Pair<Boolean, String> sshExecute(String host, int port, String user, File pemKeyFile, String password, String command)
|
||||
throws Exception {
|
||||
|
||||
return sshExecute(host, port, user, pemKeyFile, password, command, 60000, 60000, 120000);
|
||||
}
|
||||
|
||||
public static void scpTo(String host, int port, String user, File pemKeyFile, String password, String remoteTargetDirectory,
|
||||
String localFile, String fileMode) throws Exception {
|
||||
|
||||
scpTo(host, port, user, pemKeyFile, password, remoteTargetDirectory, localFile, fileMode,
|
||||
DEFAULT_CONNECT_TIMEOUT, DEFAULT_KEX_TIMEOUT);
|
||||
}
|
||||
|
||||
public static void scpTo(String host, int port, String user, File pemKeyFile, String password, String remoteTargetDirectory,
|
||||
byte[] data, String remoteFileName, String fileMode) throws Exception {
|
||||
|
||||
scpTo(host, port, user, pemKeyFile, password, remoteTargetDirectory, data, remoteFileName, fileMode,
|
||||
DEFAULT_CONNECT_TIMEOUT, DEFAULT_KEX_TIMEOUT);
|
||||
}
|
||||
|
||||
public static void scpTo(String host, int port, String user, File pemKeyFile, String password, String remoteTargetDirectory,
|
||||
String localFile, String fileMode, int connectTimeoutInMs, int kexTimeoutInMs) throws Exception {
|
||||
|
||||
com.trilead.ssh2.Connection conn = null;
|
||||
com.trilead.ssh2.SCPClient scpClient = null;
|
||||
|
||||
try {
|
||||
conn = new com.trilead.ssh2.Connection(host, port);
|
||||
conn.connect(null, connectTimeoutInMs, kexTimeoutInMs);
|
||||
|
||||
if(pemKeyFile == null) {
|
||||
if(!conn.authenticateWithPassword(user, password)) {
|
||||
String msg = "Failed to authentication SSH user " + user + " on host " + host;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
} else {
|
||||
if(!conn.authenticateWithPublicKey(user, pemKeyFile, password)) {
|
||||
String msg = "Failed to authentication SSH user " + user + " on host " + host;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
}
|
||||
|
||||
scpClient = conn.createSCPClient();
|
||||
|
||||
if(fileMode != null)
|
||||
scpClient.put(localFile, remoteTargetDirectory, fileMode);
|
||||
else
|
||||
scpClient.put(localFile, remoteTargetDirectory);
|
||||
} finally {
|
||||
if(conn != null)
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void scpTo(String host, int port, String user, File pemKeyFile, String password, String remoteTargetDirectory,
|
||||
byte[] data, String remoteFileName, String fileMode, int connectTimeoutInMs, int kexTimeoutInMs) throws Exception {
|
||||
|
||||
com.trilead.ssh2.Connection conn = null;
|
||||
com.trilead.ssh2.SCPClient scpClient = null;
|
||||
|
||||
try {
|
||||
conn = new com.trilead.ssh2.Connection(host, port);
|
||||
conn.connect(null, connectTimeoutInMs, kexTimeoutInMs);
|
||||
|
||||
if(pemKeyFile == null) {
|
||||
if(!conn.authenticateWithPassword(user, password)) {
|
||||
String msg = "Failed to authentication SSH user " + user + " on host " + host;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
} else {
|
||||
if(!conn.authenticateWithPublicKey(user, pemKeyFile, password)) {
|
||||
String msg = "Failed to authentication SSH user " + user + " on host " + host;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
}
|
||||
|
||||
scpClient = conn.createSCPClient();
|
||||
if(fileMode != null)
|
||||
scpClient.put(data, remoteFileName, remoteTargetDirectory, fileMode);
|
||||
else
|
||||
scpClient.put(data, remoteFileName, remoteTargetDirectory);
|
||||
} finally {
|
||||
if(conn != null)
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static Pair<Boolean, String> sshExecute(String host, int port, String user, File pemKeyFile, String password, String command,
|
||||
int connectTimeoutInMs, int kexTimeoutInMs, int waitResultTimeoutInMs) throws Exception {
|
||||
|
||||
com.trilead.ssh2.Connection conn = null;
|
||||
com.trilead.ssh2.Session sess = null;
|
||||
try {
|
||||
conn = new com.trilead.ssh2.Connection(host, port);
|
||||
conn.connect(null, connectTimeoutInMs, kexTimeoutInMs);
|
||||
|
||||
if(pemKeyFile == null) {
|
||||
if(!conn.authenticateWithPassword(user, password)) {
|
||||
String msg = "Failed to authentication SSH user " + user + " on host " + host;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
} else {
|
||||
if(!conn.authenticateWithPublicKey(user, pemKeyFile, password)) {
|
||||
String msg = "Failed to authentication SSH user " + user + " on host " + host;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
}
|
||||
sess = conn.openSession();
|
||||
|
||||
// There is a bug in Trilead library, wait a second before
|
||||
// starting a shell and executing commands, from http://spci.st.ewi.tudelft.nl/chiron/xref/nl/tudelft/swerl/util/SSHConnection.html
|
||||
Thread.sleep(1000);
|
||||
|
||||
sess.execCommand(command);
|
||||
|
||||
InputStream stdout = sess.getStdout();
|
||||
InputStream stderr = sess.getStderr();
|
||||
|
||||
byte[] buffer = new byte[8192];
|
||||
StringBuffer sbResult = new StringBuffer();
|
||||
|
||||
int currentReadBytes = 0;
|
||||
while (true) {
|
||||
if ((stdout.available() == 0) && (stderr.available() == 0)) {
|
||||
int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF,
|
||||
waitResultTimeoutInMs);
|
||||
|
||||
if ((conditions & ChannelCondition.TIMEOUT) != 0) {
|
||||
String msg = "Timed out in waiting SSH execution result";
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
if ((conditions & ChannelCondition.EOF) != 0) {
|
||||
if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (stdout.available() > 0) {
|
||||
currentReadBytes = stdout.read(buffer);
|
||||
sbResult.append(new String(buffer, 0, currentReadBytes));
|
||||
}
|
||||
|
||||
while (stderr.available() > 0) {
|
||||
currentReadBytes = stderr.read(buffer);
|
||||
sbResult.append(new String(buffer, 0, currentReadBytes));
|
||||
}
|
||||
}
|
||||
|
||||
String result = sbResult.toString();
|
||||
if (sess.getExitStatus() != null && sess.getExitStatus().intValue() != 0) {
|
||||
s_logger.error("SSH execution of command " + command + " has an error status code in return. result output: " + result);
|
||||
return new Pair<Boolean, String>(false, result);
|
||||
}
|
||||
|
||||
return new Pair<Boolean, String>(true, result);
|
||||
} finally {
|
||||
if(sess != null)
|
||||
sess.close();
|
||||
|
||||
if(conn != null)
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.resource;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareManager;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.cloud.utils.StringUtils;
|
||||
import com.cloud.utils.component.ComponentLocator;
|
||||
import com.vmware.apputils.version.ExtendedAppUtil;
|
||||
|
||||
public class VmwareContextFactory {
|
||||
|
||||
private static final Logger s_logger = Logger.getLogger(VmwareContextFactory.class);
|
||||
|
||||
private static volatile int s_seq = 1;
|
||||
private static VmwareManager s_vmwareMgr;
|
||||
|
||||
static {
|
||||
// skip certificate check
|
||||
System.setProperty("axis.socketSecureFactory", "org.apache.axis.components.net.SunFakeTrustSocketFactory");
|
||||
|
||||
ComponentLocator locator = ComponentLocator.getLocator("management-server");
|
||||
s_vmwareMgr = locator.getManager(VmwareManager.class);
|
||||
}
|
||||
|
||||
public static VmwareContext create(String vCenterAddress, String vCenterUserName, String vCenterPassword) throws Exception {
|
||||
assert(vCenterAddress != null);
|
||||
assert(vCenterUserName != null);
|
||||
assert(vCenterPassword != null);
|
||||
|
||||
String serviceUrl = "https://" + vCenterAddress + "/sdk/vimService";
|
||||
String[] params = new String[] {"--url", serviceUrl, "--username", vCenterUserName, "--password", vCenterPassword };
|
||||
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("initialize VmwareContext. url: " + serviceUrl + ", username: " + vCenterUserName + ", password: " + StringUtils.getMaskedPasswordForDisplay(vCenterPassword));
|
||||
|
||||
ExtendedAppUtil appUtil = ExtendedAppUtil.initialize(vCenterAddress + "-" + s_seq++, params);
|
||||
|
||||
appUtil.connect();
|
||||
VmwareContext context = new VmwareContext(appUtil, vCenterAddress);
|
||||
context.registerStockObject(VmwareManager.CONTEXT_STOCK_NAME, s_vmwareMgr);
|
||||
|
||||
// this is ugly, it is relatively easier to let cleasses in vmware-base library to access
|
||||
context.registerStockObject("serviceconsole", s_vmwareMgr.getServiceConsolePortGroupName());
|
||||
context.registerStockObject("manageportgroup", s_vmwareMgr.getManagementPortGroupName());
|
||||
|
||||
return context;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,715 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
package com.cloud.storage.resource;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.CheckHealthAnswer;
|
||||
import com.cloud.agent.api.CheckHealthCommand;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.GetStorageStatsAnswer;
|
||||
import com.cloud.agent.api.GetStorageStatsCommand;
|
||||
import com.cloud.agent.api.PingCommand;
|
||||
import com.cloud.agent.api.PingStorageCommand;
|
||||
import com.cloud.agent.api.ReadyAnswer;
|
||||
import com.cloud.agent.api.ReadyCommand;
|
||||
import com.cloud.agent.api.SecStorageFirewallCfgCommand;
|
||||
import com.cloud.agent.api.SecStorageSetupCommand;
|
||||
import com.cloud.agent.api.SecStorageFirewallCfgCommand.PortConfig;
|
||||
import com.cloud.agent.api.SecStorageVMSetupCommand;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.api.StartupStorageCommand;
|
||||
import com.cloud.agent.api.storage.CreateEntityDownloadURLCommand;
|
||||
import com.cloud.agent.api.storage.DeleteEntityDownloadURLCommand;
|
||||
import com.cloud.agent.api.storage.DeleteTemplateCommand;
|
||||
import com.cloud.agent.api.storage.DownloadCommand;
|
||||
import com.cloud.agent.api.storage.DownloadProgressCommand;
|
||||
import com.cloud.agent.api.storage.UploadCommand;
|
||||
import com.cloud.agent.api.storage.ssCommand;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.Host.Type;
|
||||
import com.cloud.resource.ServerResource;
|
||||
import com.cloud.resource.ServerResourceBase;
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.StorageLayer;
|
||||
import com.cloud.storage.template.DownloadManager;
|
||||
import com.cloud.storage.template.DownloadManagerImpl;
|
||||
import com.cloud.storage.template.TemplateInfo;
|
||||
import com.cloud.storage.template.UploadManager;
|
||||
import com.cloud.storage.template.UploadManagerImpl;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.component.ComponentLocator;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
import com.cloud.utils.net.NfsUtils;
|
||||
import com.cloud.utils.script.Script;
|
||||
|
||||
/**
|
||||
* Implementation of Secondary Storage Resource to handle CIFS share
|
||||
*
|
||||
* TODOD: After mount rest of the functionality should be similar to NfsSecondaryStroage.
|
||||
* Move common functionality of NFS and CIFS secondary storage resource class to base class
|
||||
**/
|
||||
|
||||
public class CifsSecondaryStorageResource extends ServerResourceBase implements SecondaryStorageResource {
|
||||
private static final Logger s_logger = Logger.getLogger(CifsSecondaryStorageResource.class);
|
||||
int _timeout;
|
||||
|
||||
String _instance;
|
||||
String _parent;
|
||||
|
||||
String _dc;
|
||||
String _pod;
|
||||
String _guid;
|
||||
String _nfsPath;
|
||||
String _mountParent;
|
||||
Map<String, Object> _params;
|
||||
StorageLayer _storage;
|
||||
boolean _inSystemVM = false;
|
||||
boolean _sslCopy = false;
|
||||
|
||||
Random _rand = new Random(System.currentTimeMillis());
|
||||
|
||||
DownloadManager _dlMgr;
|
||||
UploadManager _upldMgr;
|
||||
private String _configSslScr;
|
||||
private String _configAuthScr;
|
||||
private String _configIpFirewallScr;
|
||||
private String _publicIp;
|
||||
private String _hostname;
|
||||
private String _localgw;
|
||||
private String _eth1mask;
|
||||
private String _eth1ip;
|
||||
|
||||
@Override
|
||||
public void disconnected() {
|
||||
if (_parent != null && !_inSystemVM) {
|
||||
Script script = new Script(!_inSystemVM, "umount", _timeout, s_logger);
|
||||
script.add(_parent);
|
||||
script.execute();
|
||||
|
||||
File file = new File(_parent);
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer executeRequest(Command cmd) {
|
||||
if (cmd instanceof DownloadProgressCommand) {
|
||||
return _dlMgr.handleDownloadCommand(this, (DownloadProgressCommand)cmd);
|
||||
} else if (cmd instanceof DownloadCommand) {
|
||||
return _dlMgr.handleDownloadCommand(this, (DownloadCommand)cmd);
|
||||
} else if (cmd instanceof UploadCommand) {
|
||||
return _upldMgr.handleUploadCommand(this, (UploadCommand)cmd);
|
||||
} else if (cmd instanceof CreateEntityDownloadURLCommand){
|
||||
return _upldMgr.handleCreateEntityURLCommand((CreateEntityDownloadURLCommand)cmd);
|
||||
} else if(cmd instanceof DeleteEntityDownloadURLCommand){
|
||||
return _upldMgr.handleDeleteEntityDownloadURLCommand((DeleteEntityDownloadURLCommand)cmd);
|
||||
} else if (cmd instanceof GetStorageStatsCommand) {
|
||||
return execute((GetStorageStatsCommand)cmd);
|
||||
} else if (cmd instanceof CheckHealthCommand) {
|
||||
return new CheckHealthAnswer((CheckHealthCommand)cmd, true);
|
||||
} else if (cmd instanceof DeleteTemplateCommand) {
|
||||
return execute((DeleteTemplateCommand) cmd);
|
||||
} else if (cmd instanceof ReadyCommand) {
|
||||
return new ReadyAnswer((ReadyCommand)cmd);
|
||||
} else if (cmd instanceof SecStorageFirewallCfgCommand){
|
||||
return execute((SecStorageFirewallCfgCommand)cmd);
|
||||
} else if (cmd instanceof SecStorageVMSetupCommand){
|
||||
return execute((SecStorageVMSetupCommand)cmd);
|
||||
} else if (cmd instanceof SecStorageSetupCommand){
|
||||
return new Answer(cmd, true, "success");
|
||||
} else {
|
||||
return Answer.createUnsupportedCommandAnswer(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
private Answer execute(SecStorageVMSetupCommand cmd) {
|
||||
if (!_inSystemVM){
|
||||
return new Answer(cmd, true, null);
|
||||
}
|
||||
boolean success = true;
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (String cidr: cmd.getAllowedInternalSites()) {
|
||||
String tmpresult = allowOutgoingOnPrivate(cidr);
|
||||
if (tmpresult != null) {
|
||||
result.append(", ").append(tmpresult);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
if (cmd.getCopyPassword() != null && cmd.getCopyUserName() != null) {
|
||||
String tmpresult = configureAuth(cmd.getCopyUserName(), cmd.getCopyPassword());
|
||||
if (tmpresult != null) {
|
||||
result.append("Failed to configure auth for copy ").append(tmpresult);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Answer(cmd, success, result.toString());
|
||||
|
||||
}
|
||||
|
||||
private String allowOutgoingOnPrivate(String destCidr) {
|
||||
|
||||
Script command = new Script("/bin/bash", s_logger);
|
||||
String intf = "eth1";
|
||||
command.add("-c");
|
||||
command.add("iptables -I OUTPUT -o " + intf + " -d " + destCidr + " -p tcp -m state --state NEW -m tcp -j ACCEPT");
|
||||
|
||||
String result = command.execute();
|
||||
if (result != null) {
|
||||
s_logger.warn("Error in allowing outgoing to " + destCidr + ", err=" + result );
|
||||
return "Error in allowing outgoing to " + destCidr + ", err=" + result;
|
||||
}
|
||||
addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, destCidr);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private Answer execute(SecStorageFirewallCfgCommand cmd) {
|
||||
if (!_inSystemVM){
|
||||
return new Answer(cmd, true, null);
|
||||
}
|
||||
|
||||
List<String> ipList = new ArrayList<String>();
|
||||
|
||||
for (PortConfig pCfg:cmd.getPortConfigs()){
|
||||
if (pCfg.isAdd()) {
|
||||
ipList.add(pCfg.getSourceIp());
|
||||
}
|
||||
}
|
||||
boolean success = true;
|
||||
String result;
|
||||
result = configureIpFirewall(ipList);
|
||||
if (result !=null)
|
||||
success = false;
|
||||
|
||||
return new Answer(cmd, success, result);
|
||||
}
|
||||
|
||||
protected GetStorageStatsAnswer execute(final GetStorageStatsCommand cmd) {
|
||||
final long usedSize = getUsedSize();
|
||||
final long totalSize = getTotalSize();
|
||||
if (usedSize == -1 || totalSize == -1) {
|
||||
return new GetStorageStatsAnswer(cmd, "Unable to get storage stats");
|
||||
} else {
|
||||
return new GetStorageStatsAnswer(cmd, totalSize, usedSize) ;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRootDir(ssCommand cmd){
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Answer execute(final DeleteTemplateCommand cmd) {
|
||||
String relativeTemplatePath = cmd.getTemplatePath();
|
||||
String parent = _parent;
|
||||
|
||||
if (relativeTemplatePath.startsWith(File.separator)) {
|
||||
relativeTemplatePath = relativeTemplatePath.substring(1);
|
||||
}
|
||||
|
||||
if (!parent.endsWith(File.separator)) {
|
||||
parent += File.separator;
|
||||
}
|
||||
String absoluteTemplatePath = parent + relativeTemplatePath;
|
||||
File tmpltParent = new File(absoluteTemplatePath).getParentFile();
|
||||
String details = null;
|
||||
if (!tmpltParent.exists()) {
|
||||
details = "template parent directory " + tmpltParent.getName() + " doesn't exist";
|
||||
s_logger.debug(details);
|
||||
return new Answer(cmd, true, details);
|
||||
}
|
||||
File[] tmpltFiles = tmpltParent.listFiles();
|
||||
if (tmpltFiles == null || tmpltFiles.length == 0) {
|
||||
details = "No files under template parent directory " + tmpltParent.getName();
|
||||
s_logger.debug(details);
|
||||
} else {
|
||||
boolean found = false;
|
||||
for (File f : tmpltFiles) {
|
||||
if (!found && f.getName().equals("template.properties")) {
|
||||
found = true;
|
||||
}
|
||||
if (!f.delete()) {
|
||||
return new Answer(cmd, false, "Unable to delete file " + f.getName() + " under Template path "
|
||||
+ relativeTemplatePath);
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
details = "Can not find template.properties under " + tmpltParent.getName();
|
||||
s_logger.debug(details);
|
||||
}
|
||||
}
|
||||
if (!tmpltParent.delete()) {
|
||||
details = "Unable to delete directory " + tmpltParent.getName() + " under Template path "
|
||||
+ relativeTemplatePath;
|
||||
s_logger.debug(details);
|
||||
return new Answer(cmd, false, details);
|
||||
}
|
||||
return new Answer(cmd, true, null);
|
||||
}
|
||||
|
||||
protected long getUsedSize() {
|
||||
return _storage.getUsedSpace(_parent);
|
||||
}
|
||||
|
||||
protected long getTotalSize() {
|
||||
return _storage.getTotalSpace(_parent);
|
||||
}
|
||||
|
||||
protected long convertFilesystemSize(final String size) {
|
||||
if (size == null || size.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
long multiplier = 1;
|
||||
if (size.endsWith("T")) {
|
||||
multiplier = 1024l * 1024l * 1024l * 1024l;
|
||||
} else if (size.endsWith("G")) {
|
||||
multiplier = 1024l * 1024l * 1024l;
|
||||
} else if (size.endsWith("M")) {
|
||||
multiplier = 1024l * 1024l;
|
||||
} else {
|
||||
assert (false) : "Well, I have no idea what this is: " + size;
|
||||
}
|
||||
|
||||
return (long)(Double.parseDouble(size.substring(0, size.length() - 1)) * multiplier);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return Host.Type.SecondaryStorage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PingCommand getCurrentStatus(final long id) {
|
||||
return new PingStorageCommand(Host.Type.Storage, id, new HashMap<String, Boolean>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
_eth1ip = (String)params.get("eth1ip");
|
||||
if (_eth1ip != null) { //can only happen inside service vm
|
||||
params.put("private.network.device", "eth1");
|
||||
} else {
|
||||
s_logger.warn("Wait, what's going on? eth1ip is null!!");
|
||||
}
|
||||
String eth2ip = (String) params.get("eth2ip");
|
||||
if (eth2ip != null) {
|
||||
params.put("public.network.device", "eth2");
|
||||
}
|
||||
_publicIp = (String) params.get("eth2ip");
|
||||
_hostname = (String) params.get("name");
|
||||
|
||||
super.configure(name, params);
|
||||
|
||||
_params = params;
|
||||
String value = (String)params.get("scripts.timeout");
|
||||
_timeout = NumbersUtil.parseInt(value, 1440) * 1000;
|
||||
|
||||
_storage = (StorageLayer)params.get(StorageLayer.InstanceConfigKey);
|
||||
if (_storage == null) {
|
||||
value = (String)params.get(StorageLayer.ClassConfigKey);
|
||||
if (value == null) {
|
||||
value = "com.cloud.storage.JavaStorageLayer";
|
||||
}
|
||||
|
||||
try {
|
||||
Class<?> clazz = Class.forName(value);
|
||||
_storage = (StorageLayer)ComponentLocator.inject(clazz);
|
||||
_storage.configure("StorageLayer", params);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new ConfigurationException("Unable to find class " + value);
|
||||
}
|
||||
}
|
||||
_configSslScr = Script.findScript(getDefaultScriptsDir(), "config_ssl.sh");
|
||||
if (_configSslScr != null) {
|
||||
s_logger.info("config_ssl.sh found in " + _configSslScr);
|
||||
}
|
||||
|
||||
_configAuthScr = Script.findScript(getDefaultScriptsDir(), "config_auth.sh");
|
||||
if (_configSslScr != null) {
|
||||
s_logger.info("config_auth.sh found in " + _configAuthScr);
|
||||
}
|
||||
|
||||
_configIpFirewallScr = Script.findScript(getDefaultScriptsDir(), "ipfirewall.sh");
|
||||
if (_configIpFirewallScr != null) {
|
||||
s_logger.info("_configIpFirewallScr found in " + _configIpFirewallScr);
|
||||
}
|
||||
|
||||
_guid = (String)params.get("guid");
|
||||
if (_guid == null) {
|
||||
throw new ConfigurationException("Unable to find the guid");
|
||||
}
|
||||
|
||||
_dc = (String)params.get("zone");
|
||||
if (_dc == null) {
|
||||
throw new ConfigurationException("Unable to find the zone");
|
||||
}
|
||||
_pod = (String)params.get("pod");
|
||||
|
||||
_instance = (String)params.get("instance");
|
||||
|
||||
_mountParent = (String)params.get("mount.parent");
|
||||
if (_mountParent == null) {
|
||||
_mountParent = File.separator + "mnt";
|
||||
}
|
||||
|
||||
if (_instance != null) {
|
||||
_mountParent = _mountParent + File.separator + _instance;
|
||||
}
|
||||
|
||||
_nfsPath = (String)params.get("mount.path");
|
||||
if (_nfsPath == null) {
|
||||
throw new ConfigurationException("Unable to find mount.path");
|
||||
}
|
||||
|
||||
|
||||
|
||||
String inSystemVM = (String)params.get("secondary.storage.vm");
|
||||
if (inSystemVM == null || "true".equalsIgnoreCase(inSystemVM)) {
|
||||
_inSystemVM = true;
|
||||
_localgw = (String)params.get("localgw");
|
||||
if (_localgw != null) { //can only happen inside service vm
|
||||
_eth1mask = (String)params.get("eth1mask");
|
||||
String internalDns1 = (String)params.get("dns1");
|
||||
String internalDns2 = (String)params.get("dns2");
|
||||
|
||||
if (internalDns1 == null) {
|
||||
s_logger.warn("No DNS entry found during configuration of NfsSecondaryStorage");
|
||||
} else {
|
||||
addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, internalDns1);
|
||||
}
|
||||
|
||||
String mgmtHost = (String)params.get("host");
|
||||
String nfsHost = NfsUtils.getHostPart(_nfsPath);
|
||||
if (nfsHost == null) {
|
||||
s_logger.error("Invalid or corrupt nfs url " + _nfsPath);
|
||||
throw new CloudRuntimeException("Unable to determine host part of nfs path");
|
||||
}
|
||||
try {
|
||||
InetAddress nfsHostAddr = InetAddress.getByName(nfsHost);
|
||||
nfsHost = nfsHostAddr.getHostAddress();
|
||||
} catch (UnknownHostException uhe) {
|
||||
s_logger.error("Unable to resolve nfs host " + nfsHost);
|
||||
throw new CloudRuntimeException("Unable to resolve nfs host to an ip address " + nfsHost);
|
||||
}
|
||||
addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, nfsHost);
|
||||
addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, mgmtHost);
|
||||
if (internalDns2 != null) {
|
||||
addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, internalDns2);
|
||||
}
|
||||
|
||||
}
|
||||
String useSsl = (String)params.get("sslcopy");
|
||||
if (useSsl != null) {
|
||||
_sslCopy = Boolean.parseBoolean(useSsl);
|
||||
if (_sslCopy) {
|
||||
configureSSL();
|
||||
}
|
||||
}
|
||||
startAdditionalServices();
|
||||
_params.put("install.numthreads", "50");
|
||||
_params.put("secondary.storage.vm", "true");
|
||||
}
|
||||
_parent = mount(_nfsPath, _mountParent);
|
||||
if (_parent == null) {
|
||||
throw new ConfigurationException("Unable to create mount point");
|
||||
}
|
||||
|
||||
|
||||
s_logger.info("Mount point established at " + _parent);
|
||||
|
||||
try {
|
||||
_params.put("template.parent", _parent);
|
||||
_params.put(StorageLayer.InstanceConfigKey, _storage);
|
||||
_dlMgr = new DownloadManagerImpl();
|
||||
_dlMgr.configure("DownloadManager", _params);
|
||||
_upldMgr = new UploadManagerImpl();
|
||||
_upldMgr.configure("UploadManager", params);
|
||||
} catch (ConfigurationException e) {
|
||||
s_logger.warn("Caught problem while configuring DownloadManager", e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void startAdditionalServices() {
|
||||
Script command = new Script("/bin/bash", s_logger);
|
||||
command.add("-c");
|
||||
command.add("if [ -f /etc/init.d/ssh ]; then service ssh restart; else service sshd restart; fi ");
|
||||
String result = command.execute();
|
||||
if (result != null) {
|
||||
s_logger.warn("Error in starting sshd service err=" + result );
|
||||
}
|
||||
command = new Script("/bin/bash", s_logger);
|
||||
command.add("-c");
|
||||
command.add("iptables -I INPUT -i eth1 -p tcp -m state --state NEW -m tcp --dport 3922 -j ACCEPT");
|
||||
result = command.execute();
|
||||
if (result != null) {
|
||||
s_logger.warn("Error in opening up ssh port err=" + result );
|
||||
}
|
||||
}
|
||||
|
||||
private void addRouteToInternalIpOrCidr(String localgw, String eth1ip, String eth1mask, String destIpOrCidr) {
|
||||
s_logger.debug("addRouteToInternalIp: localgw=" + localgw + ", eth1ip=" + eth1ip + ", eth1mask=" + eth1mask + ",destIp=" + destIpOrCidr);
|
||||
if (destIpOrCidr == null) {
|
||||
s_logger.debug("addRouteToInternalIp: destIp is null");
|
||||
return;
|
||||
}
|
||||
if (!NetUtils.isValidIp(destIpOrCidr) && !NetUtils.isValidCIDR(destIpOrCidr)){
|
||||
s_logger.warn(" destIp is not a valid ip address or cidr destIp=" + destIpOrCidr);
|
||||
return;
|
||||
}
|
||||
boolean inSameSubnet = false;
|
||||
if (NetUtils.isValidIp(destIpOrCidr)) {
|
||||
if (eth1ip != null && eth1mask != null) {
|
||||
inSameSubnet = NetUtils.sameSubnet(eth1ip, destIpOrCidr, eth1mask);
|
||||
} else {
|
||||
s_logger.warn("addRouteToInternalIp: unable to determine same subnet: _eth1ip=" + eth1ip + ", dest ip=" + destIpOrCidr + ", _eth1mask=" + eth1mask);
|
||||
}
|
||||
} else {
|
||||
inSameSubnet = NetUtils.isNetworkAWithinNetworkB(destIpOrCidr, NetUtils.ipAndNetMaskToCidr(eth1ip, eth1mask));
|
||||
}
|
||||
if (inSameSubnet) {
|
||||
s_logger.debug("addRouteToInternalIp: dest ip " + destIpOrCidr + " is in the same subnet as eth1 ip " + eth1ip);
|
||||
return;
|
||||
}
|
||||
Script command = new Script("/bin/bash", s_logger);
|
||||
command.add("-c");
|
||||
command.add("ip route delete " + destIpOrCidr);
|
||||
command.execute();
|
||||
command = new Script("/bin/bash", s_logger);
|
||||
command.add("-c");
|
||||
command.add("ip route add " + destIpOrCidr + " via " + localgw);
|
||||
String result = command.execute();
|
||||
if (result != null) {
|
||||
s_logger.warn("Error in configuring route to internal ip err=" + result );
|
||||
} else {
|
||||
s_logger.debug("addRouteToInternalIp: added route to internal ip=" + destIpOrCidr + " via " + localgw);
|
||||
}
|
||||
}
|
||||
|
||||
private void configureSSL() {
|
||||
Script command = new Script(_configSslScr);
|
||||
command.add(_publicIp);
|
||||
command.add(_hostname);
|
||||
String result = command.execute();
|
||||
if (result != null) {
|
||||
s_logger.warn("Unable to configure httpd to use ssl");
|
||||
}
|
||||
}
|
||||
|
||||
private String configureAuth(String user, String passwd) {
|
||||
Script command = new Script(_configAuthScr);
|
||||
command.add(user);
|
||||
command.add(passwd);
|
||||
String result = command.execute();
|
||||
if (result != null) {
|
||||
s_logger.warn("Unable to configure httpd to use auth");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String configureIpFirewall(List<String> ipList){
|
||||
Script command = new Script(_configIpFirewallScr);
|
||||
for (String ip : ipList){
|
||||
command.add(ip);
|
||||
}
|
||||
|
||||
String result = command.execute();
|
||||
if (result != null) {
|
||||
s_logger.warn("Unable to configure firewall for command : " +command);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected String mount(String path, String parent) {
|
||||
String mountPoint = null;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
String mntPt = parent + File.separator + Integer.toHexString(_rand.nextInt(Integer.MAX_VALUE));
|
||||
File file = new File(mntPt);
|
||||
if (!file.exists()) {
|
||||
if (_storage.mkdir(mntPt)) {
|
||||
mountPoint = mntPt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
s_logger.debug("Unable to create mount: " + mntPt);
|
||||
}
|
||||
|
||||
if (mountPoint == null) {
|
||||
s_logger.warn("Unable to create a mount point");
|
||||
return null;
|
||||
}
|
||||
|
||||
Script script = null;
|
||||
String result = null;
|
||||
script = new Script(!_inSystemVM, "umount", _timeout, s_logger);
|
||||
script.add(path);
|
||||
result = script.execute();
|
||||
|
||||
if( _parent != null ) {
|
||||
script = new Script("rmdir", _timeout, s_logger);
|
||||
script.add(_parent);
|
||||
result = script.execute();
|
||||
}
|
||||
|
||||
Script command = new Script(!_inSystemVM, "mount", _timeout, s_logger);
|
||||
command.add("-t", "cifs");
|
||||
if (_inSystemVM) {
|
||||
//Fedora Core 12 errors out with any -o option executed from java
|
||||
//command.add("-o", "soft,timeo=133,retrans=2147483647,tcp,acdirmax=0,acdirmin=0");
|
||||
}
|
||||
String tok[] = path.split(":");
|
||||
//command.add(path);
|
||||
command.add("//"+tok[0]+tok[1]);
|
||||
command.add(mountPoint);
|
||||
result = command.execute();
|
||||
if (result != null) {
|
||||
s_logger.warn("Unable to mount " + path + " due to " + result);
|
||||
File file = new File(mountPoint);
|
||||
if (file.exists())
|
||||
file.delete();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// XXX: Adding the check for creation of snapshots dir here. Might have to move it somewhere more logical later.
|
||||
if (!checkForSnapshotsDir(mountPoint)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create the volumes dir
|
||||
if (!checkForVolumesDir(mountPoint)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return mountPoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StartupCommand[] initialize() {
|
||||
/*disconnected();
|
||||
|
||||
_parent = mount(_nfsPath, _mountParent);
|
||||
|
||||
if( _parent == null ) {
|
||||
s_logger.warn("Unable to mount the nfs server");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
_params.put("template.parent", _parent);
|
||||
_params.put(StorageLayer.InstanceConfigKey, _storage);
|
||||
_dlMgr = new DownloadManagerImpl();
|
||||
_dlMgr.configure("DownloadManager", _params);
|
||||
} catch (ConfigurationException e) {
|
||||
s_logger.warn("Caught problem while configuring folers", e);
|
||||
return null;
|
||||
}*/
|
||||
|
||||
final StartupStorageCommand cmd = new StartupStorageCommand(_parent, StoragePoolType.NetworkFilesystem, getTotalSize(), new HashMap<String, TemplateInfo>());
|
||||
|
||||
cmd.setResourceType(Storage.StorageResourceType.SECONDARY_STORAGE);
|
||||
cmd.setIqn(null);
|
||||
|
||||
fillNetworkInformation(cmd);
|
||||
cmd.setDataCenter(_dc);
|
||||
cmd.setPod(_pod);
|
||||
cmd.setGuid(_guid);
|
||||
cmd.setName(_guid);
|
||||
cmd.setVersion(NfsSecondaryStorageResource.class.getPackage().getImplementationVersion());
|
||||
cmd.getHostDetails().put("mount.parent", _mountParent);
|
||||
cmd.getHostDetails().put("mount.path", _nfsPath);
|
||||
String tok[] = _nfsPath.split(":");
|
||||
cmd.setNfsShare("nfs://" + tok[0] + tok[1]);
|
||||
if (cmd.getHostDetails().get("orig.url") == null) {
|
||||
if (tok.length != 2) {
|
||||
throw new CloudRuntimeException("Not valid NFS path" + _nfsPath);
|
||||
}
|
||||
String nfsUrl = "nfs://" + tok[0] + tok[1];
|
||||
cmd.getHostDetails().put("orig.url", nfsUrl);
|
||||
}
|
||||
InetAddress addr;
|
||||
try {
|
||||
addr = InetAddress.getByName(tok[0]);
|
||||
cmd.setPrivateIpAddress(addr.getHostAddress());
|
||||
} catch (UnknownHostException e) {
|
||||
cmd.setPrivateIpAddress(tok[0]);
|
||||
}
|
||||
return new StartupCommand [] {cmd};
|
||||
}
|
||||
|
||||
protected boolean checkForSnapshotsDir(String mountPoint) {
|
||||
String snapshotsDirLocation = mountPoint + File.separator + "snapshots";
|
||||
return createDir("snapshots", snapshotsDirLocation, mountPoint);
|
||||
}
|
||||
|
||||
protected boolean checkForVolumesDir(String mountPoint) {
|
||||
String volumesDirLocation = mountPoint + "/" + "volumes";
|
||||
return createDir("volumes", volumesDirLocation, mountPoint);
|
||||
}
|
||||
|
||||
protected boolean createDir(String dirName, String dirLocation, String mountPoint) {
|
||||
boolean dirExists = false;
|
||||
|
||||
File dir = new File(dirLocation);
|
||||
if (dir.exists()) {
|
||||
if (dir.isDirectory()) {
|
||||
s_logger.debug(dirName + " already exists on secondary storage, and is mounted at " + mountPoint);
|
||||
dirExists = true;
|
||||
} else {
|
||||
if (dir.delete() && _storage.mkdir(dirLocation)) {
|
||||
dirExists = true;
|
||||
}
|
||||
}
|
||||
} else if (_storage.mkdir(dirLocation)) {
|
||||
dirExists = true;
|
||||
}
|
||||
|
||||
if (dirExists) {
|
||||
s_logger.info(dirName + " directory created/exists on Secondary Storage.");
|
||||
} else {
|
||||
s_logger.info(dirName + " directory does not exist on Secondary Storage.");
|
||||
}
|
||||
|
||||
return dirExists;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDefaultScriptsDir() {
|
||||
return "./scripts/storage/secondary";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.storage.resource;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
|
||||
public class PremiumSecondaryStorageResource extends NfsSecondaryStorageResource {
|
||||
|
||||
private static final Logger s_logger = Logger.getLogger(PremiumSecondaryStorageResource.class);
|
||||
|
||||
private Map<Hypervisor.HypervisorType, SecondaryStorageResourceHandler> _handlers = new HashMap<Hypervisor.HypervisorType, SecondaryStorageResourceHandler>();
|
||||
|
||||
private Map<String, String> _activeOutgoingAddresses = new HashMap<String, String>();
|
||||
|
||||
@Override
|
||||
public Answer executeRequest(Command cmd) {
|
||||
String hypervisor = cmd.getContextParam("hypervisor");
|
||||
if(hypervisor != null) {
|
||||
Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.getType(hypervisor);
|
||||
if(hypervisorType == null) {
|
||||
s_logger.error("Unsupported hypervisor type in command context, hypervisor: " + hypervisor);
|
||||
return defaultAction(cmd);
|
||||
}
|
||||
|
||||
SecondaryStorageResourceHandler handler = getHandler(hypervisorType);
|
||||
if(handler == null) {
|
||||
s_logger.error("No handler can be found for hypervisor type in command context, hypervisor: " + hypervisor);
|
||||
return defaultAction(cmd);
|
||||
}
|
||||
|
||||
return handler.executeRequest(cmd);
|
||||
}
|
||||
|
||||
return defaultAction(cmd);
|
||||
}
|
||||
|
||||
public Answer defaultAction(Command cmd) {
|
||||
return super.executeRequest(cmd);
|
||||
}
|
||||
|
||||
public void ensureOutgoingRuleForAddress(String address) {
|
||||
if(address == null || address.isEmpty() || address.startsWith("0.0.0.0")) {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("Drop invalid dynamic route/firewall entry " + address);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean needToSetRule = false;
|
||||
synchronized(_activeOutgoingAddresses) {
|
||||
if(!_activeOutgoingAddresses.containsKey(address)) {
|
||||
_activeOutgoingAddresses.put(address, address);
|
||||
needToSetRule = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(needToSetRule) {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("Add dynamic route/firewall entry for " + address);
|
||||
allowOutgoingOnPrivate(address);
|
||||
}
|
||||
}
|
||||
|
||||
private void registerHandler(Hypervisor.HypervisorType hypervisorType, SecondaryStorageResourceHandler handler) {
|
||||
_handlers.put(hypervisorType, handler);
|
||||
}
|
||||
|
||||
private SecondaryStorageResourceHandler getHandler(Hypervisor.HypervisorType hypervisorType) {
|
||||
return _handlers.get(hypervisorType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
super.configure(name, params);
|
||||
|
||||
if(_inSystemVM) {
|
||||
VmwareSecondaryStorageContextFactory.initFactoryEnvironment();
|
||||
}
|
||||
|
||||
registerHandler(Hypervisor.HypervisorType.VMware, new VmwareSecondaryStorageResourceHandler(this));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.storage.resource;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
|
||||
public interface SecondaryStorageResourceHandler {
|
||||
Answer executeRequest(Command cmd);
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.storage.resource;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.vmware.apputils.version.ExtendedAppUtil;
|
||||
|
||||
public class VmwareSecondaryStorageContextFactory {
|
||||
private static volatile int s_seq = 1;
|
||||
|
||||
private static Map<String, VmwareContext> s_contextMap = new HashMap<String, VmwareContext>();
|
||||
|
||||
public static void initFactoryEnvironment() {
|
||||
System.setProperty("axis.socketSecureFactory", "org.apache.axis.components.net.SunFakeTrustSocketFactory");
|
||||
}
|
||||
|
||||
public static VmwareContext create(String vCenterAddress, String vCenterUserName, String vCenterPassword) throws Exception {
|
||||
assert(vCenterAddress != null);
|
||||
assert(vCenterUserName != null);
|
||||
assert(vCenterPassword != null);
|
||||
|
||||
VmwareContext context = null;
|
||||
|
||||
synchronized(s_contextMap) {
|
||||
context = s_contextMap.get(vCenterAddress);
|
||||
if(context == null) {
|
||||
String serviceUrl = "https://" + vCenterAddress + "/sdk/vimService";
|
||||
String[] params = new String[] {"--url", serviceUrl, "--username", vCenterUserName, "--password", vCenterPassword };
|
||||
ExtendedAppUtil appUtil = ExtendedAppUtil.initialize(vCenterAddress + "-" + s_seq++, params);
|
||||
|
||||
appUtil.connect();
|
||||
context = new VmwareContext(appUtil, vCenterAddress);
|
||||
context.registerStockObject("username", vCenterUserName);
|
||||
context.registerStockObject("password", vCenterPassword);
|
||||
|
||||
s_contextMap.put(vCenterAddress, context);
|
||||
}
|
||||
}
|
||||
|
||||
assert(context != null);
|
||||
return context;
|
||||
}
|
||||
|
||||
public static void invalidate(VmwareContext context) {
|
||||
synchronized(s_contextMap) {
|
||||
for(Map.Entry<String, VmwareContext> entry : s_contextMap.entrySet()) {
|
||||
if(entry.getValue() == context) {
|
||||
s_contextMap.remove(entry.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,292 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.storage.resource;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.BackupSnapshotCommand;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
|
||||
import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
|
||||
import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
|
||||
import com.cloud.agent.api.DeleteSnapshotBackupCommand;
|
||||
import com.cloud.agent.api.DeleteSnapshotsDirCommand;
|
||||
import com.cloud.agent.api.storage.CopyVolumeCommand;
|
||||
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareHostService;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareStorageManager;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareStorageManagerImpl;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareStorageMount;
|
||||
import com.cloud.hypervisor.vmware.mo.ClusterMO;
|
||||
import com.cloud.hypervisor.vmware.mo.HostMO;
|
||||
import com.cloud.hypervisor.vmware.mo.VmwareHostType;
|
||||
import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
|
||||
import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHostNetworkSummary;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareHelper;
|
||||
import com.cloud.serializer.GsonHelper;
|
||||
import com.google.gson.Gson;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
|
||||
public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageResourceHandler, VmwareHostService, VmwareStorageMount {
|
||||
private static final Logger s_logger = Logger.getLogger(VmwareSecondaryStorageResourceHandler.class);
|
||||
|
||||
private final PremiumSecondaryStorageResource _resource;
|
||||
private final VmwareStorageManager _storageMgr;
|
||||
|
||||
private final Gson _gson;
|
||||
|
||||
/*
|
||||
private Map<String, HostMO> _activeHosts = new HashMap<String, HostMO>();
|
||||
*/
|
||||
|
||||
public VmwareSecondaryStorageResourceHandler(PremiumSecondaryStorageResource resource) {
|
||||
_resource = resource;
|
||||
_storageMgr = new VmwareStorageManagerImpl(this);
|
||||
_gson = GsonHelper.getGsonLogger();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer executeRequest(Command cmd) {
|
||||
Answer answer;
|
||||
if (cmd instanceof PrimaryStorageDownloadCommand) {
|
||||
answer = execute((PrimaryStorageDownloadCommand)cmd);
|
||||
} else if(cmd instanceof BackupSnapshotCommand) {
|
||||
answer = execute((BackupSnapshotCommand)cmd);
|
||||
} else if(cmd instanceof DeleteSnapshotsDirCommand) {
|
||||
answer = execute((DeleteSnapshotsDirCommand)cmd);
|
||||
} else if(cmd instanceof DeleteSnapshotBackupCommand) {
|
||||
answer = execute((DeleteSnapshotBackupCommand)cmd);
|
||||
} else if(cmd instanceof CreatePrivateTemplateFromVolumeCommand) {
|
||||
answer = execute((CreatePrivateTemplateFromVolumeCommand)cmd);
|
||||
} else if(cmd instanceof CreatePrivateTemplateFromSnapshotCommand) {
|
||||
answer = execute((CreatePrivateTemplateFromSnapshotCommand)cmd);
|
||||
} else if(cmd instanceof CopyVolumeCommand) {
|
||||
answer = execute((CopyVolumeCommand)cmd);
|
||||
} else if(cmd instanceof CreateVolumeFromSnapshotCommand) {
|
||||
answer = execute((CreateVolumeFromSnapshotCommand)cmd);
|
||||
} else {
|
||||
answer = _resource.defaultAction(cmd);
|
||||
}
|
||||
|
||||
if(cmd.getContextParam("execid") != null) {
|
||||
answer.setContextParam("execid", cmd.getContextParam("execid"));
|
||||
}
|
||||
if(cmd.getContextParam("checkpoint") != null) {
|
||||
answer.setContextParam("checkpoint", cmd.getContextParam("checkpoint"));
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
private Answer execute(PrimaryStorageDownloadCommand cmd) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Executing resource PrimaryStorageDownloadCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
return _storageMgr.execute(this, cmd);
|
||||
}
|
||||
|
||||
private Answer execute(BackupSnapshotCommand cmd) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Executing resource BackupSnapshotCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
return _storageMgr.execute(this, cmd);
|
||||
}
|
||||
|
||||
private Answer execute(DeleteSnapshotsDirCommand cmd) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Executing resource DeleteSnapshotsDirCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
return _storageMgr.execute(this, cmd);
|
||||
}
|
||||
|
||||
private Answer execute(DeleteSnapshotBackupCommand cmd) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Executing resource DeleteSnapshotBackupCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
return _storageMgr.execute(this, cmd);
|
||||
}
|
||||
|
||||
private Answer execute(CreatePrivateTemplateFromVolumeCommand cmd) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Executing resource CreatePrivateTemplateFromVolumeCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
return _storageMgr.execute(this, cmd);
|
||||
}
|
||||
|
||||
private Answer execute(CreatePrivateTemplateFromSnapshotCommand cmd) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Executing resource CreatePrivateTemplateFromVolumeCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
return _storageMgr.execute(this, cmd);
|
||||
}
|
||||
|
||||
private Answer execute(CopyVolumeCommand cmd) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Executing resource CopyVolumeCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
return _storageMgr.execute(this, cmd);
|
||||
}
|
||||
|
||||
private Answer execute(CreateVolumeFromSnapshotCommand cmd) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Executing resource CreateVolumeFromSnapshotCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
return _storageMgr.execute(this, cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VmwareContext getServiceContext(Command cmd) {
|
||||
String guid = cmd.getContextParam("guid");
|
||||
if(guid == null || guid.isEmpty()) {
|
||||
s_logger.error("Invalid command context parameter guid");
|
||||
return null;
|
||||
}
|
||||
|
||||
String username = cmd.getContextParam("username");
|
||||
if(username == null || username.isEmpty()) {
|
||||
s_logger.error("Invalid command context parameter username");
|
||||
return null;
|
||||
}
|
||||
|
||||
String password = cmd.getContextParam("password");
|
||||
|
||||
// validate command guid parameter
|
||||
String[] tokens = guid.split("@");
|
||||
if(tokens == null || tokens.length != 2) {
|
||||
s_logger.error("Invalid content in command context parameter guid");
|
||||
return null;
|
||||
}
|
||||
|
||||
String vCenterAddress = tokens[1];
|
||||
String[] hostTokens = tokens[0].split(":");
|
||||
if(hostTokens == null || hostTokens.length != 2) {
|
||||
s_logger.error("Invalid content in command context parameter guid");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
_resource.ensureOutgoingRuleForAddress(vCenterAddress);
|
||||
VmwareContext context = null;
|
||||
|
||||
// cached VmwareContext may be timed out in vCenter, give it a chance to reclaim a new context from factory
|
||||
for(int i = 0; i < 2; i++) {
|
||||
context = VmwareSecondaryStorageContextFactory.create(vCenterAddress, username, password);
|
||||
if(!validateContext(context, cmd)) {
|
||||
invalidateServiceContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
if(context != null) {
|
||||
context.registerStockObject("serviceconsole", cmd.getContextParam("serviceconsole"));
|
||||
context.registerStockObject("manageportgroup", cmd.getContextParam("manageportgroup"));
|
||||
}
|
||||
return context;
|
||||
} catch(Exception e) {
|
||||
s_logger.error("Unexpected exception " + e.toString(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateServiceContext(VmwareContext context) {
|
||||
VmwareSecondaryStorageContextFactory.invalidate(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VmwareHypervisorHost getHyperHost(VmwareContext context, Command cmd) {
|
||||
String guid = cmd.getContextParam("guid");
|
||||
assert(guid != null);
|
||||
|
||||
String[] tokens = guid.split("@");
|
||||
assert(tokens != null && tokens.length == 2);
|
||||
|
||||
ManagedObjectReference morHyperHost = new ManagedObjectReference();
|
||||
String[] hostTokens = tokens[0].split(":");
|
||||
if(hostTokens == null || hostTokens.length != 2) {
|
||||
s_logger.error("Invalid content in command context parameter guid");
|
||||
return null;
|
||||
}
|
||||
|
||||
morHyperHost.setType(hostTokens[0]);
|
||||
morHyperHost.set_value(hostTokens[1]);
|
||||
|
||||
if(morHyperHost.getType().equalsIgnoreCase("HostSystem")) {
|
||||
HostMO hostMo = new HostMO(context, morHyperHost);
|
||||
|
||||
try {
|
||||
VmwareHypervisorHostNetworkSummary netSummary = hostMo.getHyperHostNetworkSummary(
|
||||
hostMo.getHostType() == VmwareHostType.ESXi ? cmd.getContextParam("manageportgroup") : cmd.getContextParam("serviceconsole"));
|
||||
_resource.ensureOutgoingRuleForAddress(netSummary.getHostIp());
|
||||
} catch(Throwable e) {
|
||||
s_logger.warn("Unable to retrive host network information due to exception " + e.toString() + ", host: " + hostTokens[0] + "-" + hostTokens[1]);
|
||||
}
|
||||
|
||||
return hostMo;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return new ClusterMO(context, morHyperHost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorkerName(VmwareContext context, Command cmd) {
|
||||
assert(cmd.getContextParam("worker") != null);
|
||||
return cmd.getContextParam("worker");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMountPoint(String storageUrl) {
|
||||
return _resource.getRootDir(storageUrl);
|
||||
}
|
||||
|
||||
private boolean validateContext(VmwareContext context, Command cmd) {
|
||||
String guid = cmd.getContextParam("guid");
|
||||
assert(guid != null);
|
||||
|
||||
String[] tokens = guid.split("@");
|
||||
assert(tokens != null && tokens.length == 2);
|
||||
|
||||
ManagedObjectReference morHyperHost = new ManagedObjectReference();
|
||||
String[] hostTokens = tokens[0].split(":");
|
||||
assert(hostTokens.length == 2);
|
||||
|
||||
morHyperHost.setType(hostTokens[0]);
|
||||
morHyperHost.set_value(hostTokens[1]);
|
||||
|
||||
if(morHyperHost.getType().equalsIgnoreCase("HostSystem")) {
|
||||
HostMO hostMo = new HostMO(context, morHyperHost);
|
||||
try {
|
||||
VmwareHypervisorHostNetworkSummary netSummary = hostMo.getHyperHostNetworkSummary(
|
||||
hostMo.getHostType() == VmwareHostType.ESXi ? cmd.getContextParam("manageportgroup") : cmd.getContextParam("serviceconsole"));
|
||||
assert(netSummary != null);
|
||||
if(netSummary.getHostIp() != null && !netSummary.getHostIp().isEmpty()) {
|
||||
if(s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Context validation succeeded. Validated via host: " + netSummary.getHostIp() + ", guid: " + guid);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
s_logger.warn("Context validation failed due to invalid host network summary");
|
||||
return false;
|
||||
} catch(Throwable e) {
|
||||
s_logger.warn("Context validation failed due to " + VmwareHelper.getExceptionMessage(e));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.vmware.apputils.version.ExtendedAppUtil;
|
||||
|
||||
public class TestVmwareContextFactory {
|
||||
private static volatile int s_seq = 1;
|
||||
|
||||
static {
|
||||
// skip certificate check
|
||||
System.setProperty("axis.socketSecureFactory", "org.apache.axis.components.net.SunFakeTrustSocketFactory");
|
||||
}
|
||||
|
||||
public static VmwareContext create(String vCenterAddress, String vCenterUserName, String vCenterPassword) throws Exception {
|
||||
assert(vCenterAddress != null);
|
||||
assert(vCenterUserName != null);
|
||||
assert(vCenterPassword != null);
|
||||
|
||||
String serviceUrl = "https://" + vCenterAddress + "/sdk/vimService";
|
||||
String[] params = new String[] {"--url", serviceUrl, "--username", vCenterUserName, "--password", vCenterPassword };
|
||||
ExtendedAppUtil appUtil = ExtendedAppUtil.initialize(vCenterAddress + "-" + s_seq++, params);
|
||||
|
||||
appUtil.connect();
|
||||
VmwareContext context = new VmwareContext(appUtil, vCenterAddress);
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.cloud.utils.testcase.Log4jEnabledTestCase;
|
||||
import com.google.gson.Gson;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.VirtualMachineConfigSpec;
|
||||
|
||||
// This test case needs a particular setup, only used for my own test
|
||||
public class TestVmwareMO extends Log4jEnabledTestCase {
|
||||
private static final Logger s_logger = Logger.getLogger(TestVmwareMO.class);
|
||||
|
||||
public void test() {
|
||||
try {
|
||||
VmwareContext context = TestVmwareContextFactory.create(
|
||||
"192.168.190.18", "Administrator", "Suite219");
|
||||
|
||||
VirtualMachineMO vmMo = new VirtualMachineMO(context, "VirtualMachine", "vm-700");
|
||||
|
||||
System.out.println("state " + vmMo.getPowerState().toString());
|
||||
|
||||
|
||||
context.close();
|
||||
} catch(Exception e) {
|
||||
s_logger.error("Unexpected exception : ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.util;
|
||||
import java.io.File;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.hypervisor.vmware.resource.SshHelper;
|
||||
import com.cloud.hypervisor.vmware.resource.VmwareContextFactory;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.testcase.Log4jEnabledTestCase;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
|
||||
// This test case needs a particular setup, only used for my own test
|
||||
public class TestVmwareUtil extends Log4jEnabledTestCase {
|
||||
private static final Logger s_logger = Logger.getLogger(TestVmwareUtil.class);
|
||||
|
||||
public void testContextCreation() {
|
||||
try {
|
||||
VmwareContext context = VmwareContextFactory.create("vsphere-1.lab.vmops.com", "Administrator", "Suite219");
|
||||
Assert.assertTrue(true);
|
||||
context.close();
|
||||
} catch(Exception e) {
|
||||
s_logger.error("Unexpected exception : ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSearchIndex() {
|
||||
try {
|
||||
VmwareContext context = VmwareContextFactory.create("vsphere-1.lab.vmops.com", "Administrator", "Suite219");
|
||||
Assert.assertTrue(true);
|
||||
|
||||
ManagedObjectReference morHost = context.getService().findByDnsName(context.getServiceContent().getSearchIndex(),
|
||||
null, "esxhost-1.lab.vmops.com", false);
|
||||
Assert.assertTrue(morHost.getType().equalsIgnoreCase("HostSystem"));
|
||||
|
||||
morHost = context.getService().findByIp(context.getServiceContent().getSearchIndex(),
|
||||
null, "192.168.1.168", false);
|
||||
Assert.assertTrue(morHost == null);
|
||||
context.close();
|
||||
} catch(Exception e) {
|
||||
s_logger.error("Unexpected exception : ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void testVmxFileDownload() {
|
||||
try {
|
||||
VmwareContext context = VmwareContextFactory.create("vsphere-1.lab.vmops.com", "Administrator", "Suite219");
|
||||
byte[] vmxContent = context.getResourceContent("https://vsphere-1.lab.vmops.com/folder/ServerRoom-Fedora32/ServerRoom-Fedora32.vmx?dcPath=cupertino&dsName=NFS%20datastore");
|
||||
System.out.print(new String(vmxContent));
|
||||
context.close();
|
||||
} catch(Exception e) {
|
||||
s_logger.error("Unexpected exception : ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void testVmxFileParser() {
|
||||
String[] tokens = "[NFS datastore] Fedora-clone-test/Fedora-clone-test.vmx".split("\\[|\\]|/");
|
||||
|
||||
for(String str : tokens) {
|
||||
System.out.println("Token " + str);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSsh() {
|
||||
try {
|
||||
File file = new File("c:\\temp\\id_rsa.kelven");
|
||||
if(!file.exists()) {
|
||||
System.out.println("key file does not exist!");
|
||||
}
|
||||
|
||||
Pair<Boolean, String> result = SshHelper.sshExecute("192.168.1.107", 22, "kelven", file, null, "ls -al");
|
||||
System.out.println("Result: " + result.second());
|
||||
} catch(Exception e) {
|
||||
s_logger.error("Unexpected exception : ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void testScp() {
|
||||
try {
|
||||
File file = new File("c:\\temp\\id_rsa.kelven");
|
||||
if(!file.exists()) {
|
||||
System.out.println("key file does not exist!");
|
||||
}
|
||||
|
||||
SshHelper.scpTo("192.168.1.107", 22, "kelven", file, null, "~", "Hello, world".getBytes(),
|
||||
"hello.txt", null);
|
||||
} catch(Exception e) {
|
||||
s_logger.error("Unexpected exception : ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -35,5 +35,21 @@
|
|||
<classpathentry exported="true" kind="lib" path="cloud-log4j-extras.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="cloud-iControl.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="cloud-manageontap.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="vmware-apputils.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="vmware-credstore.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="vmware-lib-activation.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="vmware-lib-jaxen-core.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="vmware-lib-jaxen-jdom.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="vmware-lib-jaxrpc.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="vmware-lib-jdom.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="vmware-lib-mailapi.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="vmware-lib-saxpath.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="vmware-lib-smtp.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="vmware-lib-wbem.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="vmware-lib-xalan.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="vmware-lib-xerces.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="vmware-lib-xml-apis.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="vmware-vim.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="vmware-vim25.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -8,5 +8,6 @@
|
|||
<classpathentry combineaccessrules="false" kind="src" path="/api"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/deps"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/tools"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/vmware-base"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.guru;
|
||||
|
||||
import javax.ejb.Local;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
import com.cloud.host.dao.HostDetailsDao;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.hypervisor.HypervisorGuru;
|
||||
import com.cloud.hypervisor.HypervisorGuruBase;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.storage.GuestOSVO;
|
||||
import com.cloud.storage.dao.GuestOSDao;
|
||||
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
|
||||
import com.cloud.utils.component.Inject;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
|
||||
/**
|
||||
* Implementation of Hypervisor guru for Hyper-Vr
|
||||
**/
|
||||
|
||||
@Local(value=HypervisorGuru.class)
|
||||
public class HypervGuru extends HypervisorGuruBase implements HypervisorGuru {
|
||||
|
||||
@Inject GuestOSDao _guestOsDao;
|
||||
@Inject HostDao _hostDao;
|
||||
@Inject HostDetailsDao _hostDetailsDao;
|
||||
|
||||
protected HypervGuru() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HypervisorType getHypervisorType() {
|
||||
return HypervisorType.Hyperv;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends VirtualMachine> VirtualMachineTO implement(VirtualMachineProfile<T> vm) {
|
||||
VirtualMachineTO to = toVirtualMachineTO(vm);
|
||||
to.setBootloader(BootloaderType.HVM);
|
||||
|
||||
// Determine the VM's OS description
|
||||
GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId());
|
||||
to.setOs(guestOS.getDisplayName());
|
||||
return to;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCommandHostDelegation(long hostId, Command cmd) {
|
||||
return hostId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trackVmHostChange() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
package com.cloud.hypervisor.guru;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ejb.Local;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.BackupSnapshotCommand;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
|
||||
import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
|
||||
import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
|
||||
import com.cloud.agent.api.DeleteSnapshotBackupCommand;
|
||||
import com.cloud.agent.api.DeleteSnapshotsDirCommand;
|
||||
import com.cloud.agent.api.storage.CopyVolumeCommand;
|
||||
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
import com.cloud.cluster.CheckPointManager;
|
||||
import com.cloud.cluster.ClusterManager;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.dao.HostDetailsDao;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.hypervisor.HypervisorGuru;
|
||||
import com.cloud.hypervisor.HypervisorGuruBase;
|
||||
import com.cloud.hypervisor.vmware.VmwareCleanupMaid;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareManager;
|
||||
import com.cloud.secstorage.CommandExecLogDao;
|
||||
import com.cloud.secstorage.CommandExecLogVO;
|
||||
import com.cloud.storage.GuestOSVO;
|
||||
import com.cloud.storage.dao.GuestOSDao;
|
||||
import com.cloud.storage.secondary.SecondaryStorageVmManager;
|
||||
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.Inject;
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
import com.cloud.vm.SecondaryStorageVmVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
|
||||
@Local(value=HypervisorGuru.class)
|
||||
public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
|
||||
private static final Logger s_logger = Logger.getLogger(VMwareGuru.class);
|
||||
|
||||
@Inject GuestOSDao _guestOsDao;
|
||||
@Inject HostDao _hostDao;
|
||||
@Inject HostDetailsDao _hostDetailsDao;
|
||||
@Inject CommandExecLogDao _cmdExecLogDao;
|
||||
@Inject ClusterManager _clusterMgr;
|
||||
@Inject VmwareManager _vmwareMgr;
|
||||
@Inject SecondaryStorageVmManager _secStorageMgr;
|
||||
@Inject CheckPointManager _checkPointMgr;
|
||||
|
||||
protected VMwareGuru() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HypervisorType getHypervisorType() {
|
||||
return HypervisorType.VMware;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends VirtualMachine> VirtualMachineTO implement(VirtualMachineProfile<T> vm) {
|
||||
VirtualMachineTO to = toVirtualMachineTO(vm);
|
||||
to.setBootloader(BootloaderType.HVM);
|
||||
|
||||
// Determine the VM's OS description
|
||||
GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId());
|
||||
to.setOs(guestOS.getDisplayName());
|
||||
return to;
|
||||
}
|
||||
|
||||
@Override @DB
|
||||
public long getCommandHostDelegation(long hostId, Command cmd) {
|
||||
boolean needDelegation = false;
|
||||
|
||||
if(cmd instanceof PrimaryStorageDownloadCommand ||
|
||||
cmd instanceof BackupSnapshotCommand ||
|
||||
cmd instanceof DeleteSnapshotsDirCommand ||
|
||||
cmd instanceof DeleteSnapshotBackupCommand ||
|
||||
cmd instanceof CreatePrivateTemplateFromVolumeCommand ||
|
||||
cmd instanceof CreatePrivateTemplateFromSnapshotCommand ||
|
||||
cmd instanceof CopyVolumeCommand ||
|
||||
cmd instanceof CreateVolumeFromSnapshotCommand) {
|
||||
needDelegation = true;
|
||||
}
|
||||
|
||||
if(needDelegation) {
|
||||
HostVO host = _hostDao.findById(hostId);
|
||||
assert(host != null);
|
||||
assert(host.getHypervisorType() == HypervisorType.VMware);
|
||||
long dcId = host.getDataCenterId();
|
||||
|
||||
Pair<HostVO, SecondaryStorageVmVO> cmdTarget = _secStorageMgr.assignSecStorageVm(dcId, cmd);
|
||||
if(cmdTarget != null) {
|
||||
// TODO, we need to make sure agent is actually connected too
|
||||
cmd.setContextParam("hypervisor", HypervisorType.VMware.toString());
|
||||
Map<String, String> hostDetails = _hostDetailsDao.findDetails(hostId);
|
||||
cmd.setContextParam("guid", resolveNameInGuid(hostDetails.get("guid")));
|
||||
cmd.setContextParam("username", hostDetails.get("username"));
|
||||
cmd.setContextParam("password", hostDetails.get("password"));
|
||||
cmd.setContextParam("serviceconsole", _vmwareMgr.getServiceConsolePortGroupName());
|
||||
cmd.setContextParam("manageportgroup", _vmwareMgr.getManagementPortGroupName());
|
||||
|
||||
CommandExecLogVO execLog = new CommandExecLogVO(cmdTarget.first().getId(), cmdTarget.second().getId(), cmd.getClass().getSimpleName(), 1);
|
||||
_cmdExecLogDao.persist(execLog);
|
||||
cmd.setContextParam("execid", String.valueOf(execLog.getId()));
|
||||
|
||||
if(cmd instanceof BackupSnapshotCommand ||
|
||||
cmd instanceof CreatePrivateTemplateFromVolumeCommand ||
|
||||
cmd instanceof CreatePrivateTemplateFromSnapshotCommand ||
|
||||
cmd instanceof CopyVolumeCommand ||
|
||||
cmd instanceof CreateVolumeFromSnapshotCommand) {
|
||||
|
||||
String workerName = _vmwareMgr.composeWorkerName();
|
||||
long checkPointId = _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), workerName));
|
||||
cmd.setContextParam("worker", workerName);
|
||||
cmd.setContextParam("checkpoint", String.valueOf(checkPointId));
|
||||
}
|
||||
|
||||
return cmdTarget.first().getId();
|
||||
}
|
||||
}
|
||||
|
||||
return hostId;
|
||||
}
|
||||
|
||||
public boolean trackVmHostChange() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String resolveNameInGuid(String guid) {
|
||||
String tokens[] = guid.split("@");
|
||||
assert(tokens.length == 2);
|
||||
|
||||
String vCenterIp = NetUtils.resolveToIp(tokens[1]);
|
||||
if(vCenterIp == null) {
|
||||
s_logger.error("Fatal : unable to resolve vCenter address " + tokens[1] + ", please check your DNS configuration");
|
||||
return guid;
|
||||
}
|
||||
|
||||
if(vCenterIp.equals(tokens[1]))
|
||||
return guid;
|
||||
|
||||
return tokens[0] + "@" + vCenterIp;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
package com.cloud.hypervisor.vmware;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.cluster.CheckPointManager;
|
||||
import com.cloud.cluster.CleanupMaid;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareManager;
|
||||
import com.cloud.hypervisor.vmware.mo.ClusterMO;
|
||||
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
|
||||
import com.cloud.hypervisor.vmware.mo.HostMO;
|
||||
import com.cloud.hypervisor.vmware.mo.VirtualMachineMO;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
|
||||
public class VmwareCleanupMaid implements CleanupMaid {
|
||||
private static final Logger s_logger = Logger.getLogger(VmwareCleanupMaid.class);
|
||||
|
||||
private static Map<String, List<VmwareCleanupMaid>> s_leftoverDummyVMs = new HashMap<String, List<VmwareCleanupMaid>>();
|
||||
|
||||
private String _vCenterAddress;
|
||||
private String _dcMorValue;
|
||||
private String _hostMorValue;
|
||||
private String _vmName;
|
||||
private long _checkPoint;
|
||||
|
||||
public VmwareCleanupMaid() {
|
||||
}
|
||||
|
||||
public VmwareCleanupMaid(String hostGuid, String vmName) {
|
||||
String[] tokens = hostGuid.split("@");
|
||||
assert(tokens != null);
|
||||
assert(tokens.length == 2);
|
||||
_vCenterAddress = tokens[1];
|
||||
|
||||
String[] hostTokens = tokens[0].split(":");
|
||||
assert(hostTokens != null);
|
||||
assert(hostTokens.length == 2);
|
||||
|
||||
_hostMorValue = hostTokens[1];
|
||||
|
||||
_vmName = vmName;
|
||||
}
|
||||
|
||||
public VmwareCleanupMaid(String vCenterAddress, String dcMorValue, String vmName) {
|
||||
_vCenterAddress = vCenterAddress;
|
||||
_dcMorValue = dcMorValue;
|
||||
_vmName = vmName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int cleanup(CheckPointManager checkPointMgr) {
|
||||
|
||||
// save a check-point in case we crash at current run so that we won't lose it
|
||||
_checkPoint = checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(_vCenterAddress, _dcMorValue, _vmName));
|
||||
addLeftOverVM(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCleanupProcedure() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getVCenterServer() {
|
||||
return _vCenterAddress;
|
||||
}
|
||||
|
||||
public String getDatacenterMorValue() {
|
||||
return _dcMorValue;
|
||||
}
|
||||
|
||||
public String getHostMorValue() {
|
||||
return _hostMorValue;
|
||||
}
|
||||
|
||||
public String getVmName() {
|
||||
return _vmName;
|
||||
}
|
||||
|
||||
public long getCheckPoint() {
|
||||
return _checkPoint;
|
||||
}
|
||||
|
||||
private synchronized static void addLeftOverVM(VmwareCleanupMaid cleanupMaid) {
|
||||
List<VmwareCleanupMaid> l = s_leftoverDummyVMs.get(cleanupMaid.getVCenterServer());
|
||||
if(l == null) {
|
||||
l = new ArrayList<VmwareCleanupMaid>();
|
||||
s_leftoverDummyVMs.put(cleanupMaid.getVCenterServer(), l);
|
||||
}
|
||||
|
||||
l.add(cleanupMaid);
|
||||
}
|
||||
|
||||
public synchronized static void gcLeftOverVMs(VmwareContext context) {
|
||||
List<VmwareCleanupMaid> l = s_leftoverDummyVMs.get(context.getServerAddress());
|
||||
VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
|
||||
assert(mgr != null);
|
||||
|
||||
if(l != null && l.size() > 0) {
|
||||
for(VmwareCleanupMaid cleanupMaid : l) {
|
||||
try {
|
||||
VirtualMachineMO vmMo = null;
|
||||
if(cleanupMaid.getDatacenterMorValue() != null) {
|
||||
DatacenterMO dcMo = new DatacenterMO(context, "Datacenter", cleanupMaid.getDatacenterMorValue());
|
||||
vmMo = dcMo.findVm(cleanupMaid.getVmName());
|
||||
} else {
|
||||
assert(cleanupMaid.getHostMorValue() != null);
|
||||
HostMO hostMo = new HostMO(context, "HostSystem", cleanupMaid.getHostMorValue());
|
||||
ClusterMO clusterMo = new ClusterMO(context, hostMo.getHyperHostCluster());
|
||||
vmMo = clusterMo.findVmOnHyperHost(cleanupMaid.getVmName());
|
||||
}
|
||||
|
||||
if(vmMo != null) {
|
||||
s_logger.info("Found left over dummy VM " + cleanupMaid.getVmName() + ", destroy it");
|
||||
vmMo.destroy();
|
||||
}
|
||||
} catch(Throwable e) {
|
||||
s_logger.warn("Unable to destroy left over dummy VM " + cleanupMaid.getVmName());
|
||||
} finally {
|
||||
mgr.popCleanupCheckpoint(cleanupMaid.getCheckPoint());
|
||||
}
|
||||
}
|
||||
|
||||
l.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,860 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.AgentManager;
|
||||
import com.cloud.agent.Listener;
|
||||
import com.cloud.agent.api.AgentControlAnswer;
|
||||
import com.cloud.agent.api.AgentControlCommand;
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.api.StartupRoutingCommand;
|
||||
import com.cloud.cluster.CheckPointManager;
|
||||
import com.cloud.cluster.ClusterManager;
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
import com.cloud.dc.ClusterDetailsDao;
|
||||
import com.cloud.dc.ClusterVO;
|
||||
import com.cloud.dc.dao.ClusterDao;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.DiscoveredWithErrorException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.Status;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareManager;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareStorageManager;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareStorageManagerImpl;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareStorageMount;
|
||||
import com.cloud.hypervisor.vmware.mo.HostFirewallSystemMO;
|
||||
import com.cloud.hypervisor.vmware.mo.HostMO;
|
||||
import com.cloud.hypervisor.vmware.mo.HostVirtualNicType;
|
||||
import com.cloud.hypervisor.vmware.mo.HypervisorHostHelper;
|
||||
import com.cloud.hypervisor.vmware.mo.TaskMO;
|
||||
import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType;
|
||||
import com.cloud.hypervisor.vmware.mo.VmwareHostType;
|
||||
import com.cloud.hypervisor.vmware.resource.SshHelper;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.cloud.network.router.VirtualNetworkApplianceManager;
|
||||
import com.cloud.org.Cluster.ClusterType;
|
||||
import com.cloud.secstorage.CommandExecLogDao;
|
||||
import com.cloud.serializer.GsonHelper;
|
||||
import com.cloud.storage.StorageLayer;
|
||||
import com.cloud.user.UserContext;
|
||||
import com.cloud.utils.FileUtil;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.ComponentLocator;
|
||||
import com.cloud.utils.component.Inject;
|
||||
import com.cloud.utils.component.Manager;
|
||||
import com.cloud.utils.concurrency.NamedThreadFactory;
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.db.GlobalLock;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.script.Script;
|
||||
import com.cloud.vm.DomainRouterVO;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
import com.cloud.vm.dao.DomainRouterDao;
|
||||
import com.google.gson.Gson;
|
||||
import com.vmware.apputils.vim25.ServiceUtil;
|
||||
import com.vmware.vim25.HostConnectSpec;
|
||||
import com.vmware.vim25.HostPortGroupSpec;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
|
||||
@Local(value = {VmwareManager.class})
|
||||
public class VmwareManagerImpl implements VmwareManager, VmwareStorageMount, Listener, Manager {
|
||||
private static final Logger s_logger = Logger.getLogger(VmwareManagerImpl.class);
|
||||
|
||||
private static final int STARTUP_DELAY = 60000; // 60 seconds
|
||||
private static final long DEFAULT_HOST_SCAN_INTERVAL = 600000; // every 10 minutes
|
||||
|
||||
private long _hostScanInterval = DEFAULT_HOST_SCAN_INTERVAL;
|
||||
int _timeout;
|
||||
|
||||
private String _name;
|
||||
private String _instance;
|
||||
|
||||
@Inject AgentManager _agentMgr;
|
||||
@Inject HostDao _hostDao;
|
||||
@Inject ClusterDao _clusterDao;
|
||||
@Inject ClusterDetailsDao _clusterDetailsDao;
|
||||
@Inject CommandExecLogDao _cmdExecLogDao;
|
||||
@Inject ClusterManager _clusterMgr;
|
||||
@Inject CheckPointManager _checkPointMgr;
|
||||
@Inject VirtualNetworkApplianceManager _routerMgr;
|
||||
@Inject DomainRouterDao _routerDao;
|
||||
|
||||
String _mountParent;
|
||||
StorageLayer _storage;
|
||||
|
||||
String _privateNetworkVSwitchName;
|
||||
String _publicNetworkVSwitchName;
|
||||
String _guestNetworkVSwitchName;
|
||||
String _serviceConsoleName;
|
||||
String _managemetPortGroupName;
|
||||
int _additionalPortRangeStart;
|
||||
int _additionalPortRangeSize;
|
||||
VirtualEthernetCardType _guestNicDeviceType;
|
||||
int _maxHostsPerCluster;
|
||||
|
||||
String _cpuOverprovisioningFactor = "1";
|
||||
String _reserveCpu = "false";
|
||||
|
||||
Map<String, String> _storageMounts = new HashMap<String, String>();
|
||||
|
||||
Random _rand = new Random(System.currentTimeMillis());
|
||||
Gson _gson;
|
||||
|
||||
VmwareStorageManager _storageMgr;
|
||||
GlobalLock _exclusiveOpLock = GlobalLock.getInternLock("vmware.exclusive.op");
|
||||
|
||||
private final ScheduledExecutorService _hostScanScheduler = Executors.newScheduledThreadPool(
|
||||
1, new NamedThreadFactory("Vmware-Host-Scan"));
|
||||
|
||||
public VmwareManagerImpl() {
|
||||
_gson = GsonHelper.getGsonLogger();
|
||||
_storageMgr = new VmwareStorageManagerImpl(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
s_logger.info("Configure VmwareManagerImpl, manager name: " + name);
|
||||
|
||||
_name = name;
|
||||
|
||||
ComponentLocator locator = ComponentLocator.getCurrentLocator();
|
||||
ConfigurationDao configDao = locator.getDao(ConfigurationDao.class);
|
||||
if (configDao == null) {
|
||||
throw new ConfigurationException("Unable to get the configuration dao.");
|
||||
}
|
||||
|
||||
if(!configDao.isPremium()) {
|
||||
s_logger.error("Vmware component can only run under premium distribution");
|
||||
throw new ConfigurationException("Vmware component can only run under premium distribution");
|
||||
}
|
||||
|
||||
_instance = configDao.getValue(Config.InstanceName.key());
|
||||
if (_instance == null) {
|
||||
_instance = "DEFAULT";
|
||||
}
|
||||
s_logger.info("VmwareManagerImpl config - instance.name: " + _instance);
|
||||
|
||||
_mountParent = configDao.getValue(Config.MountParent.key());
|
||||
if (_mountParent == null) {
|
||||
_mountParent = File.separator + "mnt";
|
||||
}
|
||||
|
||||
if (_instance != null) {
|
||||
_mountParent = _mountParent + File.separator + _instance;
|
||||
}
|
||||
s_logger.info("VmwareManagerImpl config - _mountParent: " + _mountParent);
|
||||
|
||||
String value = (String)params.get("scripts.timeout");
|
||||
_timeout = NumbersUtil.parseInt(value, 1440) * 1000;
|
||||
|
||||
_storage = (StorageLayer)params.get(StorageLayer.InstanceConfigKey);
|
||||
if (_storage == null) {
|
||||
value = (String)params.get(StorageLayer.ClassConfigKey);
|
||||
if (value == null) {
|
||||
value = "com.cloud.storage.JavaStorageLayer";
|
||||
}
|
||||
|
||||
try {
|
||||
Class<?> clazz = Class.forName(value);
|
||||
_storage = (StorageLayer)ComponentLocator.inject(clazz);
|
||||
_storage.configure("StorageLayer", params);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new ConfigurationException("Unable to find class " + value);
|
||||
}
|
||||
}
|
||||
|
||||
_privateNetworkVSwitchName = configDao.getValue(Config.VmwarePrivateNetworkVSwitch.key());
|
||||
if(_privateNetworkVSwitchName == null) {
|
||||
_privateNetworkVSwitchName = "vSwitch0";
|
||||
}
|
||||
|
||||
_publicNetworkVSwitchName = configDao.getValue(Config.VmwarePublicNetworkVSwitch.key());
|
||||
if(_publicNetworkVSwitchName == null) {
|
||||
_publicNetworkVSwitchName = "vSwitch0";
|
||||
}
|
||||
|
||||
_guestNetworkVSwitchName = configDao.getValue(Config.VmwareGuestNetworkVSwitch.key());
|
||||
if(_guestNetworkVSwitchName == null) {
|
||||
_guestNetworkVSwitchName = "vSwitch0";
|
||||
}
|
||||
|
||||
_serviceConsoleName = configDao.getValue(Config.VmwareServiceConsole.key());
|
||||
if(_serviceConsoleName == null) {
|
||||
_serviceConsoleName = "Service Console";
|
||||
}
|
||||
|
||||
_managemetPortGroupName = configDao.getValue(Config.VmwareManagementPortGroup.key());
|
||||
if(_managemetPortGroupName == null) {
|
||||
_managemetPortGroupName = "Management Network";
|
||||
}
|
||||
|
||||
configDao.getValue(Config.VmwareServiceConsole.key());
|
||||
_additionalPortRangeStart = NumbersUtil.parseInt(configDao.getValue(Config.VmwareAdditionalVncPortRangeStart.key()), 59000);
|
||||
if(_additionalPortRangeStart > 65535) {
|
||||
s_logger.warn("Invalid port range start port (" + _additionalPortRangeStart + ") for additional VNC port allocation, reset it to default start port 59000");
|
||||
_additionalPortRangeStart = 59000;
|
||||
}
|
||||
|
||||
_additionalPortRangeSize = NumbersUtil.parseInt(configDao.getValue(Config.VmwareAdditionalVncPortRangeSize.key()), 1000);
|
||||
if(_additionalPortRangeSize < 0 || _additionalPortRangeStart + _additionalPortRangeSize > 65535) {
|
||||
s_logger.warn("Invalid port range size (" + _additionalPortRangeSize + " for range starts at " + _additionalPortRangeStart);
|
||||
_additionalPortRangeSize = Math.min(1000, 65535 - _additionalPortRangeStart);
|
||||
}
|
||||
|
||||
_maxHostsPerCluster = NumbersUtil.parseInt(configDao.getValue(Config.VmwarePerClusterHostMax.key()), VmwareManager.MAX_HOSTS_PER_CLUSTER);
|
||||
_cpuOverprovisioningFactor = configDao.getValue(Config.CPUOverprovisioningFactor.key());
|
||||
if(_cpuOverprovisioningFactor == null || _cpuOverprovisioningFactor.isEmpty())
|
||||
_cpuOverprovisioningFactor = "1";
|
||||
|
||||
_reserveCpu = configDao.getValue(Config.VmwareReserveCpu.key());
|
||||
if(_reserveCpu == null || _reserveCpu.isEmpty())
|
||||
_reserveCpu = "false";
|
||||
|
||||
s_logger.info("Additional VNC port allocation range is settled at " + _additionalPortRangeStart + " to " + (_additionalPortRangeStart + _additionalPortRangeSize));
|
||||
|
||||
value = configDao.getValue(Config.VmwareGuestNicDeviceType.key());
|
||||
if(value == null || "E1000".equalsIgnoreCase(value))
|
||||
this._guestNicDeviceType = VirtualEthernetCardType.E1000;
|
||||
else if("PCNet32".equalsIgnoreCase(value))
|
||||
this._guestNicDeviceType = VirtualEthernetCardType.PCNet32;
|
||||
else if("Vmxnet2".equalsIgnoreCase(value))
|
||||
this._guestNicDeviceType = VirtualEthernetCardType.Vmxnet2;
|
||||
else if("Vmxnet3".equalsIgnoreCase(value))
|
||||
this._guestNicDeviceType = VirtualEthernetCardType.Vmxnet3;
|
||||
else
|
||||
this._guestNicDeviceType = VirtualEthernetCardType.E1000;
|
||||
|
||||
value = configDao.getValue("vmware.host.scan.interval");
|
||||
_hostScanInterval = NumbersUtil.parseLong(value, DEFAULT_HOST_SCAN_INTERVAL);
|
||||
s_logger.info("VmwareManagerImpl config - vmware.host.scan.interval: " + _hostScanInterval);
|
||||
|
||||
((VmwareStorageManagerImpl)_storageMgr).configure(params);
|
||||
|
||||
_agentMgr.registerForHostEvents(this, true, true, true);
|
||||
|
||||
s_logger.info("VmwareManagerImpl has been successfully configured");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
_hostScanScheduler.scheduleAtFixedRate(getHostScanTask(),
|
||||
STARTUP_DELAY, _hostScanInterval, TimeUnit.MILLISECONDS);
|
||||
|
||||
startupCleanup(_mountParent);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
_hostScanScheduler.shutdownNow();
|
||||
try {
|
||||
_hostScanScheduler.awaitTermination(3000, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
|
||||
shutdownCleanup();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String composeWorkerName() {
|
||||
return "cloud.worker." + _clusterMgr.getManagementNodeId() + "." + _clusterMgr.getCurrentRunId() + "." + UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ManagedObjectReference> addHostToPodCluster(VmwareContext serviceContext, long dcId, Long podId, Long clusterId,
|
||||
String hostInventoryPath) throws Exception {
|
||||
ManagedObjectReference mor = serviceContext.getHostMorByPath(hostInventoryPath);
|
||||
if(mor != null) {
|
||||
List<ManagedObjectReference> returnedHostList = new ArrayList<ManagedObjectReference>();
|
||||
|
||||
if(mor.getType().equals("ComputeResource")) {
|
||||
ManagedObjectReference[] hosts = (ManagedObjectReference[])serviceContext.getServiceUtil().getDynamicProperty(mor, "host");
|
||||
assert(hosts != null);
|
||||
|
||||
// For ESX host, we need to enable host firewall to allow VNC access
|
||||
HostMO hostMo = new HostMO(serviceContext, hosts[0]);
|
||||
HostFirewallSystemMO firewallMo = hostMo.getHostFirewallSystemMO();
|
||||
if(firewallMo != null) {
|
||||
firewallMo.enableRuleset("vncServer");
|
||||
firewallMo.refreshFirewall();
|
||||
}
|
||||
|
||||
// prepare at least one network on the vswitch to enable OVF importing
|
||||
String managementPortGroupName = hostMo.getPortGroupNameByNicType(HostVirtualNicType.management);
|
||||
assert(managementPortGroupName != null);
|
||||
HostPortGroupSpec spec = hostMo.getPortGroupSpec(managementPortGroupName);
|
||||
Integer vlanId = null;
|
||||
if(spec.getVlanId() != 0) {
|
||||
vlanId = spec.getVlanId();
|
||||
}
|
||||
|
||||
HypervisorHostHelper.preparePrivateNetwork(_privateNetworkVSwitchName, hostMo, vlanId, 180000);
|
||||
returnedHostList.add(hosts[0]);
|
||||
return returnedHostList;
|
||||
} else if(mor.getType().equals("ClusterComputeResource")) {
|
||||
ManagedObjectReference[] hosts = (ManagedObjectReference[])serviceContext.getServiceUtil().getDynamicProperty(mor, "host");
|
||||
assert(hosts != null);
|
||||
|
||||
if(hosts.length > _maxHostsPerCluster) {
|
||||
String msg = "vCenter cluster size is too big (current configured cluster size: " + _maxHostsPerCluster + ")";
|
||||
s_logger.error(msg);
|
||||
throw new DiscoveredWithErrorException(msg);
|
||||
}
|
||||
|
||||
for(ManagedObjectReference morHost: hosts) {
|
||||
// For ESX host, we need to enable host firewall to allow VNC access
|
||||
HostMO hostMo = new HostMO(serviceContext, morHost);
|
||||
HostFirewallSystemMO firewallMo = hostMo.getHostFirewallSystemMO();
|
||||
if(firewallMo != null) {
|
||||
firewallMo.enableRuleset("vncServer");
|
||||
firewallMo.refreshFirewall();
|
||||
}
|
||||
|
||||
String managementPortGroupName = hostMo.getPortGroupNameByNicType(HostVirtualNicType.management);
|
||||
assert(managementPortGroupName != null);
|
||||
HostPortGroupSpec spec = hostMo.getPortGroupSpec(managementPortGroupName);
|
||||
Integer vlanId = null;
|
||||
if(spec.getVlanId() != 0) {
|
||||
vlanId = spec.getVlanId();
|
||||
}
|
||||
|
||||
// prepare at least one network on the vswitch to enable OVF importing
|
||||
HypervisorHostHelper.preparePrivateNetwork(_privateNetworkVSwitchName, hostMo, vlanId, 180000);
|
||||
returnedHostList.add(morHost);
|
||||
}
|
||||
return returnedHostList;
|
||||
} else if(mor.getType().equals("HostSystem")) {
|
||||
// For ESX host, we need to enable host firewall to allow VNC access
|
||||
HostMO hostMo = new HostMO(serviceContext, mor);
|
||||
HostFirewallSystemMO firewallMo = hostMo.getHostFirewallSystemMO();
|
||||
if(firewallMo != null) {
|
||||
firewallMo.enableRuleset("vncServer");
|
||||
firewallMo.refreshFirewall();
|
||||
}
|
||||
|
||||
String managementPortGroupName = hostMo.getPortGroupNameByNicType(HostVirtualNicType.management);
|
||||
assert(managementPortGroupName != null);
|
||||
HostPortGroupSpec spec = hostMo.getPortGroupSpec(managementPortGroupName);
|
||||
Integer vlanId = null;
|
||||
if(spec.getVlanId() != 0) {
|
||||
vlanId = spec.getVlanId();
|
||||
}
|
||||
|
||||
// prepare at least one network on the vswitch to enable OVF importing
|
||||
HypervisorHostHelper.preparePrivateNetwork(_privateNetworkVSwitchName, hostMo, vlanId, 180000);
|
||||
returnedHostList.add(mor);
|
||||
return returnedHostList;
|
||||
} else {
|
||||
s_logger.error("Unsupport host type " + mor.getType() + ":" + mor.get_value() + " from inventory path: " + hostInventoryPath);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
s_logger.error("Unable to find host from inventory path: " + hostInventoryPath);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private ManagedObjectReference addHostToVCenterCluster(VmwareContext serviceContext, ManagedObjectReference morCluster,
|
||||
String host, String userName, String password) throws Exception {
|
||||
|
||||
ServiceUtil serviceUtil = serviceContext.getServiceUtil();
|
||||
ManagedObjectReference morHost = serviceUtil.getDecendentMoRef(morCluster, "HostSystem", host);
|
||||
if(morHost == null) {
|
||||
HostConnectSpec hostSpec = new HostConnectSpec();
|
||||
hostSpec.setUserName(userName);
|
||||
hostSpec.setPassword(password);
|
||||
hostSpec.setHostName(host);
|
||||
hostSpec.setForce(true); // forcely take over the host
|
||||
|
||||
ManagedObjectReference morTask = serviceContext.getService().addHost_Task(morCluster, hostSpec, true, null, null);
|
||||
String taskResult = serviceUtil.waitForTask(morTask);
|
||||
if(!taskResult.equals("sucess")) {
|
||||
s_logger.error("Unable to add host " + host + " to vSphere cluster due to " + TaskMO.getTaskFailureInfo(serviceContext, morTask));
|
||||
throw new CloudRuntimeException("Unable to add host " + host + " to vSphere cluster due to " + taskResult);
|
||||
}
|
||||
serviceContext.waitForTaskProgressDone(morTask);
|
||||
|
||||
// init morHost after it has been created
|
||||
morHost = serviceUtil.getDecendentMoRef(morCluster, "HostSystem", host);
|
||||
if(morHost == null) {
|
||||
throw new CloudRuntimeException("Successfully added host into vSphere but unable to find it later on?!. Please make sure you are either using IP address or full qualified domain name for host");
|
||||
}
|
||||
}
|
||||
|
||||
// For ESX host, we need to enable host firewall to allow VNC access
|
||||
HostMO hostMo = new HostMO(serviceContext, morHost);
|
||||
HostFirewallSystemMO firewallMo = hostMo.getHostFirewallSystemMO();
|
||||
if(firewallMo != null) {
|
||||
firewallMo.enableRuleset("vncServer");
|
||||
firewallMo.refreshFirewall();
|
||||
}
|
||||
return morHost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSecondaryStorageStoreUrl(long dcId) {
|
||||
List<HostVO> secStorageHosts = _hostDao.listSecondaryStorageHosts(dcId);
|
||||
if(secStorageHosts.size() > 0)
|
||||
return secStorageHosts.get(0).getStorageUrl();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getServiceConsolePortGroupName() {
|
||||
return _serviceConsoleName;
|
||||
}
|
||||
|
||||
public String getManagementPortGroupName() {
|
||||
return _managemetPortGroupName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getManagementPortGroupByHost(HostMO hostMo) throws Exception {
|
||||
if(hostMo.getHostType() == VmwareHostType.ESXi)
|
||||
return this._managemetPortGroupName;
|
||||
return this._serviceConsoleName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupResourceStartupParams(Map<String, Object> params) {
|
||||
params.put("private.network.vswitch.name", _privateNetworkVSwitchName);
|
||||
params.put("public.network.vswitch.name", _publicNetworkVSwitchName);
|
||||
params.put("guest.network.vswitch.name", _guestNetworkVSwitchName);
|
||||
params.put("service.console.name", _serviceConsoleName);
|
||||
params.put("management.portgroup.name", _managemetPortGroupName);
|
||||
params.put("cpu.overprovisioning.factor", _cpuOverprovisioningFactor);
|
||||
params.put("vmware.reserve.cpu", _reserveCpu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VmwareStorageManager getStorageManager() {
|
||||
return _storageMgr;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long pushCleanupCheckpoint(String hostGuid, String vmName) {
|
||||
return _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostGuid, vmName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void popCleanupCheckpoint(long checkpoint) {
|
||||
_checkPointMgr.popCheckPoint(checkpoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gcLeftOverVMs(VmwareContext context) {
|
||||
VmwareCleanupMaid.gcLeftOverVMs(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareSecondaryStorageStore(String storageUrl) {
|
||||
String mountPoint = getMountPoint(storageUrl);
|
||||
|
||||
GlobalLock lock = GlobalLock.getInternLock("prepare.systemvm");
|
||||
try {
|
||||
if(lock.lock(3600)) {
|
||||
try {
|
||||
File patchFolder = new File(mountPoint + "/systemvm");
|
||||
if(!patchFolder.exists()) {
|
||||
if(!patchFolder.mkdirs()) {
|
||||
String msg = "Unable to create systemvm folder on secondary storage. location: " + patchFolder.toString();
|
||||
s_logger.error(msg);
|
||||
throw new CloudRuntimeException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
File srcIso = getSystemVMPatchIsoFile();
|
||||
File destIso = new File(mountPoint + "/systemvm/" + getSystemVMIsoFileNameOnDatastore());
|
||||
if(!destIso.exists()) {
|
||||
try {
|
||||
FileUtil.copyfile(srcIso, destIso);
|
||||
} catch(IOException e) {
|
||||
s_logger.error("Unexpected exception ", e);
|
||||
|
||||
String msg = "Unable to copy systemvm ISO on secondary storage. src location: " + srcIso.toString() + ", dest location: " + destIso;
|
||||
s_logger.error(msg);
|
||||
throw new CloudRuntimeException(msg);
|
||||
}
|
||||
} else {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("SystemVM ISO file " + destIso.getPath() + " already exists");
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.releaseRef();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSystemVMIsoFileNameOnDatastore() {
|
||||
String version = ComponentLocator.class.getPackage().getImplementationVersion();
|
||||
String fileName = "systemvm-" + version + ".iso";
|
||||
return fileName.replace(':', '-');
|
||||
}
|
||||
|
||||
private File getSystemVMPatchIsoFile() {
|
||||
// locate systemvm.iso
|
||||
URL url = ComponentLocator.class.getProtectionDomain().getCodeSource().getLocation();
|
||||
File file = new File(url.getFile());
|
||||
File isoFile = new File(file.getParent() + "/vms/systemvm.iso");
|
||||
if (!isoFile.exists()) {
|
||||
isoFile = new File("/usr/lib64/cloud/agent/" + "/vms/systemvm.iso");
|
||||
if (!isoFile.exists()) {
|
||||
isoFile = new File("/usr/lib/cloud/agent/" + "/vms/systemvm.iso");
|
||||
}
|
||||
}
|
||||
return isoFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getSystemVMKeyFile() {
|
||||
URL url = ComponentLocator.class.getProtectionDomain().getCodeSource().getLocation();
|
||||
File file = new File(url.getFile());
|
||||
|
||||
File keyFile = new File(file.getParent(), "/scripts/vm/systemvm/id_rsa.cloud");
|
||||
if (!keyFile.exists()) {
|
||||
keyFile = new File("/usr/lib64/cloud/agent" + "/scripts/vm/systemvm/id_rsa.cloud");
|
||||
if (!keyFile.exists()) {
|
||||
keyFile = new File("/usr/lib/cloud/agent" + "/scripts/vm/systemvm/id_rsa.cloud");
|
||||
}
|
||||
}
|
||||
return keyFile;
|
||||
}
|
||||
|
||||
private Runnable getHostScanTask() {
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// TODO scan vSphere for newly added hosts.
|
||||
// we are going to both support adding host from Cloud.com UI and
|
||||
// adding host via vSphere server
|
||||
//
|
||||
// will implement host scanning later
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMountPoint(String storageUrl) {
|
||||
String mountPoint = null;
|
||||
synchronized(_storageMounts) {
|
||||
mountPoint = _storageMounts.get(storageUrl);
|
||||
if(mountPoint != null) {
|
||||
return mountPoint;
|
||||
}
|
||||
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI(storageUrl);
|
||||
} catch (URISyntaxException e) {
|
||||
s_logger.error("Invalid storage URL format ", e);
|
||||
throw new CloudRuntimeException("Unable to create mount point due to invalid storage URL format " + storageUrl);
|
||||
}
|
||||
mountPoint = mount(uri.getHost() + ":" + uri.getPath(), _mountParent);
|
||||
if(mountPoint == null) {
|
||||
s_logger.error("Unable to create mount point for " + storageUrl);
|
||||
throw new CloudRuntimeException("Unable to create mount point for " + storageUrl);
|
||||
}
|
||||
|
||||
_storageMounts.put(storageUrl, mountPoint);
|
||||
return mountPoint;
|
||||
}
|
||||
}
|
||||
|
||||
private String setupMountPoint(String parent) {
|
||||
String mountPoint = null;
|
||||
long mshostId = _clusterMgr.getManagementNodeId();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
String mntPt = parent + File.separator + String.valueOf(mshostId) + "." + Integer.toHexString(_rand.nextInt(Integer.MAX_VALUE));
|
||||
File file = new File(mntPt);
|
||||
if (!file.exists()) {
|
||||
if (_storage.mkdir(mntPt)) {
|
||||
mountPoint = mntPt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
s_logger.error("Unable to create mount: " + mntPt);
|
||||
}
|
||||
|
||||
return mountPoint;
|
||||
}
|
||||
|
||||
private void startupCleanup(String parent) {
|
||||
s_logger.info("Cleanup mounted NFS mount points used in previous session");
|
||||
|
||||
long mshostId = _clusterMgr.getManagementNodeId();
|
||||
|
||||
// cleanup left-over NFS mounts from previous session
|
||||
String[] mounts = _storage.listFiles(parent + File.separator + String.valueOf(mshostId) + ".*");
|
||||
if(mounts != null && mounts.length > 0) {
|
||||
for(String mountPoint : mounts) {
|
||||
s_logger.info("umount NFS mount from previous session: " + mountPoint);
|
||||
|
||||
String result = null;
|
||||
Script command = new Script(true, "umount", _timeout, s_logger);
|
||||
command.add(mountPoint);
|
||||
result = command.execute();
|
||||
if (result != null) {
|
||||
s_logger.warn("Unable to umount " + mountPoint + " due to " + result);
|
||||
}
|
||||
File file = new File(mountPoint);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void shutdownCleanup() {
|
||||
s_logger.info("Cleanup mounted NFS mount points used in current session");
|
||||
|
||||
for(String mountPoint : _storageMounts.values()) {
|
||||
s_logger.info("umount NFS mount: " + mountPoint);
|
||||
|
||||
String result = null;
|
||||
Script command = new Script(true, "umount", _timeout, s_logger);
|
||||
command.add(mountPoint);
|
||||
result = command.execute();
|
||||
if (result != null) {
|
||||
s_logger.warn("Unable to umount " + mountPoint + " due to " + result);
|
||||
}
|
||||
File file = new File(mountPoint);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected String mount(String path, String parent) {
|
||||
String mountPoint = setupMountPoint(parent);
|
||||
if (mountPoint == null) {
|
||||
s_logger.warn("Unable to create a mount point");
|
||||
return null;
|
||||
}
|
||||
|
||||
Script script = null;
|
||||
String result = null;
|
||||
Script command = new Script(true, "mount", _timeout, s_logger);
|
||||
command.add("-t", "nfs");
|
||||
// command.add("-o", "soft,timeo=133,retrans=2147483647,tcp,acdirmax=0,acdirmin=0");
|
||||
command.add(path);
|
||||
command.add(mountPoint);
|
||||
result = command.execute();
|
||||
if (result != null) {
|
||||
s_logger.warn("Unable to mount " + path + " due to " + result);
|
||||
File file = new File(mountPoint);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Change permissions for the mountpoint
|
||||
script = new Script(true, "chmod", _timeout, s_logger);
|
||||
script.add("777", mountPoint);
|
||||
result = script.execute();
|
||||
if (result != null) {
|
||||
s_logger.warn("Unable to set permissions for " + mountPoint + " due to " + result);
|
||||
return null;
|
||||
}
|
||||
return mountPoint;
|
||||
}
|
||||
|
||||
@DB
|
||||
private void updateClusterNativeHAState(HostVO host, StartupCommand cmd) {
|
||||
ClusterVO cluster = _clusterDao.findById(host.getClusterId());
|
||||
if(cluster.getClusterType() == ClusterType.ExternalManaged) {
|
||||
if(cmd instanceof StartupRoutingCommand) {
|
||||
StartupRoutingCommand hostStartupCmd = (StartupRoutingCommand)cmd;
|
||||
Map<String, String> details = hostStartupCmd.getHostDetails();
|
||||
|
||||
if(details.get("NativeHA") != null && details.get("NativeHA").equalsIgnoreCase("true")) {
|
||||
_clusterDetailsDao.persist(host.getClusterId(), "NativeHA", "true");
|
||||
} else {
|
||||
_clusterDetailsDao.persist(host.getClusterId(), "NativeHA", "false");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override @DB
|
||||
public boolean processAnswers(long agentId, long seq, Answer[] answers) {
|
||||
if(answers != null) {
|
||||
for(Answer answer : answers) {
|
||||
String execIdStr = answer.getContextParam("execid");
|
||||
if(execIdStr != null) {
|
||||
long execId = 0;
|
||||
try {
|
||||
execId = Long.parseLong(execIdStr);
|
||||
} catch(NumberFormatException e) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
_cmdExecLogDao.expunge(execId);
|
||||
}
|
||||
|
||||
String checkPointIdStr = answer.getContextParam("checkpoint");
|
||||
if(checkPointIdStr != null) {
|
||||
_checkPointMgr.popCheckPoint(Long.parseLong(checkPointIdStr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processCommands(long agentId, long seq, Command[] commands) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentControlAnswer processControlCommand(long agentId, AgentControlCommand cmd) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) {
|
||||
if(cmd instanceof StartupCommand) {
|
||||
if(host.getHypervisorType() == HypervisorType.VMware) {
|
||||
updateClusterNativeHAState(host, cmd);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected final int DEFAULT_DOMR_SSHPORT = 3922;
|
||||
|
||||
protected boolean shutdownRouterVM(DomainRouterVO router) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Try to shutdown router VM " + router.getInstanceName() + " directly.");
|
||||
}
|
||||
|
||||
Pair<Boolean, String> result;
|
||||
try {
|
||||
result = SshHelper.sshExecute(router.getPrivateIpAddress(), DEFAULT_DOMR_SSHPORT, "root", getSystemVMKeyFile(), null,
|
||||
"poweroff -f");
|
||||
|
||||
if (!result.first()) {
|
||||
s_logger.debug("Unable to shutdown " + router.getInstanceName() + " directly");
|
||||
return false;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
s_logger.warn("Unable to shutdown router " + router.getInstanceName() + " directly.");
|
||||
return false;
|
||||
}
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Shutdown router " + router.getInstanceName() + " successful.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processDisconnect(long agentId, Status state) {
|
||||
UserContext context = UserContext.current();
|
||||
context.setAccountId(1);
|
||||
/* Stopped VMware Host's virtual routers */
|
||||
HostVO host = _hostDao.findById(agentId);
|
||||
if (host.getHypervisorType() != HypervisorType.VMware) {
|
||||
return true;
|
||||
}
|
||||
List<DomainRouterVO> routers = _routerDao.listByHostId(agentId);
|
||||
for (DomainRouterVO router : routers) {
|
||||
try {
|
||||
State oldState = router.getState();
|
||||
_routerMgr.stopRouter(router.getId(), true);
|
||||
//In case only vCenter is disconnected, we want to shut down router directly
|
||||
if (oldState == State.Running) {
|
||||
shutdownRouterVM(router);
|
||||
}
|
||||
} catch (ResourceUnavailableException e) {
|
||||
s_logger.warn("Fail to stop router " + router.getInstanceName() + " when host disconnected!", e);
|
||||
} catch (ConcurrentOperationException e) {
|
||||
s_logger.warn("Fail to stop router " + router.getInstanceName() + " when host disconnected!", e);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRecurring() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTimeout() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processTimeout(long agentId, long seq) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean beginExclusiveOperation(int timeOutSeconds) {
|
||||
return _exclusiveOpLock.lock(timeOutSeconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endExclusiveOperation() {
|
||||
_exclusiveOpLock.unlock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<Integer, Integer> getAddiionalVncPortRange() {
|
||||
return new Pair<Integer, Integer>(_additionalPortRangeStart, _additionalPortRangeSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualEthernetCardType getGuestNicDeviceType() {
|
||||
return this._guestNicDeviceType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxHostsPerCluster() {
|
||||
return this._maxHostsPerCluster;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,250 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.alert.AlertManager;
|
||||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
import com.cloud.dc.ClusterDetailsDao;
|
||||
import com.cloud.dc.ClusterVO;
|
||||
import com.cloud.dc.dao.ClusterDao;
|
||||
import com.cloud.exception.DiscoveredWithErrorException;
|
||||
import com.cloud.exception.DiscoveryException;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareManager;
|
||||
import com.cloud.hypervisor.vmware.mo.ClusterMO;
|
||||
import com.cloud.hypervisor.vmware.mo.HostMO;
|
||||
import com.cloud.hypervisor.vmware.resource.VmwareContextFactory;
|
||||
import com.cloud.hypervisor.vmware.resource.VmwareResource;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.cloud.resource.Discoverer;
|
||||
import com.cloud.resource.DiscovererBase;
|
||||
import com.cloud.resource.ServerResource;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.Storage.TemplateType;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.UriUtils;
|
||||
import com.cloud.utils.component.ComponentLocator;
|
||||
import com.cloud.utils.component.Inject;
|
||||
import com.vmware.vim25.ClusterDasConfigInfo;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
|
||||
@Local(value=Discoverer.class)
|
||||
public class VmwareServerDiscoverer extends DiscovererBase implements Discoverer {
|
||||
private static final Logger s_logger = Logger.getLogger(VmwareServerDiscoverer.class);
|
||||
|
||||
@Inject ClusterDao _clusterDao;
|
||||
@Inject VmwareManager _vmwareMgr;
|
||||
@Inject AlertManager _alertMgr;
|
||||
@Inject VMTemplateDao _tmpltDao;
|
||||
@Inject ClusterDetailsDao _clusterDetailsDao;
|
||||
@Inject HostDao _hostDao;
|
||||
|
||||
@Override
|
||||
public Map<? extends ServerResource, Map<String, String>> find(long dcId, Long podId, Long clusterId, URI url,
|
||||
String username, String password, List<String> hostTags) throws DiscoveryException {
|
||||
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("Discover host. dc: " + dcId + ", pod: " + podId + ", cluster: " + clusterId + ", uri host: " + url.getHost());
|
||||
|
||||
if(podId == null) {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("No pod is assigned, assuming that it is not for vmware and skip it to next discoverer");
|
||||
return null;
|
||||
}
|
||||
|
||||
ClusterVO cluster = _clusterDao.findById(clusterId);
|
||||
if(cluster == null || cluster.getHypervisorType() != HypervisorType.VMware) {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("invalid cluster id or cluster is not for VMware hypervisors");
|
||||
return null;
|
||||
}
|
||||
|
||||
List<HostVO> hosts = _hostDao.listByCluster(clusterId);
|
||||
if(hosts.size() >= _vmwareMgr.getMaxHostsPerCluster()) {
|
||||
String msg = "VMware cluster " + cluster.getName() + " is too big to add new host now. (current configured cluster size: " + _vmwareMgr.getMaxHostsPerCluster() + ")";
|
||||
s_logger.error(msg);
|
||||
throw new DiscoveredWithErrorException(msg);
|
||||
}
|
||||
|
||||
VmwareContext context = null;
|
||||
try {
|
||||
context = VmwareContextFactory.create(url.getHost(), username, password);
|
||||
List<ManagedObjectReference> morHosts = _vmwareMgr.addHostToPodCluster(context, dcId, podId, clusterId,
|
||||
URLDecoder.decode(url.getPath()));
|
||||
if(morHosts == null) {
|
||||
s_logger.error("Unable to find host or cluster based on url: " + URLDecoder.decode(url.getPath()));
|
||||
return null;
|
||||
}
|
||||
|
||||
ManagedObjectReference morCluster = null;
|
||||
Map<String, String> clusterDetails = _clusterDetailsDao.findDetails(clusterId);
|
||||
if(clusterDetails.get("url") != null) {
|
||||
URI uriFromCluster = new URI(UriUtils.encodeURIComponent(clusterDetails.get("url")));
|
||||
morCluster = context.getHostMorByPath(URLDecoder.decode(uriFromCluster.getPath()));
|
||||
|
||||
if(morCluster == null || !morCluster.getType().equalsIgnoreCase("ClusterComputeResource")) {
|
||||
s_logger.warn("Cluster url does not point to a valid vSphere cluster, url: " + clusterDetails.get("url"));
|
||||
return null;
|
||||
} else {
|
||||
ClusterMO clusterMo = new ClusterMO(context, morCluster);
|
||||
ClusterDasConfigInfo dasConfig = clusterMo.getDasConfig();
|
||||
if(dasConfig != null && dasConfig.getEnabled() != null && dasConfig.getEnabled().booleanValue()) {
|
||||
clusterDetails.put("NativeHA", "true");
|
||||
_clusterDetailsDao.persist(clusterId, clusterDetails);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!validateDiscoveredHosts(context, morCluster, morHosts)) {
|
||||
if(morCluster == null)
|
||||
s_logger.warn("The discovered host is not standalone host, can not be added to a standalone cluster");
|
||||
else
|
||||
s_logger.warn("The discovered host does not belong to the cluster");
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<VmwareResource, Map<String, String>> resources = new HashMap<VmwareResource, Map<String, String>>();
|
||||
for(ManagedObjectReference morHost : morHosts) {
|
||||
Map<String, String> details = new HashMap<String, String>();
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
|
||||
HostMO hostMo = new HostMO(context, morHost);
|
||||
details.put("url", hostMo.getHostName());
|
||||
details.put("username", username);
|
||||
details.put("password", password);
|
||||
String guid = morHost.getType() + ":" + morHost.get_value() + "@"+ url.getHost();
|
||||
details.put("guid", guid);
|
||||
|
||||
params.put("url", hostMo.getHostName());
|
||||
params.put("username", username);
|
||||
params.put("password", password);
|
||||
params.put("zone", Long.toString(dcId));
|
||||
params.put("pod", Long.toString(podId));
|
||||
params.put("cluster", Long.toString(clusterId));
|
||||
params.put("guid", guid);
|
||||
|
||||
VmwareResource resource = new VmwareResource();
|
||||
try {
|
||||
resource.configure("VMware", params);
|
||||
} catch (ConfigurationException e) {
|
||||
_alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, dcId, podId, "Unable to add " + url.getHost(), "Error is " + e.getMessage());
|
||||
s_logger.warn("Unable to instantiate " + url.getHost(), e);
|
||||
}
|
||||
resource.start();
|
||||
|
||||
resources.put(resource, details);
|
||||
}
|
||||
|
||||
// place a place holder guid derived from cluster ID
|
||||
cluster.setGuid(UUID.nameUUIDFromBytes(String.valueOf(clusterId).getBytes()).toString());
|
||||
_clusterDao.update(clusterId, cluster);
|
||||
|
||||
return resources;
|
||||
} catch (DiscoveredWithErrorException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
s_logger.warn("Unable to connect to Vmware vSphere server. service address: " + url.getHost());
|
||||
return null;
|
||||
} finally {
|
||||
if(context != null)
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean validateDiscoveredHosts(VmwareContext context, ManagedObjectReference morCluster, List<ManagedObjectReference> morHosts) throws Exception {
|
||||
if(morCluster == null) {
|
||||
for(ManagedObjectReference morHost : morHosts) {
|
||||
ManagedObjectReference morParent = (ManagedObjectReference)context.getServiceUtil().getDynamicProperty(morHost, "parent");
|
||||
if(morParent.getType().equalsIgnoreCase("ClusterComputeResource"))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
for(ManagedObjectReference morHost : morHosts) {
|
||||
ManagedObjectReference morParent = (ManagedObjectReference)context.getServiceUtil().getDynamicProperty(morHost, "parent");
|
||||
if(!morParent.getType().equalsIgnoreCase("ClusterComputeResource"))
|
||||
return false;
|
||||
|
||||
if(!morParent.get_value().equals(morCluster.get_value()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDiscovery(List<HostVO> hosts, long msId) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchHypervisor(String hypervisor) {
|
||||
if(hypervisor == null)
|
||||
return true;
|
||||
|
||||
return Hypervisor.HypervisorType.VMware.toString().equalsIgnoreCase(hypervisor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hypervisor.HypervisorType getHypervisorType() {
|
||||
return Hypervisor.HypervisorType.VMware;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("Configure VmwareServerDiscoverer, discover name: " + name);
|
||||
|
||||
super.configure(name, params);
|
||||
|
||||
ComponentLocator locator = ComponentLocator.getCurrentLocator();
|
||||
ConfigurationDao configDao = locator.getDao(ConfigurationDao.class);
|
||||
if (configDao == null) {
|
||||
throw new ConfigurationException("Unable to get the configuration dao.");
|
||||
}
|
||||
|
||||
createVmwareToolsIso();
|
||||
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("VmwareServerDiscoverer has been successfully configured");
|
||||
return true;
|
||||
}
|
||||
|
||||
private void createVmwareToolsIso() {
|
||||
String isoName = "vmware-tools.iso";
|
||||
VMTemplateVO tmplt = _tmpltDao.findByTemplateName(isoName);
|
||||
Long id;
|
||||
if (tmplt == null) {
|
||||
id = _tmpltDao.getNextInSequence(Long.class, "id");
|
||||
VMTemplateVO template = new VMTemplateVO(id, isoName, isoName, ImageFormat.ISO, true, true,
|
||||
TemplateType.PERHOST, null, null, true, 64,
|
||||
Account.ACCOUNT_ID_SYSTEM, null, "VMware Tools Installer ISO", false, 1, false, HypervisorType.VMware);
|
||||
_tmpltDao.persist(template);
|
||||
} else {
|
||||
id = tmplt.getId();
|
||||
tmplt.setTemplateType(TemplateType.PERHOST);
|
||||
tmplt.setUrl(null);
|
||||
_tmpltDao.update(id, tmplt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.secstorage;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface CommandExecLogDao extends GenericDao<CommandExecLogVO, Long> {
|
||||
public void expungeExpiredRecords(Date cutTime);
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.secstorage;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.ejb.Local;
|
||||
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.SearchCriteria.Op;
|
||||
|
||||
@Local(value={CommandExecLogDao.class})
|
||||
public class CommandExecLogDaoImpl extends GenericDaoBase<CommandExecLogVO, Long> implements CommandExecLogDao {
|
||||
|
||||
protected final SearchBuilder<CommandExecLogVO> ExpungeSearch;
|
||||
|
||||
public CommandExecLogDaoImpl() {
|
||||
ExpungeSearch = createSearchBuilder();
|
||||
ExpungeSearch.and("created", ExpungeSearch.entity().getCreated(), Op.LT);
|
||||
ExpungeSearch.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expungeExpiredRecords(Date cutTime) {
|
||||
SearchCriteria<CommandExecLogVO> sc = ExpungeSearch.create();
|
||||
sc.setParameters("created", cutTime);
|
||||
expunge(sc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.secstorage;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import com.cloud.utils.DateUtil;
|
||||
|
||||
@Entity
|
||||
@Table(name="cmd_exec_log")
|
||||
public class CommandExecLogVO {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy=GenerationType.IDENTITY)
|
||||
@Column(name="id")
|
||||
private long id;
|
||||
|
||||
@Column(name="host_id")
|
||||
private long hostId;
|
||||
|
||||
@Column(name="instance_id")
|
||||
private long instanceId;
|
||||
|
||||
@Column(name="command_name")
|
||||
private String commandName;
|
||||
|
||||
@Column(name="weight")
|
||||
private int weight;
|
||||
|
||||
@Column(name="created")
|
||||
@Temporal(value=TemporalType.TIMESTAMP)
|
||||
private Date created;
|
||||
|
||||
public CommandExecLogVO() {
|
||||
}
|
||||
|
||||
public CommandExecLogVO(long hostId, long instanceId, String commandName, int weight) {
|
||||
this.hostId = hostId;
|
||||
this.instanceId = instanceId;
|
||||
this.commandName = commandName;
|
||||
this.weight = weight;
|
||||
this.created = DateUtil.currentGMTTime();
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public long getHostId() {
|
||||
return this.hostId;
|
||||
}
|
||||
|
||||
public void setHostId(long hostId) {
|
||||
this.hostId = hostId;
|
||||
}
|
||||
|
||||
public long getInstanceId() {
|
||||
return this.instanceId;
|
||||
}
|
||||
|
||||
public void setInstanceId(long instanceId) {
|
||||
this.instanceId = instanceId;
|
||||
}
|
||||
|
||||
public String getCommandName() {
|
||||
return this.commandName;
|
||||
}
|
||||
|
||||
public void setCommandName(String commandName) {
|
||||
this.commandName = commandName;
|
||||
}
|
||||
|
||||
public int getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
public void setWeight(int weight) {
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
public Date getCreated() {
|
||||
return this.created;
|
||||
}
|
||||
|
||||
public void setCreated(Date created) {
|
||||
this.created = created;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.secstorage;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.Status;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.storage.secondary.SecondaryStorageManagerImpl;
|
||||
import com.cloud.storage.secondary.SecondaryStorageVmManager;
|
||||
import com.cloud.utils.DateUtil;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.Inject;
|
||||
import com.cloud.utils.db.JoinBuilder.JoinType;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.SearchCriteria.Op;
|
||||
import com.cloud.vm.SecondaryStorageVm;
|
||||
import com.cloud.vm.SecondaryStorageVmVO;
|
||||
import com.cloud.vm.SystemVmLoadScanner.AfterScanAction;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
import com.cloud.vm.dao.SecondaryStorageVmDao;
|
||||
|
||||
@Local(value = { SecondaryStorageVmManager.class })
|
||||
public class PremiumSecondaryStorageManagerImpl extends SecondaryStorageManagerImpl {
|
||||
private static final Logger s_logger = Logger.getLogger(PremiumSecondaryStorageManagerImpl.class);
|
||||
|
||||
private int _capacityPerSSVM = SecondaryStorageVmManager.DEFAULT_SS_VM_CAPACITY;
|
||||
private int _standbyCapacity = SecondaryStorageVmManager.DEFAULT_STANDBY_CAPACITY;
|
||||
private int _maxExecutionTimeMs = 1800000;
|
||||
|
||||
@Inject SecondaryStorageVmDao _secStorageVmDao;
|
||||
@Inject CommandExecLogDao _cmdExecLogDao;
|
||||
@Inject HostDao _hostDao;
|
||||
protected SearchBuilder<CommandExecLogVO> ActiveCommandSearch;
|
||||
protected SearchBuilder<HostVO> HostSearch;
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
super.configure(name, params);
|
||||
|
||||
_capacityPerSSVM = NumbersUtil.parseInt(_configDao.getValue(Config.SecStorageSessionMax.key()), DEFAULT_SS_VM_CAPACITY);
|
||||
_standbyCapacity = NumbersUtil.parseInt(_configDao.getValue(Config.SecStorageCapacityStandby.key()), DEFAULT_STANDBY_CAPACITY);
|
||||
|
||||
int nMaxExecutionMinutes = NumbersUtil.parseInt(_configDao.getValue(Config.SecStorageCmdExecutionTimeMax.key()), 30);
|
||||
_maxExecutionTimeMs = nMaxExecutionMinutes*60*1000;
|
||||
|
||||
HostSearch = _hostDao.createSearchBuilder();
|
||||
HostSearch.and("dc", HostSearch.entity().getDataCenterId(), Op.EQ);
|
||||
HostSearch.and("status", HostSearch.entity().getStatus(), Op.EQ);
|
||||
|
||||
ActiveCommandSearch = _cmdExecLogDao.createSearchBuilder();
|
||||
ActiveCommandSearch.and("created", ActiveCommandSearch.entity().getCreated(), Op.GTEQ);
|
||||
ActiveCommandSearch.join("hostSearch", HostSearch, ActiveCommandSearch.entity().getInstanceId(), HostSearch.entity().getId(), JoinType.INNER);
|
||||
|
||||
HostSearch.done();
|
||||
ActiveCommandSearch.done();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<AfterScanAction, Object> scanPool(Long pool) {
|
||||
long dataCenterId = pool.longValue();
|
||||
Date cutTime = new Date(DateUtil.currentGMTTime().getTime() - _maxExecutionTimeMs);
|
||||
|
||||
_cmdExecLogDao.expungeExpiredRecords(cutTime);
|
||||
|
||||
boolean suspendAutoLoading = !reserveStandbyCapacity();
|
||||
if(!suspendAutoLoading) {
|
||||
// this is a hacking, has nothing to do with console proxy, it is just a flag that primary storage is being under maintenance mode
|
||||
String restart = _configDao.getValue("consoleproxy.restart");
|
||||
if (restart != null && restart.equalsIgnoreCase("false")) {
|
||||
s_logger.debug("Capacity scan disabled purposefully, consoleproxy.restart = false. This happens when the primarystorage is in maintenance mode");
|
||||
suspendAutoLoading = true;
|
||||
}
|
||||
}
|
||||
|
||||
List<SecondaryStorageVmVO> alreadyRunning = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, dataCenterId, State.Running,
|
||||
State.Migrating, State.Starting);
|
||||
if (alreadyRunning.size() == 0) {
|
||||
s_logger.info("No running secondary storage vms found in datacenter id=" + dataCenterId + ", starting one");
|
||||
|
||||
List<SecondaryStorageVmVO> stopped = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, dataCenterId, State.Stopped,
|
||||
State.Stopping);
|
||||
if(stopped.size() == 0 || !suspendAutoLoading) {
|
||||
List<SecondaryStorageVmVO> stopping = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, State.Stopping);
|
||||
if(stopping.size() > 0) {
|
||||
s_logger.info("Found SSVMs that are currently at stopping state, wait until they are settled");
|
||||
return new Pair<AfterScanAction, Object>(AfterScanAction.nop, null);
|
||||
}
|
||||
|
||||
expandPool(pool, SecondaryStorageVm.Role.templateProcessor);
|
||||
}
|
||||
}
|
||||
|
||||
if(!suspendAutoLoading) {
|
||||
// this is to avoid surprises that people may accidently see two SSVMs being launched, capacity expanding only happens when we have at least the primary SSVM is up
|
||||
if(alreadyRunning.size() == 0) {
|
||||
s_logger.info("Primary secondary storage is not even started, wait until next turn");
|
||||
return new Pair<AfterScanAction, Object>(AfterScanAction.nop, null);
|
||||
}
|
||||
|
||||
alreadyRunning = _secStorageVmDao.getSecStorageVmListInStates(null, dataCenterId, State.Running,
|
||||
State.Migrating, State.Starting);
|
||||
|
||||
List<CommandExecLogVO> activeCmds = listActiveCommands(dataCenterId, cutTime);
|
||||
if(alreadyRunning.size()*_capacityPerSSVM - activeCmds.size() < _standbyCapacity) {
|
||||
s_logger.info("secondary storage command execution standby capactiy low (running VMs: " + alreadyRunning.size() + ", active cmds: " + activeCmds.size() + "), starting a new one");
|
||||
return new Pair<AfterScanAction, Object>(AfterScanAction.expand, SecondaryStorageVm.Role.commandExecutor);
|
||||
}
|
||||
}
|
||||
|
||||
return new Pair<AfterScanAction, Object>(AfterScanAction.nop, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<HostVO, SecondaryStorageVmVO> assignSecStorageVm(long zoneId, Command cmd) {
|
||||
|
||||
// TODO, need performance optimization
|
||||
List<Long> vms = _secStorageVmDao.listRunningSecStorageOrderByLoad(null, zoneId);
|
||||
for(Long vmId : vms) {
|
||||
SecondaryStorageVmVO secStorageVm = _secStorageVmDao.findById(vmId);
|
||||
HostVO host;
|
||||
host = _hostDao.findByName(secStorageVm.getHostName());
|
||||
if(host != null && host.getStatus() == Status.Up)
|
||||
return new Pair<HostVO, SecondaryStorageVmVO>(host, secStorageVm);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<CommandExecLogVO> listActiveCommands(long dcId, Date cutTime) {
|
||||
SearchCriteria<CommandExecLogVO> sc = ActiveCommandSearch.create();
|
||||
|
||||
sc.setParameters("created", cutTime);
|
||||
sc.setJoinParameters("hostSearch", "dc", dcId);
|
||||
sc.setJoinParameters("hostSearch", "status", Status.Up);
|
||||
|
||||
return _cmdExecLogDao.search(sc, null);
|
||||
}
|
||||
|
||||
private boolean reserveStandbyCapacity() {
|
||||
String value = _configDao.getValue(Config.SystemVMAutoReserveCapacity.key());
|
||||
if(value != null && value.equalsIgnoreCase("true")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/deps"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/utils"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>vmware-base</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.vmware.vim25.CustomFieldDef;
|
||||
import com.vmware.vim25.CustomFieldStringValue;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
|
||||
public class BaseMO {
|
||||
private static final Logger s_logger = Logger.getLogger(BaseMO.class);
|
||||
|
||||
protected VmwareContext _context;
|
||||
protected ManagedObjectReference _mor;
|
||||
|
||||
// cached name for the vCenter managed entity object
|
||||
private String _name;
|
||||
|
||||
public BaseMO(VmwareContext context, ManagedObjectReference mor) {
|
||||
assert(context != null);
|
||||
|
||||
_context = context;
|
||||
_mor = mor;
|
||||
}
|
||||
|
||||
public BaseMO(VmwareContext context, String morType, String morValue) {
|
||||
assert(context != null);
|
||||
assert(morType != null);
|
||||
assert(morValue != null);
|
||||
|
||||
_context = context;
|
||||
_mor = new ManagedObjectReference();
|
||||
_mor.setType(morType);
|
||||
_mor.set_value(morValue);
|
||||
}
|
||||
|
||||
public VmwareContext getContext() {
|
||||
return _context;
|
||||
}
|
||||
|
||||
public ManagedObjectReference getMor() {
|
||||
assert(_mor != null);
|
||||
return _mor;
|
||||
}
|
||||
|
||||
public ManagedObjectReference getParentMor() throws Exception {
|
||||
return (ManagedObjectReference)_context.getServiceUtil().getDynamicProperty(_mor, "parent");
|
||||
}
|
||||
|
||||
public String getName() throws Exception {
|
||||
if(_name == null)
|
||||
_name = (String)_context.getServiceUtil().getDynamicProperty(_mor, "name");
|
||||
|
||||
return _name;
|
||||
}
|
||||
|
||||
public boolean destroy() throws Exception {
|
||||
ManagedObjectReference morTask = _context.getService().destroy_Task(_mor);
|
||||
|
||||
String result = _context.getServiceUtil().waitForTask(morTask);
|
||||
if(result.equals("sucess")) {
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
return true;
|
||||
} else {
|
||||
s_logger.error("VMware destroy_Task failed due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void reload() throws Exception {
|
||||
_context.getService().reload(_mor);
|
||||
}
|
||||
|
||||
public boolean rename(String newName) throws Exception {
|
||||
ManagedObjectReference morTask = _context.getService().rename_Task(_mor, newName);
|
||||
|
||||
String result = _context.getServiceUtil().waitForTask(morTask);
|
||||
if(result.equals("sucess")) {
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
return true;
|
||||
} else {
|
||||
s_logger.error("VMware rename_Task failed due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setCustomFieldValue(String fieldName, String value) throws Exception {
|
||||
CustomFieldsManagerMO cfmMo = new CustomFieldsManagerMO(_context,
|
||||
_context.getServiceContent().getCustomFieldsManager());
|
||||
|
||||
int key = getCustomFieldKey(fieldName);
|
||||
if(key == 0) {
|
||||
try {
|
||||
CustomFieldDef field = cfmMo.addCustomerFieldDef(fieldName, getMor().getType(), null, null);
|
||||
key = field.getKey();
|
||||
} catch (Exception e) {
|
||||
// assuming the exception is caused by concurrent operation from other places
|
||||
// so we retieve the key again
|
||||
key = getCustomFieldKey(fieldName);
|
||||
}
|
||||
}
|
||||
|
||||
if(key == 0)
|
||||
throw new Exception("Unable to setup custom field facility");
|
||||
|
||||
cfmMo.setField(getMor(), key, value);
|
||||
}
|
||||
|
||||
public String getCustomFieldValue(String fieldName) throws Exception {
|
||||
int key = getCustomFieldKey(fieldName);
|
||||
if(key == 0)
|
||||
return null;
|
||||
|
||||
CustomFieldStringValue cfValue = (CustomFieldStringValue)_context.getServiceUtil().getDynamicProperty(getMor(),
|
||||
String.format("value[%d]", key));
|
||||
if(cfValue != null)
|
||||
return cfValue.getValue();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getCustomFieldKey(String fieldName) throws Exception {
|
||||
return getCustomFieldKey(getMor().getType(), fieldName);
|
||||
}
|
||||
|
||||
public int getCustomFieldKey(String morType, String fieldName) throws Exception {
|
||||
assert(morType != null);
|
||||
|
||||
CustomFieldsManagerMO cfmMo = new CustomFieldsManagerMO(_context,
|
||||
_context.getServiceContent().getCustomFieldsManager());
|
||||
|
||||
return cfmMo.getCustomFieldKey(morType, fieldName);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,566 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.google.gson.Gson;
|
||||
import com.vmware.apputils.vim25.ServiceUtil;
|
||||
import com.vmware.vim25.ArrayOfHostIpRouteEntry;
|
||||
import com.vmware.vim25.ClusterComputeResourceSummary;
|
||||
import com.vmware.vim25.ClusterConfigInfoEx;
|
||||
import com.vmware.vim25.ClusterDasConfigInfo;
|
||||
import com.vmware.vim25.ClusterHostRecommendation;
|
||||
import com.vmware.vim25.ComputeResourceSummary;
|
||||
import com.vmware.vim25.CustomFieldStringValue;
|
||||
import com.vmware.vim25.DatastoreInfo;
|
||||
import com.vmware.vim25.DynamicProperty;
|
||||
import com.vmware.vim25.HostHardwareSummary;
|
||||
import com.vmware.vim25.HostIpRouteEntry;
|
||||
import com.vmware.vim25.HostRuntimeInfo;
|
||||
import com.vmware.vim25.HostSystemConnectionState;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.NasDatastoreInfo;
|
||||
import com.vmware.vim25.ObjectContent;
|
||||
import com.vmware.vim25.ObjectSpec;
|
||||
import com.vmware.vim25.OptionValue;
|
||||
import com.vmware.vim25.PropertyFilterSpec;
|
||||
import com.vmware.vim25.PropertySpec;
|
||||
import com.vmware.vim25.SelectionSpec;
|
||||
import com.vmware.vim25.TraversalSpec;
|
||||
import com.vmware.vim25.VirtualMachineConfigSpec;
|
||||
|
||||
//
|
||||
// TODO : ClusterMO was designed to be able to work as a special host before, therefore it implements VmwareHypervisorHost
|
||||
// interface. This has changed as ClusterMO no longer works as a special host anymore. Need to refactor accordingly
|
||||
//
|
||||
public class ClusterMO extends BaseMO implements VmwareHypervisorHost {
|
||||
private static final Logger s_logger = Logger.getLogger(ClusterMO.class);
|
||||
|
||||
public ClusterMO(VmwareContext context, ManagedObjectReference morCluster) {
|
||||
super(context, morCluster);
|
||||
}
|
||||
|
||||
public ClusterMO(VmwareContext context, String morType, String morValue) {
|
||||
super(context, morType, morValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHyperHostName() throws Exception {
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClusterDasConfigInfo getDasConfig() throws Exception {
|
||||
// Note getDynamicProperty() with "configurationEx.dasConfig" does not work here because of that dasConfig is a property in subclass
|
||||
ClusterConfigInfoEx configInfo = (ClusterConfigInfoEx)_context.getServiceUtil().getDynamicProperty(_mor, "configurationEx");
|
||||
return configInfo.getDasConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedObjectReference getHyperHostDatacenter() throws Exception {
|
||||
Pair<DatacenterMO, String> dcPair = DatacenterMO.getOwnerDatacenter(getContext(), getMor());
|
||||
assert(dcPair != null);
|
||||
return dcPair.first().getMor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedObjectReference getHyperHostOwnerResourcePool() throws Exception {
|
||||
ServiceUtil serviceUtil = _context.getServiceUtil();
|
||||
return (ManagedObjectReference)serviceUtil.getDynamicProperty(getMor(), "resourcePool");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedObjectReference getHyperHostCluster() throws Exception {
|
||||
return _mor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualMachineMO findVmOnHyperHost(String name) throws Exception {
|
||||
ObjectContent[] ocs = getVmPropertiesOnHyperHost(new String[] { "name" });
|
||||
return HypervisorHostHelper.findVmFromObjectContent(_context, ocs, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualMachineMO findVmOnPeerHyperHost(String name) throws Exception {
|
||||
ObjectContent[] ocs = getVmPropertiesOnHyperHost(new String[] { "name" });
|
||||
if(ocs != null && ocs.length > 0) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
DynamicProperty[] props = oc.getPropSet();
|
||||
if(props != null) {
|
||||
for(DynamicProperty prop : props) {
|
||||
if(prop.getVal().toString().equals(name))
|
||||
return new VirtualMachineMO(_context, oc.getObj());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectContent[] getVmPropertiesOnHyperHost(String[] propertyPaths) throws Exception {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - retrieveProperties() for VM properties. target MOR: " + _mor.get_value() + ", properties: " + new Gson().toJson(propertyPaths));
|
||||
|
||||
PropertySpec pSpec = new PropertySpec();
|
||||
pSpec.setType("VirtualMachine");
|
||||
pSpec.setPathSet(propertyPaths);
|
||||
|
||||
TraversalSpec host2VmFolderTraversal = new TraversalSpec();
|
||||
host2VmFolderTraversal.setType("HostSystem");
|
||||
host2VmFolderTraversal.setPath("vm");
|
||||
host2VmFolderTraversal.setName("host2VmFolderTraversal");
|
||||
|
||||
TraversalSpec cluster2HostFolderTraversal = new TraversalSpec();
|
||||
cluster2HostFolderTraversal.setType("ClusterComputeResource");
|
||||
cluster2HostFolderTraversal.setPath("host");
|
||||
cluster2HostFolderTraversal.setName("cluster2HostFolderTraversal");
|
||||
cluster2HostFolderTraversal.setSelectSet(new SelectionSpec[] { host2VmFolderTraversal });
|
||||
|
||||
ObjectSpec oSpec = new ObjectSpec();
|
||||
oSpec.setObj(getMor());
|
||||
oSpec.setSkip(Boolean.TRUE);
|
||||
oSpec.setSelectSet(new SelectionSpec[] { cluster2HostFolderTraversal });
|
||||
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.setPropSet(new PropertySpec[] { pSpec });
|
||||
pfSpec.setObjectSet(new ObjectSpec[] { oSpec });
|
||||
|
||||
ObjectContent[] properties = _context.getService().retrieveProperties(
|
||||
_context.getServiceContent().getPropertyCollector(),
|
||||
new PropertyFilterSpec[] { pfSpec });
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - retrieveProperties() done");
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectContent[] getDatastorePropertiesOnHyperHost(String[] propertyPaths) throws Exception {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - retrieveProperties() on Datastore properties. target MOR: " + _mor.get_value() + ", properties: " + new Gson().toJson(propertyPaths));
|
||||
|
||||
PropertySpec pSpec = new PropertySpec();
|
||||
pSpec.setType("Datastore");
|
||||
pSpec.setPathSet(propertyPaths);
|
||||
|
||||
TraversalSpec cluster2DatastoreTraversal = new TraversalSpec();
|
||||
cluster2DatastoreTraversal.setType("ClusterComputeResource");
|
||||
cluster2DatastoreTraversal.setPath("datastore");
|
||||
cluster2DatastoreTraversal.setName("cluster2DatastoreTraversal");
|
||||
|
||||
ObjectSpec oSpec = new ObjectSpec();
|
||||
oSpec.setObj(_mor);
|
||||
oSpec.setSkip(Boolean.TRUE);
|
||||
oSpec.setSelectSet(new SelectionSpec[] { cluster2DatastoreTraversal });
|
||||
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.setPropSet(new PropertySpec[] { pSpec });
|
||||
pfSpec.setObjectSet(new ObjectSpec[] { oSpec });
|
||||
|
||||
ObjectContent[] properties = _context.getService().retrieveProperties(
|
||||
_context.getServiceContent().getPropertyCollector(),
|
||||
new PropertyFilterSpec[] { pfSpec });
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - retrieveProperties() done");
|
||||
return properties;
|
||||
}
|
||||
|
||||
private ObjectContent[] getHostPropertiesOnCluster(String[] propertyPaths) throws Exception {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - retrieveProperties() on Host properties. target MOR: " + _mor.get_value() + ", properties: " + new Gson().toJson(propertyPaths));
|
||||
|
||||
PropertySpec pSpec = new PropertySpec();
|
||||
pSpec.setType("HostSystem");
|
||||
pSpec.setPathSet(propertyPaths);
|
||||
|
||||
TraversalSpec cluster2HostTraversal = new TraversalSpec();
|
||||
cluster2HostTraversal.setType("ClusterComputeResource");
|
||||
cluster2HostTraversal.setPath("host");
|
||||
cluster2HostTraversal.setName("cluster2HostTraversal");
|
||||
|
||||
ObjectSpec oSpec = new ObjectSpec();
|
||||
oSpec.setObj(_mor);
|
||||
oSpec.setSkip(Boolean.TRUE);
|
||||
oSpec.setSelectSet(new SelectionSpec[] { cluster2HostTraversal });
|
||||
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.setPropSet(new PropertySpec[] { pSpec });
|
||||
pfSpec.setObjectSet(new ObjectSpec[] { oSpec });
|
||||
|
||||
ObjectContent[] properties = _context.getService().retrieveProperties(
|
||||
_context.getServiceContent().getPropertyCollector(),
|
||||
new PropertyFilterSpec[] { pfSpec });
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - retrieveProperties() done");
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createVm(VirtualMachineConfigSpec vmSpec) throws Exception {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - createVM_Task(). target MOR: " + _mor.get_value() + ", VirtualMachineConfigSpec: " + new Gson().toJson(vmSpec));
|
||||
|
||||
assert(vmSpec != null);
|
||||
DatacenterMO dcMo = new DatacenterMO(_context, getHyperHostDatacenter());
|
||||
ManagedObjectReference morPool = getHyperHostOwnerResourcePool();
|
||||
|
||||
ManagedObjectReference morTask = _context.getService().createVM_Task(
|
||||
dcMo.getVmFolder(), vmSpec, morPool, null);
|
||||
String result = _context.getServiceUtil().waitForTask(morTask);
|
||||
|
||||
if(result.equals("sucess")) {
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - createVM_Task() done(successfully)");
|
||||
return true;
|
||||
} else {
|
||||
s_logger.error("VMware createVM_Task failed due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
}
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - createVM_Task() done(failed)");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void importVmFromOVF(String ovfFilePath, String vmName, DatastoreMO dsMo, String diskOption) throws Exception {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - importVmFromOVF(). target MOR: " + _mor.get_value() + ", ovfFilePath: " + ovfFilePath + ", vmName: " + vmName
|
||||
+ ", datastore: " + dsMo.getMor().get_value() + ", diskOption: " + diskOption);
|
||||
|
||||
ManagedObjectReference morRp = getHyperHostOwnerResourcePool();
|
||||
assert(morRp != null);
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - importVmFromOVF(). resource pool: " + morRp.get_value());
|
||||
|
||||
HypervisorHostHelper.importVmFromOVF(this, ovfFilePath, vmName, dsMo, diskOption, morRp, null);
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - importVmFromOVF() done");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createBlankVm(String vmName, int cpuCount, int cpuSpeedMHz, int cpuReservedMHz, boolean limitCpuUse, int memoryMB,
|
||||
String guestOsIdentifier, ManagedObjectReference morDs, boolean snapshotDirToParent) throws Exception {
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - createBlankVm(). target MOR: " + _mor.get_value() + ", vmName: " + vmName + ", cpuCount: " + cpuCount
|
||||
+ ", cpuSpeedMhz: " + cpuSpeedMHz + ", cpuReservedMHz: " + cpuReservedMHz + ", limitCpu: " + limitCpuUse + ", memoryMB: " + memoryMB
|
||||
+ ", guestOS: " + guestOsIdentifier + ", datastore: " + morDs.get_value() + ", snapshotDirToParent: " + snapshotDirToParent);
|
||||
|
||||
boolean result = HypervisorHostHelper.createBlankVm(this, vmName, cpuCount, cpuSpeedMHz, cpuReservedMHz, limitCpuUse,
|
||||
memoryMB, guestOsIdentifier, morDs, snapshotDirToParent);
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - createBlankVm() done");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedObjectReference mountDatastore(boolean vmfsDatastore, String poolHostAddress,
|
||||
int poolHostPort, String poolPath, String poolUuid) throws Exception {
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - mountDatastore(). target MOR: " + _mor.get_value() + ", vmfs: " + vmfsDatastore + ", poolHost: " + poolHostAddress
|
||||
+ ", poolHostPort: " + poolHostPort + ", poolPath: " + poolPath + ", poolUuid: " + poolUuid);
|
||||
|
||||
ManagedObjectReference morDs = null;
|
||||
ManagedObjectReference morDsFirst = null;
|
||||
ManagedObjectReference[] hosts = (ManagedObjectReference[])_context.getServiceUtil().getDynamicProperty(_mor, "host");
|
||||
if(hosts != null && hosts.length > 0) {
|
||||
for(ManagedObjectReference morHost : hosts) {
|
||||
HostMO hostMo = new HostMO(_context, morHost);
|
||||
morDs = hostMo.mountDatastore(vmfsDatastore, poolHostAddress, poolHostPort, poolPath, poolUuid);
|
||||
if(morDsFirst == null)
|
||||
morDsFirst = morDs;
|
||||
|
||||
// assume datastore is in scope of datacenter
|
||||
assert(morDsFirst.get_value().equals(morDs.get_value()));
|
||||
}
|
||||
}
|
||||
|
||||
if(morDs == null) {
|
||||
String msg = "Failed to mount datastore in all hosts within the cluster";
|
||||
s_logger.error(msg);
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - mountDatastore() done(failed)");
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - mountDatastore() done(successfully)");
|
||||
|
||||
return morDs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unmountDatastore(String poolUuid) throws Exception {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - unmountDatastore(). target MOR: " + _mor.get_value() + ", poolUuid: " + poolUuid);
|
||||
|
||||
ManagedObjectReference[] hosts = (ManagedObjectReference[])_context.getServiceUtil().getDynamicProperty(_mor, "host");
|
||||
if(hosts != null && hosts.length > 0) {
|
||||
for(ManagedObjectReference morHost : hosts) {
|
||||
HostMO hostMo = new HostMO(_context, morHost);
|
||||
hostMo.unmountDatastore(poolUuid);
|
||||
}
|
||||
}
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - unmountDatastore() done");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedObjectReference findDatastore(String poolUuid) throws Exception {
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - findDatastore(). target MOR: " + _mor.get_value() + ", poolUuid: " + poolUuid);
|
||||
|
||||
CustomFieldsManagerMO cfmMo = new CustomFieldsManagerMO(_context,
|
||||
_context.getServiceContent().getCustomFieldsManager());
|
||||
int key = cfmMo.getCustomFieldKey("Datastore", CustomFieldConstants.CLOUD_UUID);
|
||||
assert(key != 0);
|
||||
|
||||
ObjectContent[] ocs = getDatastorePropertiesOnHyperHost(new String[] {"name", String.format("value[%d]", key)});
|
||||
if(ocs != null) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
if(oc.getPropSet(0).getVal().equals(poolUuid))
|
||||
return oc.getObj();
|
||||
|
||||
if(oc.getPropSet().length > 1) {
|
||||
DynamicProperty prop = oc.getPropSet(1);
|
||||
if(prop != null && prop.getVal() != null) {
|
||||
if(prop.getVal() instanceof CustomFieldStringValue) {
|
||||
String val = ((CustomFieldStringValue)prop.getVal()).getValue();
|
||||
if(val.equalsIgnoreCase(poolUuid)) {
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - findDatastore() done(successfully)");
|
||||
return oc.getObj();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - findDatastore() done(failed)");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedObjectReference findDatastoreByExportPath(String exportPath) throws Exception {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - findDatastoreByExportPath(). target MOR: " + _mor.get_value() + ", exportPath: " + exportPath);
|
||||
|
||||
ObjectContent[] ocs = getDatastorePropertiesOnHyperHost(new String[] {"info"});
|
||||
if(ocs != null && ocs.length > 0) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
DatastoreInfo dsInfo = (DatastoreInfo)oc.getPropSet(0).getVal();
|
||||
if(dsInfo != null && dsInfo instanceof NasDatastoreInfo) {
|
||||
NasDatastoreInfo info = (NasDatastoreInfo)dsInfo;
|
||||
if(info != null) {
|
||||
String vmwareUrl = info.getUrl();
|
||||
if(vmwareUrl.charAt(vmwareUrl.length() - 1) == '/')
|
||||
vmwareUrl = vmwareUrl.substring(0, vmwareUrl.length() - 1);
|
||||
|
||||
URI uri = new URI(vmwareUrl);
|
||||
if(uri.getPath().equals("/" + exportPath)) {
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - findDatastoreByExportPath() done(successfully)");
|
||||
return oc.getObj();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - findDatastoreByExportPath() done(failed)");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedObjectReference findMigrationTarget(VirtualMachineMO vmMo) throws Exception {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - findMigrationTarget(). target MOR: " + _mor.get_value() + ", vm: " + vmMo.getName());
|
||||
|
||||
ClusterHostRecommendation[] candidates = recommendHostsForVm(vmMo);
|
||||
if(candidates != null && candidates.length > 0) {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - findMigrationTarget() done(successfully)");
|
||||
return candidates[0].getHost();
|
||||
}
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - findMigrationTarget() done(failed)");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHyperHostConnected() throws Exception {
|
||||
ObjectContent[] ocs = getHostPropertiesOnCluster(new String[] {"runtime"});
|
||||
if(ocs != null && ocs.length > 0) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
HostRuntimeInfo runtimeInfo = (HostRuntimeInfo)oc.getPropSet(0).getVal();
|
||||
// as long as we have one host connected, we assume the cluster is up
|
||||
if(runtimeInfo.getConnectionState() == HostSystemConnectionState.connected)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHyperHostDefaultGateway() throws Exception {
|
||||
ObjectContent[] ocs = getHostPropertiesOnCluster(new String[] {"config.network.routeTableInfo.ipRoute"});
|
||||
if(ocs != null && ocs.length > 0) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
ArrayOfHostIpRouteEntry entries = (ArrayOfHostIpRouteEntry)oc.getPropSet(0).getVal();
|
||||
if(entries != null) {
|
||||
for(HostIpRouteEntry entry : entries.getHostIpRouteEntry()) {
|
||||
if(entry.getNetwork().equalsIgnoreCase("0.0.0.0"))
|
||||
return entry.getGateway();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception("Could not find host default gateway, host is not properly configured?");
|
||||
}
|
||||
|
||||
@Override
|
||||
public VmwareHypervisorHostResourceSummary getHyperHostResourceSummary() throws Exception {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - getHyperHostResourceSummary(). target MOR: " + _mor.get_value());
|
||||
|
||||
VmwareHypervisorHostResourceSummary summary = new VmwareHypervisorHostResourceSummary();
|
||||
|
||||
ComputeResourceSummary vmwareSummary = (ComputeResourceSummary)_context.getServiceUtil().getDynamicProperty(
|
||||
_mor, "summary");
|
||||
|
||||
// TODO, need to use traversal to optimize retrieve of
|
||||
int cpuNumInCpuThreads = 1;
|
||||
ManagedObjectReference[] hosts = (ManagedObjectReference[])_context.getServiceUtil().getDynamicProperty(_mor, "host");
|
||||
if(hosts != null && hosts.length > 0) {
|
||||
for(ManagedObjectReference morHost : hosts) {
|
||||
HostMO hostMo = new HostMO(_context, morHost);
|
||||
HostHardwareSummary hardwareSummary = hostMo.getHostHardwareSummary();
|
||||
|
||||
if(hardwareSummary.getNumCpuCores()*hardwareSummary.getNumCpuThreads() > cpuNumInCpuThreads)
|
||||
cpuNumInCpuThreads = hardwareSummary.getNumCpuCores()*hardwareSummary.getNumCpuThreads();
|
||||
}
|
||||
}
|
||||
summary.setCpuCount(cpuNumInCpuThreads);
|
||||
summary.setCpuSpeed(vmwareSummary.getTotalCpu());
|
||||
summary.setMemoryBytes(vmwareSummary.getTotalMemory());
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - getHyperHostResourceSummary() done");
|
||||
return summary;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VmwareHypervisorHostNetworkSummary getHyperHostNetworkSummary(String esxServiceConsolePort) throws Exception {
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - getHyperHostNetworkSummary(). target MOR: " + _mor.get_value() + ", mgmtPortgroup: " + esxServiceConsolePort);
|
||||
|
||||
ManagedObjectReference[] hosts = (ManagedObjectReference[])_context.getServiceUtil().getDynamicProperty(_mor, "host");
|
||||
if(hosts != null && hosts.length > 0) {
|
||||
VmwareHypervisorHostNetworkSummary summary = new HostMO(_context, hosts[0]).getHyperHostNetworkSummary(esxServiceConsolePort);
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - getHyperHostResourceSummary() done(successfully)");
|
||||
return summary;
|
||||
}
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - getHyperHostResourceSummary() done(failed)");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComputeResourceSummary getHyperHostHardwareSummary() throws Exception {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - getHyperHostHardwareSummary(). target MOR: " + _mor.get_value());
|
||||
|
||||
ClusterComputeResourceSummary hardwareSummary = (ClusterComputeResourceSummary)
|
||||
_context.getServiceUtil().getDynamicProperty(_mor, "summary");
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - getHyperHostHardwareSummary() done");
|
||||
return hardwareSummary;
|
||||
}
|
||||
|
||||
public ClusterHostRecommendation[] recommendHostsForVm(VirtualMachineMO vmMo) throws Exception {
|
||||
return _context.getService().recommendHostsForVm(_mor, vmMo.getMor(),
|
||||
getHyperHostOwnerResourcePool());
|
||||
}
|
||||
|
||||
public List<Pair<ManagedObjectReference, String>> getClusterHosts() throws Exception {
|
||||
List<Pair<ManagedObjectReference, String>> hosts = new ArrayList<Pair<ManagedObjectReference, String>>();
|
||||
|
||||
ObjectContent[] ocs = getHostPropertiesOnCluster(new String[] {"name"});
|
||||
if(ocs != null) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
ManagedObjectReference morHost = oc.getObj();
|
||||
String name = (String)oc.getPropSet(0).getVal();
|
||||
|
||||
hosts.add(new Pair<ManagedObjectReference, String>(morHost, name));
|
||||
}
|
||||
}
|
||||
return hosts;
|
||||
}
|
||||
|
||||
public HashMap<String, Integer> getVmVncPortsOnCluster() throws Exception {
|
||||
ObjectContent[] ocs = getVmPropertiesOnHyperHost(
|
||||
new String[] { "name", "config.extraConfig[\"RemoteDisplay.vnc.port\"]" }
|
||||
);
|
||||
|
||||
HashMap<String, Integer> portInfo = new HashMap<String, Integer>();
|
||||
if(ocs != null && ocs.length > 0) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
DynamicProperty[] objProps = oc.getPropSet();
|
||||
if(objProps != null) {
|
||||
String name = null;
|
||||
String value = null;
|
||||
for(DynamicProperty objProp : objProps) {
|
||||
if(objProp.getName().equals("name")) {
|
||||
name = (String)objProp.getVal();
|
||||
} else {
|
||||
OptionValue optValue = (OptionValue)objProp.getVal();
|
||||
value = (String)optValue.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
if(name != null && value != null) {
|
||||
portInfo.put(name, Integer.parseInt(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return portInfo;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
public interface CustomFieldConstants {
|
||||
public final static String CLOUD_UUID = "cloud.uuid";
|
||||
public final static String CLOUD_GC = "cloud.gc";
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.vmware.vim25.CustomFieldDef;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.PrivilegePolicyDef;
|
||||
|
||||
public class CustomFieldsManagerMO extends BaseMO {
|
||||
|
||||
public CustomFieldsManagerMO(VmwareContext context, ManagedObjectReference mor) {
|
||||
super(context, mor);
|
||||
}
|
||||
|
||||
public CustomFieldsManagerMO(VmwareContext context, String morType, String morValue) {
|
||||
super(context, morType, morValue);
|
||||
}
|
||||
|
||||
public CustomFieldDef addCustomerFieldDef(String fieldName, String morType,
|
||||
PrivilegePolicyDef fieldDefPolicy, PrivilegePolicyDef fieldPolicy) throws Exception {
|
||||
return _context.getService().addCustomFieldDef(getMor(), fieldName, morType, fieldDefPolicy, fieldPolicy);
|
||||
}
|
||||
|
||||
public void removeCustomFieldDef(int key) throws Exception {
|
||||
_context.getService().removeCustomFieldDef(getMor(), key);
|
||||
}
|
||||
|
||||
public void renameCustomFieldDef(int key, String name) throws Exception {
|
||||
_context.getService().renameCustomFieldDef(getMor(), key, name);
|
||||
}
|
||||
|
||||
public void setField(ManagedObjectReference morEntity, int key, String value) throws Exception {
|
||||
_context.getService().setField(getMor(), morEntity, key, value);
|
||||
}
|
||||
|
||||
public CustomFieldDef[] getFields() throws Exception {
|
||||
return (CustomFieldDef[])_context.getServiceUtil().getDynamicProperty(getMor(), "field");
|
||||
}
|
||||
|
||||
public int getCustomFieldKey(String morType, String fieldName) throws Exception {
|
||||
CustomFieldDef[] fields = getFields();
|
||||
if(fields != null) {
|
||||
for(CustomFieldDef field : fields) {
|
||||
if(field.getName().equals(fieldName) && field.getManagedObjectType().equals(morType))
|
||||
return field.getKey();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int ensureCustomFieldDef(String morType, String fieldName) throws Exception {
|
||||
int key = getCustomFieldKey(morType, fieldName);
|
||||
if(key > 0)
|
||||
return key;
|
||||
|
||||
try {
|
||||
CustomFieldDef field = addCustomerFieldDef(fieldName, morType, null, null);
|
||||
return field.getKey();
|
||||
} catch(Exception e) {
|
||||
// assuming that someone is adding it
|
||||
key = getCustomFieldKey(morType, fieldName);
|
||||
}
|
||||
|
||||
if(key == 0)
|
||||
throw new Exception("Unable to setup custom field facility for " + morType + ":" + fieldName);
|
||||
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,295 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.vmware.apputils.vim25.ServiceUtil;
|
||||
import com.vmware.vim25.CustomFieldStringValue;
|
||||
import com.vmware.vim25.DynamicProperty;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.ObjectContent;
|
||||
import com.vmware.vim25.ObjectSpec;
|
||||
import com.vmware.vim25.PropertyFilterSpec;
|
||||
import com.vmware.vim25.PropertySpec;
|
||||
import com.vmware.vim25.SelectionSpec;
|
||||
import com.vmware.vim25.TraversalSpec;
|
||||
|
||||
public class DatacenterMO extends BaseMO {
|
||||
|
||||
public DatacenterMO(VmwareContext context, ManagedObjectReference morDc) {
|
||||
super(context, morDc);
|
||||
}
|
||||
|
||||
public DatacenterMO(VmwareContext context, String morType, String morValue) {
|
||||
super(context, morType, morValue);
|
||||
}
|
||||
|
||||
public DatacenterMO(VmwareContext context, String dcName) throws Exception {
|
||||
super(context, null);
|
||||
|
||||
_mor = _context.getServiceUtil().getDecendentMoRef(_context.getRootFolder(), "Datacenter", dcName);
|
||||
assert(_mor != null);
|
||||
}
|
||||
|
||||
public String getName() throws Exception {
|
||||
return (String)_context.getServiceUtil().getDynamicProperty(_mor, "name");
|
||||
}
|
||||
|
||||
public void registerTemplate(ManagedObjectReference morHost, String datastoreName,
|
||||
String templateName, String templateFileName) throws Exception {
|
||||
|
||||
ServiceUtil serviceUtil = _context.getServiceUtil();
|
||||
|
||||
ManagedObjectReference morFolder = (ManagedObjectReference)serviceUtil.getDynamicProperty(
|
||||
_mor, "vmFolder");
|
||||
assert(morFolder != null);
|
||||
|
||||
ManagedObjectReference morTask = _context.getService().registerVM_Task(
|
||||
morFolder,
|
||||
String.format("[%s] %s/%s", datastoreName, templateName, templateFileName),
|
||||
templateName, true,
|
||||
null, morHost);
|
||||
|
||||
String result = serviceUtil.waitForTask(morTask);
|
||||
if (!result.equalsIgnoreCase("Sucess")) {
|
||||
throw new Exception("Unable to register template due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
} else {
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
}
|
||||
}
|
||||
|
||||
public VirtualMachineMO findVm(String vmName) throws Exception {
|
||||
ObjectContent[] ocs = getVmPropertiesOnDatacenterVmFolder(new String[] { "name" });
|
||||
if(ocs != null && ocs.length > 0) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
DynamicProperty[] props = oc.getPropSet();
|
||||
if(props != null) {
|
||||
for(DynamicProperty prop : props) {
|
||||
if(prop.getVal().toString().equals(vmName))
|
||||
return new VirtualMachineMO(_context, oc.getObj());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<VirtualMachineMO> findVmByNameAndLabel(String vmLabel) throws Exception {
|
||||
CustomFieldsManagerMO cfmMo = new CustomFieldsManagerMO(_context,
|
||||
_context.getServiceContent().getCustomFieldsManager());
|
||||
int key = cfmMo.getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_UUID);
|
||||
assert(key != 0);
|
||||
|
||||
List<VirtualMachineMO> list = new ArrayList<VirtualMachineMO>();
|
||||
|
||||
ObjectContent[] ocs = getVmPropertiesOnDatacenterVmFolder(new String[] { "name", String.format("value[%d]", key)});
|
||||
if(ocs != null && ocs.length > 0) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
DynamicProperty[] props = oc.getPropSet();
|
||||
if(props != null) {
|
||||
for(DynamicProperty prop : props) {
|
||||
if(prop.getVal() != null) {
|
||||
if(prop.getName().equalsIgnoreCase("name")) {
|
||||
if(prop.getVal().toString().equals(vmLabel)) {
|
||||
list.add(new VirtualMachineMO(_context, oc.getObj()));
|
||||
break; // break out inner loop
|
||||
}
|
||||
} else if(prop.getVal() instanceof CustomFieldStringValue) {
|
||||
String val = ((CustomFieldStringValue)prop.getVal()).getValue();
|
||||
if(val.equals(vmLabel)) {
|
||||
list.add(new VirtualMachineMO(_context, oc.getObj()));
|
||||
break; // break out inner loop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<Pair<ManagedObjectReference, String>> getAllVmsOnDatacenter() throws Exception {
|
||||
List<Pair<ManagedObjectReference, String>> vms = new ArrayList<Pair<ManagedObjectReference, String>>();
|
||||
|
||||
ObjectContent[] ocs = getVmPropertiesOnDatacenterVmFolder(new String[] { "name" });
|
||||
if(ocs != null) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
String vmName = oc.getPropSet(0).getVal().toString();
|
||||
vms.add(new Pair<ManagedObjectReference, String>(oc.getObj(), vmName));
|
||||
}
|
||||
}
|
||||
|
||||
return vms;
|
||||
}
|
||||
|
||||
public ManagedObjectReference findDatastore(String name) throws Exception {
|
||||
assert(name != null);
|
||||
|
||||
ObjectContent[] ocs = getDatastorePropertiesOnDatacenter(new String[] { "name" });
|
||||
if(ocs != null) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
if(oc.getPropSet(0).getVal().toString().equals(name)) {
|
||||
return oc.getObj();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ManagedObjectReference findHost(String name) throws Exception {
|
||||
ObjectContent[] ocs= getHostPropertiesOnDatacenterHostFolder(new String[] { "name" });
|
||||
|
||||
if(ocs != null) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
if(oc.getPropSet(0).getVal().toString().equals(name)) {
|
||||
return oc.getObj();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ManagedObjectReference getVmFolder() throws Exception {
|
||||
return (ManagedObjectReference)_context.getServiceUtil().getDynamicProperty(_mor, "vmFolder");
|
||||
}
|
||||
|
||||
public ObjectContent[] getHostPropertiesOnDatacenterHostFolder(String[] propertyPaths) throws Exception {
|
||||
PropertySpec pSpec = new PropertySpec();
|
||||
pSpec.setType("HostSystem");
|
||||
pSpec.setPathSet(propertyPaths);
|
||||
|
||||
TraversalSpec computeResource2HostTraversal = new TraversalSpec();
|
||||
computeResource2HostTraversal.setType("ComputeResource");
|
||||
computeResource2HostTraversal.setPath("host");
|
||||
computeResource2HostTraversal.setName("computeResource2HostTraversal");
|
||||
|
||||
SelectionSpec recurseFolders = new SelectionSpec();
|
||||
recurseFolders.setName("folder2childEntity");
|
||||
|
||||
TraversalSpec folder2childEntity = new TraversalSpec();
|
||||
folder2childEntity.setType("Folder");
|
||||
folder2childEntity.setPath("childEntity");
|
||||
folder2childEntity.setName(recurseFolders.getName());
|
||||
folder2childEntity.setSelectSet(new SelectionSpec[] { recurseFolders, computeResource2HostTraversal });
|
||||
|
||||
TraversalSpec dc2HostFolderTraversal = new TraversalSpec();
|
||||
dc2HostFolderTraversal.setType("Datacenter");
|
||||
dc2HostFolderTraversal.setPath("hostFolder");
|
||||
dc2HostFolderTraversal.setName("dc2HostFolderTraversal");
|
||||
dc2HostFolderTraversal.setSelectSet(new SelectionSpec[] { folder2childEntity } );
|
||||
|
||||
ObjectSpec oSpec = new ObjectSpec();
|
||||
oSpec.setObj(_mor);
|
||||
oSpec.setSkip(Boolean.TRUE);
|
||||
oSpec.setSelectSet(new SelectionSpec[] { dc2HostFolderTraversal });
|
||||
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.setPropSet(new PropertySpec[] { pSpec });
|
||||
pfSpec.setObjectSet(new ObjectSpec[] { oSpec });
|
||||
|
||||
return _context.getService().retrieveProperties(
|
||||
_context.getServiceContent().getPropertyCollector(),
|
||||
new PropertyFilterSpec[] { pfSpec });
|
||||
}
|
||||
|
||||
public ObjectContent[] getDatastorePropertiesOnDatacenter(String[] propertyPaths) throws Exception {
|
||||
|
||||
PropertySpec pSpec = new PropertySpec();
|
||||
pSpec.setType("Datastore");
|
||||
pSpec.setPathSet(propertyPaths);
|
||||
|
||||
TraversalSpec dc2DatastoreTraversal = new TraversalSpec();
|
||||
dc2DatastoreTraversal.setType("Datacenter");
|
||||
dc2DatastoreTraversal.setPath("datastore");
|
||||
dc2DatastoreTraversal.setName("dc2DatastoreTraversal");
|
||||
|
||||
ObjectSpec oSpec = new ObjectSpec();
|
||||
oSpec.setObj(_mor);
|
||||
oSpec.setSkip(Boolean.TRUE);
|
||||
oSpec.setSelectSet(new SelectionSpec[] { dc2DatastoreTraversal });
|
||||
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.setPropSet(new PropertySpec[] { pSpec });
|
||||
pfSpec.setObjectSet(new ObjectSpec[] { oSpec });
|
||||
|
||||
return _context.getService().retrieveProperties(
|
||||
_context.getServiceContent().getPropertyCollector(),
|
||||
new PropertyFilterSpec[] { pfSpec });
|
||||
}
|
||||
|
||||
public ObjectContent[] getVmPropertiesOnDatacenterVmFolder(String[] propertyPaths) throws Exception {
|
||||
PropertySpec pSpec = new PropertySpec();
|
||||
pSpec.setType("VirtualMachine");
|
||||
pSpec.setPathSet(propertyPaths);
|
||||
|
||||
TraversalSpec dc2VmFolderTraversal = new TraversalSpec();
|
||||
dc2VmFolderTraversal.setType("Datacenter");
|
||||
dc2VmFolderTraversal.setPath("vmFolder");
|
||||
dc2VmFolderTraversal.setName("dc2VmFolderTraversal");
|
||||
|
||||
SelectionSpec recurseFolders = new SelectionSpec();
|
||||
recurseFolders.setName("folder2childEntity");
|
||||
|
||||
TraversalSpec folder2childEntity = new TraversalSpec();
|
||||
folder2childEntity.setType("Folder");
|
||||
folder2childEntity.setPath("childEntity");
|
||||
folder2childEntity.setName(recurseFolders.getName());
|
||||
folder2childEntity.setSelectSet(new SelectionSpec[] { recurseFolders });
|
||||
dc2VmFolderTraversal.setSelectSet(new SelectionSpec[] { folder2childEntity } );
|
||||
|
||||
ObjectSpec oSpec = new ObjectSpec();
|
||||
oSpec.setObj(_mor);
|
||||
oSpec.setSkip(Boolean.TRUE);
|
||||
oSpec.setSelectSet(new SelectionSpec[] { dc2VmFolderTraversal });
|
||||
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.setPropSet(new PropertySpec[] { pSpec });
|
||||
pfSpec.setObjectSet(new ObjectSpec[] { oSpec });
|
||||
|
||||
return _context.getService().retrieveProperties(
|
||||
_context.getServiceContent().getPropertyCollector(),
|
||||
new PropertyFilterSpec[] { pfSpec });
|
||||
}
|
||||
|
||||
public static Pair<DatacenterMO, String> getOwnerDatacenter(VmwareContext context,
|
||||
ManagedObjectReference morEntity) throws Exception {
|
||||
|
||||
PropertySpec pSpec = new PropertySpec();
|
||||
pSpec.setType("Datacenter");
|
||||
pSpec.setPathSet(new String[] { "name" });
|
||||
|
||||
TraversalSpec entityParentTraversal = new TraversalSpec();
|
||||
entityParentTraversal.setType("ManagedEntity");
|
||||
entityParentTraversal.setPath("parent");
|
||||
entityParentTraversal.setName("entityParentTraversal");
|
||||
entityParentTraversal.setSelectSet(new SelectionSpec[] { new SelectionSpec(null, null, "entityParentTraversal") });
|
||||
|
||||
ObjectSpec oSpec = new ObjectSpec();
|
||||
oSpec.setObj(morEntity);
|
||||
oSpec.setSkip(Boolean.TRUE);
|
||||
oSpec.setSelectSet(new SelectionSpec[] { entityParentTraversal });
|
||||
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.setPropSet(new PropertySpec[] { pSpec });
|
||||
pfSpec.setObjectSet(new ObjectSpec[] { oSpec });
|
||||
|
||||
ObjectContent[] ocs = context.getService().retrieveProperties(
|
||||
context.getServiceContent().getPropertyCollector(),
|
||||
new PropertyFilterSpec[] { pfSpec });
|
||||
|
||||
assert(ocs != null);
|
||||
assert(ocs[0].getObj() != null);
|
||||
assert(ocs[0].getPropSet(0) != null);
|
||||
assert(ocs[0].getPropSet(0).getVal() != null);
|
||||
|
||||
String dcName = ocs[0].getPropSet(0).getVal().toString();
|
||||
return new Pair<DatacenterMO, String>(new DatacenterMO(context, ocs[0].getObj()), dcName);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
public class DatastoreFile {
|
||||
private String _path;
|
||||
|
||||
public DatastoreFile(String path) {
|
||||
assert(path != null);
|
||||
_path = path;
|
||||
}
|
||||
|
||||
public DatastoreFile(String datastoreName, String pathWithoutDatastoreName) {
|
||||
_path = String.format("[%s] %s", datastoreName, pathWithoutDatastoreName);
|
||||
}
|
||||
|
||||
public DatastoreFile(String datastoreName, String dir, String fileName) {
|
||||
if(dir == null || dir.isEmpty())
|
||||
_path = String.format("[%s] %s", datastoreName, fileName);
|
||||
else
|
||||
_path = String.format("[%s] %s/%s", datastoreName, dir, fileName);
|
||||
}
|
||||
|
||||
public String getDatastoreName() {
|
||||
return getDatastoreNameFromPath(_path);
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return _path;
|
||||
}
|
||||
|
||||
public String getRelativePath() {
|
||||
int pos = _path.indexOf(']');
|
||||
if(pos < 0)
|
||||
pos = 0;
|
||||
else
|
||||
pos++;
|
||||
|
||||
return _path.substring(pos).trim();
|
||||
}
|
||||
|
||||
public String getDir() {
|
||||
int startPos = _path.indexOf("]");
|
||||
if(startPos < 0)
|
||||
startPos = 0;
|
||||
|
||||
int endPos = _path.lastIndexOf('/');
|
||||
if(endPos < 0)
|
||||
endPos = 0;
|
||||
|
||||
if(endPos > startPos) {
|
||||
return _path.substring(startPos + 1, endPos).trim();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
int startPos = _path.indexOf("]");
|
||||
if(startPos < 0)
|
||||
startPos = 0;
|
||||
else
|
||||
startPos++;
|
||||
|
||||
int endPos = _path.lastIndexOf('/');
|
||||
if(endPos < 0) {
|
||||
return _path.substring(startPos).trim();
|
||||
} else {
|
||||
return _path.substring(endPos + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public String getFileBaseName() {
|
||||
String name = getFileName();
|
||||
int endPos = name.lastIndexOf('.');
|
||||
if(endPos < 0)
|
||||
return name;
|
||||
return name.substring(0, endPos);
|
||||
}
|
||||
|
||||
public String getFileExtName() {
|
||||
String name = getFileName();
|
||||
int endPos = name.lastIndexOf('.');
|
||||
if(endPos < 0)
|
||||
return "";
|
||||
|
||||
return name.substring(endPos);
|
||||
}
|
||||
|
||||
public String getCompanionPath(String companionFileName) {
|
||||
return getCompanionDatastorePath(_path, companionFileName);
|
||||
}
|
||||
|
||||
public static boolean isFullDatastorePath(String path) {
|
||||
return path.matches("^\\[.*\\].*");
|
||||
}
|
||||
|
||||
public static String getDatastoreNameFromPath(String path) {
|
||||
if(isFullDatastorePath(path)) {
|
||||
int endPos = path.indexOf("]");
|
||||
return path.substring(1, endPos).trim();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getCompanionDatastorePath(String path, String companionFileName) {
|
||||
if(isFullDatastorePath(path)) {
|
||||
int endPos = path.indexOf("]");
|
||||
String dsName = path.substring(1, endPos);
|
||||
String dsRelativePath = path.substring(endPos + 1).trim();
|
||||
|
||||
int fileNamePos = dsRelativePath.lastIndexOf('/');
|
||||
if(fileNamePos < 0) {
|
||||
return String.format("[%s] %s", dsName, companionFileName);
|
||||
} else {
|
||||
return String.format("[%s] %s/%s", dsName,
|
||||
dsRelativePath.substring(0, fileNamePos),
|
||||
companionFileName);
|
||||
}
|
||||
}
|
||||
return companionFileName;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,305 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.vmware.vim25.DatastoreSummary;
|
||||
import com.vmware.vim25.FileInfo;
|
||||
import com.vmware.vim25.HostDatastoreBrowserSearchResults;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.ObjectContent;
|
||||
import com.vmware.vim25.ObjectSpec;
|
||||
import com.vmware.vim25.PropertyFilterSpec;
|
||||
import com.vmware.vim25.PropertySpec;
|
||||
import com.vmware.vim25.SelectionSpec;
|
||||
import com.vmware.vim25.TraversalSpec;
|
||||
|
||||
public class DatastoreMO extends BaseMO {
|
||||
private static final Logger s_logger = Logger.getLogger(DatastoreMO.class);
|
||||
|
||||
// cache copy to reduce calls to vCenter
|
||||
private String _name;
|
||||
private Pair<DatacenterMO, String> _ownerDc;
|
||||
|
||||
public DatastoreMO(VmwareContext context, ManagedObjectReference morDatastore) {
|
||||
super(context, morDatastore);
|
||||
}
|
||||
|
||||
public DatastoreMO(VmwareContext context, String morType, String morValue) {
|
||||
super(context, morType, morValue);
|
||||
}
|
||||
|
||||
public String getName() throws Exception {
|
||||
if(_name == null)
|
||||
_name = (String)_context.getServiceUtil().getDynamicProperty(_mor, "name");
|
||||
|
||||
return _name;
|
||||
}
|
||||
|
||||
public DatastoreSummary getSummary() throws Exception {
|
||||
return (DatastoreSummary)_context.getServiceUtil().getDynamicProperty(_mor, "summary");
|
||||
}
|
||||
|
||||
public HostDatastoreBrowserMO getHostDatastoreBrowserMO() throws Exception {
|
||||
return new HostDatastoreBrowserMO(_context,
|
||||
(ManagedObjectReference)_context.getServiceUtil().getDynamicProperty(_mor, "browser"));
|
||||
}
|
||||
|
||||
public String getInventoryPath() throws Exception {
|
||||
Pair<DatacenterMO, String> dcInfo = getOwnerDatacenter();
|
||||
return dcInfo.second() + "/" + getName();
|
||||
}
|
||||
|
||||
public Pair<DatacenterMO, String> getOwnerDatacenter() throws Exception {
|
||||
if(_ownerDc != null)
|
||||
return _ownerDc;
|
||||
|
||||
PropertySpec pSpec = new PropertySpec();
|
||||
pSpec.setType("Datacenter");
|
||||
pSpec.setPathSet(new String[] { "name" });
|
||||
|
||||
TraversalSpec folderParentTraversal = new TraversalSpec();
|
||||
folderParentTraversal.setType("Folder");
|
||||
folderParentTraversal.setPath("parent");
|
||||
folderParentTraversal.setName("folderParentTraversal");
|
||||
folderParentTraversal.setSelectSet(new SelectionSpec[] { new SelectionSpec(null, null, "folderParentTraversal") });
|
||||
|
||||
TraversalSpec dsParentTraversal = new TraversalSpec();
|
||||
dsParentTraversal.setType("Datastore");
|
||||
dsParentTraversal.setPath("parent");
|
||||
dsParentTraversal.setName("dsParentTraversal");
|
||||
dsParentTraversal.setSelectSet(new SelectionSpec[] { folderParentTraversal });
|
||||
|
||||
ObjectSpec oSpec = new ObjectSpec();
|
||||
oSpec.setObj(getMor());
|
||||
oSpec.setSkip(Boolean.TRUE);
|
||||
oSpec.setSelectSet(new SelectionSpec[] { dsParentTraversal });
|
||||
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.setPropSet(new PropertySpec[] { pSpec });
|
||||
pfSpec.setObjectSet(new ObjectSpec[] { oSpec });
|
||||
|
||||
ObjectContent[] ocs = _context.getService().retrieveProperties(
|
||||
_context.getServiceContent().getPropertyCollector(),
|
||||
new PropertyFilterSpec[] { pfSpec });
|
||||
|
||||
assert(ocs != null);
|
||||
assert(ocs[0].getObj() != null);
|
||||
assert(ocs[0].getPropSet() != null);
|
||||
String dcName = ocs[0].getPropSet()[0].getVal().toString();
|
||||
_ownerDc = new Pair<DatacenterMO, String>(new DatacenterMO(_context, ocs[0].getObj()), dcName);
|
||||
return _ownerDc;
|
||||
}
|
||||
|
||||
public void makeDirectory(String path, ManagedObjectReference morDc) throws Exception {
|
||||
String datastoreName = getName();
|
||||
ManagedObjectReference morFileManager = _context.getServiceContent().getFileManager();
|
||||
|
||||
String fullPath = path;
|
||||
if(!DatastoreFile.isFullDatastorePath(fullPath))
|
||||
fullPath = String.format("[%s] %s", datastoreName, path);
|
||||
|
||||
_context.getService().makeDirectory(morFileManager, fullPath, morDc, true);
|
||||
}
|
||||
|
||||
public boolean deleteFile(String path, ManagedObjectReference morDc, boolean testExistence) throws Exception {
|
||||
String datastoreName = getName();
|
||||
ManagedObjectReference morFileManager = _context.getServiceContent().getFileManager();
|
||||
|
||||
String fullPath = path;
|
||||
if(!DatastoreFile.isFullDatastorePath(fullPath))
|
||||
fullPath = String.format("[%s] %s", datastoreName, path);
|
||||
|
||||
try {
|
||||
if(testExistence && !fileExists(fullPath))
|
||||
return true;
|
||||
} catch(Exception e) {
|
||||
s_logger.info("Unable to test file existence due to exception " + e.getClass().getName() + ", skip deleting of it");
|
||||
return true;
|
||||
}
|
||||
|
||||
ManagedObjectReference morTask = _context.getService().deleteDatastoreFile_Task(morFileManager,
|
||||
fullPath, morDc);
|
||||
|
||||
String result = _context.getServiceUtil().waitForTask(morTask);
|
||||
if(result.equals("sucess")) {
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
return true;
|
||||
} else {
|
||||
s_logger.error("VMware deleteDatastoreFile_Task failed due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean copyDatastoreFile(String srcFilePath, ManagedObjectReference morSrcDc,
|
||||
ManagedObjectReference morDestDs, String destFilePath, ManagedObjectReference morDestDc,
|
||||
boolean forceOverwrite) throws Exception {
|
||||
|
||||
String srcDsName = getName();
|
||||
DatastoreMO destDsMo = new DatastoreMO(_context, morDestDs);
|
||||
String destDsName = destDsMo.getName();
|
||||
|
||||
ManagedObjectReference morFileManager = _context.getServiceContent().getFileManager();
|
||||
String srcFullPath = srcFilePath;
|
||||
if(!DatastoreFile.isFullDatastorePath(srcFullPath))
|
||||
srcFullPath = String.format("[%s] %s", srcDsName, srcFilePath);
|
||||
|
||||
String destFullPath = destFilePath;
|
||||
if(!DatastoreFile.isFullDatastorePath(destFullPath))
|
||||
destFullPath = String.format("[%s] %s", destDsName, destFilePath);
|
||||
|
||||
ManagedObjectReference morTask = _context.getService().copyDatastoreFile_Task(morFileManager,
|
||||
srcFullPath, morSrcDc, destFullPath, morDestDc, forceOverwrite);
|
||||
|
||||
String result = _context.getServiceUtil().waitForTask(morTask);
|
||||
if(result.equals("sucess")) {
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
return true;
|
||||
} else {
|
||||
s_logger.error("VMware copyDatastoreFile_Task failed due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean moveDatastoreFile(String srcFilePath, ManagedObjectReference morSrcDc,
|
||||
ManagedObjectReference morDestDs, String destFilePath, ManagedObjectReference morDestDc,
|
||||
boolean forceOverwrite) throws Exception {
|
||||
|
||||
String srcDsName = getName();
|
||||
DatastoreMO destDsMo = new DatastoreMO(_context, morDestDs);
|
||||
String destDsName = destDsMo.getName();
|
||||
|
||||
ManagedObjectReference morFileManager = _context.getServiceContent().getFileManager();
|
||||
String srcFullPath = srcFilePath;
|
||||
if(!DatastoreFile.isFullDatastorePath(srcFullPath))
|
||||
srcFullPath = String.format("[%s] %s", srcDsName, srcFilePath);
|
||||
|
||||
String destFullPath = destFilePath;
|
||||
if(!DatastoreFile.isFullDatastorePath(destFullPath))
|
||||
destFullPath = String.format("[%s] %s", destDsName, destFilePath);
|
||||
|
||||
ManagedObjectReference morTask = _context.getService().moveDatastoreFile_Task(morFileManager,
|
||||
srcFullPath, morSrcDc, destFullPath, morDestDc, forceOverwrite);
|
||||
|
||||
String result = _context.getServiceUtil().waitForTask(morTask);
|
||||
if(result.equals("sucess")) {
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
return true;
|
||||
} else {
|
||||
s_logger.error("VMware moveDatgastoreFile_Task failed due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String[] getVmdkFileChain(String rootVmdkDatastoreFullPath) throws Exception {
|
||||
Pair<DatacenterMO, String> dcPair = getOwnerDatacenter();
|
||||
|
||||
List<String> files = new ArrayList<String>();
|
||||
files.add(rootVmdkDatastoreFullPath);
|
||||
|
||||
String currentVmdkFullPath = rootVmdkDatastoreFullPath;
|
||||
while(true) {
|
||||
String url = getContext().composeDatastoreBrowseUrl(dcPair.second(), currentVmdkFullPath);
|
||||
byte[] content = getContext().getResourceContent(url);
|
||||
if(content == null || content.length == 0)
|
||||
break;
|
||||
|
||||
VmdkFileDescriptor descriptor = new VmdkFileDescriptor();
|
||||
descriptor.parse(content);
|
||||
|
||||
String parentFileName = descriptor.getParentFileName();
|
||||
if(parentFileName == null)
|
||||
break;
|
||||
|
||||
if(parentFileName.startsWith("/")) {
|
||||
// when parent file is not at the same directory as it is, assume it is at parent directory
|
||||
// this is only valid in cloud.com primary storage deployment
|
||||
DatastoreFile dsFile = new DatastoreFile(currentVmdkFullPath);
|
||||
String dir = dsFile.getDir();
|
||||
if(dir != null && dir.lastIndexOf('/') > 0)
|
||||
dir = dir.substring(0, dir.lastIndexOf('/'));
|
||||
else
|
||||
dir = "";
|
||||
|
||||
currentVmdkFullPath = new DatastoreFile(dsFile.getDatastoreName(), dir,
|
||||
parentFileName.substring(parentFileName.lastIndexOf('/') + 1)).getPath();
|
||||
files.add(currentVmdkFullPath);
|
||||
} else {
|
||||
currentVmdkFullPath = DatastoreFile.getCompanionDatastorePath(currentVmdkFullPath, parentFileName);
|
||||
files.add(currentVmdkFullPath);
|
||||
}
|
||||
}
|
||||
|
||||
return files.toArray(new String[0]);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String[] listDirContent(String path) throws Exception {
|
||||
String fullPath = path;
|
||||
if(!DatastoreFile.isFullDatastorePath(fullPath))
|
||||
fullPath = String.format("[%s] %s", getName(), fullPath);
|
||||
|
||||
Pair<DatacenterMO, String> dcPair = getOwnerDatacenter();
|
||||
String url = getContext().composeDatastoreBrowseUrl(dcPair.second(), fullPath);
|
||||
|
||||
// TODO, VMware currently does not have a formal API to list Datastore directory content,
|
||||
// folloing hacking may have performance hit if datastore has a large number of files
|
||||
return _context.listDatastoreDirContent(url);
|
||||
}
|
||||
|
||||
public boolean fileExists(String fileFullPath) throws Exception {
|
||||
DatastoreFile file = new DatastoreFile(fileFullPath);
|
||||
DatastoreFile dirFile = new DatastoreFile(file.getDatastoreName(), file.getDir());
|
||||
|
||||
HostDatastoreBrowserMO browserMo = getHostDatastoreBrowserMO();
|
||||
|
||||
s_logger.info("Search file " + file.getFileName() + " on " + dirFile.getPath());
|
||||
HostDatastoreBrowserSearchResults results = browserMo.searchDatastore(dirFile.getPath(), file.getFileName(), true);
|
||||
if(results != null) {
|
||||
FileInfo[] info = results.getFile();
|
||||
if(info != null && info.length > 0) {
|
||||
s_logger.info("File " + fileFullPath + " exists on datastore");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
s_logger.info("File " + fileFullPath + " does not exist on datastore");
|
||||
return false;
|
||||
|
||||
/*
|
||||
String[] fileNames = listDirContent(dirFile.getPath());
|
||||
|
||||
String fileName = file.getFileName();
|
||||
for(String name : fileNames) {
|
||||
if(name.equalsIgnoreCase(fileName))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
*/
|
||||
}
|
||||
|
||||
public boolean folderExists(String folderParentDatastorePath, String folderName) throws Exception {
|
||||
HostDatastoreBrowserMO browserMo = getHostDatastoreBrowserMO();
|
||||
|
||||
HostDatastoreBrowserSearchResults results = browserMo.searchDatastore(folderParentDatastorePath, folderName, true);
|
||||
if(results != null) {
|
||||
FileInfo[] info = results.getFile();
|
||||
if(info != null && info.length > 0) {
|
||||
s_logger.info("Folder " + folderName + " exists on datastore");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
s_logger.info("Folder " + folderName + " does not exist on datastore");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/* * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
|
||||
*
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It 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 3 of the License, or any later version.
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.vmware.vim25.HostDatastoreBrowserSearchResults;
|
||||
import com.vmware.vim25.HostDatastoreBrowserSearchSpec;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
|
||||
public class HostDatastoreBrowserMO extends BaseMO {
|
||||
|
||||
private static final Logger s_logger = Logger.getLogger(HostDatastoreBrowserMO.class);
|
||||
|
||||
public HostDatastoreBrowserMO(VmwareContext context, ManagedObjectReference morHostDatastoreBrowser) {
|
||||
super(context, morHostDatastoreBrowser);
|
||||
}
|
||||
|
||||
public HostDatastoreBrowserMO(VmwareContext context, String morType, String morValue) {
|
||||
super(context, morType, morValue);
|
||||
}
|
||||
|
||||
public void DeleteFile(String datastoreFullPath) throws Exception {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - deleteFile(). target mor: " + _mor.get_value() + ", file datastore path: " + datastoreFullPath);
|
||||
|
||||
_context.getService().deleteFile(_mor, datastoreFullPath);
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - deleteFile() done");
|
||||
}
|
||||
|
||||
public HostDatastoreBrowserSearchResults searchDatastore(String datastorePath, HostDatastoreBrowserSearchSpec searchSpec) throws Exception {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - searchDatastore(). target mor: " + _mor.get_value() + ", file datastore path: " + datastorePath);
|
||||
|
||||
try {
|
||||
ManagedObjectReference morTask = _context.getService().searchDatastore_Task(_mor, datastorePath, searchSpec);
|
||||
|
||||
String result = _context.getServiceUtil().waitForTask(morTask);
|
||||
if(result.equals("sucess")) {
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
|
||||
return (HostDatastoreBrowserSearchResults)_context.getServiceUtil().getDynamicProperty(morTask, "info.result");
|
||||
} else {
|
||||
s_logger.error("VMware searchDaastore_Task failed due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
}
|
||||
} finally {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - searchDatastore() done");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public HostDatastoreBrowserSearchResults searchDatastore(String datastorePath, String fileName, boolean caseInsensitive) throws Exception {
|
||||
HostDatastoreBrowserSearchSpec spec = new HostDatastoreBrowserSearchSpec();
|
||||
spec.setSearchCaseInsensitive(caseInsensitive);
|
||||
spec.setMatchPattern(new String[] { fileName });
|
||||
|
||||
return searchDatastore(datastorePath, spec);
|
||||
}
|
||||
|
||||
public HostDatastoreBrowserSearchResults searchDatastoreSubFolders(String datastorePath, HostDatastoreBrowserSearchSpec searchSpec) throws Exception {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - searchDatastoreSubFolders(). target mor: " + _mor.get_value() + ", file datastore path: " + datastorePath);
|
||||
|
||||
try {
|
||||
ManagedObjectReference morTask = _context.getService().searchDatastoreSubFolders_Task(_mor, datastorePath, searchSpec);
|
||||
|
||||
String result = _context.getServiceUtil().waitForTask(morTask);
|
||||
if(result.equals("sucess")) {
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
|
||||
return (HostDatastoreBrowserSearchResults)_context.getServiceUtil().getDynamicProperty(morTask, "info.result");
|
||||
} else {
|
||||
s_logger.error("VMware searchDaastoreSubFolders_Task failed due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
}
|
||||
} finally {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - searchDatastore() done");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public HostDatastoreBrowserSearchResults searchDatastoreSubFolders(String datastorePath, String folderName, boolean caseInsensitive) throws Exception {
|
||||
HostDatastoreBrowserSearchSpec spec = new HostDatastoreBrowserSearchSpec();
|
||||
spec.setSearchCaseInsensitive(caseInsensitive);
|
||||
spec.setMatchPattern(new String[] { folderName });
|
||||
|
||||
return searchDatastore(datastorePath, spec);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.vmware.vim25.CustomFieldStringValue;
|
||||
import com.vmware.vim25.DatastoreInfo;
|
||||
import com.vmware.vim25.DynamicProperty;
|
||||
import com.vmware.vim25.HostNasVolumeSpec;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.NasDatastoreInfo;
|
||||
import com.vmware.vim25.ObjectContent;
|
||||
import com.vmware.vim25.ObjectSpec;
|
||||
import com.vmware.vim25.PropertyFilterSpec;
|
||||
import com.vmware.vim25.PropertySpec;
|
||||
import com.vmware.vim25.SelectionSpec;
|
||||
import com.vmware.vim25.TraversalSpec;
|
||||
|
||||
public class HostDatastoreSystemMO extends BaseMO {
|
||||
|
||||
public HostDatastoreSystemMO(VmwareContext context, ManagedObjectReference morHostDatastore) {
|
||||
super(context, morHostDatastore);
|
||||
}
|
||||
|
||||
public HostDatastoreSystemMO(VmwareContext context, String morType, String morValue) {
|
||||
super(context, morType, morValue);
|
||||
}
|
||||
|
||||
public ManagedObjectReference findDatastore(String name) throws Exception {
|
||||
// added cloud.com specific name convention, we will use custom field "cloud.uuid" as datastore name as well
|
||||
CustomFieldsManagerMO cfmMo = new CustomFieldsManagerMO(_context,
|
||||
_context.getServiceContent().getCustomFieldsManager());
|
||||
int key = cfmMo.getCustomFieldKey("Datastore", CustomFieldConstants.CLOUD_UUID);
|
||||
assert(key != 0);
|
||||
|
||||
ObjectContent[] ocs = getDatastorePropertiesOnHostDatastoreSystem(
|
||||
new String[] { "name", String.format("value[%d]", key) });
|
||||
if(ocs != null) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
if(oc.getPropSet(0).getVal().equals(name))
|
||||
return oc.getObj();
|
||||
|
||||
if(oc.getPropSet().length > 1) {
|
||||
DynamicProperty prop = oc.getPropSet(1);
|
||||
if(prop != null && prop.getVal() != null) {
|
||||
if(prop.getVal() instanceof CustomFieldStringValue) {
|
||||
String val = ((CustomFieldStringValue)prop.getVal()).getValue();
|
||||
if(val.equalsIgnoreCase(name))
|
||||
return oc.getObj();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// storeUrl in nfs://host/exportpath format
|
||||
public ManagedObjectReference findDatastoreByUrl(String storeUrl) throws Exception {
|
||||
assert(storeUrl != null);
|
||||
|
||||
ManagedObjectReference[] datastores = getDatastores();
|
||||
if(datastores != null && datastores.length > 0) {
|
||||
for(ManagedObjectReference morDatastore : datastores) {
|
||||
NasDatastoreInfo info = getNasDatastoreInfo(morDatastore);
|
||||
if(info != null) {
|
||||
URI uri = new URI(storeUrl);
|
||||
String vmwareStyleUrl = "netfs://" + uri.getHost() + "/" + uri.getPath() + "/";
|
||||
if(info.getUrl().equals(vmwareStyleUrl))
|
||||
return morDatastore;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO this is a hacking helper method, when we can pass down storage pool info along with volume
|
||||
// we should be able to find the datastore by name
|
||||
public ManagedObjectReference findDatastoreByExportPath(String exportPath) throws Exception {
|
||||
assert(exportPath != null);
|
||||
|
||||
ManagedObjectReference[] datastores = getDatastores();
|
||||
if(datastores != null && datastores.length > 0) {
|
||||
for(ManagedObjectReference morDatastore : datastores) {
|
||||
DatastoreMO dsMo = new DatastoreMO(_context, morDatastore);
|
||||
if(dsMo.getInventoryPath().equals(exportPath))
|
||||
return morDatastore;
|
||||
|
||||
NasDatastoreInfo info = getNasDatastoreInfo(morDatastore);
|
||||
if(info != null) {
|
||||
String vmwareUrl = info.getUrl();
|
||||
if(vmwareUrl.charAt(vmwareUrl.length() - 1) == '/')
|
||||
vmwareUrl = vmwareUrl.substring(0, vmwareUrl.length() - 1);
|
||||
|
||||
URI uri = new URI(vmwareUrl);
|
||||
if(uri.getPath().equals("/" + exportPath))
|
||||
return morDatastore;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean deleteDatastore(String name) throws Exception {
|
||||
ManagedObjectReference morDatastore = findDatastore(name);
|
||||
if(morDatastore != null) {
|
||||
_context.getService().removeDatastore(_mor, morDatastore);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public ManagedObjectReference createNfsDatastore(String host, int port,
|
||||
String exportPath, String uuid) throws Exception {
|
||||
|
||||
HostNasVolumeSpec spec = new HostNasVolumeSpec();
|
||||
spec.setRemoteHost(host);
|
||||
spec.setRemotePath(exportPath);
|
||||
spec.setType("nfs");
|
||||
spec.setLocalPath(uuid);
|
||||
|
||||
// readOnly/readWrite
|
||||
spec.setAccessMode("readWrite");
|
||||
return _context.getService().createNasDatastore(_mor, spec);
|
||||
}
|
||||
|
||||
public ManagedObjectReference[] getDatastores() throws Exception {
|
||||
return (ManagedObjectReference[])_context.getServiceUtil().getDynamicProperty(
|
||||
_mor, "datastore");
|
||||
}
|
||||
|
||||
public DatastoreInfo getDatastoreInfo(ManagedObjectReference morDatastore) throws Exception {
|
||||
return (DatastoreInfo)_context.getServiceUtil().getDynamicProperty(morDatastore, "info");
|
||||
}
|
||||
|
||||
public NasDatastoreInfo getNasDatastoreInfo(ManagedObjectReference morDatastore) throws Exception {
|
||||
DatastoreInfo info = (DatastoreInfo)_context.getServiceUtil().getDynamicProperty(morDatastore, "info");
|
||||
if(info instanceof NasDatastoreInfo)
|
||||
return (NasDatastoreInfo)info;
|
||||
return null;
|
||||
}
|
||||
|
||||
public ObjectContent[] getDatastorePropertiesOnHostDatastoreSystem(String[] propertyPaths) throws Exception {
|
||||
|
||||
PropertySpec pSpec = new PropertySpec();
|
||||
pSpec.setType("Datastore");
|
||||
pSpec.setPathSet(propertyPaths);
|
||||
|
||||
TraversalSpec hostDsSys2DatastoreTraversal = new TraversalSpec();
|
||||
hostDsSys2DatastoreTraversal.setType("HostDatastoreSystem");
|
||||
hostDsSys2DatastoreTraversal.setPath("datastore");
|
||||
hostDsSys2DatastoreTraversal.setName("hostDsSys2DatastoreTraversal");
|
||||
|
||||
ObjectSpec oSpec = new ObjectSpec();
|
||||
oSpec.setObj(_mor);
|
||||
oSpec.setSkip(Boolean.TRUE);
|
||||
oSpec.setSelectSet(new SelectionSpec[] { hostDsSys2DatastoreTraversal });
|
||||
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.setPropSet(new PropertySpec[] { pSpec });
|
||||
pfSpec.setObjectSet(new ObjectSpec[] { oSpec });
|
||||
|
||||
return _context.getService().retrieveProperties(
|
||||
_context.getServiceContent().getPropertyCollector(),
|
||||
new PropertyFilterSpec[] { pfSpec });
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
|
||||
public class HostFirewallSystemMO extends BaseMO {
|
||||
private static final Logger s_logger = Logger.getLogger(HostFirewallSystemMO.class);
|
||||
|
||||
public HostFirewallSystemMO(VmwareContext context, ManagedObjectReference morFirewallSystem) {
|
||||
super(context, morFirewallSystem);
|
||||
}
|
||||
|
||||
public HostFirewallSystemMO(VmwareContext context, String morType, String morValue) {
|
||||
super(context, morType, morValue);
|
||||
}
|
||||
|
||||
public void enableRuleset(String rulesetName) throws Exception {
|
||||
_context.getService().enableRuleset(_mor, rulesetName);
|
||||
}
|
||||
|
||||
public void disableRuleset(String rulesetName) throws Exception {
|
||||
_context.getService().disableRuleset(_mor, rulesetName);
|
||||
}
|
||||
|
||||
public void refreshFirewall() throws Exception {
|
||||
_context.getService().refreshFirewall(_mor);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,887 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareHelper;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.google.gson.Gson;
|
||||
import com.vmware.apputils.vim25.ServiceUtil;
|
||||
import com.vmware.vim25.AboutInfo;
|
||||
import com.vmware.vim25.ClusterDasConfigInfo;
|
||||
import com.vmware.vim25.ComputeResourceSummary;
|
||||
import com.vmware.vim25.DatastoreSummary;
|
||||
import com.vmware.vim25.DynamicProperty;
|
||||
import com.vmware.vim25.HostConfigManager;
|
||||
import com.vmware.vim25.HostConnectInfo;
|
||||
import com.vmware.vim25.HostHardwareSummary;
|
||||
import com.vmware.vim25.HostHyperThreadScheduleInfo;
|
||||
import com.vmware.vim25.HostIpRouteEntry;
|
||||
import com.vmware.vim25.HostListSummaryQuickStats;
|
||||
import com.vmware.vim25.HostNetworkInfo;
|
||||
import com.vmware.vim25.HostNetworkPolicy;
|
||||
import com.vmware.vim25.HostNetworkTrafficShapingPolicy;
|
||||
import com.vmware.vim25.HostPortGroup;
|
||||
import com.vmware.vim25.HostPortGroupSpec;
|
||||
import com.vmware.vim25.HostRuntimeInfo;
|
||||
import com.vmware.vim25.HostSystemConnectionState;
|
||||
import com.vmware.vim25.HostVirtualNic;
|
||||
import com.vmware.vim25.HostVirtualSwitch;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.ObjectContent;
|
||||
import com.vmware.vim25.ObjectSpec;
|
||||
import com.vmware.vim25.OptionValue;
|
||||
import com.vmware.vim25.PropertyFilterSpec;
|
||||
import com.vmware.vim25.PropertySpec;
|
||||
import com.vmware.vim25.SelectionSpec;
|
||||
import com.vmware.vim25.TraversalSpec;
|
||||
import com.vmware.vim25.VirtualMachineConfigSpec;
|
||||
import com.vmware.vim25.VirtualNicManagerNetConfig;
|
||||
|
||||
public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
private static final Logger s_logger = Logger.getLogger(HostMO.class);
|
||||
Map<String, VirtualMachineMO> _vmCache = new HashMap<String, VirtualMachineMO>();
|
||||
|
||||
public HostMO (VmwareContext context, ManagedObjectReference morHost) {
|
||||
super(context, morHost);
|
||||
}
|
||||
|
||||
public HostMO (VmwareContext context, String morType, String morValue) {
|
||||
super(context, morType, morValue);
|
||||
}
|
||||
|
||||
public HostHardwareSummary getHostHardwareSummary() throws Exception {
|
||||
HostConnectInfo hostInfo = _context.getService().queryHostConnectionInfo(_mor);
|
||||
HostHardwareSummary hardwareSummary = hostInfo.getHost().getHardware();
|
||||
return hardwareSummary;
|
||||
}
|
||||
|
||||
public HostConfigManager getHostConfigManager() throws Exception {
|
||||
return (HostConfigManager)_context.getServiceUtil().getDynamicProperty(_mor, "configManager");
|
||||
}
|
||||
|
||||
public VirtualNicManagerNetConfig[] getHostVirtualNicManagerNetConfig() throws Exception {
|
||||
VirtualNicManagerNetConfig[] netConfigs = (VirtualNicManagerNetConfig[])_context.getServiceUtil().getDynamicProperty(_mor,
|
||||
"config.virtualNicManagerInfo.netConfig");
|
||||
return netConfigs;
|
||||
}
|
||||
|
||||
public HostIpRouteEntry[] getHostIpRouteEntries() throws Exception {
|
||||
HostIpRouteEntry[] entries = (HostIpRouteEntry[])_context.getServiceUtil().getDynamicProperty(_mor,
|
||||
"config.network.routeTableInfo.ipRoute");
|
||||
return entries;
|
||||
}
|
||||
|
||||
public HostListSummaryQuickStats getHostQuickStats() throws Exception {
|
||||
return (HostListSummaryQuickStats)_context.getServiceUtil().getDynamicProperty(_mor, "summary.quickStats");
|
||||
}
|
||||
|
||||
public HostHyperThreadScheduleInfo getHostHyperThreadInfo() throws Exception {
|
||||
return (HostHyperThreadScheduleInfo)_context.getServiceUtil().getDynamicProperty(_mor, "config.hyperThread");
|
||||
}
|
||||
|
||||
public HostNetworkInfo getHostNetworkInfo() throws Exception {
|
||||
return (HostNetworkInfo)_context.getServiceUtil().getDynamicProperty(_mor, "config.network");
|
||||
}
|
||||
|
||||
public HostPortGroupSpec getHostPortGroupSpec(String portGroupName) throws Exception {
|
||||
|
||||
HostNetworkInfo hostNetInfo = getHostNetworkInfo();
|
||||
|
||||
HostPortGroup[] portGroups = hostNetInfo.getPortgroup();
|
||||
if(portGroups != null) {
|
||||
for(HostPortGroup portGroup : portGroups) {
|
||||
HostPortGroupSpec spec = portGroup.getSpec();
|
||||
if(spec.getName().equals(portGroupName))
|
||||
return spec;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHyperHostName() throws Exception {
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClusterDasConfigInfo getDasConfig() throws Exception {
|
||||
ManagedObjectReference morParent = getParentMor();
|
||||
if(morParent.getType().equals("ClusterComputeResource")) {
|
||||
ClusterMO clusterMo = new ClusterMO(_context, morParent);
|
||||
return clusterMo.getDasConfig();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHyperHostDefaultGateway() throws Exception {
|
||||
HostIpRouteEntry[] entries = getHostIpRouteEntries();
|
||||
for(HostIpRouteEntry entry : entries) {
|
||||
if(entry.getNetwork().equalsIgnoreCase("0.0.0.0"))
|
||||
return entry.getGateway();
|
||||
}
|
||||
|
||||
throw new Exception("Could not find host default gateway, host is not properly configured?");
|
||||
}
|
||||
|
||||
public HostDatastoreSystemMO getHostDatastoreSystemMO() throws Exception {
|
||||
return new HostDatastoreSystemMO(_context,
|
||||
(ManagedObjectReference)_context.getServiceUtil().getDynamicProperty(
|
||||
_mor, "configManager.datastoreSystem")
|
||||
);
|
||||
}
|
||||
|
||||
public HostDatastoreBrowserMO getHostDatastoreBrowserMO() throws Exception {
|
||||
return new HostDatastoreBrowserMO(_context,
|
||||
(ManagedObjectReference)_context.getServiceUtil().getDynamicProperty(
|
||||
_mor, "datastoreBrowser")
|
||||
);
|
||||
}
|
||||
|
||||
private DatastoreMO getHostDatastoreMO(String datastoreName) throws Exception {
|
||||
ObjectContent[] ocs = getDatastorePropertiesOnHyperHost(new String[] { "name"} );
|
||||
if(ocs != null && ocs.length > 0) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
DynamicProperty[] objProps = oc.getPropSet();
|
||||
if(objProps != null) {
|
||||
for(DynamicProperty objProp : objProps) {
|
||||
if(objProp.getVal().toString().equals(datastoreName))
|
||||
return new DatastoreMO(_context, oc.getObj());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public HostNetworkSystemMO getHostNetworkSystemMO() throws Exception {
|
||||
HostConfigManager configMgr = getHostConfigManager();
|
||||
return new HostNetworkSystemMO(_context, configMgr.getNetworkSystem());
|
||||
}
|
||||
|
||||
public HostFirewallSystemMO getHostFirewallSystemMO() throws Exception {
|
||||
HostConfigManager configMgr = getHostConfigManager();
|
||||
ManagedObjectReference morFirewall = configMgr.getFirewallSystem();
|
||||
|
||||
// only ESX hosts have firewall manager
|
||||
if(morFirewall != null)
|
||||
return new HostFirewallSystemMO(_context, morFirewall);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedObjectReference getHyperHostDatacenter() throws Exception {
|
||||
Pair<DatacenterMO, String> dcPair = DatacenterMO.getOwnerDatacenter(getContext(), getMor());
|
||||
assert(dcPair != null);
|
||||
return dcPair.first().getMor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedObjectReference getHyperHostOwnerResourcePool() throws Exception {
|
||||
ServiceUtil serviceUtil = _context.getServiceUtil();
|
||||
ManagedObjectReference morComputerResource = (ManagedObjectReference)serviceUtil.getDynamicProperty(_mor, "parent");
|
||||
return (ManagedObjectReference)serviceUtil.getDynamicProperty(morComputerResource, "resourcePool");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedObjectReference getHyperHostCluster() throws Exception {
|
||||
ServiceUtil serviceUtil = _context.getServiceUtil();
|
||||
ManagedObjectReference morParent = (ManagedObjectReference)serviceUtil.getDynamicProperty(_mor, "parent");
|
||||
|
||||
if(morParent.getType().equalsIgnoreCase("ClusterComputeResource")) {
|
||||
return morParent;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw new Exception("Standalone host is not supported");
|
||||
}
|
||||
|
||||
public ManagedObjectReference[] getHostLocalDatastore() throws Exception {
|
||||
ServiceUtil serviceUtil = _context.getServiceUtil();
|
||||
ManagedObjectReference[] datastores = (ManagedObjectReference[])serviceUtil.getDynamicProperty(
|
||||
_mor, "datastore");
|
||||
List<ManagedObjectReference> l = new ArrayList<ManagedObjectReference>();
|
||||
if(datastores != null) {
|
||||
for(ManagedObjectReference mor : datastores) {
|
||||
DatastoreSummary summary = (DatastoreSummary)serviceUtil.getDynamicProperty(mor, "summary");
|
||||
if(summary.getType().equalsIgnoreCase("VMFS") && !summary.getMultipleHostAccess())
|
||||
l.add(mor);
|
||||
}
|
||||
}
|
||||
return l.toArray(new ManagedObjectReference[1]);
|
||||
}
|
||||
|
||||
public HostVirtualSwitch getHostVirtualSwitchByName(String name) throws Exception {
|
||||
HostVirtualSwitch[] switches = (HostVirtualSwitch[])_context.getServiceUtil().getDynamicProperty(
|
||||
_mor, "config.network.vswitch");
|
||||
|
||||
if(switches != null) {
|
||||
for(HostVirtualSwitch vswitch : switches) {
|
||||
if(vswitch.getName().equals(name))
|
||||
return vswitch;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public HostVirtualSwitch[] getHostVirtualSwitch() throws Exception {
|
||||
return (HostVirtualSwitch[])_context.getServiceUtil().getDynamicProperty(_mor, "config.network.vswitch");
|
||||
}
|
||||
|
||||
public AboutInfo getHostAboutInfo() throws Exception {
|
||||
return (AboutInfo)_context.getServiceUtil().getDynamicProperty(_mor, "config.product");
|
||||
}
|
||||
|
||||
public VmwareHostType getHostType() throws Exception {
|
||||
AboutInfo aboutInfo = getHostAboutInfo();
|
||||
if("VMware ESXi".equals(aboutInfo.getName()))
|
||||
return VmwareHostType.ESXi;
|
||||
else if("VMware ESX".equals(aboutInfo.getName()))
|
||||
return VmwareHostType.ESX;
|
||||
|
||||
throw new Exception("Unrecognized VMware host type " + aboutInfo.getName());
|
||||
}
|
||||
|
||||
// default virtual switch is which management network residents on
|
||||
public HostVirtualSwitch getHostDefaultVirtualSwitch() throws Exception {
|
||||
String managementPortGroup = getPortGroupNameByNicType(HostVirtualNicType.management);
|
||||
if(managementPortGroup != null)
|
||||
return getPortGroupVirtualSwitch(managementPortGroup);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public HostVirtualSwitch getPortGroupVirtualSwitch(String portGroupName) throws Exception {
|
||||
String vSwitchName = getPortGroupVirtualSwitchName(portGroupName);
|
||||
if(vSwitchName != null)
|
||||
return getVirtualSwitchByName(vSwitchName);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public HostVirtualSwitch getVirtualSwitchByName(String vSwitchName) throws Exception {
|
||||
|
||||
HostVirtualSwitch[] vSwitchs = getHostVirtualSwitch();
|
||||
if(vSwitchs != null) {
|
||||
for(HostVirtualSwitch vSwitch: vSwitchs) {
|
||||
if(vSwitch.getName().equals(vSwitchName))
|
||||
return vSwitch;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getPortGroupVirtualSwitchName(String portGroupName) throws Exception {
|
||||
HostNetworkInfo hostNetInfo = getHostNetworkInfo();
|
||||
HostPortGroup[] portGroups = hostNetInfo.getPortgroup();
|
||||
if(portGroups != null) {
|
||||
for(HostPortGroup portGroup : portGroups) {
|
||||
HostPortGroupSpec spec = portGroup.getSpec();
|
||||
if(spec.getName().equals(portGroupName))
|
||||
return spec.getVswitchName();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public HostPortGroupSpec getPortGroupSpec(String portGroupName) throws Exception {
|
||||
HostNetworkInfo hostNetInfo = getHostNetworkInfo();
|
||||
HostPortGroup[] portGroups = hostNetInfo.getPortgroup();
|
||||
if(portGroups != null) {
|
||||
for(HostPortGroup portGroup : portGroups) {
|
||||
HostPortGroupSpec spec = portGroup.getSpec();
|
||||
if(spec.getName().equals(portGroupName))
|
||||
return spec;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getPortGroupNameByNicType(HostVirtualNicType nicType) throws Exception {
|
||||
assert(nicType != null);
|
||||
|
||||
VirtualNicManagerNetConfig[] netConfigs = (VirtualNicManagerNetConfig[])_context.getServiceUtil().getDynamicProperty(_mor,
|
||||
"config.virtualNicManagerInfo.netConfig");
|
||||
|
||||
if(netConfigs != null) {
|
||||
for(VirtualNicManagerNetConfig netConfig : netConfigs) {
|
||||
if(netConfig.getNicType().equals(nicType.toString())) {
|
||||
HostVirtualNic[] nics = netConfig.getCandidateVnic();
|
||||
if(nics != null) {
|
||||
for(HostVirtualNic nic : nics) {
|
||||
return nic.getPortgroup();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(nicType == HostVirtualNicType.management) {
|
||||
// ESX management network is configured in service console
|
||||
HostNetworkInfo netInfo = getHostNetworkInfo();
|
||||
assert(netInfo != null);
|
||||
HostVirtualNic[] nics = netInfo.getConsoleVnic();
|
||||
if(nics != null) {
|
||||
for(HostVirtualNic nic : nics) {
|
||||
return nic.getPortgroup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasPortGroup(HostVirtualSwitch vSwitch, String portGroupName) throws Exception {
|
||||
ManagedObjectReference morNetwork = getNetworkMor(portGroupName);
|
||||
if(morNetwork != null)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void createPortGroup(HostVirtualSwitch vSwitch, String portGroupName, Integer vlanId, HostNetworkTrafficShapingPolicy shapingPolicy) throws Exception {
|
||||
assert(portGroupName != null);
|
||||
HostNetworkSystemMO hostNetMo = getHostNetworkSystemMO();
|
||||
assert(hostNetMo != null);
|
||||
|
||||
HostPortGroupSpec spec = new HostPortGroupSpec();
|
||||
|
||||
spec.setName(portGroupName);
|
||||
if(vlanId != null)
|
||||
spec.setVlanId(vlanId.intValue());
|
||||
HostNetworkPolicy policy = new HostNetworkPolicy();
|
||||
policy.setShapingPolicy(shapingPolicy);
|
||||
spec.setPolicy(policy);
|
||||
spec.setVswitchName(vSwitch.getName());
|
||||
hostNetMo.addPortGroup(spec);
|
||||
}
|
||||
|
||||
public void updatePortGroup(HostVirtualSwitch vSwitch, String portGroupName, Integer vlanId, HostNetworkTrafficShapingPolicy shapingPolicy) throws Exception {
|
||||
assert(portGroupName != null);
|
||||
HostNetworkSystemMO hostNetMo = getHostNetworkSystemMO();
|
||||
assert(hostNetMo != null);
|
||||
|
||||
HostPortGroupSpec spec = new HostPortGroupSpec();
|
||||
|
||||
spec.setName(portGroupName);
|
||||
if(vlanId != null)
|
||||
spec.setVlanId(vlanId.intValue());
|
||||
HostNetworkPolicy policy = new HostNetworkPolicy();
|
||||
policy.setShapingPolicy(shapingPolicy);
|
||||
spec.setPolicy(policy);
|
||||
spec.setVswitchName(vSwitch.getName());
|
||||
hostNetMo.updatePortGroup(portGroupName, spec);
|
||||
}
|
||||
|
||||
public void deletePortGroup(String portGroupName) throws Exception {
|
||||
assert(portGroupName != null);
|
||||
HostNetworkSystemMO hostNetMo = getHostNetworkSystemMO();
|
||||
assert(hostNetMo != null);
|
||||
hostNetMo.removePortGroup(portGroupName);
|
||||
}
|
||||
|
||||
public ManagedObjectReference getNetworkMor(String portGroupName) throws Exception {
|
||||
PropertySpec pSpec = new PropertySpec();
|
||||
pSpec.setType("Network");
|
||||
pSpec.setPathSet(new String[] {"summary.name"});
|
||||
|
||||
TraversalSpec host2NetworkTraversal = new TraversalSpec();
|
||||
host2NetworkTraversal.setType("HostSystem");
|
||||
host2NetworkTraversal.setPath("network");
|
||||
host2NetworkTraversal.setName("host2NetworkTraversal");
|
||||
|
||||
ObjectSpec oSpec = new ObjectSpec();
|
||||
oSpec.setObj(_mor);
|
||||
oSpec.setSkip(Boolean.TRUE);
|
||||
oSpec.setSelectSet(new SelectionSpec[] { host2NetworkTraversal });
|
||||
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.setPropSet(new PropertySpec[] { pSpec });
|
||||
pfSpec.setObjectSet(new ObjectSpec[] { oSpec });
|
||||
|
||||
ObjectContent[] ocs = _context.getService().retrieveProperties(
|
||||
_context.getServiceContent().getPropertyCollector(),
|
||||
new PropertyFilterSpec[] { pfSpec });
|
||||
|
||||
if(ocs != null) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
DynamicProperty[] props = oc.getPropSet();
|
||||
if(props != null) {
|
||||
for(DynamicProperty prop : props) {
|
||||
if(prop.getVal().equals(portGroupName))
|
||||
return oc.getObj();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ManagedObjectReference[] getVmMorsOnNetwork(String portGroupName) throws Exception {
|
||||
ManagedObjectReference morNetwork = getNetworkMor(portGroupName);
|
||||
if(morNetwork != null)
|
||||
return (ManagedObjectReference[])_context.getServiceUtil().getDynamicProperty(morNetwork, "vm");
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getHostName() throws Exception {
|
||||
return (String)_context.getServiceUtil().getDynamicProperty(_mor, "name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized VirtualMachineMO findVmOnHyperHost(String name) throws Exception {
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("find VM " + name + " on host");
|
||||
|
||||
VirtualMachineMO vmMo = _vmCache.get(name);
|
||||
if(vmMo != null) {
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("VM " + name + " found in host cache");
|
||||
return vmMo;
|
||||
}
|
||||
|
||||
loadVmCache();
|
||||
return _vmCache.get(name);
|
||||
}
|
||||
|
||||
private void loadVmCache() throws Exception {
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("load VM cache on host");
|
||||
|
||||
_vmCache.clear();
|
||||
|
||||
ObjectContent[] ocs = getVmPropertiesOnHyperHost(new String[] { "name" });
|
||||
if(ocs != null && ocs.length > 0) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
String vmName = oc.getPropSet()[0].getVal().toString();
|
||||
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("put " + vmName + " into host cache");
|
||||
|
||||
_vmCache.put(vmName, new VirtualMachineMO(_context, oc.getObj()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualMachineMO findVmOnPeerHyperHost(String name) throws Exception {
|
||||
ManagedObjectReference morParent = getParentMor();
|
||||
|
||||
if(morParent.getType().equals("ClusterComputeResource")) {
|
||||
ClusterMO clusterMo = new ClusterMO(_context, morParent);
|
||||
return clusterMo.findVmOnHyperHost(name);
|
||||
} else {
|
||||
// we don't support standalone host, all hosts have to be managed by
|
||||
// a cluster within vCenter
|
||||
assert(false);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createVm(VirtualMachineConfigSpec vmSpec) throws Exception {
|
||||
assert(vmSpec != null);
|
||||
DatacenterMO dcMo = new DatacenterMO(_context, getHyperHostDatacenter());
|
||||
ManagedObjectReference morPool = getHyperHostOwnerResourcePool();
|
||||
|
||||
ManagedObjectReference morTask = _context.getService().createVM_Task(
|
||||
dcMo.getVmFolder(), vmSpec, morPool, _mor);
|
||||
String result = _context.getServiceUtil().waitForTask(morTask);
|
||||
|
||||
if(result.equals("sucess")) {
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
return true;
|
||||
} else {
|
||||
s_logger.error("VMware createVM_Task failed due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public HashMap<String, Integer> getVmVncPortsOnHost() throws Exception {
|
||||
ObjectContent[] ocs = getVmPropertiesOnHyperHost(
|
||||
new String[] { "name", "config.extraConfig[\"RemoteDisplay.vnc.port\"]" }
|
||||
);
|
||||
|
||||
HashMap<String, Integer> portInfo = new HashMap<String, Integer>();
|
||||
if(ocs != null && ocs.length > 0) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
DynamicProperty[] objProps = oc.getPropSet();
|
||||
if(objProps != null) {
|
||||
String name = null;
|
||||
String value = null;
|
||||
for(DynamicProperty objProp : objProps) {
|
||||
if(objProp.getName().equals("name")) {
|
||||
name = (String)objProp.getVal();
|
||||
} else {
|
||||
OptionValue optValue = (OptionValue)objProp.getVal();
|
||||
value = (String)optValue.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
if(name != null && value != null) {
|
||||
portInfo.put(name, Integer.parseInt(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return portInfo;
|
||||
}
|
||||
|
||||
public ObjectContent[] getVmPropertiesOnHyperHost(String[] propertyPaths) throws Exception {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - retrieveProperties() for VM properties. target MOR: " + _mor.get_value() + ", properties: " + new Gson().toJson(propertyPaths));
|
||||
|
||||
PropertySpec pSpec = new PropertySpec();
|
||||
pSpec.setType("VirtualMachine");
|
||||
pSpec.setPathSet(propertyPaths);
|
||||
|
||||
TraversalSpec host2VmTraversal = new TraversalSpec();
|
||||
host2VmTraversal.setType("HostSystem");
|
||||
host2VmTraversal.setPath("vm");
|
||||
host2VmTraversal.setName("host2VmTraversal");
|
||||
|
||||
ObjectSpec oSpec = new ObjectSpec();
|
||||
oSpec.setObj(_mor);
|
||||
oSpec.setSkip(Boolean.TRUE);
|
||||
oSpec.setSelectSet(new SelectionSpec[] { host2VmTraversal });
|
||||
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.setPropSet(new PropertySpec[] { pSpec });
|
||||
pfSpec.setObjectSet(new ObjectSpec[] { oSpec });
|
||||
|
||||
ObjectContent[] properties = _context.getService().retrieveProperties(
|
||||
_context.getServiceContent().getPropertyCollector(),
|
||||
new PropertyFilterSpec[] { pfSpec });
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - retrieveProperties() done");
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectContent[] getDatastorePropertiesOnHyperHost(String[] propertyPaths) throws Exception {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - retrieveProperties() on Datastore properties. target MOR: " + _mor.get_value() + ", properties: " + new Gson().toJson(propertyPaths));
|
||||
|
||||
PropertySpec pSpec = new PropertySpec();
|
||||
pSpec.setType("Datastore");
|
||||
pSpec.setPathSet(propertyPaths);
|
||||
|
||||
TraversalSpec host2DatastoreTraversal = new TraversalSpec();
|
||||
host2DatastoreTraversal.setType("HostSystem");
|
||||
host2DatastoreTraversal.setPath("datastore");
|
||||
host2DatastoreTraversal.setName("host2DatastoreTraversal");
|
||||
|
||||
ObjectSpec oSpec = new ObjectSpec();
|
||||
oSpec.setObj(_mor);
|
||||
oSpec.setSkip(Boolean.TRUE);
|
||||
oSpec.setSelectSet(new SelectionSpec[] { host2DatastoreTraversal });
|
||||
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.setPropSet(new PropertySpec[] { pSpec });
|
||||
pfSpec.setObjectSet(new ObjectSpec[] { oSpec });
|
||||
|
||||
ObjectContent[] properties = _context.getService().retrieveProperties(
|
||||
_context.getServiceContent().getPropertyCollector(),
|
||||
new PropertyFilterSpec[] { pfSpec });
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - retrieveProperties() done");
|
||||
return properties;
|
||||
}
|
||||
|
||||
public List<Pair<ManagedObjectReference, String>> getDatastoreMountsOnHost() throws Exception {
|
||||
List<Pair<ManagedObjectReference, String>> mounts = new ArrayList<Pair<ManagedObjectReference, String>>();
|
||||
|
||||
ObjectContent[] ocs = getDatastorePropertiesOnHyperHost(new String[] {
|
||||
String.format("host[\"%s\"].mountInfo.path", _mor.get_value()) });
|
||||
if(ocs != null) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
Pair<ManagedObjectReference, String> mount = new Pair<ManagedObjectReference, String>(
|
||||
oc.getObj(), oc.getPropSet(0).getVal().toString());
|
||||
mounts.add(mount);
|
||||
}
|
||||
}
|
||||
return mounts;
|
||||
}
|
||||
|
||||
public List<Pair<ManagedObjectReference, String>> getLocalDatastoreOnHost() throws Exception {
|
||||
List<Pair<ManagedObjectReference, String>> dsList = new ArrayList<Pair<ManagedObjectReference, String>>();
|
||||
|
||||
ObjectContent[] ocs = getDatastorePropertiesOnHyperHost(new String[] { "name", "summary" });
|
||||
if(ocs != null) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
DatastoreSummary dsSummary = (DatastoreSummary)VmwareHelper.getPropValue(oc, "summary");
|
||||
if(dsSummary.getMultipleHostAccess() == false) {
|
||||
ManagedObjectReference morDs = oc.getObj();
|
||||
String name = (String)VmwareHelper.getPropValue(oc, "name");
|
||||
|
||||
dsList.add(new Pair<ManagedObjectReference, String>(morDs, name));
|
||||
}
|
||||
}
|
||||
}
|
||||
return dsList;
|
||||
}
|
||||
|
||||
public void importVmFromOVF(String ovfFilePath, String vmName, String datastoreName, String diskOption) throws Exception {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - importVmFromOVF(). target MOR: " + _mor.get_value() + ", ovfFilePath: " + ovfFilePath + ", vmName: " + vmName
|
||||
+ ",datastoreName: " + datastoreName + ", diskOption: " + diskOption);
|
||||
|
||||
DatastoreMO dsMo = getHostDatastoreMO(datastoreName);
|
||||
if(dsMo == null)
|
||||
throw new Exception("Invalid datastore name: " + datastoreName);
|
||||
|
||||
importVmFromOVF(ovfFilePath, vmName, dsMo, diskOption);
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - importVmFromOVF() done");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void importVmFromOVF(String ovfFilePath, String vmName, DatastoreMO dsMo, String diskOption) throws Exception {
|
||||
|
||||
ManagedObjectReference morRp = getHyperHostOwnerResourcePool();
|
||||
assert(morRp != null);
|
||||
|
||||
HypervisorHostHelper.importVmFromOVF(this, ovfFilePath, vmName, dsMo, diskOption, morRp, _mor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createBlankVm(String vmName, int cpuCount, int cpuSpeedMHz, int cpuReservedMHz, boolean limitCpuUse, int memoryMB,
|
||||
String guestOsIdentifier, ManagedObjectReference morDs, boolean snapshotDirToParent) throws Exception {
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - createBlankVm(). target MOR: " + _mor.get_value() + ", vmName: " + vmName + ", cpuCount: " + cpuCount
|
||||
+ ", cpuSpeedMhz: " + cpuSpeedMHz + ", cpuReservedMHz: " + cpuReservedMHz + ", limitCpu: " + limitCpuUse + ", memoryMB: " + memoryMB
|
||||
+ ", guestOS: " + guestOsIdentifier + ", datastore: " + morDs.get_value() + ", snapshotDirToParent: " + snapshotDirToParent);
|
||||
|
||||
boolean result = HypervisorHostHelper.createBlankVm(this, vmName, cpuCount, cpuSpeedMHz, cpuReservedMHz, limitCpuUse,
|
||||
memoryMB, guestOsIdentifier, morDs, snapshotDirToParent);
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - createBlankVm() done");
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedObjectReference mountDatastore(boolean vmfsDatastore, String poolHostAddress,
|
||||
int poolHostPort, String poolPath, String poolUuid) throws Exception {
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - mountDatastore(). target MOR: " + _mor.get_value() + ", vmfs: " + vmfsDatastore + ", poolHost: " + poolHostAddress
|
||||
+ ", poolHostPort: " + poolHostPort + ", poolPath: " + poolPath + ", poolUuid: " + poolUuid);
|
||||
|
||||
HostDatastoreSystemMO hostDatastoreSystemMo = getHostDatastoreSystemMO();
|
||||
ManagedObjectReference morDatastore = hostDatastoreSystemMo.findDatastore(poolUuid);
|
||||
if(morDatastore == null) {
|
||||
if(!vmfsDatastore) {
|
||||
morDatastore = hostDatastoreSystemMo.createNfsDatastore(
|
||||
poolHostAddress,
|
||||
poolHostPort,
|
||||
poolPath,
|
||||
poolUuid);
|
||||
if(morDatastore == null) {
|
||||
String msg = "Unable to create NFS datastore. host: " + poolHostAddress + ", port: "
|
||||
+ poolHostPort + ", path: " + poolPath + ", uuid: " + poolUuid;
|
||||
s_logger.error(msg);
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - mountDatastore() done(failed)");
|
||||
throw new Exception(msg);
|
||||
}
|
||||
} else {
|
||||
morDatastore = _context.getDatastoreMorByPath(poolPath);
|
||||
if(morDatastore == null) {
|
||||
String msg = "Unable to create VMFS datastore. host: " + poolHostAddress + ", port: "
|
||||
+ poolHostPort + ", path: " + poolPath + ", uuid: " + poolUuid;
|
||||
s_logger.error(msg);
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - mountDatastore() done(failed)");
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
DatastoreMO dsMo = new DatastoreMO(_context, morDatastore);
|
||||
dsMo.setCustomFieldValue(CustomFieldConstants.CLOUD_UUID, poolUuid);
|
||||
}
|
||||
}
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - mountDatastore() done(successfully)");
|
||||
|
||||
return morDatastore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unmountDatastore(String poolUuid) throws Exception {
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - unmountDatastore(). target MOR: " + _mor.get_value() + ", poolUuid: " + poolUuid);
|
||||
|
||||
HostDatastoreSystemMO hostDatastoreSystemMo = getHostDatastoreSystemMO();
|
||||
if(!hostDatastoreSystemMo.deleteDatastore(poolUuid)) {
|
||||
String msg = "Unable to unmount datastore. uuid: " + poolUuid;
|
||||
s_logger.error(msg);
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - unmountDatastore() done(failed)");
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - unmountDatastore() done");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedObjectReference findDatastore(String poolUuid) throws Exception {
|
||||
HostDatastoreSystemMO hostDsMo = getHostDatastoreSystemMO();
|
||||
return hostDsMo.findDatastore(poolUuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedObjectReference findDatastoreByExportPath(String exportPath) throws Exception {
|
||||
HostDatastoreSystemMO datastoreSystemMo = getHostDatastoreSystemMO();
|
||||
return datastoreSystemMo.findDatastoreByExportPath(exportPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedObjectReference findMigrationTarget(VirtualMachineMO vmMo) throws Exception {
|
||||
return _mor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VmwareHypervisorHostResourceSummary getHyperHostResourceSummary() throws Exception {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - getHyperHostResourceSummary(). target MOR: " + _mor.get_value());
|
||||
|
||||
VmwareHypervisorHostResourceSummary summary = new VmwareHypervisorHostResourceSummary();
|
||||
|
||||
HostConnectInfo hostInfo = _context.getService().queryHostConnectionInfo(_mor);
|
||||
HostHardwareSummary hardwareSummary = hostInfo.getHost().getHardware();
|
||||
|
||||
// TODO: not sure how hyper-thread is counted in VMware resource pool
|
||||
summary.setCpuCount(hardwareSummary.getNumCpuCores()*hardwareSummary.getNumCpuPkgs());
|
||||
summary.setMemoryBytes(hardwareSummary.getMemorySize());
|
||||
summary.setCpuSpeed(hardwareSummary.getCpuMhz());
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - getHyperHostResourceSummary() done");
|
||||
return summary;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VmwareHypervisorHostNetworkSummary getHyperHostNetworkSummary(String managementPortGroup) throws Exception {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - getHyperHostNetworkSummary(). target MOR: " + _mor.get_value() + ", mgmtPortgroup: " + managementPortGroup);
|
||||
|
||||
VmwareHypervisorHostNetworkSummary summary = new VmwareHypervisorHostNetworkSummary();
|
||||
|
||||
if(this.getHostType() == VmwareHostType.ESXi) {
|
||||
VirtualNicManagerNetConfig[] netConfigs = (VirtualNicManagerNetConfig[])_context.getServiceUtil().getDynamicProperty(_mor,
|
||||
"config.virtualNicManagerInfo.netConfig");
|
||||
assert(netConfigs != null);
|
||||
|
||||
for(int i = 0; i < netConfigs.length; i++) {
|
||||
if(netConfigs[i].getNicType().equals("management")) {
|
||||
for(HostVirtualNic nic : netConfigs[i].getCandidateVnic()) {
|
||||
if(nic.getPortgroup().equals(managementPortGroup)) {
|
||||
summary.setHostIp(nic.getSpec().getIp().getIpAddress());
|
||||
summary.setHostNetmask(nic.getSpec().getIp().getSubnetMask());
|
||||
summary.setHostMacAddress(nic.getSpec().getMac());
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - getHyperHostNetworkSummary() done(successfully)");
|
||||
return summary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// try with ESX path
|
||||
HostVirtualNic[] hostVNics = (HostVirtualNic[])_context.getServiceUtil().getDynamicProperty(_mor,
|
||||
"config.network.consoleVnic");
|
||||
|
||||
if(hostVNics != null) {
|
||||
for(HostVirtualNic vnic : hostVNics) {
|
||||
if(vnic.getPortgroup().equals(managementPortGroup)) {
|
||||
summary.setHostIp(vnic.getSpec().getIp().getIpAddress());
|
||||
summary.setHostNetmask(vnic.getSpec().getIp().getSubnetMask());
|
||||
summary.setHostMacAddress(vnic.getSpec().getMac());
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - getHyperHostNetworkSummary() done(successfully)");
|
||||
return summary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - getHyperHostNetworkSummary() done(failed)");
|
||||
throw new Exception("Uanble to find management port group " + managementPortGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComputeResourceSummary getHyperHostHardwareSummary() throws Exception {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - getHyperHostHardwareSummary(). target MOR: " + _mor.get_value());
|
||||
|
||||
//
|
||||
// This is to adopt the model when using Cluster as a big host while ComputeResourceSummary is used
|
||||
// directly from VMware resource pool
|
||||
//
|
||||
// When we break cluster hosts into individual hosts used in our resource allocator,
|
||||
// we will have to populate ComputeResourceSummary by ourselves here
|
||||
//
|
||||
HostHardwareSummary hardwareSummary = getHostHardwareSummary();
|
||||
|
||||
ComputeResourceSummary resourceSummary = new ComputeResourceSummary();
|
||||
|
||||
// TODO: not sure how hyper-threading is counted in VMware
|
||||
short totalCores = (short)(hardwareSummary.getNumCpuCores()*hardwareSummary.getNumCpuPkgs());
|
||||
resourceSummary.setNumCpuCores(totalCores);
|
||||
|
||||
// Note: memory here is in Byte unit
|
||||
resourceSummary.setTotalMemory(hardwareSummary.getMemorySize());
|
||||
|
||||
// Total CPU is based on socket x core x Mhz
|
||||
int totalCpu = hardwareSummary.getCpuMhz() * totalCores;
|
||||
resourceSummary.setTotalCpu(totalCpu);
|
||||
|
||||
HostListSummaryQuickStats stats = getHostQuickStats();
|
||||
if(stats.getOverallCpuUsage() == null || stats.getOverallMemoryUsage() == null)
|
||||
throw new Exception("Unable to get valid overal CPU/Memory usage data, host may be disconnected");
|
||||
|
||||
resourceSummary.setEffectiveCpu(totalCpu - stats.getOverallCpuUsage());
|
||||
|
||||
// Note effective memory is in MB unit
|
||||
resourceSummary.setEffectiveMemory(hardwareSummary.getMemorySize()/(1024*1024) - stats.getOverallMemoryUsage());
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - getHyperHostHardwareSummary() done");
|
||||
return resourceSummary;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHyperHostConnected() throws Exception {
|
||||
HostRuntimeInfo runtimeInfo = (HostRuntimeInfo)_context.getServiceUtil().getDynamicProperty(_mor, "runtime");
|
||||
return runtimeInfo.getConnectionState() == HostSystemConnectionState.connected;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.vmware.vim25.HostPortGroupSpec;
|
||||
import com.vmware.vim25.HostVirtualSwitchSpec;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
|
||||
public class HostNetworkSystemMO extends BaseMO {
|
||||
private static final Logger s_logger = Logger.getLogger(HostNetworkSystemMO.class);
|
||||
|
||||
public HostNetworkSystemMO(VmwareContext context, ManagedObjectReference morNetworkSystem) {
|
||||
super(context, morNetworkSystem);
|
||||
}
|
||||
|
||||
public HostNetworkSystemMO(VmwareContext context, String morType, String morValue) {
|
||||
super(context, morType, morValue);
|
||||
}
|
||||
|
||||
public void addPortGroup(HostPortGroupSpec spec) throws Exception {
|
||||
_context.getService().addPortGroup(_mor, spec);
|
||||
}
|
||||
|
||||
public void updatePortGroup(String portGroupName, HostPortGroupSpec spec) throws Exception {
|
||||
_context.getService().updatePortGroup(_mor, portGroupName, spec);
|
||||
}
|
||||
|
||||
public void removePortGroup(String portGroupName) throws Exception {
|
||||
_context.getService().removePortGroup(_mor, portGroupName);
|
||||
}
|
||||
|
||||
public void addVirtualSwitch(String vSwitchName, HostVirtualSwitchSpec spec) throws Exception {
|
||||
_context.getService().addVirtualSwitch(_mor, vSwitchName, spec);
|
||||
}
|
||||
|
||||
public void updateVirtualSwitch(String vSwitchName, HostVirtualSwitchSpec spec) throws Exception {
|
||||
_context.getService().updateVirtualSwitch(_mor, vSwitchName, spec);
|
||||
}
|
||||
|
||||
public void removeVirtualSwitch(String vSwitchName) throws Exception {
|
||||
_context.getService().removeVirtualSwitch(_mor, vSwitchName);
|
||||
}
|
||||
|
||||
public void refresh() throws Exception {
|
||||
_context.getService().refreshNetworkSystem(_mor);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
public enum HostVirtualNicType {
|
||||
management,
|
||||
vmotion,
|
||||
faultToleranceLogging
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.vmware.vim25.HttpNfcLeaseInfo;
|
||||
import com.vmware.vim25.HttpNfcLeaseManifestEntry;
|
||||
import com.vmware.vim25.HttpNfcLeaseState;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.OvfCreateImportSpecResult;
|
||||
import com.vmware.vim25.OvfFileItem;
|
||||
|
||||
public class HttpNfcLeaseMO extends BaseMO {
|
||||
private static final Logger s_logger = Logger.getLogger(HttpNfcLeaseMO.class);
|
||||
|
||||
public HttpNfcLeaseMO(VmwareContext context, ManagedObjectReference morHttpNfcLease) {
|
||||
super(context, morHttpNfcLease);
|
||||
}
|
||||
|
||||
public HttpNfcLeaseMO(VmwareContext context, String morType, String morValue) {
|
||||
super(context, morType, morValue);
|
||||
}
|
||||
|
||||
public HttpNfcLeaseState getState() throws Exception {
|
||||
return (HttpNfcLeaseState)_context.getServiceUtil().getDynamicProperty(_mor, "state");
|
||||
}
|
||||
|
||||
public HttpNfcLeaseState waitState(HttpNfcLeaseState[] states) throws Exception {
|
||||
assert(states != null);
|
||||
assert(states.length > 0);
|
||||
|
||||
HttpNfcLeaseState state;
|
||||
while(true) {
|
||||
state = getState();
|
||||
if(state == HttpNfcLeaseState.ready || state == HttpNfcLeaseState.error)
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
public HttpNfcLeaseInfo getLeaseInfo() throws Exception {
|
||||
return (HttpNfcLeaseInfo)_context.getServiceUtil().getDynamicProperty(_mor, "info");
|
||||
}
|
||||
|
||||
public HttpNfcLeaseManifestEntry[] getLeaseManifest() throws Exception {
|
||||
return _context.getService().httpNfcLeaseGetManifest(_mor);
|
||||
}
|
||||
|
||||
public void completeLease() throws Exception {
|
||||
_context.getService().httpNfcLeaseComplete(_mor);
|
||||
}
|
||||
|
||||
public void abortLease() throws Exception {
|
||||
_context.getService().httpNfcLeaseAbort(_mor, null);
|
||||
}
|
||||
|
||||
public void updateLeaseProgress(int percent) throws Exception {
|
||||
// make sure percentage is in right range
|
||||
if(percent < 0)
|
||||
percent = 0;
|
||||
else if(percent > 100)
|
||||
percent = 100;
|
||||
|
||||
_context.getService().httpNfcLeaseProgress(_mor, percent);
|
||||
}
|
||||
|
||||
public ProgressReporter createProgressReporter() {
|
||||
return new ProgressReporter();
|
||||
}
|
||||
|
||||
public static long calcTotalBytes(OvfCreateImportSpecResult ovfImportResult) {
|
||||
OvfFileItem[] fileItemArr = ovfImportResult.getFileItem();
|
||||
long totalBytes = 0;
|
||||
if (fileItemArr != null) {
|
||||
for (OvfFileItem fi : fileItemArr) {
|
||||
totalBytes += fi.getSize();
|
||||
}
|
||||
}
|
||||
return totalBytes;
|
||||
}
|
||||
|
||||
public static String readOvfContent(String ovfFilePath) throws IOException {
|
||||
StringBuffer strContent = new StringBuffer();
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(ovfFilePath)));
|
||||
String lineStr;
|
||||
while ((lineStr = in.readLine()) != null) {
|
||||
strContent.append(lineStr);
|
||||
}
|
||||
|
||||
in.close();
|
||||
return strContent.toString();
|
||||
}
|
||||
|
||||
public class ProgressReporter extends Thread {
|
||||
volatile int _percent;
|
||||
volatile boolean _done;
|
||||
|
||||
public ProgressReporter() {
|
||||
_percent = 0;
|
||||
_done = false;
|
||||
|
||||
setDaemon(true);
|
||||
start();
|
||||
}
|
||||
|
||||
public void reportProgress(int percent) {
|
||||
_percent = percent;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("close ProgressReporter, interrupt reporter runner to let it quit");
|
||||
|
||||
_done = true;
|
||||
interrupt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while(!_done) {
|
||||
try {
|
||||
Thread.sleep(1000); // update progess every 1 second
|
||||
updateLeaseProgress(_percent);
|
||||
} catch(InterruptedException e) {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("ProgressReporter is interrupted, quiting");
|
||||
break;
|
||||
} catch(Exception e) {
|
||||
s_logger.warn("Unexpected exception ", e);
|
||||
}
|
||||
}
|
||||
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("ProgressReporter stopped");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,538 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareHelper;
|
||||
import com.cloud.utils.ActionDelegate;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.GlobalLock;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
import com.vmware.vim25.DynamicProperty;
|
||||
import com.vmware.vim25.HostNetworkTrafficShapingPolicy;
|
||||
import com.vmware.vim25.HostVirtualSwitch;
|
||||
import com.vmware.vim25.HttpNfcLeaseDeviceUrl;
|
||||
import com.vmware.vim25.HttpNfcLeaseInfo;
|
||||
import com.vmware.vim25.HttpNfcLeaseState;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.ObjectContent;
|
||||
import com.vmware.vim25.OvfCreateImportSpecParams;
|
||||
import com.vmware.vim25.OvfCreateImportSpecResult;
|
||||
import com.vmware.vim25.OvfFileItem;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpec;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
|
||||
import com.vmware.vim25.VirtualLsiLogicController;
|
||||
import com.vmware.vim25.VirtualMachineConfigSpec;
|
||||
import com.vmware.vim25.VirtualMachineFileInfo;
|
||||
import com.vmware.vim25.VirtualMachineVideoCard;
|
||||
import com.vmware.vim25.VirtualSCSISharing;
|
||||
|
||||
public class HypervisorHostHelper {
|
||||
private static final Logger s_logger = Logger.getLogger(HypervisorHostHelper.class);
|
||||
private static final int DEFAULT_LOCK_TIMEOUT_SECONDS = 600;
|
||||
|
||||
// make vmware-base loosely coupled with cloud-specific stuff, duplicate VLAN.UNTAGGED constant here
|
||||
private static final String UNTAGGED_VLAN_NAME = "untagged";
|
||||
|
||||
public static VirtualMachineMO findVmFromObjectContent(VmwareContext context,
|
||||
ObjectContent[] ocs, String name) {
|
||||
|
||||
if(ocs != null && ocs.length > 0) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
DynamicProperty prop = oc.getPropSet(0);
|
||||
assert(prop != null);
|
||||
if(prop.getVal().toString().equals(name))
|
||||
return new VirtualMachineMO(context, oc.getObj());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static DatastoreMO getHyperHostDatastoreMO(VmwareHypervisorHost hyperHost, String datastoreName) throws Exception {
|
||||
ObjectContent[] ocs = hyperHost.getDatastorePropertiesOnHyperHost(new String[] { "name"} );
|
||||
if(ocs != null && ocs.length > 0) {
|
||||
for(ObjectContent oc : ocs) {
|
||||
DynamicProperty[] objProps = oc.getPropSet();
|
||||
if(objProps != null) {
|
||||
for(DynamicProperty objProp : objProps) {
|
||||
if(objProp.getVal().toString().equals(datastoreName))
|
||||
return new DatastoreMO(hyperHost.getContext(), oc.getObj());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getPublicNetworkNamePrefix(String vlanId) {
|
||||
if (UNTAGGED_VLAN_NAME.equalsIgnoreCase(vlanId)) {
|
||||
return "cloud.public.untagged";
|
||||
} else {
|
||||
return "cloud.public." + vlanId;
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized Pair<ManagedObjectReference, String> preparePublicNetwork(String vSwitchName,
|
||||
HostMO hostMo, String vlanId, Integer networkRateMbps, Integer networkRateMulticastMbps, long timeOutMs, boolean syncPeerHosts) throws Exception {
|
||||
|
||||
HostVirtualSwitch vSwitch = hostMo.getHostVirtualSwitchByName(vSwitchName);
|
||||
if (vSwitch == null) {
|
||||
String msg = "Unable to find vSwitch configured for public network";
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
boolean createGCTag = false;
|
||||
String networkName;
|
||||
Integer vid = null;
|
||||
if(vlanId != null && !UNTAGGED_VLAN_NAME.equalsIgnoreCase(vlanId)) {
|
||||
createGCTag = true;
|
||||
vid = Integer.parseInt(vlanId);
|
||||
}
|
||||
|
||||
networkName = composeCloudNetworkName("cloud.public", vlanId, networkRateMbps, vSwitchName);
|
||||
|
||||
HostNetworkTrafficShapingPolicy shapingPolicy = null;
|
||||
if(networkRateMbps != null && networkRateMbps.intValue() > 0) {
|
||||
shapingPolicy = new HostNetworkTrafficShapingPolicy();
|
||||
shapingPolicy.setEnabled(true);
|
||||
shapingPolicy.setAverageBandwidth((long)networkRateMbps.intValue()*1024L*1024L);
|
||||
|
||||
//
|
||||
// TODO : people may have different opinion on how to set the following
|
||||
//
|
||||
|
||||
// give 50% premium to peek
|
||||
shapingPolicy.setPeakBandwidth((long)(shapingPolicy.getAverageBandwidth()*1.5));
|
||||
|
||||
// allow 5 seconds of burst transfer
|
||||
shapingPolicy.setBurstSize(5*shapingPolicy.getAverageBandwidth()/8);
|
||||
}
|
||||
|
||||
if (!hostMo.hasPortGroup(vSwitch, networkName)) {
|
||||
hostMo.createPortGroup(vSwitch, networkName, vid, shapingPolicy);
|
||||
} else {
|
||||
hostMo.updatePortGroup(vSwitch, networkName, vid, shapingPolicy);
|
||||
}
|
||||
|
||||
ManagedObjectReference morNetwork = waitForNetworkReady(hostMo, networkName, timeOutMs);
|
||||
if (morNetwork == null) {
|
||||
String msg = "Failed to create public network on vSwitch " + vSwitchName;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
if(createGCTag) {
|
||||
NetworkMO networkMo = new NetworkMO(hostMo.getContext(), morNetwork);
|
||||
networkMo.setCustomFieldValue(CustomFieldConstants.CLOUD_GC, "true");
|
||||
}
|
||||
|
||||
if(syncPeerHosts) {
|
||||
ManagedObjectReference morParent = hostMo.getParentMor();
|
||||
if(morParent != null && morParent.getType().equals("ClusterComputeResource")) {
|
||||
|
||||
// to be conservative, lock cluster
|
||||
GlobalLock lock = GlobalLock.getInternLock("ClusterLock." + morParent.get_value());
|
||||
try {
|
||||
if(lock.lock(DEFAULT_LOCK_TIMEOUT_SECONDS)) {
|
||||
try {
|
||||
ManagedObjectReference[] hosts = (ManagedObjectReference[])hostMo.getContext().getServiceUtil().getDynamicProperty(morParent, "host");
|
||||
if(hosts != null) {
|
||||
for(ManagedObjectReference otherHost: hosts) {
|
||||
if(!otherHost.get_value().equals(hostMo.getMor().get_value())) {
|
||||
HostMO otherHostMo = new HostMO(hostMo.getContext(), otherHost);
|
||||
try {
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("prepare public network on other host, vlan: " + vlanId + ", host: " + otherHostMo.getHostName());
|
||||
preparePublicNetwork(vSwitchName, otherHostMo, vlanId, networkRateMbps, networkRateMulticastMbps, timeOutMs, false);
|
||||
} catch(Exception e) {
|
||||
s_logger.warn("Unable to prepare public network on other host, vlan: " + vlanId + ", host: " + otherHostMo.getHostName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
} else {
|
||||
s_logger.warn("Unable to lock cluster to prepare public network, vlan: " + vlanId);
|
||||
}
|
||||
} finally {
|
||||
lock.releaseRef();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_logger.info("Network " + networkName + " is ready on vSwitch " + vSwitchName);
|
||||
return new Pair<ManagedObjectReference, String>(morNetwork, networkName);
|
||||
}
|
||||
|
||||
public static Pair<ManagedObjectReference, String> preparePrivateNetwork(String vSwitchName,
|
||||
HostMO hostMo, Integer vlanId, long timeOutMs) throws Exception {
|
||||
|
||||
HostVirtualSwitch vSwitch = hostMo.getHostVirtualSwitchByName(vSwitchName);
|
||||
if (vSwitch == null) {
|
||||
String msg = "Unable to find vSwitch configured for private network";
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
String networkName;
|
||||
networkName = composeCloudNetworkName("cloud.private", vlanId == null ? null : String.valueOf(vlanId), null, vSwitchName);
|
||||
|
||||
if (!hostMo.hasPortGroup(vSwitch, networkName)) {
|
||||
hostMo.createPortGroup(vSwitch, networkName, vlanId, null);
|
||||
}
|
||||
|
||||
ManagedObjectReference morNetwork = waitForNetworkReady(hostMo, networkName, timeOutMs);
|
||||
if (morNetwork == null) {
|
||||
String msg = "Failed to create private network";
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
s_logger.info("Network " + networkName + " is ready on vSwitch " + vSwitchName);
|
||||
return new Pair<ManagedObjectReference, String>(morNetwork, networkName);
|
||||
}
|
||||
|
||||
public static String composeCloudNetworkName(String prefix, String vlanId, Integer networkRateMbps, String vSwitchName) {
|
||||
StringBuffer sb = new StringBuffer(prefix);
|
||||
if(vlanId == null || UNTAGGED_VLAN_NAME.equalsIgnoreCase(vlanId))
|
||||
sb.append(".untagged");
|
||||
else
|
||||
sb.append(".").append(vlanId);
|
||||
|
||||
if(networkRateMbps != null && networkRateMbps.intValue() > 0)
|
||||
sb.append(".").append(String.valueOf(networkRateMbps));
|
||||
else
|
||||
sb.append(".0");
|
||||
sb.append(".").append(VersioningContants.PORTGROUP_NAMING_VERSION);
|
||||
sb.append("-").append(vSwitchName);
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static Pair<ManagedObjectReference, String> prepareGuestNetwork(String vSwitchName,
|
||||
HostMO hostMo, String vlanId, Integer networkRateMbps, Integer networkRateMulticastMbps,
|
||||
long timeOutMs, boolean syncPeerHosts) throws Exception {
|
||||
|
||||
HostVirtualSwitch vSwitch;
|
||||
vSwitch = hostMo.getHostVirtualSwitchByName(vSwitchName);
|
||||
|
||||
if (vSwitch == null) {
|
||||
String msg = "Unable to find the default virtual switch";
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
boolean createGCTag = false;
|
||||
String networkName;
|
||||
Integer vid = null;
|
||||
|
||||
if(vlanId != null && !UNTAGGED_VLAN_NAME.equalsIgnoreCase(vlanId)) {
|
||||
createGCTag = true;
|
||||
vid = Integer.parseInt(vlanId);
|
||||
}
|
||||
|
||||
networkName = composeCloudNetworkName("cloud.guest", vlanId, networkRateMbps, vSwitchName);
|
||||
|
||||
HostNetworkTrafficShapingPolicy shapingPolicy = null;
|
||||
if(networkRateMbps != null && networkRateMbps.intValue() > 0) {
|
||||
shapingPolicy = new HostNetworkTrafficShapingPolicy();
|
||||
shapingPolicy.setEnabled(true);
|
||||
shapingPolicy.setAverageBandwidth((long)networkRateMbps.intValue()*1024L*1024L);
|
||||
|
||||
//
|
||||
// TODO : people may have different opinion on how to set the following
|
||||
//
|
||||
|
||||
// give 50% premium to peek
|
||||
shapingPolicy.setPeakBandwidth((long)(shapingPolicy.getAverageBandwidth()*1.5));
|
||||
|
||||
// allow 5 seconds of burst transfer
|
||||
shapingPolicy.setBurstSize(5*shapingPolicy.getAverageBandwidth()/8);
|
||||
}
|
||||
|
||||
if (!hostMo.hasPortGroup(vSwitch, networkName)) {
|
||||
hostMo.createPortGroup(vSwitch, networkName, vid, shapingPolicy);
|
||||
} else {
|
||||
hostMo.updatePortGroup(vSwitch, networkName, vid, shapingPolicy);
|
||||
}
|
||||
|
||||
ManagedObjectReference morNetwork = waitForNetworkReady(hostMo, networkName, timeOutMs);
|
||||
if (morNetwork == null) {
|
||||
String msg = "Failed to create guest network " + networkName;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
if(createGCTag) {
|
||||
NetworkMO networkMo = new NetworkMO(hostMo.getContext(), morNetwork);
|
||||
networkMo.setCustomFieldValue(CustomFieldConstants.CLOUD_GC, "true");
|
||||
}
|
||||
|
||||
if(syncPeerHosts) {
|
||||
ManagedObjectReference morParent = hostMo.getParentMor();
|
||||
if(morParent != null && morParent.getType().equals("ClusterComputeResource")) {
|
||||
// to be conservative, lock cluster
|
||||
GlobalLock lock = GlobalLock.getInternLock("ClusterLock." + morParent.get_value());
|
||||
try {
|
||||
if(lock.lock(DEFAULT_LOCK_TIMEOUT_SECONDS)) {
|
||||
try {
|
||||
ManagedObjectReference[] hosts = (ManagedObjectReference[])hostMo.getContext().getServiceUtil().getDynamicProperty(morParent, "host");
|
||||
if(hosts != null) {
|
||||
for(ManagedObjectReference otherHost: hosts) {
|
||||
if(!otherHost.get_value().equals(hostMo.getMor().get_value())) {
|
||||
HostMO otherHostMo = new HostMO(hostMo.getContext(), otherHost);
|
||||
try {
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("Prepare guest network on other host, vlan: " + vlanId + ", host: " + otherHostMo.getHostName());
|
||||
prepareGuestNetwork(vSwitchName, otherHostMo, vlanId, networkRateMbps, networkRateMulticastMbps, timeOutMs, false);
|
||||
} catch(Exception e) {
|
||||
s_logger.warn("Unable to prepare guest network on other host, vlan: " + vlanId + ", host: " + otherHostMo.getHostName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
} else {
|
||||
s_logger.warn("Unable to lock cluster to prepare guest network, vlan: " + vlanId);
|
||||
}
|
||||
} finally {
|
||||
lock.releaseRef();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_logger.info("Network " + networkName + " is ready on vSwitch " + vSwitchName);
|
||||
return new Pair<ManagedObjectReference, String>(morNetwork, networkName);
|
||||
}
|
||||
|
||||
public static ManagedObjectReference waitForNetworkReady(HostMO hostMo,
|
||||
String networkName, long timeOutMs) throws Exception {
|
||||
|
||||
ManagedObjectReference morNetwork = null;
|
||||
|
||||
// if portGroup is just created, getNetwork may fail to retrieve it, we
|
||||
// need to retry
|
||||
long startTick = System.currentTimeMillis();
|
||||
while (System.currentTimeMillis() - startTick <= timeOutMs) {
|
||||
morNetwork = hostMo.getNetworkMor(networkName);
|
||||
if (morNetwork != null) {
|
||||
break;
|
||||
}
|
||||
|
||||
s_logger.info("Waiting for network " + networkName + " to be ready");
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
|
||||
return morNetwork;
|
||||
}
|
||||
|
||||
public static boolean createBlankVm(VmwareHypervisorHost host, String vmName,
|
||||
int cpuCount, int cpuSpeedMHz, int cpuReservedMHz, boolean limitCpuUse, int memoryMB, String guestOsIdentifier,
|
||||
ManagedObjectReference morDs, boolean snapshotDirToParent) throws Exception {
|
||||
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("Create blank VM. cpuCount: " + cpuCount + ", cpuSpeed(MHz): " + cpuSpeedMHz + ", mem(Mb): " + memoryMB);
|
||||
|
||||
// VM config basics
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
vmConfig.setName(vmName);
|
||||
VmwareHelper.setBasicVmConfig(vmConfig, cpuCount, cpuSpeedMHz, cpuReservedMHz, memoryMB, guestOsIdentifier, limitCpuUse);
|
||||
|
||||
// Scsi controller
|
||||
VirtualLsiLogicController scsiController = new VirtualLsiLogicController();
|
||||
scsiController.setSharedBus(VirtualSCSISharing.noSharing);
|
||||
scsiController.setBusNumber(0);
|
||||
scsiController.setKey(1);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.add);
|
||||
|
||||
VirtualMachineFileInfo fileInfo = new VirtualMachineFileInfo();
|
||||
DatastoreMO dsMo = new DatastoreMO(host.getContext(), morDs);
|
||||
fileInfo.setVmPathName(String.format("[%s]", dsMo.getName()));
|
||||
vmConfig.setFiles(fileInfo);
|
||||
|
||||
VirtualMachineVideoCard videoCard = new VirtualMachineVideoCard();
|
||||
videoCard.setControllerKey(100);
|
||||
videoCard.setUseAutoDetect(true);
|
||||
|
||||
VirtualDeviceConfigSpec videoDeviceSpec = new VirtualDeviceConfigSpec();
|
||||
videoDeviceSpec.setDevice(videoCard);
|
||||
videoDeviceSpec.setOperation(VirtualDeviceConfigSpecOperation.add);
|
||||
|
||||
vmConfig.setDeviceChange(new VirtualDeviceConfigSpec[] { scsiControllerSpec, videoDeviceSpec });
|
||||
if(host.createVm(vmConfig)) {
|
||||
VirtualMachineMO vmMo = host.findVmOnHyperHost(vmName);
|
||||
assert(vmMo != null);
|
||||
|
||||
int ideControllerKey = -1;
|
||||
while(ideControllerKey < 0) {
|
||||
ideControllerKey = vmMo.tryGetIDEDeviceControllerKey();
|
||||
if(ideControllerKey >= 0)
|
||||
break;
|
||||
|
||||
s_logger.info("Waiting for IDE controller be ready in VM: " + vmName);
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
|
||||
if(snapshotDirToParent) {
|
||||
String snapshotDir = String.format("/vmfs/volumes/%s/", dsMo.getName());
|
||||
|
||||
s_logger.info("Switch snapshot working directory to " + snapshotDir + " for " + vmName);
|
||||
vmMo.setSnapshotDirectory(snapshotDir);
|
||||
|
||||
// Don't have a good way to test if the VM is really ready for use through normal API after configuration file manipulation,
|
||||
// delay 3 seconds
|
||||
Thread.sleep(3000);
|
||||
}
|
||||
|
||||
s_logger.info("Blank VM: " + vmName + " is ready for use");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String resolveHostNameInUrl(DatacenterMO dcMo, String url) {
|
||||
|
||||
s_logger.info("Resolving host name in url through vCenter, url: " + url);
|
||||
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI(url);
|
||||
} catch (URISyntaxException e) {
|
||||
s_logger.warn("URISyntaxException on url " + url);
|
||||
return url;
|
||||
}
|
||||
|
||||
String host = uri.getHost();
|
||||
if(NetUtils.isValidIp(host)) {
|
||||
s_logger.info("host name in url is already in IP address, url: " + url);
|
||||
return url;
|
||||
}
|
||||
|
||||
try {
|
||||
ManagedObjectReference morHost = dcMo.findHost(host);
|
||||
if(morHost != null) {
|
||||
HostMO hostMo = new HostMO(dcMo.getContext(), morHost);
|
||||
String managementPortGroupName;
|
||||
if(hostMo.getHostType() == VmwareHostType.ESXi)
|
||||
managementPortGroupName = (String)dcMo.getContext().getStockObject("manageportgroup");
|
||||
else
|
||||
managementPortGroupName = (String)dcMo.getContext().getStockObject("serviceconsole");
|
||||
|
||||
VmwareHypervisorHostNetworkSummary summary = hostMo.getHyperHostNetworkSummary(managementPortGroupName);
|
||||
if(summary == null) {
|
||||
s_logger.warn("Unable to resolve host name in url through vSphere, url: " + url);
|
||||
return url;
|
||||
}
|
||||
|
||||
String hostIp = summary.getHostIp();
|
||||
|
||||
try {
|
||||
URI resolvedUri = new URI(uri.getScheme(), uri.getUserInfo(), hostIp, uri.getPort(), uri.getPath(), uri.getQuery(), uri.getFragment());
|
||||
|
||||
s_logger.info("url " + url + " is resolved to " + resolvedUri.toString() + " through vCenter");
|
||||
return resolvedUri.toString();
|
||||
} catch (URISyntaxException e) {
|
||||
assert(false);
|
||||
return url;
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
s_logger.warn("Unexpected exception ", e);
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
public static void importVmFromOVF(VmwareHypervisorHost host, String ovfFilePath, String vmName, DatastoreMO dsMo, String diskOption,
|
||||
ManagedObjectReference morRp, ManagedObjectReference morHost) throws Exception {
|
||||
|
||||
assert(morRp != null);
|
||||
|
||||
OvfCreateImportSpecParams importSpecParams = new OvfCreateImportSpecParams();
|
||||
importSpecParams.setHostSystem(morHost);
|
||||
importSpecParams.setLocale("US");
|
||||
importSpecParams.setEntityName(vmName);
|
||||
importSpecParams.setDeploymentOption("");
|
||||
importSpecParams.setDiskProvisioning(diskOption); // diskOption: thin, thick, etc
|
||||
importSpecParams.setPropertyMapping(null);
|
||||
|
||||
String ovfDescriptor = HttpNfcLeaseMO.readOvfContent(ovfFilePath);
|
||||
VmwareContext context = host.getContext();
|
||||
OvfCreateImportSpecResult ovfImportResult = context.getService().createImportSpec(
|
||||
context.getServiceContent().getOvfManager(), ovfDescriptor, morRp,
|
||||
dsMo.getMor(), importSpecParams);
|
||||
|
||||
if(ovfImportResult == null) {
|
||||
String msg = "createImportSpec() failed. ovfFilePath: " + ovfFilePath + ", vmName: "
|
||||
+ vmName + ", diskOption: " + diskOption;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
DatacenterMO dcMo = new DatacenterMO(context, host.getHyperHostDatacenter());
|
||||
ManagedObjectReference morLease = context.getService().importVApp(morRp,
|
||||
ovfImportResult.getImportSpec(), dcMo.getVmFolder(), morHost);
|
||||
if(morLease == null) {
|
||||
String msg = "importVApp() failed. ovfFilePath: " + ovfFilePath + ", vmName: "
|
||||
+ vmName + ", diskOption: " + diskOption;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
final HttpNfcLeaseMO leaseMo = new HttpNfcLeaseMO(context, morLease);
|
||||
HttpNfcLeaseState state = leaseMo.waitState(
|
||||
new HttpNfcLeaseState[] { HttpNfcLeaseState.ready, HttpNfcLeaseState.error });
|
||||
try {
|
||||
if(state == HttpNfcLeaseState.ready) {
|
||||
final long totalBytes = HttpNfcLeaseMO.calcTotalBytes(ovfImportResult);
|
||||
File ovfFile = new File(ovfFilePath);
|
||||
|
||||
HttpNfcLeaseInfo httpNfcLeaseInfo = leaseMo.getLeaseInfo();
|
||||
HttpNfcLeaseDeviceUrl[] deviceUrls = httpNfcLeaseInfo.getDeviceUrl();
|
||||
long bytesAlreadyWritten = 0;
|
||||
|
||||
final HttpNfcLeaseMO.ProgressReporter progressReporter = leaseMo.createProgressReporter();
|
||||
try {
|
||||
for (HttpNfcLeaseDeviceUrl deviceUrl : deviceUrls) {
|
||||
String deviceKey = deviceUrl.getImportKey();
|
||||
for (OvfFileItem ovfFileItem : ovfImportResult.getFileItem()) {
|
||||
if (deviceKey.equals(ovfFileItem.getDeviceId())) {
|
||||
String absoluteFile = ovfFile.getParent() + File.separator + ovfFileItem.getPath();
|
||||
String urlToPost = deviceUrl.getUrl();
|
||||
urlToPost = resolveHostNameInUrl(dcMo, urlToPost);
|
||||
|
||||
context.uploadVmdkFile(ovfFileItem.isCreate() ? "PUT" : "POST", urlToPost, absoluteFile,
|
||||
bytesAlreadyWritten, new ActionDelegate<Long> () {
|
||||
public void action(Long param) {
|
||||
progressReporter.reportProgress((int)(param * 100 / totalBytes));
|
||||
}
|
||||
});
|
||||
|
||||
bytesAlreadyWritten += ovfFileItem.getSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
progressReporter.close();
|
||||
}
|
||||
leaseMo.updateLeaseProgress(100);
|
||||
}
|
||||
} finally {
|
||||
leaseMo.completeLease();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
|
||||
public class NetworkDetails {
|
||||
|
||||
private String _name;
|
||||
private ManagedObjectReference _morNetwork;
|
||||
private ManagedObjectReference[] _morVMsOnNetwork;
|
||||
private String _gcTag;
|
||||
|
||||
public NetworkDetails(String name, ManagedObjectReference morNetwork, ManagedObjectReference[] morVMsOnNetwork, String gcTag) {
|
||||
_name = name;
|
||||
_morNetwork = morNetwork;
|
||||
_morVMsOnNetwork = morVMsOnNetwork;
|
||||
_gcTag = gcTag;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
public ManagedObjectReference getNetworkMor() {
|
||||
return _morNetwork;
|
||||
}
|
||||
|
||||
public ManagedObjectReference[] getVMMorsOnNetwork() {
|
||||
return _morVMsOnNetwork;
|
||||
}
|
||||
|
||||
public String getGCTag() {
|
||||
return _gcTag;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
|
||||
public class NetworkMO extends BaseMO {
|
||||
public NetworkMO(VmwareContext context, ManagedObjectReference morCluster) {
|
||||
super(context, morCluster);
|
||||
}
|
||||
|
||||
public NetworkMO(VmwareContext context, String morType, String morValue) {
|
||||
super(context, morType, morValue);
|
||||
}
|
||||
|
||||
public void destroyNetwork() throws Exception {
|
||||
_context.getService().destroyNetwork(_mor);
|
||||
}
|
||||
|
||||
public ManagedObjectReference[] getVMsOnNetwork() throws Exception {
|
||||
ManagedObjectReference[] vms = (ManagedObjectReference[])_context.getServiceUtil().getDynamicProperty(_mor, "vm");
|
||||
return vms;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.vmware.vim25.PerfCounterInfo;
|
||||
import com.vmware.vim25.PerfSummaryType;
|
||||
|
||||
public class PerfCounterInfoMapper {
|
||||
// map <group name, counter name, list of PerfCounterInfo based on rollupType>
|
||||
Map<String, Map<String, List<PerfCounterInfo>>> _mapCounterInfos =
|
||||
new HashMap<String, Map<String, List<PerfCounterInfo>>>();
|
||||
|
||||
public PerfCounterInfoMapper(PerfCounterInfo[] counterInfos) {
|
||||
if(counterInfos != null) {
|
||||
for(PerfCounterInfo counterInfo : counterInfos) {
|
||||
List<PerfCounterInfo> counterInfoList = getSafeCounterInfoList(
|
||||
counterInfo.getGroupInfo().getKey(), counterInfo.getNameInfo().getKey());
|
||||
counterInfoList.add(counterInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PerfCounterInfo[] lookup(String groupName, String counterName, PerfSummaryType rollupType) {
|
||||
assert(groupName != null);
|
||||
assert(counterName != null);
|
||||
|
||||
Map<String, List<PerfCounterInfo>> groupMap = _mapCounterInfos.get(groupName);
|
||||
if(groupMap == null)
|
||||
return null;
|
||||
|
||||
List<PerfCounterInfo> counterInfoList = groupMap.get(counterName);
|
||||
if(counterInfoList == null)
|
||||
return null;
|
||||
|
||||
if(rollupType == null) {
|
||||
return counterInfoList.toArray(new PerfCounterInfo[0]);
|
||||
}
|
||||
|
||||
for(PerfCounterInfo info : counterInfoList) {
|
||||
if(info.getRollupType() == rollupType)
|
||||
return new PerfCounterInfo[] { info };
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public PerfCounterInfo lookupOne(String groupName, String counterName, PerfSummaryType rollupType) {
|
||||
PerfCounterInfo[] infos = lookup(groupName, counterName, rollupType);
|
||||
if(infos != null && infos.length > 0)
|
||||
return infos[0];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Map<String, List<PerfCounterInfo>> getSafeGroupMap(String groupName) {
|
||||
Map<String, List<PerfCounterInfo>> groupMap = _mapCounterInfos.get(groupName);
|
||||
if(groupMap == null) {
|
||||
groupMap = new HashMap<String, List<PerfCounterInfo>>();
|
||||
_mapCounterInfos.put(groupName, groupMap);
|
||||
}
|
||||
return groupMap;
|
||||
}
|
||||
|
||||
private List<PerfCounterInfo> getSafeCounterInfoList(String groupName, String counterName) {
|
||||
Map<String, List<PerfCounterInfo>> groupMap = getSafeGroupMap(groupName);
|
||||
assert(groupMap != null);
|
||||
|
||||
List<PerfCounterInfo> counterInfoList = groupMap.get(counterName);
|
||||
if(counterInfoList == null) {
|
||||
counterInfoList = new ArrayList<PerfCounterInfo>();
|
||||
groupMap.put(counterName, counterInfoList);
|
||||
}
|
||||
return counterInfoList;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.PerfCompositeMetric;
|
||||
import com.vmware.vim25.PerfCounterInfo;
|
||||
import com.vmware.vim25.PerfEntityMetricBase;
|
||||
import com.vmware.vim25.PerfInterval;
|
||||
import com.vmware.vim25.PerfMetricId;
|
||||
import com.vmware.vim25.PerfProviderSummary;
|
||||
import com.vmware.vim25.PerfQuerySpec;
|
||||
|
||||
public class PerfManagerMO extends BaseMO {
|
||||
public PerfManagerMO(VmwareContext context, ManagedObjectReference mor) {
|
||||
super(context, mor);
|
||||
}
|
||||
|
||||
public PerfManagerMO(VmwareContext context, String morType, String morValue) {
|
||||
super(context, morType, morValue);
|
||||
}
|
||||
|
||||
public void createPerfInterval(PerfInterval interval) throws Exception {
|
||||
_context.getService().createPerfInterval(_mor, interval);
|
||||
}
|
||||
|
||||
public PerfMetricId[] queryAvailablePerfMetric(ManagedObjectReference morEntity, Calendar beginTime,
|
||||
Calendar endTime, Integer intervalId) throws Exception {
|
||||
|
||||
return _context.getService().queryAvailablePerfMetric(_mor, morEntity, beginTime, endTime, intervalId);
|
||||
}
|
||||
|
||||
public PerfCompositeMetric queryPerfComposite(PerfQuerySpec spec) throws Exception {
|
||||
return _context.getService().queryPerfComposite(_mor, spec);
|
||||
}
|
||||
|
||||
public PerfCounterInfo[] queryPerfCounter(int[] counterId) throws Exception {
|
||||
return _context.getService().queryPerfCounter(_mor, counterId);
|
||||
}
|
||||
|
||||
public PerfCounterInfo[] queryPerfCounterByLevel(int level) throws Exception {
|
||||
return _context.getService().queryPerfCounterByLevel(_mor, level);
|
||||
}
|
||||
|
||||
public PerfProviderSummary queryPerfProviderSummary(ManagedObjectReference morEntity) throws Exception {
|
||||
return _context.getService().queryPerfProviderSummary(_mor, morEntity);
|
||||
}
|
||||
|
||||
public PerfEntityMetricBase[] queryPerf(PerfQuerySpec[] specs) throws Exception {
|
||||
return _context.getService().queryPerf(_mor, specs);
|
||||
}
|
||||
|
||||
public void removePerfInterval(int samplePeriod) throws Exception {
|
||||
_context.getService().removePerfInterval(_mor, samplePeriod);
|
||||
}
|
||||
|
||||
public void updatePerfInterval(PerfInterval interval) throws Exception {
|
||||
_context.getService().updatePerfInterval(_mor, interval);
|
||||
}
|
||||
|
||||
public PerfCounterInfo[] getCounterInfo() throws Exception {
|
||||
return (PerfCounterInfo[])_context.getServiceUtil().getDynamicProperty(_mor, "perfCounter");
|
||||
}
|
||||
|
||||
public PerfInterval[] getIntervalInfo() throws Exception {
|
||||
return (PerfInterval[])_context.getServiceUtil().getDynamicProperty(_mor, "historicalInterval");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
public class SnapshotDescriptor {
|
||||
private static final Logger s_logger = Logger.getLogger(SnapshotDescriptor.class);
|
||||
|
||||
private Properties _properties = new Properties();
|
||||
|
||||
public SnapshotDescriptor() {
|
||||
}
|
||||
|
||||
public void parse(byte[] vmsdFileContent) throws IOException {
|
||||
BufferedReader in = null;
|
||||
try {
|
||||
in = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(vmsdFileContent)));
|
||||
String line;
|
||||
while((line = in.readLine()) != null) {
|
||||
// TODO, remember to remove this log, temporarily added for debugging purpose
|
||||
s_logger.info("Parse snapshot file content: " + line);
|
||||
|
||||
String[] tokens = line.split("=");
|
||||
if(tokens.length == 2) {
|
||||
String name = tokens[0].trim();
|
||||
String value = tokens[1].trim();
|
||||
if(value.charAt(0) == '\"')
|
||||
value = value.substring(1, value.length() -1);
|
||||
|
||||
_properties.put(name, value);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if(in != null)
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeDiskReferenceFromSnapshot(String diskFileName) {
|
||||
String numSnapshotsStr = _properties.getProperty("snapshot.numSnapshots");
|
||||
if(numSnapshotsStr != null) {
|
||||
int numSnaphosts = Integer.parseInt(numSnapshotsStr);
|
||||
for(int i = 0; i < numSnaphosts; i++) {
|
||||
String numDisksStr = _properties.getProperty(String.format("snapshot%d.numDisks", i));
|
||||
int numDisks = Integer.parseInt(numDisksStr);
|
||||
|
||||
boolean diskFound = false;
|
||||
for(int j = 0; j < numDisks; j++) {
|
||||
String keyName = String.format("snapshot%d.disk%d.fileName", i, j);
|
||||
String fileName = _properties.getProperty(keyName);
|
||||
if(!diskFound) {
|
||||
if(fileName.equalsIgnoreCase(diskFileName)) {
|
||||
diskFound = true;
|
||||
_properties.remove(keyName);
|
||||
}
|
||||
} else {
|
||||
_properties.setProperty(String.format("snapshot%d.disk%d.fileName", i, j - 1), fileName);
|
||||
}
|
||||
}
|
||||
|
||||
if(diskFound)
|
||||
_properties.setProperty(String.format("snapshot%d.numDisks", i), String.valueOf(numDisks-1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getVmsdContent() {
|
||||
BufferedWriter out = null;
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
|
||||
try {
|
||||
out = new BufferedWriter(new OutputStreamWriter(bos, "UTF-8"));
|
||||
|
||||
out.write(".encoding = \"UTF-8\""); out.newLine();
|
||||
out.write(String.format("snapshot.lastUID = \"%s\"", _properties.getProperty("snapshot.lastUID"))); out.newLine();
|
||||
String numSnapshotsStr = _properties.getProperty("snapshot.numSnapshots");
|
||||
if(numSnapshotsStr == null || numSnapshotsStr.isEmpty())
|
||||
numSnapshotsStr = "0";
|
||||
out.write(String.format("snapshot.numSnapshots = \"%s\"", numSnapshotsStr)); out.newLine();
|
||||
|
||||
String value = _properties.getProperty("snapshot.current");
|
||||
if(value != null) {
|
||||
out.write(String.format("snapshot.current = \"%s\"", value));
|
||||
out.newLine();
|
||||
}
|
||||
|
||||
String key;
|
||||
for(int i = 0; i < Integer.parseInt(numSnapshotsStr); i++) {
|
||||
key = String.format("snapshot%d.uid", i);
|
||||
value = _properties.getProperty(key);
|
||||
out.write(String.format("%s = \"%s\"", key, value)); out.newLine();
|
||||
|
||||
key = String.format("snapshot%d.filename", i);
|
||||
value = _properties.getProperty(key);
|
||||
out.write(String.format("%s = \"%s\"", key, value)); out.newLine();
|
||||
|
||||
key = String.format("snapshot%d.displayName", i);
|
||||
value = _properties.getProperty(key);
|
||||
out.write(String.format("%s = \"%s\"", key, value)); out.newLine();
|
||||
|
||||
key = String.format("snapshot%d.description", i);
|
||||
value = _properties.getProperty(key);
|
||||
out.write(String.format("%s = \"%s\"", key, value)); out.newLine();
|
||||
|
||||
key = String.format("snapshot%d.createTimeHigh", i);
|
||||
value = _properties.getProperty(key);
|
||||
out.write(String.format("%s = \"%s\"", key, value)); out.newLine();
|
||||
|
||||
key = String.format("snapshot%d.createTimeLow", i);
|
||||
value = _properties.getProperty(key);
|
||||
out.write(String.format("%s = \"%s\"", key, value)); out.newLine();
|
||||
|
||||
key = String.format("snapshot%d.numDisks", i);
|
||||
value = _properties.getProperty(key);
|
||||
out.write(String.format("%s = \"%s\"", key, value)); out.newLine();
|
||||
|
||||
int numDisks = Integer.parseInt(value);
|
||||
for(int j = 0; j < numDisks; j++) {
|
||||
key = String.format("snapshot%d.disk%d.fileName", i, j);
|
||||
value = _properties.getProperty(key);
|
||||
out.write(String.format("%s = \"%s\"", key, value)); out.newLine();
|
||||
|
||||
key = String.format("snapshot%d.disk%d.node", i, j);
|
||||
value = _properties.getProperty(key);
|
||||
out.write(String.format("%s = \"%s\"", key, value)); out.newLine();
|
||||
}
|
||||
}
|
||||
} catch(IOException e) {
|
||||
assert(false);
|
||||
s_logger.error("Unexpected exception ", e);
|
||||
} finally {
|
||||
if(out != null) {
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bos.toByteArray();
|
||||
}
|
||||
|
||||
private int getSnapshotId(String seqStr) {
|
||||
if(seqStr != null) {
|
||||
int seq = Integer.parseInt(seqStr);
|
||||
String numSnapshotStr = _properties.getProperty("snapshot.numSnapshots");
|
||||
assert(numSnapshotStr != null);
|
||||
for(int i = 0; i < Integer.parseInt(numSnapshotStr); i++) {
|
||||
String value = _properties.getProperty(String.format("snapshot%d.uid", i));
|
||||
if(value != null && Integer.parseInt(value) == seq)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public SnapshotInfo[] getCurrentDiskChain() {
|
||||
ArrayList<SnapshotInfo> l = new ArrayList<SnapshotInfo>();
|
||||
String current = _properties.getProperty("snapshot.current");
|
||||
int id;
|
||||
while(current != null) {
|
||||
id = getSnapshotId(current);
|
||||
String numDisksStr = _properties.getProperty(String.format("snapshot%d.numDisks", id));
|
||||
assert(numDisksStr != null);
|
||||
int numDisks = Integer.parseInt(numDisksStr);
|
||||
DiskInfo[] disks = new DiskInfo[numDisks];
|
||||
for(int i = 0; i < numDisks; i++) {
|
||||
disks[i] = new DiskInfo(
|
||||
_properties.getProperty(String.format("snapshot%d.disk%d.fileName", id, i)),
|
||||
_properties.getProperty(String.format("snapshot%d.disk%d.node", id, i))
|
||||
);
|
||||
}
|
||||
|
||||
SnapshotInfo info = new SnapshotInfo();
|
||||
info.setId(id);
|
||||
info.setNumOfDisks(numDisks);
|
||||
info.setDisks(disks);
|
||||
info.setDisplayName(_properties.getProperty(String.format("snapshot%d.displayName", id)));
|
||||
l.add(info);
|
||||
|
||||
current = _properties.getProperty(String.format("snapshot%d.parent", id));
|
||||
}
|
||||
|
||||
return l.toArray(new SnapshotInfo[0]);
|
||||
}
|
||||
|
||||
public static class SnapshotInfo {
|
||||
private int _id;
|
||||
private String _displayName;
|
||||
private int _numOfDisks;
|
||||
private DiskInfo[] _disks;
|
||||
|
||||
public SnapshotInfo() {
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
_id = id;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return _id;
|
||||
}
|
||||
|
||||
public void setDisplayName(String name) {
|
||||
_displayName = name;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return _displayName;
|
||||
}
|
||||
|
||||
public void setNumOfDisks(int numOfDisks) {
|
||||
_numOfDisks = numOfDisks;
|
||||
}
|
||||
|
||||
public int getNumOfDisks() {
|
||||
return _numOfDisks;
|
||||
}
|
||||
|
||||
public void setDisks(DiskInfo[] disks) {
|
||||
_disks = disks;
|
||||
}
|
||||
|
||||
public DiskInfo[] getDisks() {
|
||||
return _disks;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DiskInfo {
|
||||
private String _diskFileName;
|
||||
private String _deviceName;
|
||||
|
||||
public DiskInfo(String diskFileName, String deviceName) {
|
||||
_diskFileName = diskFileName;
|
||||
_deviceName = deviceName;
|
||||
}
|
||||
|
||||
public String getDiskFileName() {
|
||||
return _diskFileName;
|
||||
}
|
||||
|
||||
public String getDeviceName() {
|
||||
return _deviceName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.vmware.vim25.LocalizableMessage;
|
||||
import com.vmware.vim25.LocalizedMethodFault;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.TaskInfo;
|
||||
import com.vmware.vim25.TaskInfoState;
|
||||
|
||||
public class TaskMO extends BaseMO {
|
||||
public TaskMO(VmwareContext context, ManagedObjectReference morTask) {
|
||||
super(context, morTask);
|
||||
}
|
||||
|
||||
public TaskMO(VmwareContext context, String morType, String morValue) {
|
||||
super(context, morType, morValue);
|
||||
}
|
||||
|
||||
public TaskInfo getTaskInfo() throws Exception {
|
||||
return (TaskInfo)getContext().getServiceUtil().getDynamicProperty(_mor, "info");
|
||||
}
|
||||
|
||||
public void setTaskDescription(LocalizableMessage description) throws Exception {
|
||||
_context.getService().setTaskDescription(_mor, description);
|
||||
}
|
||||
|
||||
public void setTaskState(TaskInfoState state, Object result, LocalizedMethodFault fault) throws Exception {
|
||||
_context.getService().setTaskState(_mor, state, result, fault);
|
||||
}
|
||||
|
||||
public void updateProgress(int percentDone) throws Exception {
|
||||
_context.getService().updateProgress(_mor, percentDone);
|
||||
}
|
||||
|
||||
public void cancelTask() throws Exception {
|
||||
_context.getService().cancelTask(_mor);
|
||||
}
|
||||
|
||||
public static String getTaskFailureInfo(VmwareContext context, ManagedObjectReference morTask) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
try {
|
||||
TaskInfo info = (TaskInfo)context.getServiceUtil().getDynamicProperty(morTask, "info");
|
||||
if(info != null) {
|
||||
LocalizedMethodFault fault = info.getError();
|
||||
if(fault != null) {
|
||||
sb.append(fault.getLocalizedMessage()).append(" ");
|
||||
|
||||
if(fault.getFault() != null)
|
||||
sb.append(fault.getFault().getClass().getName());
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
public interface VersioningContants {
|
||||
|
||||
// portgroups created on vSwitch will carry a version number now, so that when CloudStack has a major naming convention upgrade
|
||||
// we know how to cleanup at vCenter side
|
||||
public final static int PORTGROUP_NAMING_VERSION = 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.vmware.vim25.HostDiskDimensionsChs;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.VirtualDiskSpec;
|
||||
|
||||
public class VirtualDiskManagerMO extends BaseMO {
|
||||
private static final Logger s_logger = Logger.getLogger(VirtualDiskManagerMO.class);
|
||||
|
||||
public VirtualDiskManagerMO(VmwareContext context, ManagedObjectReference morDiskMgr) {
|
||||
super(context, morDiskMgr);
|
||||
}
|
||||
|
||||
public VirtualDiskManagerMO(VmwareContext context, String morType, String morValue) {
|
||||
super(context, morType, morValue);
|
||||
}
|
||||
|
||||
public void copyVirtualDisk(String srcName, ManagedObjectReference morSrcDc,
|
||||
String destName, ManagedObjectReference morDestDc, VirtualDiskSpec diskSpec,
|
||||
boolean force) throws Exception {
|
||||
|
||||
ManagedObjectReference morTask = _context.getService().copyVirtualDisk_Task(_mor, srcName, morSrcDc, destName, morDestDc, diskSpec, force);
|
||||
|
||||
String result = _context.getServiceUtil().waitForTask(morTask);
|
||||
if(!result.equals("sucess"))
|
||||
throw new Exception("Unable to copy virtual disk " + srcName + " to " + destName
|
||||
+ " due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
}
|
||||
|
||||
public void createVirtualDisk(String name, ManagedObjectReference morDc, VirtualDiskSpec diskSpec) throws Exception {
|
||||
ManagedObjectReference morTask = _context.getService().createVirtualDisk_Task(_mor, name, morDc, diskSpec);
|
||||
|
||||
String result = _context.getServiceUtil().waitForTask(morTask);
|
||||
if(!result.equals("sucess"))
|
||||
throw new Exception("Unable to create virtual disk " + name
|
||||
+ " due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
}
|
||||
|
||||
public void defragmentVirtualDisk(String name, ManagedObjectReference morDc) throws Exception {
|
||||
ManagedObjectReference morTask = _context.getService().defragmentVirtualDisk_Task(_mor, name, morDc);
|
||||
|
||||
String result = _context.getServiceUtil().waitForTask(morTask);
|
||||
if(!result.equals("sucess"))
|
||||
throw new Exception("Unable to defragment virtual disk " + name + " due to " + result);
|
||||
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
}
|
||||
|
||||
public void deleteVirtualDisk(String name, ManagedObjectReference morDc) throws Exception {
|
||||
ManagedObjectReference morTask = _context.getService().deleteVirtualDisk_Task(_mor, name, morDc);
|
||||
|
||||
String result = _context.getServiceUtil().waitForTask(morTask);
|
||||
if(!result.equals("sucess"))
|
||||
throw new Exception("Unable to delete virtual disk " + name + " due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
}
|
||||
|
||||
public void eagerZeroVirtualDisk(String name, ManagedObjectReference morDc) throws Exception {
|
||||
ManagedObjectReference morTask = _context.getService().eagerZeroVirtualDisk_Task(_mor, name, morDc);
|
||||
|
||||
String result = _context.getServiceUtil().waitForTask(morTask);
|
||||
if(!result.equals("sucess"))
|
||||
throw new Exception("Unable to eager zero virtual disk " + name + " due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
}
|
||||
|
||||
public void extendVirtualDisk(String name, ManagedObjectReference morDc, long newCapacityKb, boolean eagerZero) throws Exception {
|
||||
ManagedObjectReference morTask = _context.getService().extendVirtualDisk_Task(_mor, name, morDc, newCapacityKb, eagerZero);
|
||||
|
||||
String result = _context.getServiceUtil().waitForTask(morTask);
|
||||
if(!result.equals("sucess"))
|
||||
throw new Exception("Unable to extend virtual disk " + name + " due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
}
|
||||
|
||||
public void inflateVirtualDisk(String name, ManagedObjectReference morDc) throws Exception {
|
||||
ManagedObjectReference morTask = _context.getService().inflateVirtualDisk_Task(_mor, name, morDc);
|
||||
|
||||
String result = _context.getServiceUtil().waitForTask(morTask);
|
||||
if(!result.equals("sucess"))
|
||||
throw new Exception("Unable to inflate virtual disk " + name + " due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
}
|
||||
|
||||
public void shrinkVirtualDisk(String name, ManagedObjectReference morDc, boolean copy) throws Exception {
|
||||
ManagedObjectReference morTask = _context.getService().shrinkVirtualDisk_Task(_mor, name, morDc, copy);
|
||||
|
||||
String result = _context.getServiceUtil().waitForTask(morTask);
|
||||
if(!result.equals("sucess"))
|
||||
throw new Exception("Unable to shrink virtual disk " + name + " due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
}
|
||||
|
||||
public void zeroFillVirtualDisk(String name, ManagedObjectReference morDc) throws Exception {
|
||||
ManagedObjectReference morTask = _context.getService().zeroFillVirtualDisk_Task(_mor, name, morDc);
|
||||
|
||||
String result = _context.getServiceUtil().waitForTask(morTask);
|
||||
if(!result.equals("sucess"))
|
||||
throw new Exception("Unable to zero fill virtual disk " + name + " due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
}
|
||||
|
||||
public void moveVirtualDisk(String srcName, ManagedObjectReference morSrcDc,
|
||||
String destName, ManagedObjectReference morDestDc, boolean force) throws Exception {
|
||||
|
||||
ManagedObjectReference morTask = _context.getService().moveVirtualDisk_Task(_mor, srcName, morSrcDc,
|
||||
destName, morDestDc, force);
|
||||
|
||||
String result = _context.getServiceUtil().waitForTask(morTask);
|
||||
if(!result.equals("sucess"))
|
||||
throw new Exception("Unable to move virtual disk " + srcName + " to " + destName
|
||||
+ " due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
}
|
||||
|
||||
public int queryVirtualDiskFragmentation(String name, ManagedObjectReference morDc) throws Exception {
|
||||
return _context.getService().queryVirtualDiskFragmentation(_mor, name, morDc);
|
||||
}
|
||||
|
||||
public HostDiskDimensionsChs queryVirtualDiskGeometry(String name, ManagedObjectReference morDc) throws Exception {
|
||||
return _context.getService().queryVirtualDiskGeometry(_mor, name, morDc);
|
||||
}
|
||||
|
||||
public String queryVirtualDiskUuid(String name, ManagedObjectReference morDc) throws Exception {
|
||||
return _context.getService().queryVirtualDiskUuid(_mor, name, morDc);
|
||||
}
|
||||
|
||||
public void setVirtualDiskUuid(String name, ManagedObjectReference morDc, String uuid) throws Exception {
|
||||
_context.getService().setVirtualDiskUuid(_mor, name, morDc, uuid);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
public enum VirtualEthernetCardType {
|
||||
E1000, PCNet32, Vmxnet2, Vmxnet3
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,146 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
public class VmdkFileDescriptor {
|
||||
private static final Logger s_logger = Logger.getLogger(VmdkFileDescriptor.class);
|
||||
|
||||
private Properties _properties = new Properties();
|
||||
private String _baseFileName;
|
||||
|
||||
public VmdkFileDescriptor() {
|
||||
}
|
||||
|
||||
public void parse(byte[] vmdkFileContent) throws IOException {
|
||||
BufferedReader in = null;
|
||||
try {
|
||||
in = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(vmdkFileContent)));
|
||||
String line;
|
||||
while((line = in.readLine()) != null) {
|
||||
// ignore empty and comment lines
|
||||
line = line.trim();
|
||||
if(line.isEmpty())
|
||||
continue;
|
||||
if(line.charAt(0) == '#')
|
||||
continue;
|
||||
|
||||
String[] tokens = line.split("=");
|
||||
if(tokens.length == 2) {
|
||||
String name = tokens[0].trim();
|
||||
String value = tokens[1].trim();
|
||||
if(value.charAt(0) == '\"')
|
||||
value = value.substring(1, value.length() -1);
|
||||
|
||||
_properties.put(name, value);
|
||||
} else {
|
||||
if(line.startsWith("RW")) {
|
||||
int startPos = line.indexOf('\"');
|
||||
int endPos = line.lastIndexOf('\"');
|
||||
assert(startPos > 0);
|
||||
assert(endPos > 0);
|
||||
|
||||
_baseFileName = line.substring(startPos + 1, endPos);
|
||||
} else {
|
||||
s_logger.warn("Unrecognized vmdk line content: " + line);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if(in != null)
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
public String getBaseFileName() {
|
||||
return _baseFileName;
|
||||
}
|
||||
|
||||
public String getParentFileName() {
|
||||
return _properties.getProperty("parentFileNameHint");
|
||||
}
|
||||
|
||||
public static byte[] changeVmdkContentBaseInfo(byte[] vmdkContent,
|
||||
String baseFileName, String parentFileName) throws IOException {
|
||||
|
||||
assert(vmdkContent != null);
|
||||
|
||||
BufferedReader in = null;
|
||||
BufferedWriter out = null;
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
|
||||
try {
|
||||
in = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(vmdkContent)));
|
||||
out = new BufferedWriter(new OutputStreamWriter(bos));
|
||||
String line;
|
||||
while((line = in.readLine()) != null) {
|
||||
// ignore empty and comment lines
|
||||
line = line.trim();
|
||||
if(line.isEmpty()) {
|
||||
out.newLine();
|
||||
continue;
|
||||
}
|
||||
if(line.charAt(0) == '#') {
|
||||
out.write(line);
|
||||
out.newLine();
|
||||
continue;
|
||||
}
|
||||
|
||||
String[] tokens = line.split("=");
|
||||
if(tokens.length == 2) {
|
||||
String name = tokens[0].trim();
|
||||
String value = tokens[1].trim();
|
||||
if(value.charAt(0) == '\"')
|
||||
value = value.substring(1, value.length() - 1);
|
||||
|
||||
if(parentFileName != null && name.equals("parentFileNameHint")) {
|
||||
out.write(name + "=\"" + parentFileName + "\"");
|
||||
out.newLine();
|
||||
} else {
|
||||
out.write(line);
|
||||
out.newLine();
|
||||
}
|
||||
} else {
|
||||
if(line.startsWith("RW")) {
|
||||
if(baseFileName != null) {
|
||||
int startPos = line.indexOf('\"');
|
||||
int endPos = line.lastIndexOf('\"');
|
||||
assert(startPos > 0);
|
||||
assert(endPos > 0);
|
||||
|
||||
// replace it with base file name
|
||||
out.write(line.substring(0, startPos + 1));
|
||||
out.write(baseFileName);
|
||||
out.write(line.substring(endPos));
|
||||
out.newLine();
|
||||
} else {
|
||||
out.write(line);
|
||||
out.newLine();
|
||||
}
|
||||
} else {
|
||||
s_logger.warn("Unrecognized vmdk line content: " + line);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if(in != null)
|
||||
in.close();
|
||||
if(out != null)
|
||||
out.close();
|
||||
}
|
||||
|
||||
return bos.toByteArray();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
public enum VmwareHostType {
|
||||
ESXi, ESX
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.vmware.vim25.ClusterDasConfigInfo;
|
||||
import com.vmware.vim25.ComputeResourceSummary;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.ObjectContent;
|
||||
import com.vmware.vim25.VirtualMachineConfigSpec;
|
||||
|
||||
/**
|
||||
* Interface to consolidate ESX(i) hosts and HA/FT clusters into a common interface used by Cloud.com Hypervisor resources
|
||||
*/
|
||||
public interface VmwareHypervisorHost {
|
||||
VmwareContext getContext();
|
||||
ManagedObjectReference getMor();
|
||||
|
||||
String getHyperHostName() throws Exception;
|
||||
|
||||
ClusterDasConfigInfo getDasConfig() throws Exception;
|
||||
|
||||
ManagedObjectReference getHyperHostDatacenter() throws Exception;
|
||||
ManagedObjectReference getHyperHostOwnerResourcePool() throws Exception;
|
||||
ManagedObjectReference getHyperHostCluster() throws Exception;
|
||||
|
||||
boolean isHyperHostConnected() throws Exception;
|
||||
String getHyperHostDefaultGateway() throws Exception;
|
||||
|
||||
VirtualMachineMO findVmOnHyperHost(String name) throws Exception;
|
||||
VirtualMachineMO findVmOnPeerHyperHost(String name) throws Exception;
|
||||
|
||||
boolean createVm(VirtualMachineConfigSpec vmSpec) throws Exception;
|
||||
boolean createBlankVm(String vmName, int cpuCount, int cpuSpeedMHz, int cpuReservedMHz, boolean limitCpuUse, int memoryMB,
|
||||
String guestOsIdentifier, ManagedObjectReference morDs, boolean snapshotDirToParent) throws Exception;
|
||||
void importVmFromOVF(String ovfFilePath, String vmName, DatastoreMO dsMo, String diskOption) throws Exception;
|
||||
|
||||
ObjectContent[] getVmPropertiesOnHyperHost(String[] propertyPaths) throws Exception;
|
||||
ObjectContent[] getDatastorePropertiesOnHyperHost(String[] propertyPaths) throws Exception;
|
||||
|
||||
ManagedObjectReference mountDatastore(boolean vmfsDatastore, String poolHostAddress,
|
||||
int poolHostPort, String poolPath, String poolUuid) throws Exception;
|
||||
void unmountDatastore(String poolUuid) throws Exception;
|
||||
|
||||
ManagedObjectReference findDatastore(String poolUuid) throws Exception;
|
||||
|
||||
@Deprecated
|
||||
ManagedObjectReference findDatastoreByExportPath(String exportPath) throws Exception;
|
||||
|
||||
ManagedObjectReference findMigrationTarget(VirtualMachineMO vmMo) throws Exception;
|
||||
|
||||
VmwareHypervisorHostResourceSummary getHyperHostResourceSummary() throws Exception;
|
||||
VmwareHypervisorHostNetworkSummary getHyperHostNetworkSummary(String esxServiceConsolePort) throws Exception;
|
||||
ComputeResourceSummary getHyperHostHardwareSummary() throws Exception;
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
public class VmwareHypervisorHostNetworkSummary {
|
||||
private String hostIp;
|
||||
private String hostNetmask;
|
||||
private String hostMacAddress;
|
||||
|
||||
public VmwareHypervisorHostNetworkSummary() {
|
||||
}
|
||||
|
||||
public String getHostIp() {
|
||||
return hostIp;
|
||||
}
|
||||
|
||||
public void setHostIp(String hostIp) {
|
||||
this.hostIp = hostIp;
|
||||
}
|
||||
|
||||
public String getHostNetmask() {
|
||||
return hostNetmask;
|
||||
}
|
||||
|
||||
public void setHostNetmask(String hostNetmask) {
|
||||
this.hostNetmask = hostNetmask;
|
||||
}
|
||||
|
||||
public String getHostMacAddress() {
|
||||
return hostMacAddress;
|
||||
}
|
||||
|
||||
public void setHostMacAddress(String hostMacAddress) {
|
||||
this.hostMacAddress = hostMacAddress;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
public class VmwareHypervisorHostResourceSummary {
|
||||
private long memoryBytes;
|
||||
private long cpuCount;
|
||||
private long cpuSpeed;
|
||||
|
||||
public VmwareHypervisorHostResourceSummary() {
|
||||
}
|
||||
|
||||
public long getMemoryBytes() {
|
||||
return memoryBytes;
|
||||
}
|
||||
|
||||
public void setMemoryBytes(long memoryBytes) {
|
||||
this.memoryBytes = memoryBytes;
|
||||
}
|
||||
|
||||
public long getCpuCount() {
|
||||
return cpuCount;
|
||||
}
|
||||
|
||||
public void setCpuCount(long cpuCount) {
|
||||
this.cpuCount = cpuCount;
|
||||
}
|
||||
|
||||
public long getCpuSpeed() {
|
||||
return cpuSpeed;
|
||||
}
|
||||
|
||||
public void setCpuSpeed(long cpuSpeed) {
|
||||
this.cpuSpeed = cpuSpeed;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,593 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.util;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLSession;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
|
||||
import com.cloud.hypervisor.vmware.mo.DatastoreFile;
|
||||
import com.cloud.utils.ActionDelegate;
|
||||
import com.vmware.apputils.version.ExtendedAppUtil;
|
||||
import com.vmware.apputils.vim25.ServiceConnection;
|
||||
import com.vmware.apputils.vim25.ServiceUtil;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.ObjectContent;
|
||||
import com.vmware.vim25.ObjectSpec;
|
||||
import com.vmware.vim25.PropertyFilterSpec;
|
||||
import com.vmware.vim25.PropertySpec;
|
||||
import com.vmware.vim25.SelectionSpec;
|
||||
import com.vmware.vim25.ServiceContent;
|
||||
import com.vmware.vim25.TaskInfo;
|
||||
import com.vmware.vim25.TraversalSpec;
|
||||
import com.vmware.vim25.VimPortType;
|
||||
|
||||
public class VmwareContext {
|
||||
private static final Logger s_logger = Logger.getLogger(VmwareContext.class);
|
||||
|
||||
private ExtendedAppUtil _appUtil;
|
||||
private String _serverAddress;
|
||||
|
||||
private Map<String, Object> _stockMap = new HashMap<String, Object>();
|
||||
|
||||
static {
|
||||
try {
|
||||
javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
|
||||
javax.net.ssl.TrustManager tm = new TrustAllManager();
|
||||
trustAllCerts[0] = tm;
|
||||
javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");
|
||||
sc.init(null, trustAllCerts, null);
|
||||
javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
|
||||
} catch (Exception e) {
|
||||
s_logger.error("Unexpected exception ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public VmwareContext(ExtendedAppUtil appUtil, String address) {
|
||||
assert(appUtil != null) : "Invalid parameter in constructing VmwareContext object";
|
||||
|
||||
_appUtil = appUtil;
|
||||
_serverAddress = address;
|
||||
}
|
||||
|
||||
public void registerStockObject(String name, Object obj) {
|
||||
synchronized(_stockMap) {
|
||||
_stockMap.put(name, obj);
|
||||
}
|
||||
}
|
||||
|
||||
public void uregisterStockObject(String name) {
|
||||
synchronized(_stockMap) {
|
||||
_stockMap.remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getStockObject(String name) {
|
||||
synchronized(_stockMap) {
|
||||
return (T)_stockMap.get(name);
|
||||
}
|
||||
}
|
||||
|
||||
public String getServerAddress() {
|
||||
return _serverAddress;
|
||||
}
|
||||
|
||||
public ServiceConnection getServiceConnection() {
|
||||
return _appUtil.getServiceConnection3();
|
||||
}
|
||||
|
||||
public VimPortType getService() {
|
||||
return getServiceConnection().getService();
|
||||
}
|
||||
|
||||
public ServiceContent getServiceContent() {
|
||||
return getServiceConnection().getServiceContent();
|
||||
}
|
||||
|
||||
public ServiceUtil getServiceUtil() {
|
||||
return _appUtil.getServiceUtil3();
|
||||
}
|
||||
|
||||
public ManagedObjectReference getRootFolder() {
|
||||
return getServiceContent().getRootFolder();
|
||||
}
|
||||
|
||||
public ManagedObjectReference getHostMorByPath(String inventoryPath) throws Exception {
|
||||
assert(inventoryPath != null);
|
||||
|
||||
String[] tokens;
|
||||
if(inventoryPath.startsWith("/"))
|
||||
tokens = inventoryPath.substring(1).split("/");
|
||||
else
|
||||
tokens = inventoryPath.split("/");
|
||||
|
||||
ManagedObjectReference mor = getRootFolder();
|
||||
for(int i=0; i < tokens.length;i++) {
|
||||
String token = tokens[i];
|
||||
ObjectContent[] ocs;
|
||||
if(mor.getType().equalsIgnoreCase("Datacenter")) {
|
||||
PropertySpec pSpec = new PropertySpec();
|
||||
pSpec.setType("ManagedEntity");
|
||||
pSpec.setPathSet(new String[] { "name" });
|
||||
|
||||
TraversalSpec dcHostFolderTraversal = new TraversalSpec();
|
||||
dcHostFolderTraversal.setType("Datacenter");
|
||||
dcHostFolderTraversal.setPath("hostFolder");
|
||||
dcHostFolderTraversal.setName("dcHostFolderTraversal");
|
||||
|
||||
ObjectSpec oSpec = new ObjectSpec();
|
||||
oSpec.setObj(mor);
|
||||
oSpec.setSkip(Boolean.TRUE);
|
||||
oSpec.setSelectSet(new SelectionSpec[] { dcHostFolderTraversal });
|
||||
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.setPropSet(new PropertySpec[] { pSpec });
|
||||
pfSpec.setObjectSet(new ObjectSpec[] { oSpec });
|
||||
ocs = getService().retrieveProperties(
|
||||
getServiceContent().getPropertyCollector(),
|
||||
new PropertyFilterSpec[] { pfSpec });
|
||||
|
||||
} else if(mor.getType().equalsIgnoreCase("Folder")) {
|
||||
PropertySpec pSpec = new PropertySpec();
|
||||
pSpec.setType("ManagedEntity");
|
||||
pSpec.setPathSet(new String[] { "name" });
|
||||
|
||||
TraversalSpec folderChildrenTraversal = new TraversalSpec();
|
||||
folderChildrenTraversal.setType("Folder");
|
||||
folderChildrenTraversal.setPath("childEntity");
|
||||
folderChildrenTraversal.setName("folderChildrenTraversal");
|
||||
|
||||
ObjectSpec oSpec = new ObjectSpec();
|
||||
oSpec.setObj(mor);
|
||||
oSpec.setSkip(Boolean.TRUE);
|
||||
oSpec.setSelectSet(new SelectionSpec[] { folderChildrenTraversal });
|
||||
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.setPropSet(new PropertySpec[] { pSpec });
|
||||
pfSpec.setObjectSet(new ObjectSpec[] { oSpec });
|
||||
|
||||
ocs = getService().retrieveProperties(
|
||||
getServiceContent().getPropertyCollector(),
|
||||
new PropertyFilterSpec[] { pfSpec });
|
||||
} else if(mor.getType().equalsIgnoreCase("ClusterComputeResource")) {
|
||||
PropertySpec pSpec = new PropertySpec();
|
||||
pSpec.setType("ManagedEntity");
|
||||
pSpec.setPathSet(new String[] { "name" });
|
||||
|
||||
TraversalSpec clusterHostTraversal = new TraversalSpec();
|
||||
clusterHostTraversal.setType("ClusterComputeResource");
|
||||
clusterHostTraversal.setPath("host");
|
||||
clusterHostTraversal.setName("folderChildrenTraversal");
|
||||
|
||||
ObjectSpec oSpec = new ObjectSpec();
|
||||
oSpec.setObj(mor);
|
||||
oSpec.setSkip(Boolean.TRUE);
|
||||
oSpec.setSelectSet(new SelectionSpec[] { clusterHostTraversal });
|
||||
|
||||
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
|
||||
pfSpec.setPropSet(new PropertySpec[] { pSpec });
|
||||
pfSpec.setObjectSet(new ObjectSpec[] { oSpec });
|
||||
|
||||
ocs = getService().retrieveProperties(
|
||||
getServiceContent().getPropertyCollector(),
|
||||
new PropertyFilterSpec[] { pfSpec });
|
||||
} else {
|
||||
s_logger.error("Invalid inventory path, path element can only be datacenter and folder");
|
||||
return null;
|
||||
}
|
||||
|
||||
if(ocs != null && ocs.length > 0) {
|
||||
boolean found = false;
|
||||
for(ObjectContent oc : ocs) {
|
||||
String name = oc.getPropSet()[0].getVal().toString();
|
||||
if(name.equalsIgnoreCase(token) || name.equalsIgnoreCase("host")) {
|
||||
mor = oc.getObj();
|
||||
found = true;
|
||||
if (name.equalsIgnoreCase("host"))
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
s_logger.error("Path element points to an un-existing inventory entity");
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
s_logger.error("Path element points to an un-existing inventory entity");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return mor;
|
||||
}
|
||||
|
||||
// path in format of <datacenter name>/<datastore name>
|
||||
public ManagedObjectReference getDatastoreMorByPath(String inventoryPath) throws Exception {
|
||||
assert(inventoryPath != null);
|
||||
|
||||
String[] tokens;
|
||||
if(inventoryPath.startsWith("/"))
|
||||
tokens = inventoryPath.substring(1).split("/");
|
||||
else
|
||||
tokens = inventoryPath.split("/");
|
||||
|
||||
if(tokens == null || tokens.length != 2) {
|
||||
s_logger.error("Invalid datastore inventory path. path: " + inventoryPath);
|
||||
return null;
|
||||
}
|
||||
|
||||
DatacenterMO dcMo = new DatacenterMO(this, tokens[0]);
|
||||
if(dcMo.getMor() == null) {
|
||||
s_logger.error("Unable to locate the datacenter specified in path: " + inventoryPath);
|
||||
return null;
|
||||
}
|
||||
|
||||
return dcMo.findDatastore(tokens[1]);
|
||||
}
|
||||
|
||||
public void waitForTaskProgressDone(ManagedObjectReference morTask) throws Exception {
|
||||
while(true) {
|
||||
TaskInfo tinfo = (TaskInfo)getServiceUtil().getDynamicProperty(morTask, "info");
|
||||
Integer progress = tinfo.getProgress();
|
||||
if(progress == null)
|
||||
break;
|
||||
|
||||
if(progress.intValue() >= 100)
|
||||
break;
|
||||
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
public void getFile(String urlString, String localFileFullName) throws Exception {
|
||||
HttpURLConnection conn = getHTTPConnection(urlString);
|
||||
|
||||
InputStream in = conn.getInputStream();
|
||||
OutputStream out = new FileOutputStream(new File(localFileFullName));
|
||||
byte[] buf = new byte[102400];
|
||||
int len = 0;
|
||||
while ((len = in.read(buf)) > 0) {
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
|
||||
public void uploadFile(String urlString, String localFileFullName) throws Exception {
|
||||
uploadFile(urlString, new File(localFileFullName));
|
||||
}
|
||||
|
||||
public void uploadFile(String urlString, File localFile) throws Exception {
|
||||
HttpURLConnection conn = getHTTPConnection(urlString, "PUT");
|
||||
OutputStream out = null;
|
||||
InputStream in = null;
|
||||
BufferedReader br = null;
|
||||
|
||||
try {
|
||||
out = conn.getOutputStream();
|
||||
in = new FileInputStream(localFile);
|
||||
byte[] buf = new byte[102400];
|
||||
int len = 0;
|
||||
while ((len = in.read(buf)) > 0) {
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
out.flush();
|
||||
|
||||
br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("Upload " + urlString + " response: " + line);
|
||||
}
|
||||
} finally {
|
||||
if(in != null)
|
||||
in.close();
|
||||
|
||||
if(out != null)
|
||||
out.close();
|
||||
|
||||
if(br != null)
|
||||
br.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void uploadVmdkFile(String httpMethod, String urlString, String localFileName,
|
||||
long totalBytesUpdated, ActionDelegate progressUpdater) throws Exception {
|
||||
|
||||
HttpURLConnection conn = getRawHTTPConnection(urlString);
|
||||
|
||||
conn.setDoOutput(true);
|
||||
conn.setUseCaches(false);
|
||||
|
||||
int CHUCK_LEN = 64*1024;
|
||||
conn.setChunkedStreamingMode(CHUCK_LEN);
|
||||
conn.setRequestMethod(httpMethod);
|
||||
conn.setRequestProperty("Connection", "Keep-Alive");
|
||||
conn.setRequestProperty("Content-Type", "application/x-vnd.vmware-streamVmdk");
|
||||
conn.setRequestProperty("Content-Length", Long.toString(new File(localFileName).length()));
|
||||
conn.connect();
|
||||
|
||||
BufferedOutputStream bos = null;
|
||||
BufferedInputStream is = null;
|
||||
try {
|
||||
bos = new BufferedOutputStream(conn.getOutputStream());
|
||||
is = new BufferedInputStream(new FileInputStream(localFileName));
|
||||
int bytesAvailable = is.available();
|
||||
int bufferSize = Math.min(bytesAvailable, CHUCK_LEN);
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
while (true) {
|
||||
int bytesRead = is.read(buffer, 0, bufferSize);
|
||||
if (bytesRead == -1) {
|
||||
break;
|
||||
}
|
||||
bos.write(buffer, 0, bufferSize);
|
||||
totalBytesUpdated += bytesRead;
|
||||
bos.flush();
|
||||
if(progressUpdater != null)
|
||||
progressUpdater.action(new Long(totalBytesUpdated));
|
||||
}
|
||||
bos.flush();
|
||||
} finally {
|
||||
if(is != null)
|
||||
is.close();
|
||||
if(bos != null)
|
||||
bos.close();
|
||||
|
||||
conn.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
public long downloadVmdkFile(String urlString, String localFileName,
|
||||
long totalBytesDownloaded, ActionDelegate progressUpdater) throws Exception {
|
||||
HttpURLConnection conn = getRawHTTPConnection(urlString);
|
||||
|
||||
String cookieString = getServiceCookie();
|
||||
conn.setRequestProperty(org.apache.axis.transport.http.HTTPConstants.HEADER_COOKIE, cookieString);
|
||||
conn.setDoInput(true);
|
||||
conn.setDoOutput(true);
|
||||
conn.setAllowUserInteraction(true);
|
||||
conn.connect();
|
||||
|
||||
long bytesWritten = 0;
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
try {
|
||||
in = conn.getInputStream();
|
||||
out = new FileOutputStream(new File(localFileName));
|
||||
|
||||
byte[] buf = new byte[64*1024];
|
||||
int len = 0;
|
||||
while ((len = in.read(buf)) > 0) {
|
||||
out.write(buf, 0, len);
|
||||
bytesWritten += len;
|
||||
totalBytesDownloaded += len;
|
||||
|
||||
if(progressUpdater != null)
|
||||
progressUpdater.action(new Long(totalBytesDownloaded));
|
||||
}
|
||||
} catch(Throwable e) {
|
||||
s_logger.error("Unexpected exception ", e);
|
||||
} finally {
|
||||
if(in != null)
|
||||
in.close();
|
||||
if(out != null)
|
||||
out.close();
|
||||
|
||||
conn.disconnect();
|
||||
}
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
public byte[] getResourceContent(String urlString) throws Exception {
|
||||
HttpURLConnection conn = getHTTPConnection(urlString);
|
||||
InputStream in = conn.getInputStream();
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
byte[] buf = new byte[102400];
|
||||
int len = 0;
|
||||
while ((len = in.read(buf)) > 0) {
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
in.close();
|
||||
out.close();
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
public void uploadResourceContent(String urlString, byte[] content) throws Exception {
|
||||
// vSphere does not support POST
|
||||
HttpURLConnection conn = getHTTPConnection(urlString, "PUT");
|
||||
|
||||
OutputStream out = conn.getOutputStream();
|
||||
out.write(content);
|
||||
out.flush();
|
||||
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
String line;
|
||||
while ((line = in.readLine()) != null) {
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("Upload " + urlString + " response: " + line);
|
||||
}
|
||||
out.close();
|
||||
in.close();
|
||||
}
|
||||
|
||||
/*
|
||||
* Sample content returned by query a datastore directory
|
||||
*
|
||||
* Url for the query
|
||||
* https://vsphere-1.lab.vmops.com/folder/Fedora-clone-test?dcPath=cupertino&dsName=NFS+datastore
|
||||
*
|
||||
* Returned conent from vSphere
|
||||
*
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
<title>Index of Fedora-clone-test on datastore NFS datastore in datacenter cupertino</title></head>
|
||||
<body>
|
||||
<h1>Index of Fedora-clone-test on datastore NFS datastore in datacenter cupertino</h1>
|
||||
<table>
|
||||
<tr><th>Name</th><th>Last modified</th><th>Size</th></tr><tr><th colspan="3"><hr></th></tr>
|
||||
<tr><td><a href="/folder?dcPath=cupertino&dsName=NFS%20datastore">Parent Directory</a></td><td> </td><td align="right"> - </td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2da2013465%2ehlog?dcPath=cupertino&dsName=NFS%20datastore">Fedora-clone-test-a2013465.hlog</a></td><td align="right">15-Aug-2010 00:13</td><td align="right">1</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2da2013465%2evswp?dcPath=cupertino&dsName=NFS%20datastore">Fedora-clone-test-a2013465.vswp</a></td><td align="right">14-Aug-2010 23:01</td><td align="right">402653184</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2dflat%2evmdk?dcPath=cupertino&dsName=NFS%20datastore">Fedora-clone-test-flat.vmdk</a></td><td align="right">26-Aug-2010 18:43</td><td align="right">17179869184</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2envram?dcPath=cupertino&dsName=NFS%20datastore">Fedora-clone-test.nvram</a></td><td align="right">15-Aug-2010 00:13</td><td align="right">8684</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2evmdk?dcPath=cupertino&dsName=NFS%20datastore">Fedora-clone-test.vmdk</a></td><td align="right">15-Aug-2010 00:13</td><td align="right">479</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2evmsd?dcPath=cupertino&dsName=NFS%20datastore">Fedora-clone-test.vmsd</a></td><td align="right">14-Aug-2010 16:59</td><td align="right">0</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2evmx?dcPath=cupertino&dsName=NFS%20datastore">Fedora-clone-test.vmx</a></td><td align="right">15-Aug-2010 00:13</td><td align="right">3500</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2evmxf?dcPath=cupertino&dsName=NFS%20datastore">Fedora-clone-test.vmxf</a></td><td align="right">15-Aug-2010 00:13</td><td align="right">272</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/test%2etxt?dcPath=cupertino&dsName=NFS%20datastore">test.txt</a></td><td align="right">24-Aug-2010 01:03</td><td align="right">12</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2d2%2elog?dcPath=cupertino&dsName=NFS%20datastore">vmware-2.log</a></td><td align="right">14-Aug-2010 16:51</td><td align="right">80782</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2d3%2elog?dcPath=cupertino&dsName=NFS%20datastore">vmware-3.log</a></td><td align="right">14-Aug-2010 19:07</td><td align="right">58573</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2d4%2elog?dcPath=cupertino&dsName=NFS%20datastore">vmware-4.log</a></td><td align="right">14-Aug-2010 23:00</td><td align="right">49751</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2d5%2elog?dcPath=cupertino&dsName=NFS%20datastore">vmware-5.log</a></td><td align="right">15-Aug-2010 00:04</td><td align="right">64024</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2d6%2elog?dcPath=cupertino&dsName=NFS%20datastore">vmware-6.log</a></td><td align="right">15-Aug-2010 00:11</td><td align="right">59742</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2d7%2elog?dcPath=cupertino&dsName=NFS%20datastore">vmware-7.log</a></td><td align="right">15-Aug-2010 00:13</td><td align="right">59859</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2elog?dcPath=cupertino&dsName=NFS%20datastore">vmware.log</a></td><td align="right">15-Aug-2010 00:23</td><td align="right">47157</td></tr>
|
||||
<tr><th colspan="5"><hr></th></tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
*/
|
||||
public String[] listDatastoreDirContent(String urlString) throws Exception {
|
||||
List<String> fileList = new ArrayList<String>();
|
||||
String content = new String(getResourceContent(urlString));
|
||||
String marker = "</a></td><td ";
|
||||
int parsePos = -1;
|
||||
do {
|
||||
parsePos = content.indexOf(marker, parsePos < 0 ? 0 : parsePos);
|
||||
if(parsePos > 0) {
|
||||
int beginPos = content.lastIndexOf('>', parsePos -1);
|
||||
if(beginPos < 0)
|
||||
beginPos = 0;
|
||||
|
||||
fileList.add((content.substring(beginPos + 1, parsePos)));
|
||||
parsePos += marker.length();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while(parsePos > 0);
|
||||
return fileList.toArray(new String[0]);
|
||||
}
|
||||
|
||||
public String composeDatastoreBrowseUrl(String dcName, String fullPath) {
|
||||
DatastoreFile dsFile = new DatastoreFile(fullPath);
|
||||
return composeDatastoreBrowseUrl(dcName, dsFile.getDatastoreName(), dsFile.getRelativePath());
|
||||
}
|
||||
|
||||
public String composeDatastoreBrowseUrl(String dcName, String datastoreName, String relativePath) {
|
||||
assert(relativePath != null);
|
||||
assert(datastoreName != null);
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("https://");
|
||||
sb.append(_serverAddress);
|
||||
sb.append("/folder/");
|
||||
sb.append(relativePath);
|
||||
sb.append("?dcPath=").append(URLEncoder.encode(dcName)).append("&dsName=");
|
||||
sb.append(URLEncoder.encode(datastoreName));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public HttpURLConnection getHTTPConnection(String urlString) throws Exception {
|
||||
return getHTTPConnection(urlString, "GET");
|
||||
}
|
||||
|
||||
public HttpURLConnection getHTTPConnection(String urlString, String httpMethod) throws Exception {
|
||||
String cookieString = getServiceCookie();
|
||||
HostnameVerifier hv = new HostnameVerifier() {
|
||||
public boolean verify(String urlHostName, SSLSession session) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
HttpsURLConnection.setDefaultHostnameVerifier(hv);
|
||||
URL url = new URL(urlString);
|
||||
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
|
||||
|
||||
conn.setDoInput(true);
|
||||
conn.setDoOutput(true);
|
||||
conn.setAllowUserInteraction(true);
|
||||
conn.setRequestProperty(org.apache.axis.transport.http.HTTPConstants.HEADER_COOKIE, cookieString);
|
||||
conn.setRequestMethod(httpMethod);
|
||||
conn.connect();
|
||||
return conn;
|
||||
}
|
||||
|
||||
public HttpURLConnection getRawHTTPConnection(String urlString) throws Exception {
|
||||
HostnameVerifier hv = new HostnameVerifier() {
|
||||
public boolean verify(String urlHostName, SSLSession session) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
HttpsURLConnection.setDefaultHostnameVerifier(hv);
|
||||
URL url = new URL(urlString);
|
||||
return (HttpURLConnection)url.openConnection();
|
||||
}
|
||||
|
||||
private String getServiceCookie() throws Exception {
|
||||
com.vmware.vim25.VimPortType service = getService();
|
||||
org.apache.axis.client.Stub st = (org.apache.axis.client.Stub)service;
|
||||
org.apache.axis.client.Call callObj = st._getCall();
|
||||
org.apache.axis.MessageContext msgContext = callObj.getMessageContext();
|
||||
String cookieString = (String)msgContext.getProperty(org.apache.axis.transport.http.HTTPConstants.HEADER_COOKIE);
|
||||
return cookieString;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
_appUtil.disConnect();
|
||||
} catch(Exception e) {
|
||||
s_logger.warn("Unexpected exception: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TrustAllManager implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager {
|
||||
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isServerTrusted(java.security.cert.X509Certificate[] certs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isClientTrusted(java.security.cert.X509Certificate[] certs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
|
||||
throws java.security.cert.CertificateException {
|
||||
return;
|
||||
}
|
||||
|
||||
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
|
||||
throws java.security.cert.CertificateException {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.util;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.vmware.vim25.VirtualMachineGuestOsIdentifier;
|
||||
|
||||
public class VmwareGuestOsMapper {
|
||||
private static Map<String, VirtualMachineGuestOsIdentifier> s_mapper = new HashMap<String, VirtualMachineGuestOsIdentifier>();
|
||||
static {
|
||||
s_mapper.put("Windows 7 (32-bit)", VirtualMachineGuestOsIdentifier.windows7Guest);
|
||||
s_mapper.put("Windows 7 (64-bit)", VirtualMachineGuestOsIdentifier.windows7_64Guest);
|
||||
s_mapper.put("Windows Server 2003 Enterprise Edition(32-bit)", VirtualMachineGuestOsIdentifier.winNetEnterpriseGuest);
|
||||
s_mapper.put("Windows Server 2003 Enterprise Edition(64-bit)", VirtualMachineGuestOsIdentifier.winNetEnterprise64Guest);
|
||||
s_mapper.put("Windows Server 2008 (32-bit)", VirtualMachineGuestOsIdentifier.winLonghornGuest);
|
||||
s_mapper.put("Windows Server 2008 (64-bit)", VirtualMachineGuestOsIdentifier.winLonghorn64Guest);
|
||||
s_mapper.put("Windows Server 2008 R2 (64-bit)", VirtualMachineGuestOsIdentifier.winLonghorn64Guest);
|
||||
s_mapper.put("Windows 2000 Server SP4 (32-bit)", VirtualMachineGuestOsIdentifier.win2000ServGuest);
|
||||
s_mapper.put("Windows Vista (32-bit)", VirtualMachineGuestOsIdentifier.winVistaGuest);
|
||||
s_mapper.put("Windows XP SP2 (32-bit)", VirtualMachineGuestOsIdentifier.winXPProGuest);
|
||||
s_mapper.put("Windows XP SP3 (32-bit)", VirtualMachineGuestOsIdentifier.winXPProGuest);
|
||||
s_mapper.put("Other Ubuntu (32-bit)", VirtualMachineGuestOsIdentifier.ubuntuGuest);
|
||||
s_mapper.put("Other (32-bit)", VirtualMachineGuestOsIdentifier.otherGuest);
|
||||
s_mapper.put("Windows 2000 Server", VirtualMachineGuestOsIdentifier.win2000ServGuest);
|
||||
s_mapper.put("Windows 98", VirtualMachineGuestOsIdentifier.win98Guest);
|
||||
s_mapper.put("Windows 95", VirtualMachineGuestOsIdentifier.win95Guest);
|
||||
s_mapper.put("Windows NT 4", VirtualMachineGuestOsIdentifier.winNTGuest);
|
||||
s_mapper.put("Windows 3.1", VirtualMachineGuestOsIdentifier.win31Guest);
|
||||
s_mapper.put("Red Hat Enterprise Linux 3(32-bit)", VirtualMachineGuestOsIdentifier.rhel3Guest);
|
||||
s_mapper.put("Red Hat Enterprise Linux 3(64-bit)", VirtualMachineGuestOsIdentifier.rhel3_64Guest);
|
||||
s_mapper.put("Open Enterprise Server", VirtualMachineGuestOsIdentifier.oesGuest);
|
||||
s_mapper.put("Asianux 3(32-bit)", VirtualMachineGuestOsIdentifier.asianux3Guest);
|
||||
s_mapper.put("Asianux 3(64-bit)", VirtualMachineGuestOsIdentifier.asianux3_64Guest);
|
||||
s_mapper.put("Debian GNU/Linux 5(64-bit)", VirtualMachineGuestOsIdentifier.debian5_64Guest);
|
||||
s_mapper.put("Debian GNU/Linux 4(32-bit)", VirtualMachineGuestOsIdentifier.debian4Guest);
|
||||
s_mapper.put("Debian GNU/Linux 4(64-bit)", VirtualMachineGuestOsIdentifier.debian4_64Guest);
|
||||
s_mapper.put("Other 2.6x Linux (32-bit)", VirtualMachineGuestOsIdentifier.other26xLinuxGuest);
|
||||
s_mapper.put("Other 2.6x Linux (64-bit)", VirtualMachineGuestOsIdentifier.other26xLinux64Guest);
|
||||
s_mapper.put("Novell Netware 6.x", VirtualMachineGuestOsIdentifier.netware6Guest);
|
||||
s_mapper.put("Novell Netware 5.1", VirtualMachineGuestOsIdentifier.netware5Guest);
|
||||
s_mapper.put("Sun Solaris 10(32-bit)", VirtualMachineGuestOsIdentifier.solaris10Guest);
|
||||
s_mapper.put("Sun Solaris 10(64-bit)", VirtualMachineGuestOsIdentifier.solaris10_64Guest);
|
||||
s_mapper.put("Sun Solaris 9(Experimental)", VirtualMachineGuestOsIdentifier.solaris9Guest);
|
||||
s_mapper.put("Sun Solaris 8(Experimental)", VirtualMachineGuestOsIdentifier.solaris8Guest);
|
||||
s_mapper.put("FreeBSD (32-bit)", VirtualMachineGuestOsIdentifier.freebsdGuest);
|
||||
s_mapper.put("FreeBSD (64-bit)", VirtualMachineGuestOsIdentifier.freebsd64Guest);
|
||||
s_mapper.put("SCO OpenServer 5", VirtualMachineGuestOsIdentifier.otherGuest);
|
||||
s_mapper.put("SCO UnixWare 7", VirtualMachineGuestOsIdentifier.unixWare7Guest);
|
||||
s_mapper.put("Windows Server 2003 DataCenter Edition(32-bit)", VirtualMachineGuestOsIdentifier.winNetDatacenterGuest);
|
||||
s_mapper.put("Windows Server 2003 DataCenter Edition(64-bit)", VirtualMachineGuestOsIdentifier.winNetDatacenter64Guest);
|
||||
s_mapper.put("Windows Server 2003 Standard Edition(32-bit)", VirtualMachineGuestOsIdentifier.winNetStandardGuest);
|
||||
s_mapper.put("Windows Server 2003 Standard Edition(64-bit)", VirtualMachineGuestOsIdentifier.winNetStandard64Guest);
|
||||
s_mapper.put("Windows Server 2003 Web Edition", VirtualMachineGuestOsIdentifier.winNetWebGuest);
|
||||
s_mapper.put("Microsoft Small Bussiness Server 2003", VirtualMachineGuestOsIdentifier.winNetBusinessGuest);
|
||||
s_mapper.put("Windows XP (32-bit)", VirtualMachineGuestOsIdentifier.winXPProGuest);
|
||||
s_mapper.put("Windows XP (64-bit)", VirtualMachineGuestOsIdentifier.winXPPro64Guest);
|
||||
s_mapper.put("Windows 2000 Advanced Server", VirtualMachineGuestOsIdentifier.win2000AdvServGuest);
|
||||
s_mapper.put("SUSE Linux Enterprise 8(32-bit)", VirtualMachineGuestOsIdentifier.suseGuest);
|
||||
s_mapper.put("SUSE Linux Enterprise 8(64-bit)", VirtualMachineGuestOsIdentifier.suse64Guest);
|
||||
s_mapper.put("Other Linux (32-bit)", VirtualMachineGuestOsIdentifier.otherLinuxGuest);
|
||||
s_mapper.put("Other Linux (64-bit)", VirtualMachineGuestOsIdentifier.otherLinux64Guest);
|
||||
s_mapper.put("Other Ubuntu (64-bit)", VirtualMachineGuestOsIdentifier.ubuntu64Guest);
|
||||
s_mapper.put("Windows Vista (64-bit)", VirtualMachineGuestOsIdentifier.winVista64Guest);
|
||||
s_mapper.put("DOS", VirtualMachineGuestOsIdentifier.dosGuest);
|
||||
s_mapper.put("Other (64-bit)", VirtualMachineGuestOsIdentifier.otherGuest64);
|
||||
s_mapper.put("OS/2", VirtualMachineGuestOsIdentifier.os2Guest);
|
||||
s_mapper.put("Windows 2000 Professional", VirtualMachineGuestOsIdentifier.win2000ProGuest);
|
||||
s_mapper.put("Red Hat Enterprise Linux 4(64-bit)", VirtualMachineGuestOsIdentifier.rhel4_64Guest);
|
||||
s_mapper.put("SUSE Linux Enterprise 9(32-bit)", VirtualMachineGuestOsIdentifier.suseGuest);
|
||||
s_mapper.put("SUSE Linux Enterprise 9(64-bit)", VirtualMachineGuestOsIdentifier.suse64Guest);
|
||||
s_mapper.put("SUSE Linux Enterprise 10(32-bit)", VirtualMachineGuestOsIdentifier.suseGuest);
|
||||
s_mapper.put("SUSE Linux Enterprise 10(64-bit)", VirtualMachineGuestOsIdentifier.suse64Guest);
|
||||
s_mapper.put("CentOS 5.5 (32-bit)", VirtualMachineGuestOsIdentifier.centosGuest);
|
||||
s_mapper.put("CentOS 5.5 (64-bit)", VirtualMachineGuestOsIdentifier.centos64Guest);
|
||||
s_mapper.put("Red Hat Enterprise Linux 5.5 (32-bit)", VirtualMachineGuestOsIdentifier.rhel5Guest);
|
||||
s_mapper.put("Red Hat Enterprise Linux 5.5 (64-bit)", VirtualMachineGuestOsIdentifier.rhel5_64Guest);
|
||||
s_mapper.put("Red Hat Enterprise Linux 2", VirtualMachineGuestOsIdentifier.rhel2Guest);
|
||||
s_mapper.put("Ubuntu 10.04 (32-bit)", VirtualMachineGuestOsIdentifier.ubuntuGuest);
|
||||
s_mapper.put("Ubuntu 9.10 (32-bit)", VirtualMachineGuestOsIdentifier.ubuntuGuest);
|
||||
s_mapper.put("Ubuntu 9.04 (32-bit)", VirtualMachineGuestOsIdentifier.ubuntuGuest);
|
||||
s_mapper.put("Ubuntu 8.10 (32-bit)", VirtualMachineGuestOsIdentifier.ubuntuGuest);
|
||||
s_mapper.put("Ubuntu 8.04 (32-bit)", VirtualMachineGuestOsIdentifier.ubuntuGuest);
|
||||
s_mapper.put("Ubuntu 10.04 (64-bit)", VirtualMachineGuestOsIdentifier.ubuntu64Guest);
|
||||
s_mapper.put("Ubuntu 9.10 (64-bit)", VirtualMachineGuestOsIdentifier.ubuntu64Guest);
|
||||
s_mapper.put("Ubuntu 9.04 (64-bit)", VirtualMachineGuestOsIdentifier.ubuntu64Guest);
|
||||
s_mapper.put("Ubuntu 8.10 (64-bit)", VirtualMachineGuestOsIdentifier.ubuntu64Guest);
|
||||
s_mapper.put("Ubuntu 8.04 (64-bit)", VirtualMachineGuestOsIdentifier.ubuntu64Guest);
|
||||
}
|
||||
|
||||
public static VirtualMachineGuestOsIdentifier getGuestOsIdentifier(String guestOsName) {
|
||||
return s_mapper.get(guestOsName);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,513 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.util;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
|
||||
import com.cloud.hypervisor.vmware.mo.DatastoreMO;
|
||||
import com.cloud.hypervisor.vmware.mo.HostMO;
|
||||
import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType;
|
||||
import com.cloud.hypervisor.vmware.mo.VirtualMachineMO;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.Ternary;
|
||||
import com.cloud.utils.exception.ExceptionUtil;
|
||||
import com.vmware.vim25.DynamicProperty;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.MethodFault;
|
||||
import com.vmware.vim25.ObjectContent;
|
||||
import com.vmware.vim25.OptionValue;
|
||||
import com.vmware.vim25.ResourceAllocationInfo;
|
||||
import com.vmware.vim25.VirtualCdrom;
|
||||
import com.vmware.vim25.VirtualCdromIsoBackingInfo;
|
||||
import com.vmware.vim25.VirtualCdromRemotePassthroughBackingInfo;
|
||||
import com.vmware.vim25.VirtualDevice;
|
||||
import com.vmware.vim25.VirtualDeviceBackingInfo;
|
||||
import com.vmware.vim25.VirtualDeviceConnectInfo;
|
||||
import com.vmware.vim25.VirtualDisk;
|
||||
import com.vmware.vim25.VirtualDiskFlatVer1BackingInfo;
|
||||
import com.vmware.vim25.VirtualDiskFlatVer2BackingInfo;
|
||||
import com.vmware.vim25.VirtualDiskMode;
|
||||
import com.vmware.vim25.VirtualDiskRawDiskMappingVer1BackingInfo;
|
||||
import com.vmware.vim25.VirtualDiskSparseVer1BackingInfo;
|
||||
import com.vmware.vim25.VirtualDiskSparseVer2BackingInfo;
|
||||
import com.vmware.vim25.VirtualE1000;
|
||||
import com.vmware.vim25.VirtualEthernetCard;
|
||||
import com.vmware.vim25.VirtualEthernetCardNetworkBackingInfo;
|
||||
import com.vmware.vim25.VirtualMachineConfigSpec;
|
||||
import com.vmware.vim25.VirtualMachineSnapshotTree;
|
||||
import com.vmware.vim25.VirtualPCNet32;
|
||||
import com.vmware.vim25.VirtualVmxnet2;
|
||||
import com.vmware.vim25.VirtualVmxnet3;
|
||||
|
||||
public class VmwareHelper {
|
||||
private static final Logger s_logger = Logger.getLogger(VmwareHelper.class);
|
||||
|
||||
public static VirtualDevice prepareNicDevice(VirtualMachineMO vmMo, ManagedObjectReference morNetwork, VirtualEthernetCardType deviceType,
|
||||
String portGroupName, String macAddress, int deviceNumber, int contextNumber, boolean conntected, boolean connectOnStart) throws Exception {
|
||||
|
||||
VirtualEthernetCard nic;
|
||||
switch(deviceType) {
|
||||
case E1000 :
|
||||
nic = new VirtualE1000();
|
||||
break;
|
||||
|
||||
case PCNet32 :
|
||||
nic = new VirtualPCNet32();
|
||||
break;
|
||||
|
||||
case Vmxnet2 :
|
||||
nic = new VirtualVmxnet2();
|
||||
break;
|
||||
|
||||
case Vmxnet3 :
|
||||
nic = new VirtualVmxnet3();
|
||||
break;
|
||||
|
||||
default :
|
||||
assert(false);
|
||||
nic = new VirtualE1000();
|
||||
}
|
||||
|
||||
VirtualEthernetCardNetworkBackingInfo nicBacking = new VirtualEthernetCardNetworkBackingInfo();
|
||||
nicBacking.setDeviceName(portGroupName);
|
||||
nicBacking.setNetwork(morNetwork);
|
||||
nic.setBacking(nicBacking);
|
||||
|
||||
VirtualDeviceConnectInfo connectInfo = new VirtualDeviceConnectInfo();
|
||||
connectInfo.setAllowGuestControl(true);
|
||||
connectInfo.setConnected(conntected);
|
||||
connectInfo.setStartConnected(connectOnStart);
|
||||
nic.setAddressType("Manual");
|
||||
nic.setConnectable(connectInfo);
|
||||
nic.setMacAddress(macAddress);
|
||||
nic.setControllerKey(vmMo.getPCIDeviceControllerKey());
|
||||
|
||||
if(deviceNumber < 0)
|
||||
deviceNumber = vmMo.getNextPCIDeviceNumber();
|
||||
nic.setUnitNumber(deviceNumber);
|
||||
nic.setKey(-contextNumber);
|
||||
return nic;
|
||||
}
|
||||
|
||||
// vmdkDatastorePath: [datastore name] vmdkFilePath
|
||||
public static VirtualDevice prepareDiskDevice(VirtualMachineMO vmMo, int controllerKey, String vmdkDatastorePath,
|
||||
int sizeInMb, ManagedObjectReference morDs, int deviceNumber, int contextNumber) throws Exception {
|
||||
|
||||
if(controllerKey < 0)
|
||||
controllerKey = vmMo.getIDEDeviceControllerKey();
|
||||
|
||||
VirtualDisk disk = new VirtualDisk();
|
||||
|
||||
VirtualDiskFlatVer2BackingInfo backingInfo = new VirtualDiskFlatVer2BackingInfo();
|
||||
backingInfo.setDiskMode(VirtualDiskMode.persistent.toString());
|
||||
backingInfo.setThinProvisioned(true);
|
||||
backingInfo.setEagerlyScrub(false);
|
||||
backingInfo.setDatastore(morDs);
|
||||
backingInfo.setFileName(vmdkDatastorePath);
|
||||
disk.setBacking(backingInfo);
|
||||
|
||||
if(deviceNumber < 0)
|
||||
deviceNumber = vmMo.getNextDeviceNumber(controllerKey);
|
||||
disk.setControllerKey(controllerKey);
|
||||
disk.setKey(-contextNumber);
|
||||
disk.setUnitNumber(deviceNumber);
|
||||
disk.setCapacityInKB(sizeInMb*1024);
|
||||
|
||||
VirtualDeviceConnectInfo connectInfo = new VirtualDeviceConnectInfo();
|
||||
connectInfo.setConnected(true);
|
||||
connectInfo.setStartConnected(true);
|
||||
disk.setConnectable(connectInfo);
|
||||
|
||||
return disk;
|
||||
}
|
||||
|
||||
// vmdkDatastorePath: [datastore name] vmdkFilePath, create delta disk based on disk from template
|
||||
public static VirtualDevice prepareDiskDevice(VirtualMachineMO vmMo, int controllerKey, String vmdkDatastorePath,
|
||||
int sizeInMb, ManagedObjectReference morDs, VirtualDisk templateDisk, int deviceNumber, int contextNumber) throws Exception {
|
||||
|
||||
assert(templateDisk != null);
|
||||
VirtualDeviceBackingInfo parentBacking = templateDisk.getBacking();
|
||||
assert(parentBacking != null);
|
||||
|
||||
// TODO Not sure if we need to check if the disk in template and the new disk needs to share the
|
||||
// same datastore
|
||||
VirtualDisk disk = new VirtualDisk();
|
||||
if(parentBacking instanceof VirtualDiskFlatVer1BackingInfo) {
|
||||
VirtualDiskFlatVer1BackingInfo backingInfo = new VirtualDiskFlatVer1BackingInfo();
|
||||
backingInfo.setDiskMode(((VirtualDiskFlatVer1BackingInfo)parentBacking).getDiskMode());
|
||||
backingInfo.setDatastore(morDs);
|
||||
backingInfo.setFileName(vmdkDatastorePath);
|
||||
backingInfo.setParent((VirtualDiskFlatVer1BackingInfo)parentBacking);
|
||||
disk.setBacking(backingInfo);
|
||||
} else if(parentBacking instanceof VirtualDiskFlatVer2BackingInfo) {
|
||||
VirtualDiskFlatVer2BackingInfo backingInfo = new VirtualDiskFlatVer2BackingInfo();
|
||||
backingInfo.setDiskMode(((VirtualDiskFlatVer2BackingInfo)parentBacking).getDiskMode());
|
||||
backingInfo.setDatastore(morDs);
|
||||
backingInfo.setFileName(vmdkDatastorePath);
|
||||
backingInfo.setParent((VirtualDiskFlatVer2BackingInfo)parentBacking);
|
||||
disk.setBacking(backingInfo);
|
||||
} else if(parentBacking instanceof VirtualDiskRawDiskMappingVer1BackingInfo) {
|
||||
VirtualDiskRawDiskMappingVer1BackingInfo backingInfo = new VirtualDiskRawDiskMappingVer1BackingInfo();
|
||||
backingInfo.setDiskMode(((VirtualDiskRawDiskMappingVer1BackingInfo)parentBacking).getDiskMode());
|
||||
backingInfo.setDatastore(morDs);
|
||||
backingInfo.setFileName(vmdkDatastorePath);
|
||||
backingInfo.setParent((VirtualDiskRawDiskMappingVer1BackingInfo)parentBacking);
|
||||
disk.setBacking(backingInfo);
|
||||
} else if(parentBacking instanceof VirtualDiskSparseVer1BackingInfo) {
|
||||
VirtualDiskSparseVer1BackingInfo backingInfo = new VirtualDiskSparseVer1BackingInfo();
|
||||
backingInfo.setDiskMode(((VirtualDiskSparseVer1BackingInfo)parentBacking).getDiskMode());
|
||||
backingInfo.setDatastore(morDs);
|
||||
backingInfo.setFileName(vmdkDatastorePath);
|
||||
backingInfo.setParent((VirtualDiskSparseVer1BackingInfo)parentBacking);
|
||||
disk.setBacking(backingInfo);
|
||||
} else if(parentBacking instanceof VirtualDiskSparseVer2BackingInfo) {
|
||||
VirtualDiskSparseVer2BackingInfo backingInfo = new VirtualDiskSparseVer2BackingInfo();
|
||||
backingInfo.setDiskMode(((VirtualDiskSparseVer2BackingInfo)parentBacking).getDiskMode());
|
||||
backingInfo.setDatastore(morDs);
|
||||
backingInfo.setFileName(vmdkDatastorePath);
|
||||
backingInfo.setParent((VirtualDiskSparseVer2BackingInfo)parentBacking);
|
||||
disk.setBacking(backingInfo);
|
||||
} else {
|
||||
throw new Exception("Unsupported disk backing: " + parentBacking.getClass().getCanonicalName());
|
||||
}
|
||||
|
||||
if(controllerKey < 0)
|
||||
controllerKey = vmMo.getIDEDeviceControllerKey();
|
||||
disk.setControllerKey(controllerKey);
|
||||
|
||||
if(deviceNumber < 0)
|
||||
deviceNumber = vmMo.getNextDeviceNumber(controllerKey);
|
||||
disk.setKey(-contextNumber);
|
||||
disk.setUnitNumber(deviceNumber);
|
||||
disk.setCapacityInKB(sizeInMb*1024);
|
||||
|
||||
VirtualDeviceConnectInfo connectInfo = new VirtualDeviceConnectInfo();
|
||||
connectInfo.setConnected(true);
|
||||
connectInfo.setStartConnected(true);
|
||||
disk.setConnectable(connectInfo);
|
||||
return disk;
|
||||
}
|
||||
|
||||
// vmdkDatastorePath: [datastore name] vmdkFilePath
|
||||
public static VirtualDevice prepareDiskDevice(VirtualMachineMO vmMo, int controllerKey, String vmdkDatastorePathChain[],
|
||||
ManagedObjectReference morDs, int deviceNumber, int contextNumber) throws Exception {
|
||||
|
||||
assert(vmdkDatastorePathChain != null);
|
||||
assert(vmdkDatastorePathChain.length >= 1);
|
||||
|
||||
if(controllerKey < 0)
|
||||
controllerKey = vmMo.getIDEDeviceControllerKey();
|
||||
|
||||
VirtualDisk disk = new VirtualDisk();
|
||||
|
||||
VirtualDiskFlatVer2BackingInfo backingInfo = new VirtualDiskFlatVer2BackingInfo();
|
||||
backingInfo.setDatastore(morDs);
|
||||
backingInfo.setFileName(vmdkDatastorePathChain[0]);
|
||||
backingInfo.setDiskMode(VirtualDiskMode.persistent.toString());
|
||||
if(vmdkDatastorePathChain.length > 1) {
|
||||
String[] parentDisks = new String[vmdkDatastorePathChain.length - 1];
|
||||
for(int i = 0; i < vmdkDatastorePathChain.length - 1; i++)
|
||||
parentDisks[i] = vmdkDatastorePathChain[i + 1];
|
||||
|
||||
setParentBackingInfo(backingInfo, morDs, parentDisks);
|
||||
}
|
||||
|
||||
disk.setBacking(backingInfo);
|
||||
|
||||
if(deviceNumber < 0)
|
||||
deviceNumber = vmMo.getNextDeviceNumber(controllerKey);
|
||||
|
||||
disk.setControllerKey(controllerKey);
|
||||
disk.setKey(-contextNumber);
|
||||
disk.setUnitNumber(deviceNumber);
|
||||
|
||||
VirtualDeviceConnectInfo connectInfo = new VirtualDeviceConnectInfo();
|
||||
connectInfo.setConnected(true);
|
||||
connectInfo.setStartConnected(true);
|
||||
disk.setConnectable(connectInfo);
|
||||
|
||||
return disk;
|
||||
}
|
||||
|
||||
private static void setParentBackingInfo(VirtualDiskFlatVer2BackingInfo backingInfo,
|
||||
ManagedObjectReference morDs, String[] parentDatastorePathList) {
|
||||
|
||||
VirtualDiskFlatVer2BackingInfo parentBacking = new VirtualDiskFlatVer2BackingInfo();
|
||||
parentBacking.setDatastore(morDs);
|
||||
parentBacking.setDiskMode(VirtualDiskMode.persistent.toString());
|
||||
|
||||
if(parentDatastorePathList.length > 1) {
|
||||
String[] nextDatastorePathList = new String[parentDatastorePathList.length -1];
|
||||
for(int i = 0; i < parentDatastorePathList.length -1; i++)
|
||||
nextDatastorePathList[i] = parentDatastorePathList[i + 1];
|
||||
setParentBackingInfo(parentBacking, morDs, nextDatastorePathList);
|
||||
}
|
||||
parentBacking.setFileName(parentDatastorePathList[0]);
|
||||
|
||||
backingInfo.setParent(parentBacking);
|
||||
}
|
||||
|
||||
public static Pair<VirtualDevice, Boolean> prepareIsoDevice(VirtualMachineMO vmMo, String isoDatastorePath, ManagedObjectReference morDs,
|
||||
boolean connect, boolean connectAtBoot, int deviceNumber, int contextNumber) throws Exception {
|
||||
|
||||
boolean newCdRom = false;
|
||||
VirtualCdrom cdRom = (VirtualCdrom )vmMo.getIsoDevice();
|
||||
if(cdRom == null) {
|
||||
newCdRom = true;
|
||||
cdRom = new VirtualCdrom();
|
||||
assert(vmMo.getIDEDeviceControllerKey() >= 0);
|
||||
cdRom.setControllerKey(vmMo.getIDEDeviceControllerKey());
|
||||
|
||||
if(deviceNumber < 0)
|
||||
deviceNumber = vmMo.getNextIDEDeviceNumber();
|
||||
cdRom.setUnitNumber(deviceNumber);
|
||||
cdRom.setKey(-contextNumber);
|
||||
}
|
||||
|
||||
VirtualDeviceConnectInfo cInfo = new VirtualDeviceConnectInfo();
|
||||
cInfo.setConnected(connect);
|
||||
cInfo.setStartConnected(connectAtBoot);
|
||||
cdRom.setConnectable(cInfo);
|
||||
|
||||
if(isoDatastorePath != null) {
|
||||
VirtualCdromIsoBackingInfo backingInfo = new VirtualCdromIsoBackingInfo();
|
||||
backingInfo.setFileName(isoDatastorePath);
|
||||
backingInfo.setDatastore(morDs);
|
||||
cdRom.setBacking(backingInfo);
|
||||
} else {
|
||||
VirtualCdromRemotePassthroughBackingInfo backingInfo = new VirtualCdromRemotePassthroughBackingInfo();
|
||||
backingInfo.setDeviceName("");
|
||||
cdRom.setBacking(backingInfo);
|
||||
}
|
||||
|
||||
return new Pair<VirtualDevice, Boolean>(cdRom, newCdRom);
|
||||
}
|
||||
|
||||
public static VirtualDisk getRootDisk(VirtualDisk[] disks) {
|
||||
if(disks.length == 1)
|
||||
return disks[0];
|
||||
|
||||
// TODO : for now, always return the first disk as root disk
|
||||
return disks[0];
|
||||
}
|
||||
|
||||
public static ManagedObjectReference findSnapshotInTree(VirtualMachineSnapshotTree[] snapTree, String findName) {
|
||||
assert(findName != null);
|
||||
|
||||
ManagedObjectReference snapMor = null;
|
||||
if (snapTree == null)
|
||||
return snapMor;
|
||||
|
||||
for (int i = 0; i < snapTree.length && snapMor == null; i++) {
|
||||
VirtualMachineSnapshotTree node = snapTree[i];
|
||||
|
||||
if (node.getName().equals(findName)) {
|
||||
snapMor = node.getSnapshot();
|
||||
} else {
|
||||
VirtualMachineSnapshotTree[] childTree = node.getChildSnapshotList();
|
||||
snapMor = findSnapshotInTree(childTree, findName);
|
||||
}
|
||||
}
|
||||
return snapMor;
|
||||
}
|
||||
|
||||
public static byte[] composeDiskInfo(List<Ternary<String, String, String>> diskInfo, int disksInChain, boolean includeBase) throws IOException {
|
||||
|
||||
BufferedWriter out = null;
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
|
||||
try {
|
||||
out = new BufferedWriter(new OutputStreamWriter(bos));
|
||||
|
||||
out.write("disksInChain=" + disksInChain);
|
||||
out.newLine();
|
||||
|
||||
out.write("disksInBackup=" + diskInfo.size());
|
||||
out.newLine();
|
||||
|
||||
out.write("baseDiskIncluded=" + includeBase);
|
||||
out.newLine();
|
||||
|
||||
int seq = disksInChain - 1;
|
||||
for(Ternary<String, String, String> item : diskInfo) {
|
||||
out.write(String.format("disk%d.fileName=%s", seq, item.first()));
|
||||
out.newLine();
|
||||
|
||||
out.write(String.format("disk%d.baseFileName=%s", seq, item.second()));
|
||||
out.newLine();
|
||||
|
||||
if(item.third() != null) {
|
||||
out.write(String.format("disk%d.parentFileName=%s", seq, item.third()));
|
||||
out.newLine();
|
||||
}
|
||||
seq--;
|
||||
}
|
||||
|
||||
out.newLine();
|
||||
} finally {
|
||||
if(out != null)
|
||||
out.close();
|
||||
}
|
||||
|
||||
return bos.toByteArray();
|
||||
}
|
||||
|
||||
public static OptionValue[] composeVncOptions(OptionValue[] optionsToMerge,
|
||||
boolean enableVnc, String vncPassword, int vncPort, String keyboardLayout) {
|
||||
|
||||
int numOptions = 3;
|
||||
boolean needKeyboardSetup = false;
|
||||
if(keyboardLayout != null && !keyboardLayout.isEmpty()) {
|
||||
numOptions++;
|
||||
needKeyboardSetup = true;
|
||||
}
|
||||
|
||||
if(optionsToMerge != null)
|
||||
numOptions += optionsToMerge.length;
|
||||
|
||||
OptionValue[] options = new OptionValue[numOptions];
|
||||
int i = 0;
|
||||
if(optionsToMerge != null) {
|
||||
for(int j = 0; j < optionsToMerge.length; j++)
|
||||
options[i++] = optionsToMerge[j];
|
||||
}
|
||||
|
||||
options[i] = new OptionValue();
|
||||
options[i].setKey("RemoteDisplay.vnc.enabled");
|
||||
options[i++].setValue(enableVnc ? "true" : "false");
|
||||
|
||||
options[i] = new OptionValue();
|
||||
options[i].setKey("RemoteDisplay.vnc.password");
|
||||
options[i++].setValue(vncPassword);
|
||||
|
||||
options[i] = new OptionValue();
|
||||
options[i].setKey("RemoteDisplay.vnc.port");
|
||||
options[i++].setValue("" + vncPort);
|
||||
|
||||
if(needKeyboardSetup) {
|
||||
options[i] = new OptionValue();
|
||||
options[i].setKey("RemoteDisplay.vnc.keymap");
|
||||
options[i++].setValue(keyboardLayout);
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
public static void setBasicVmConfig(VirtualMachineConfigSpec vmConfig, int cpuCount, int cpuSpeedMHz, int cpuReservedMhz,
|
||||
int memoryMB, String guestOsIdentifier, boolean limitCpuUse) {
|
||||
|
||||
// VM config basics
|
||||
vmConfig.setMemoryMB((long)memoryMB);
|
||||
vmConfig.setNumCPUs(cpuCount);
|
||||
|
||||
ResourceAllocationInfo cpuInfo = new ResourceAllocationInfo();
|
||||
if (limitCpuUse) {
|
||||
cpuInfo.setLimit((long)cpuSpeedMHz);
|
||||
} else {
|
||||
cpuInfo.setLimit(-1L);
|
||||
}
|
||||
|
||||
cpuInfo.setReservation((long)cpuReservedMhz);
|
||||
vmConfig.setCpuAllocation(cpuInfo);
|
||||
|
||||
ResourceAllocationInfo memInfo = new ResourceAllocationInfo();
|
||||
memInfo.setLimit((long)memoryMB);
|
||||
memInfo.setReservation((long)memoryMB);
|
||||
vmConfig.setMemoryAllocation(memInfo);
|
||||
|
||||
vmConfig.setGuestId(guestOsIdentifier);
|
||||
}
|
||||
|
||||
public static ManagedObjectReference getDiskDeviceDatastore(VirtualDisk diskDevice) throws Exception {
|
||||
VirtualDeviceBackingInfo backingInfo = diskDevice.getBacking();
|
||||
assert(backingInfo instanceof VirtualDiskFlatVer2BackingInfo);
|
||||
return ((VirtualDiskFlatVer2BackingInfo)backingInfo).getDatastore();
|
||||
}
|
||||
|
||||
public static Object getPropValue(ObjectContent oc, String name) {
|
||||
DynamicProperty[] props = oc.getPropSet();
|
||||
|
||||
for(DynamicProperty prop : props) {
|
||||
if(prop.getName().equalsIgnoreCase(name))
|
||||
return prop.getVal();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getFileExtension(String fileName, String defaultExtension) {
|
||||
int pos = fileName.lastIndexOf('.');
|
||||
if(pos < 0)
|
||||
return defaultExtension;
|
||||
|
||||
return fileName.substring(pos);
|
||||
}
|
||||
|
||||
public static boolean isSameHost(String ipAddress, String destName) {
|
||||
// TODO : may need to do DNS lookup to compare IP address exactly
|
||||
return ipAddress.equals(destName);
|
||||
}
|
||||
|
||||
public static void deleteVolumeVmdkFiles(DatastoreMO dsMo, String volumeName, DatacenterMO dcMo) throws Exception {
|
||||
String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeName);
|
||||
dsMo.deleteFile(volumeDatastorePath, dcMo.getMor(), true);
|
||||
|
||||
volumeDatastorePath = String.format("[%s] %s-flat.vmdk", dsMo.getName(), volumeName);
|
||||
dsMo.deleteFile(volumeDatastorePath, dcMo.getMor(), true);
|
||||
|
||||
volumeDatastorePath = String.format("[%s] %s-delta.vmdk", dsMo.getName(), volumeName);
|
||||
dsMo.deleteFile(volumeDatastorePath, dcMo.getMor(), true);
|
||||
}
|
||||
|
||||
public static String getExceptionMessage(Throwable e) {
|
||||
return getExceptionMessage(e, false);
|
||||
}
|
||||
|
||||
public static String getExceptionMessage(Throwable e, boolean printStack) {
|
||||
if(e instanceof MethodFault) {
|
||||
final StringWriter writer = new StringWriter();
|
||||
writer.append("Exception: " + e.getClass().getName() + "\n");
|
||||
writer.append("message: " + ((MethodFault)e).getFaultString() + "\n");
|
||||
|
||||
if(printStack) {
|
||||
writer.append("stack: ");
|
||||
e.printStackTrace(new PrintWriter(writer));
|
||||
}
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
return ExceptionUtil.toString(e, printStack);
|
||||
}
|
||||
|
||||
public static VirtualMachineMO pickOneVmOnRunningHost(List<VirtualMachineMO> vmList, boolean bFirstFit) throws Exception {
|
||||
List<VirtualMachineMO> candidates = new ArrayList<VirtualMachineMO>();
|
||||
|
||||
for(VirtualMachineMO vmMo : vmList) {
|
||||
HostMO hostMo = vmMo.getRunningHost();
|
||||
if(hostMo.isHyperHostConnected())
|
||||
candidates.add(vmMo);
|
||||
}
|
||||
|
||||
if(candidates.size() == 0)
|
||||
return null;
|
||||
|
||||
if(bFirstFit)
|
||||
return candidates.get(0);
|
||||
|
||||
Random random = new Random();
|
||||
return candidates.get(random.nextInt(candidates.size()));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue