Move VMware/Premium Secondary storage VM to opensource

This commit is contained in:
Kelven Yang 2011-08-23 14:28:45 -07:00
parent d3eb9db7fa
commit 4f8a52f94c
82 changed files with 16872 additions and 1 deletions

View File

@ -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" />

View File

@ -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>

View File

@ -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>

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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();
}
}
}

View File

@ -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

View File

@ -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";
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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

16
deps/.classpath vendored
View File

@ -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>

BIN
deps/vmware-apputils.jar vendored Normal file

Binary file not shown.

BIN
deps/vmware-credstore.jar vendored Normal file

Binary file not shown.

BIN
deps/vmware-lib-activation.jar vendored Normal file

Binary file not shown.

BIN
deps/vmware-lib-jaxen-core.jar vendored Normal file

Binary file not shown.

BIN
deps/vmware-lib-jaxen-jdom.jar vendored Normal file

Binary file not shown.

BIN
deps/vmware-lib-jaxrpc.jar vendored Normal file

Binary file not shown.

BIN
deps/vmware-lib-jdom.jar vendored Normal file

Binary file not shown.

BIN
deps/vmware-lib-mailapi.jar vendored Normal file

Binary file not shown.

BIN
deps/vmware-lib-saxpath.jar vendored Normal file

Binary file not shown.

BIN
deps/vmware-lib-smtp.jar vendored Normal file

Binary file not shown.

BIN
deps/vmware-lib-wbem.jar vendored Normal file

Binary file not shown.

BIN
deps/vmware-lib-xalan.jar vendored Normal file

Binary file not shown.

BIN
deps/vmware-lib-xerces.jar vendored Normal file

Binary file not shown.

BIN
deps/vmware-lib-xml-apis.jar vendored Normal file

Binary file not shown.

BIN
deps/vmware-vim.jar vendored Normal file

Binary file not shown.

BIN
deps/vmware-vim25.jar vendored Normal file

Binary file not shown.

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

8
vmware-base/.classpath Normal file
View File

@ -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>

17
vmware-base/.project Normal file
View File

@ -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>

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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";
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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 });
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,8 @@
package com.cloud.hypervisor.vmware.mo;
public enum HostVirtualNicType {
management,
vmotion,
faultToleranceLogging
}

View File

@ -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");
}
}
}

View File

@ -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();
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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");
}
}

View File

@ -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;
}
}
}

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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();
}
}

View File

@ -0,0 +1,8 @@
/**
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
*/
package com.cloud.hypervisor.vmware.mo;
public enum VmwareHostType {
ESXi, ESX
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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&amp;dsName=NFS%20datastore">Parent Directory</a></td><td>&nbsp;</td><td align="right"> - </td></tr>
<tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2da2013465%2ehlog?dcPath=cupertino&amp;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&amp;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&amp;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&amp;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&amp;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&amp;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&amp;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&amp;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&amp;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&amp;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&amp;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&amp;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&amp;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&amp;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&amp;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&amp;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;
}
}
}

View File

@ -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);
}
}

View File

@ -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()));
}
}