mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Move VMware/Premium Secondary storage VM to opensource
This commit is contained in:
parent
d3eb9db7fa
commit
4f8a52f94c
@ -111,6 +111,8 @@
|
||||
<property name="meld.home" location="/usr/local/bin" />
|
||||
<property name="assertion" value="-da" />
|
||||
|
||||
<!-- directory for vmware-base library -->
|
||||
<property name="vmware-base.dir" location="${base.dir}/vmware-base" />
|
||||
|
||||
<!-- directories for testing -->
|
||||
<property name="test.target.dir" location="${target.dir}/test" />
|
||||
@ -126,6 +128,7 @@
|
||||
<property name="console-common.jar" value="cloud-console-common.jar" />
|
||||
<property name="console-proxy.jar" value="cloud-console-proxy.jar" />
|
||||
<property name="api.jar" value="cloud-api.jar"/>
|
||||
<property name="vmware-base.jar" value="cloud-vmware-base.jar" />
|
||||
|
||||
<!--
|
||||
Import information about the build version and company information
|
||||
@ -199,10 +202,18 @@
|
||||
<path refid="deps.classpath" />
|
||||
<path refid="dist.classpath" />
|
||||
</path>
|
||||
<target name="compile-core" depends="-init, compile-utils, compile-api" description="Compile the core business logic.">
|
||||
<target name="compile-core" depends="-init, compile-utils, compile-api, compile-vmware-base" description="Compile the core business logic.">
|
||||
<compile-java jar.name="${core.jar}" top.dir="${core.dir}" classpath="core.classpath" />
|
||||
</target>
|
||||
|
||||
<path id="vmware-base.classpath">
|
||||
<path refid="thirdparty.classpath" />
|
||||
<path refid="dist.classpath" />
|
||||
</path>
|
||||
<target name="compile-vmware-base" depends="-init, compile-utils" description="Compile the VMware support library">
|
||||
<compile-java jar.name="${vmware-base.jar}" top.dir="${vmware-base.dir}" classpath="vmware-base.classpath" />
|
||||
</target>
|
||||
|
||||
<path id="server.classpath">
|
||||
<path refid="deps.classpath" />
|
||||
<path refid="dist.classpath" />
|
||||
|
||||
@ -185,12 +185,33 @@
|
||||
<include name="cloud-commons-codec-1.4.jar" />
|
||||
<include name="cloud-commons-pool-1.4.jar" />
|
||||
<include name="cloud-cglib.jar" />
|
||||
<include name="cloud-axis.jar" />
|
||||
<include name="cloud-commons-discovery.jar" />
|
||||
<include name="cloud-wsdl4j.jar" />
|
||||
<include name="vmware-apputils.jar" />
|
||||
<include name="vmware-lib-jaxen-core.jar" />
|
||||
<include name="vmware-lib-jdom.jar" />
|
||||
<include name="vmware-lib-smtp.jar" />
|
||||
<include name="vmware-lib-xerces.jar" />
|
||||
<include name="vmware-vim.jar" />
|
||||
<include name="vmware-credstore.jar" />
|
||||
<include name="vmware-lib-jaxen-jdom.jar" />
|
||||
<include name="vmware-lib-mailapi.jar" />
|
||||
<include name="vmware-lib-wbem.jar" />
|
||||
<include name="vmware-lib-xml-apis.jar" />
|
||||
<include name="vmware-lib-activation.jar" />
|
||||
<include name="vmware-lib-jaxrpc.jar" />
|
||||
<include name="vmware-lib-saxpath.jar" />
|
||||
<include name="vmware-lib-xalan.jar" />
|
||||
<include name="vmware-vim25.jar" />
|
||||
<include name="vmware-vim.jar" />
|
||||
</zipfileset>
|
||||
<zipfileset dir="${jar.dir}">
|
||||
<include name="${agent.jar}" />
|
||||
<include name="${utils.jar}" />
|
||||
<include name="${core.jar}" />
|
||||
<include name="${api.jar}" />
|
||||
<include name="${vmware-base.jar}" />
|
||||
</zipfileset>
|
||||
<zipfileset dir="${console-proxy.dist.dir}" filemode="555">
|
||||
</zipfileset>
|
||||
|
||||
@ -7,5 +7,6 @@
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/api"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/deps"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/tools"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/vmware-base"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.manager;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
|
||||
public interface VmwareHostService {
|
||||
VmwareContext getServiceContext(Command cmd);
|
||||
void invalidateServiceContext(VmwareContext context);
|
||||
VmwareHypervisorHost getHyperHost(VmwareContext context, Command cmd);
|
||||
|
||||
String getWorkerName(VmwareContext context, Command cmd);
|
||||
}
|
||||
54
core/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java
Executable file
54
core/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java
Executable 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();
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.manager;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.BackupSnapshotCommand;
|
||||
import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
|
||||
import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
|
||||
import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
|
||||
import com.cloud.agent.api.DeleteSnapshotBackupCommand;
|
||||
import com.cloud.agent.api.DeleteSnapshotsDirCommand;
|
||||
import com.cloud.agent.api.storage.CopyVolumeCommand;
|
||||
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
|
||||
|
||||
public interface VmwareStorageManager {
|
||||
Answer execute(VmwareHostService hostService, PrimaryStorageDownloadCommand cmd);
|
||||
Answer execute(VmwareHostService hostService, BackupSnapshotCommand cmd);
|
||||
Answer execute(VmwareHostService hostService, DeleteSnapshotsDirCommand cmd);
|
||||
Answer execute(VmwareHostService hostService, DeleteSnapshotBackupCommand cmd);
|
||||
Answer execute(VmwareHostService hostService, CreatePrivateTemplateFromVolumeCommand cmd);
|
||||
Answer execute(VmwareHostService hostService, CreatePrivateTemplateFromSnapshotCommand cmd);
|
||||
Answer execute(VmwareHostService hostService, CopyVolumeCommand cmd);
|
||||
Answer execute(VmwareHostService hostService, CreateVolumeFromSnapshotCommand cmd);
|
||||
}
|
||||
@ -0,0 +1,905 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.manager;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.BackupSnapshotAnswer;
|
||||
import com.cloud.agent.api.BackupSnapshotCommand;
|
||||
import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
|
||||
import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
|
||||
import com.cloud.agent.api.CreateVolumeFromSnapshotAnswer;
|
||||
import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
|
||||
import com.cloud.agent.api.DeleteSnapshotBackupAnswer;
|
||||
import com.cloud.agent.api.DeleteSnapshotBackupCommand;
|
||||
import com.cloud.agent.api.DeleteSnapshotsDirCommand;
|
||||
import com.cloud.agent.api.storage.CopyVolumeAnswer;
|
||||
import com.cloud.agent.api.storage.CopyVolumeCommand;
|
||||
import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
|
||||
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
|
||||
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
|
||||
import com.cloud.agent.api.to.StorageFilerTO;
|
||||
import com.cloud.hypervisor.vmware.mo.CustomFieldConstants;
|
||||
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
|
||||
import com.cloud.hypervisor.vmware.mo.DatastoreMO;
|
||||
import com.cloud.hypervisor.vmware.mo.HostMO;
|
||||
import com.cloud.hypervisor.vmware.mo.HypervisorHostHelper;
|
||||
import com.cloud.hypervisor.vmware.mo.VirtualMachineMO;
|
||||
import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpec;
|
||||
import com.vmware.vim25.VirtualLsiLogicController;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareHelper;
|
||||
import com.cloud.storage.JavaStorageLayer;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.StorageLayer;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.StringUtils;
|
||||
import com.cloud.utils.Ternary;
|
||||
import com.cloud.utils.script.Script;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.VirtualDisk;
|
||||
import com.vmware.vim25.VirtualMachineConfigSpec;
|
||||
import com.vmware.vim25.VirtualMachineFileInfo;
|
||||
import com.vmware.vim25.VirtualMachineGuestOsIdentifier;
|
||||
import com.vmware.vim25.VirtualSCSISharing;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpec;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
|
||||
|
||||
public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
||||
private static final Logger s_logger = Logger.getLogger(VmwareStorageManagerImpl.class);
|
||||
|
||||
private final VmwareStorageMount _mountService;
|
||||
private final StorageLayer _storage = new JavaStorageLayer();
|
||||
|
||||
private int _timeout;
|
||||
|
||||
public VmwareStorageManagerImpl(VmwareStorageMount mountService) {
|
||||
assert(mountService != null);
|
||||
_mountService = mountService;
|
||||
}
|
||||
|
||||
public void configure(Map<String, Object> params) {
|
||||
s_logger.info("Configure VmwareStorageManagerImpl");
|
||||
|
||||
String value = (String)params.get("scripts.timeout");
|
||||
_timeout = NumbersUtil.parseInt(value, 1440) * 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer execute(VmwareHostService hostService, PrimaryStorageDownloadCommand cmd) {
|
||||
String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
|
||||
assert (secondaryStorageUrl != null);
|
||||
|
||||
String templateUrl = cmd.getUrl();
|
||||
|
||||
String templateName = null;
|
||||
String mountPoint = null;
|
||||
if (templateUrl.endsWith(".ova")) {
|
||||
int index = templateUrl.lastIndexOf("/");
|
||||
mountPoint = templateUrl.substring(0, index);
|
||||
mountPoint = mountPoint.substring(secondaryStorageUrl.length() + 1);
|
||||
if (!mountPoint.endsWith("/")) {
|
||||
mountPoint = mountPoint + "/";
|
||||
}
|
||||
|
||||
templateName = templateUrl.substring(index + 1).replace("." + ImageFormat.OVA.getFileExtension(), "");
|
||||
|
||||
if (templateName == null || templateName.isEmpty()) {
|
||||
templateName = cmd.getName();
|
||||
}
|
||||
} else {
|
||||
mountPoint = templateUrl.substring(secondaryStorageUrl.length() + 1);
|
||||
if (!mountPoint.endsWith("/")) {
|
||||
mountPoint = mountPoint + "/";
|
||||
}
|
||||
templateName = cmd.getName();
|
||||
}
|
||||
|
||||
VmwareContext context = hostService.getServiceContext(cmd);
|
||||
try {
|
||||
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
|
||||
|
||||
String templateUuidName = UUID.nameUUIDFromBytes((templateName + "@" + cmd.getPoolUuid() + "-" + hyperHost.getMor().get_value()).getBytes()).toString();
|
||||
|
||||
DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
|
||||
VirtualMachineMO templateMo = VmwareHelper.pickOneVmOnRunningHost(dcMo.findVmByNameAndLabel(templateUuidName), true);
|
||||
|
||||
if (templateMo == null) {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("Template " + templateName + " is not setup yet, setup template from secondary storage with uuid name: " + templateUuidName);
|
||||
ManagedObjectReference morDs = hyperHost.findDatastore(cmd.getPoolUuid());
|
||||
assert (morDs != null);
|
||||
DatastoreMO primaryStorageDatastoreMo = new DatastoreMO(context, morDs);
|
||||
|
||||
copyTemplateFromSecondaryToPrimary(hyperHost,
|
||||
primaryStorageDatastoreMo, secondaryStorageUrl,
|
||||
mountPoint, templateUuidName);
|
||||
} else {
|
||||
s_logger.info("Template " + templateName + " has already been setup, skip the template setup process in primary storage");
|
||||
}
|
||||
|
||||
return new PrimaryStorageDownloadAnswer(templateUuidName, 0);
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof RemoteException) {
|
||||
hostService.invalidateServiceContext(context);
|
||||
}
|
||||
|
||||
String msg = "Unable to execute PrimaryStorageDownloadCommand due to exception";
|
||||
s_logger.error(msg, e);
|
||||
return new PrimaryStorageDownloadAnswer(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer execute(VmwareHostService hostService, BackupSnapshotCommand cmd) {
|
||||
Long accountId = cmd.getAccountId();
|
||||
Long volumeId = cmd.getVolumeId();
|
||||
String secondaryStoragePoolURL = cmd.getSecondaryStoragePoolURL();
|
||||
String snapshotUuid = cmd.getSnapshotUuid(); // not null: Precondition.
|
||||
String prevSnapshotUuid = cmd.getPrevSnapshotUuid();
|
||||
String prevBackupUuid = cmd.getPrevBackupUuid();
|
||||
VirtualMachineMO workerVm=null;
|
||||
String workerVMName = null;
|
||||
String volumePath = cmd.getVolumePath();
|
||||
ManagedObjectReference morDs = null;
|
||||
String snapshotUUID = null;
|
||||
DatastoreMO dsMo=null;
|
||||
|
||||
// By default assume failure
|
||||
String details = null;
|
||||
boolean success = false;
|
||||
String snapshotBackupUuid = null;
|
||||
|
||||
VmwareContext context = hostService.getServiceContext(cmd);
|
||||
try {
|
||||
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
|
||||
morDs = hyperHost.findDatastore(cmd.getPool().getUuid());
|
||||
|
||||
VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(cmd.getVmName());
|
||||
if (vmMo == null) {
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("Unable to find owner VM for BackupSnapshotCommand on host " + hyperHost.getHyperHostName() + ", will try within datacenter");
|
||||
|
||||
vmMo = hyperHost.findVmOnPeerHyperHost(cmd.getVmName());
|
||||
if(vmMo == null) {
|
||||
dsMo = new DatastoreMO(hyperHost.getContext(), morDs);
|
||||
//restrict VM name to 32 chars, (else snapshot descriptor file name will be truncated to 32 chars of vm name)
|
||||
workerVMName = UUID.randomUUID().toString().replaceAll("-", "");
|
||||
|
||||
//attach a volume to dummay wrapper VM for taking snapshot and exporting the VM for backup
|
||||
if (!hyperHost.createBlankVm(workerVMName, 1, 512, 0, false, 4, VirtualMachineGuestOsIdentifier._otherGuest.toString(), morDs, false)) {
|
||||
String msg = "Unable to create worker VM to execute BackupSnapshotCommand";
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
vmMo = hyperHost.findVmOnHyperHost(workerVMName);
|
||||
if (vmMo == null) {
|
||||
throw new Exception("Failed to find the newly create or relocated VM. vmName: " + workerVMName);
|
||||
}
|
||||
workerVm = vmMo;
|
||||
|
||||
//attach volume to worker VM
|
||||
String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumePath);
|
||||
vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs);
|
||||
snapshotUUID = UUID.randomUUID().toString();
|
||||
if (!vmMo.createSnapshot(snapshotUUID, "Snapshot taken for " + cmd.getSnapshotName(), false, false)) {
|
||||
throw new Exception("Failed to take snapshot " + cmd.getSnapshotName() + " on vm: " + cmd.getVmName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snapshotBackupUuid = backupSnapshotToSecondaryStorage(vmMo, accountId,
|
||||
volumeId, cmd.getVolumePath(), snapshotUuid,
|
||||
secondaryStoragePoolURL, prevSnapshotUuid,
|
||||
prevBackupUuid,
|
||||
hostService.getWorkerName(context, cmd));
|
||||
|
||||
success = (snapshotBackupUuid != null);
|
||||
|
||||
if (success) {
|
||||
details = "Successfully backedUp the snapshotUuid: " + snapshotUuid + " to secondary storage.";
|
||||
vmMo.removeAllSnapshots();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof RemoteException) {
|
||||
hostService.invalidateServiceContext(context);
|
||||
}
|
||||
|
||||
s_logger.error("Unexpecpted exception ", e);
|
||||
|
||||
details = "BackupSnapshotCommand exception: " + StringUtils.getExceptionStackInfo(e);
|
||||
return new BackupSnapshotAnswer(cmd, false, details, snapshotBackupUuid, true);
|
||||
} finally {
|
||||
try {
|
||||
if (workerVm != null) {
|
||||
//detach volume and destroy worker vm
|
||||
workerVm.moveAllVmDiskFiles(dsMo, "", false);
|
||||
workerVm.detachAllDisks();
|
||||
workerVm.destroy();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
s_logger.warn("Failed to destroy worker VM: " + workerVMName);
|
||||
}
|
||||
}
|
||||
|
||||
return new BackupSnapshotAnswer(cmd, success, details, snapshotBackupUuid, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer execute(VmwareHostService hostService, DeleteSnapshotsDirCommand cmd) {
|
||||
Long accountId = cmd.getAccountId();
|
||||
Long volumeId = cmd.getVolumeId();
|
||||
String secondaryStoragePoolURL = cmd.getSecondaryStoragePoolURL();
|
||||
|
||||
String details = null;
|
||||
boolean success = false;
|
||||
|
||||
VmwareContext context = hostService.getServiceContext(cmd);
|
||||
try {
|
||||
details = deleteSnapshotDirOnSecondaryStorage(accountId, volumeId, secondaryStoragePoolURL);
|
||||
if (details == null) {
|
||||
success = true;
|
||||
}
|
||||
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof RemoteException) {
|
||||
hostService.invalidateServiceContext(context);
|
||||
}
|
||||
|
||||
s_logger.error("Unexpecpted exception ", e);
|
||||
|
||||
details = "DeleteSnapshotDirCommand exception: " + StringUtils.getExceptionStackInfo(e);
|
||||
return new Answer(cmd, false, details);
|
||||
}
|
||||
|
||||
return new Answer(cmd, success, details);
|
||||
}
|
||||
|
||||
public Answer execute(VmwareHostService hostService, DeleteSnapshotBackupCommand cmd) {
|
||||
Long accountId = cmd.getAccountId();
|
||||
Long volumeId = cmd.getVolumeId();
|
||||
String secStorageUrl = cmd.getSecondaryStoragePoolURL();
|
||||
String backupUUID = cmd.getSnapshotUuid();
|
||||
String details = null;
|
||||
boolean success = false;
|
||||
|
||||
VmwareContext context = hostService.getServiceContext(cmd);
|
||||
try {
|
||||
details = deleteSnapshotOnSecondaryStorge(accountId, volumeId, secStorageUrl, backupUUID);
|
||||
if (details == null) {
|
||||
success = true;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof RemoteException) {
|
||||
hostService.invalidateServiceContext(context);
|
||||
}
|
||||
|
||||
s_logger.error("Unexpecpted exception ", e);
|
||||
details = "DeleteSnapshotBackupCommand exception: " + StringUtils.getExceptionStackInfo(e);
|
||||
return new DeleteSnapshotBackupAnswer(cmd, false, details);
|
||||
}
|
||||
|
||||
return new DeleteSnapshotBackupAnswer(cmd, success, details);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer execute(VmwareHostService hostService, CreatePrivateTemplateFromVolumeCommand cmd) {
|
||||
String secondaryStoragePoolURL = cmd.getSecondaryStorageURL();
|
||||
String volumePath = cmd.getVolumePath();
|
||||
Long accountId = cmd.getAccountId();
|
||||
Long templateId = cmd.getTemplateId();
|
||||
String details = null;
|
||||
|
||||
VmwareContext context = hostService.getServiceContext(cmd);
|
||||
try {
|
||||
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
|
||||
|
||||
VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(cmd.getVmName());
|
||||
if (vmMo == null) {
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("Unable to find the owner VM for CreatePrivateTemplateFromVolumeCommand on host " + hyperHost.getHyperHostName() + ", try within datacenter");
|
||||
vmMo = hyperHost.findVmOnPeerHyperHost(cmd.getVmName());
|
||||
|
||||
if(vmMo == null) {
|
||||
String msg = "Unable to find the owner VM for volume operation. vm: " + cmd.getVmName();
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
}
|
||||
|
||||
Ternary<String, Long, Long> result = createTemplateFromVolume(vmMo,
|
||||
accountId, templateId, cmd.getTemplateName(),
|
||||
secondaryStoragePoolURL, volumePath,
|
||||
hostService.getWorkerName(context, cmd));
|
||||
|
||||
return new CreatePrivateTemplateAnswer(cmd, true, null,
|
||||
result.first(), result.third(), result.second(),
|
||||
cmd.getTemplateName(), ImageFormat.OVA);
|
||||
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof RemoteException) {
|
||||
hostService.invalidateServiceContext(context);
|
||||
}
|
||||
|
||||
s_logger.error("Unexpecpted exception ", e);
|
||||
|
||||
details = "CreatePrivateTemplateFromVolumeCommand exception: " + StringUtils.getExceptionStackInfo(e);
|
||||
return new CreatePrivateTemplateAnswer(cmd, false, details);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer execute(VmwareHostService hostService, CreatePrivateTemplateFromSnapshotCommand cmd) {
|
||||
Long accountId = cmd.getAccountId();
|
||||
Long volumeId = cmd.getVolumeId();
|
||||
String secondaryStoragePoolURL = cmd.getSecondaryStoragePoolURL();
|
||||
String backedUpSnapshotUuid = cmd.getSnapshotUuid();
|
||||
Long newTemplateId = cmd.getNewTemplateId();
|
||||
String details;
|
||||
String uniqeName = UUID.randomUUID().toString();
|
||||
|
||||
VmwareContext context = hostService.getServiceContext(cmd);
|
||||
try {
|
||||
Ternary<String, Long, Long> result = createTemplateFromSnapshot(accountId,
|
||||
newTemplateId, uniqeName,
|
||||
secondaryStoragePoolURL, volumeId,
|
||||
backedUpSnapshotUuid);
|
||||
|
||||
return new CreatePrivateTemplateAnswer(cmd, true, null,
|
||||
result.first(), result.third(), result.second(),
|
||||
uniqeName, ImageFormat.OVA);
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof RemoteException) {
|
||||
hostService.invalidateServiceContext(context);
|
||||
}
|
||||
|
||||
s_logger.error("Unexpecpted exception ", e);
|
||||
|
||||
details = "CreatePrivateTemplateFromSnapshotCommand exception: " + StringUtils.getExceptionStackInfo(e);
|
||||
return new CreatePrivateTemplateAnswer(cmd, false, details);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer execute(VmwareHostService hostService, CopyVolumeCommand cmd) {
|
||||
Long volumeId = cmd.getVolumeId();
|
||||
String volumePath = cmd.getVolumePath();
|
||||
String secondaryStorageURL = cmd.getSecondaryStorageURL();
|
||||
String vmName = cmd.getVmName();
|
||||
|
||||
VmwareContext context = hostService.getServiceContext(cmd);
|
||||
try {
|
||||
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
|
||||
|
||||
Pair<String, String> result;
|
||||
if (cmd.toSecondaryStorage()) {
|
||||
result = copyVolumeToSecStorage(
|
||||
hyperHost, vmName, volumeId, cmd.getPool().getUuid(), volumePath,
|
||||
secondaryStorageURL,
|
||||
hostService.getWorkerName(context, cmd));
|
||||
} else {
|
||||
StorageFilerTO poolTO = cmd.getPool();
|
||||
|
||||
ManagedObjectReference morDatastore = hyperHost.findDatastore(poolTO.getUuid());
|
||||
if (morDatastore == null) {
|
||||
morDatastore = hyperHost.mountDatastore(
|
||||
false,
|
||||
poolTO.getHost(), 0, poolTO.getPath(),
|
||||
poolTO.getUuid());
|
||||
|
||||
if (morDatastore == null) {
|
||||
throw new Exception("Unable to mount storage pool on host. storeUrl: " + poolTO.getHost() + ":/" + poolTO.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
result = copyVolumeFromSecStorage(
|
||||
hyperHost, volumeId,
|
||||
new DatastoreMO(context, morDatastore),
|
||||
secondaryStorageURL, volumePath);
|
||||
}
|
||||
return new CopyVolumeAnswer(cmd, true, null, result.first(), result.second());
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof RemoteException) {
|
||||
hostService.invalidateServiceContext(context);
|
||||
}
|
||||
|
||||
String msg = "Unable to execute CopyVolumeCommand due to exception";
|
||||
s_logger.error(msg, e);
|
||||
return new CopyVolumeAnswer(cmd, false, "CopyVolumeCommand failed due to exception: " + StringUtils.getExceptionStackInfo(e), null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer execute(VmwareHostService hostService, CreateVolumeFromSnapshotCommand cmd) {
|
||||
|
||||
String primaryStorageNameLabel = cmd.getPrimaryStoragePoolNameLabel();
|
||||
Long accountId = cmd.getAccountId();
|
||||
Long volumeId = cmd.getVolumeId();
|
||||
String secondaryStoragePoolURL = cmd.getSecondaryStoragePoolURL();
|
||||
String backedUpSnapshotUuid = cmd.getSnapshotUuid();
|
||||
|
||||
String details = null;
|
||||
boolean success = false;
|
||||
String newVolumeName = UUID.randomUUID().toString().replaceAll("-", "");
|
||||
|
||||
VmwareContext context = hostService.getServiceContext(cmd);
|
||||
try {
|
||||
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
|
||||
|
||||
ManagedObjectReference morPrimaryDs = hyperHost.findDatastore(primaryStorageNameLabel);
|
||||
if (morPrimaryDs == null) {
|
||||
String msg = "Unable to find datastore: " + primaryStorageNameLabel;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
DatastoreMO primaryDsMo = new DatastoreMO(hyperHost.getContext(), morPrimaryDs);
|
||||
details = createVolumeFromSnapshot(hyperHost, primaryDsMo,
|
||||
newVolumeName, accountId, volumeId,
|
||||
secondaryStoragePoolURL, backedUpSnapshotUuid);
|
||||
if (details == null) {
|
||||
success = true;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof RemoteException) {
|
||||
hostService.invalidateServiceContext(context);
|
||||
}
|
||||
|
||||
s_logger.error("Unexpecpted exception ", e);
|
||||
details = "CreateVolumeFromSnapshotCommand exception: " + StringUtils.getExceptionStackInfo(e);
|
||||
}
|
||||
|
||||
return new CreateVolumeFromSnapshotAnswer(cmd, success, details, newVolumeName);
|
||||
}
|
||||
|
||||
private void copyTemplateFromSecondaryToPrimary(VmwareHypervisorHost hyperHost, DatastoreMO datastoreMo, String secondaryStorageUrl,
|
||||
String templatePathAtSecondaryStorage, String templateName) throws Exception {
|
||||
|
||||
s_logger.info("Executing copyTemplateFromSecondaryToPrimary. secondaryStorage: "
|
||||
+ secondaryStorageUrl + ", templatePathAtSecondaryStorage: " + templatePathAtSecondaryStorage
|
||||
+ ", templateName: " + templateName);
|
||||
|
||||
String secondaryMountPoint = _mountService.getMountPoint(secondaryStorageUrl);
|
||||
s_logger.info("Secondary storage mount point: " + secondaryMountPoint);
|
||||
|
||||
String srcOVAFileName = secondaryMountPoint + "/" + templatePathAtSecondaryStorage +
|
||||
templateName + "." + ImageFormat.OVA.getFileExtension();
|
||||
|
||||
String srcFileName = getOVFFilePath(srcOVAFileName);
|
||||
if(srcFileName == null) {
|
||||
String msg = "Unable to locate OVF file in template package directory: " + srcOVAFileName;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
String vmName = templateName;
|
||||
hyperHost.importVmFromOVF(srcFileName, vmName, datastoreMo, "thin");
|
||||
|
||||
VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
|
||||
if(vmMo == null) {
|
||||
String msg = "Failed to import OVA template. secondaryStorage: "
|
||||
+ secondaryStorageUrl + ", templatePathAtSecondaryStorage: " + templatePathAtSecondaryStorage
|
||||
+ ", templateName: " + templateName;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
if(vmMo.createSnapshot("cloud.template.base", "Base snapshot", false, false)) {
|
||||
vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_UUID, templateName);
|
||||
vmMo.markAsTemplate();
|
||||
} else {
|
||||
vmMo.destroy();
|
||||
String msg = "Unable to create base snapshot for template: " + templateName;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private Ternary<String, Long, Long> createTemplateFromVolume(VirtualMachineMO vmMo, long accountId, long templateId, String templateName,
|
||||
String secStorageUrl, String volumePath, String workerVmName) throws Exception {
|
||||
|
||||
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
|
||||
String installPath = getTemplateRelativeDirInSecStorage(accountId, templateId);
|
||||
String installFullPath = secondaryMountPoint + "/" + installPath;
|
||||
synchronized(installPath.intern()) {
|
||||
Script command = new Script(false, "mkdir", _timeout, s_logger);
|
||||
command.add("-p");
|
||||
command.add(installFullPath);
|
||||
|
||||
String result = command.execute();
|
||||
if(result != null) {
|
||||
String msg = "unable to prepare template directory: "
|
||||
+ installPath + ", storage: " + secStorageUrl + ", error msg: " + result;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
}
|
||||
|
||||
String tmpSnapshotName = UUID.randomUUID().toString();
|
||||
VirtualMachineMO clonedVm = null;
|
||||
try {
|
||||
Pair<VirtualDisk, String> volumeDeviceInfo = vmMo.getDiskDevice(volumePath, false);
|
||||
if(volumeDeviceInfo == null) {
|
||||
String msg = "Unable to find related disk device for volume. volume path: " + volumePath;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
if(!vmMo.createSnapshot(tmpSnapshotName, "Temporary snapshot for template creation", false, false)) {
|
||||
String msg = "Unable to take snapshot for creating template from volume. volume path: " + volumePath;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
// 4 MB is the minimum requirement for VM memory in VMware
|
||||
vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(),
|
||||
VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()));
|
||||
clonedVm = vmMo.getRunningHost().findVmOnHyperHost(workerVmName);
|
||||
if(clonedVm == null) {
|
||||
String msg = "Unable to create dummy VM to export volume. volume path: " + volumePath;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
clonedVm.exportVm(secondaryMountPoint + "/" + installPath, templateName, true, false);
|
||||
|
||||
// TODO, need to find out virtual size and physical size
|
||||
long size = new File(installFullPath + "/" + templateName + ".ova").length();
|
||||
postCreatePrivateTemplate(installFullPath, templateId, templateName, size, size);
|
||||
|
||||
return new Ternary<String, Long, Long>(installPath + "/" + templateName + ".ova", size, size);
|
||||
|
||||
} finally {
|
||||
if(clonedVm != null)
|
||||
clonedVm.destroy();
|
||||
|
||||
vmMo.removeSnapshot(tmpSnapshotName, false);
|
||||
}
|
||||
}
|
||||
|
||||
private Ternary<String, Long, Long> createTemplateFromSnapshot(long accountId, long templateId, String templateName,
|
||||
String secStorageUrl, long volumeId, String backedUpSnapshotUuid) throws Exception {
|
||||
|
||||
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
|
||||
String installPath = getTemplateRelativeDirInSecStorage(accountId, templateId);
|
||||
String installFullPath = secondaryMountPoint + "/" + installPath;
|
||||
String installFullName = installFullPath + "/" + templateName + ".ova";
|
||||
String snapshotFullName = secondaryMountPoint + "/" + getSnapshotRelativeDirInSecStorage(accountId, volumeId)
|
||||
+ "/" + backedUpSnapshotUuid + ".ova";
|
||||
String result;
|
||||
Script command;
|
||||
|
||||
synchronized(installPath.intern()) {
|
||||
command = new Script(false, "mkdir", _timeout, s_logger);
|
||||
command.add("-p");
|
||||
command.add(installFullPath);
|
||||
|
||||
result = command.execute();
|
||||
if(result != null) {
|
||||
String msg = "unable to prepare template directory: "
|
||||
+ installPath + ", storage: " + secStorageUrl + ", error msg: " + result;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
command = new Script(false, "cp", _timeout, s_logger);
|
||||
command.add(snapshotFullName);
|
||||
command.add(installFullName);
|
||||
result = command.execute();
|
||||
if(result != null) {
|
||||
String msg = "unable to copy snapshot " + snapshotFullName + " to " + installFullPath;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
// untar OVA file at template directory
|
||||
command = new Script("tar", 0, s_logger);
|
||||
command.add("-xf", installFullName);
|
||||
command.setWorkDir(installFullPath);
|
||||
result = command.execute();
|
||||
if(result != null) {
|
||||
String msg = "unable to copy snapshot " + snapshotFullName + " to " + installFullPath;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
long size = new File(installFullName).length();
|
||||
postCreatePrivateTemplate(installFullPath, templateId, templateName, size, size);
|
||||
return new Ternary<String, Long, Long>(installPath + "/" + templateName + ".ova", size, size);
|
||||
|
||||
} catch(Exception e) {
|
||||
// TODO, clean up left over files
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private void postCreatePrivateTemplate(String installFullPath, long templateId,
|
||||
String templateName, long size, long virtualSize) throws Exception {
|
||||
|
||||
// TODO a bit ugly here
|
||||
BufferedWriter out = null;
|
||||
try {
|
||||
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(installFullPath + "/template.properties")));
|
||||
out.write("filename=" + templateName + ".ova");
|
||||
out.newLine();
|
||||
out.write("description=");
|
||||
out.newLine();
|
||||
out.write("checksum=");
|
||||
out.newLine();
|
||||
out.write("hvm=false");
|
||||
out.newLine();
|
||||
out.write("size=" + size);
|
||||
out.newLine();
|
||||
out.write("ova=true");
|
||||
out.newLine();
|
||||
out.write("id=" + templateId);
|
||||
out.newLine();
|
||||
out.write("public=false");
|
||||
out.newLine();
|
||||
out.write("ova.filename=" + templateName + ".ova");
|
||||
out.newLine();
|
||||
out.write("uniquename=" + templateName);
|
||||
out.newLine();
|
||||
out.write("ova.virtualsize=" + virtualSize);
|
||||
out.newLine();
|
||||
out.write("virtualsize=" + virtualSize);
|
||||
out.newLine();
|
||||
out.write("ova.size=" + size);
|
||||
out.newLine();
|
||||
} finally {
|
||||
if(out != null)
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
private String createVolumeFromSnapshot(VmwareHypervisorHost hyperHost, DatastoreMO primaryDsMo, String newVolumeName,
|
||||
long accountId, long volumeId, String secStorageUrl, String snapshotBackupUuid) throws Exception {
|
||||
|
||||
restoreVolumeFromSecStorage(hyperHost, primaryDsMo, newVolumeName,
|
||||
secStorageUrl, getSnapshotRelativeDirInSecStorage(accountId, volumeId), snapshotBackupUuid);
|
||||
return null;
|
||||
}
|
||||
|
||||
private void restoreVolumeFromSecStorage(VmwareHypervisorHost hyperHost, DatastoreMO primaryDsMo, String newVolumeName,
|
||||
String secStorageUrl, String secStorageDir, String backupName) throws Exception {
|
||||
|
||||
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
|
||||
String srcOVAFileName = secondaryMountPoint + "/" + secStorageDir + "/"
|
||||
+ backupName + "." + ImageFormat.OVA.getFileExtension();
|
||||
|
||||
String srcFileName = getOVFFilePath(srcOVAFileName);
|
||||
if(srcFileName == null) {
|
||||
Script command = new Script("tar", 0, s_logger);
|
||||
command.add("-xf", srcOVAFileName);
|
||||
command.setWorkDir(secondaryMountPoint + "/" + secStorageDir);
|
||||
String result = command.execute();
|
||||
if(result != null) {
|
||||
String msg = "Unable to unpack snapshot OVA file at: " + srcOVAFileName;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
}
|
||||
|
||||
srcFileName = getOVFFilePath(srcOVAFileName);
|
||||
if(srcFileName == null) {
|
||||
String msg = "Unable to locate OVF file in template package directory: " + srcOVAFileName;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
VirtualMachineMO clonedVm = null;
|
||||
try {
|
||||
hyperHost.importVmFromOVF(srcFileName, newVolumeName, primaryDsMo, "thin");
|
||||
clonedVm = hyperHost.findVmOnHyperHost(newVolumeName);
|
||||
if(clonedVm == null)
|
||||
throw new Exception("Unable to create container VM for volume creation");
|
||||
|
||||
clonedVm.moveAllVmDiskFiles(primaryDsMo, "", false);
|
||||
clonedVm.detachAllDisks();
|
||||
} finally {
|
||||
if(clonedVm != null)
|
||||
clonedVm.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
private String backupSnapshotToSecondaryStorage(VirtualMachineMO vmMo, long accountId, long volumeId,
|
||||
String volumePath, String snapshotUuid, String secStorageUrl,
|
||||
String prevSnapshotUuid, String prevBackupUuid, String workerVmName) throws Exception {
|
||||
|
||||
String backupUuid = UUID.randomUUID().toString();
|
||||
exportVolumeToSecondaryStroage(vmMo, volumePath, secStorageUrl,
|
||||
getSnapshotRelativeDirInSecStorage(accountId, volumeId), backupUuid, workerVmName);
|
||||
return backupUuid;
|
||||
}
|
||||
|
||||
private void exportVolumeToSecondaryStroage(VirtualMachineMO vmMo, String volumePath,
|
||||
String secStorageUrl, String secStorageDir, String exportName,
|
||||
String workerVmName) throws Exception {
|
||||
|
||||
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
|
||||
String exportPath = secondaryMountPoint + "/" + secStorageDir;
|
||||
|
||||
synchronized(exportPath.intern()) {
|
||||
if(!new File(exportPath).exists()) {
|
||||
Script command = new Script(false, "mkdir", _timeout, s_logger);
|
||||
command.add("-p");
|
||||
command.add(exportPath);
|
||||
if(command.execute() != null)
|
||||
throw new Exception("unable to prepare snapshot backup directory");
|
||||
}
|
||||
}
|
||||
|
||||
VirtualMachineMO clonedVm = null;
|
||||
try {
|
||||
|
||||
Pair<VirtualDisk, String> volumeDeviceInfo = vmMo.getDiskDevice(volumePath, false);
|
||||
if(volumeDeviceInfo == null) {
|
||||
String msg = "Unable to find related disk device for volume. volume path: " + volumePath;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
// 4 MB is the minimum requirement for VM memory in VMware
|
||||
vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(),
|
||||
VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()));
|
||||
clonedVm = vmMo.getRunningHost().findVmOnHyperHost(workerVmName);
|
||||
if(clonedVm == null) {
|
||||
String msg = "Unable to create dummy VM to export volume. volume path: " + volumePath;
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
clonedVm.exportVm(exportPath, exportName, true, true);
|
||||
} finally {
|
||||
if(clonedVm != null)
|
||||
clonedVm.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
private String deleteSnapshotOnSecondaryStorge(long accountId, long volumeId, String secStorageUrl, String backupUuid) throws Exception {
|
||||
|
||||
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
|
||||
String snapshotMountRoot = secondaryMountPoint + "/" + getSnapshotRelativeDirInSecStorage(accountId, volumeId);
|
||||
File file = new File(snapshotMountRoot + "/" + backupUuid + ".ova");
|
||||
if(file.exists()) {
|
||||
if(file.delete())
|
||||
return null;
|
||||
|
||||
} else {
|
||||
return "Backup file does not exist. backupUuid: " + backupUuid;
|
||||
}
|
||||
|
||||
return "Failed to delete snapshot backup file, backupUuid: " + backupUuid;
|
||||
}
|
||||
|
||||
private String deleteSnapshotDirOnSecondaryStorage(long accountId, long volumeId, String secStorageUrl) throws Exception {
|
||||
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
|
||||
String snapshotMountRoot = secondaryMountPoint + "/" + getSnapshotRelativeDirInSecStorage(accountId, volumeId);
|
||||
|
||||
synchronized(snapshotMountRoot.intern()) {
|
||||
Script command = new Script(false, "rm", _timeout, s_logger);
|
||||
command.add("-rf");
|
||||
command.add(snapshotMountRoot);
|
||||
return command.execute();
|
||||
}
|
||||
}
|
||||
|
||||
private Pair<String, String> copyVolumeToSecStorage(VmwareHypervisorHost hyperHost, String vmName, long volumeId, String poolId, String volumePath,
|
||||
String secStorageUrl, String workerVmName) throws Exception {
|
||||
String volumeFolder = String.valueOf(volumeId) + "/";
|
||||
VirtualMachineMO workerVm=null;
|
||||
VirtualMachineMO vmMo=null;
|
||||
String exportName = UUID.randomUUID().toString();
|
||||
|
||||
try {
|
||||
ManagedObjectReference morDs = hyperHost.findDatastore(poolId);
|
||||
|
||||
if (morDs == null) {
|
||||
String msg = "Unable to find volumes's storage pool for copy volume operation";
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
vmMo = hyperHost.findVmOnHyperHost(vmName);
|
||||
if (vmMo == null) {
|
||||
//create a dummy worker vm for attaching the volume
|
||||
DatastoreMO dsMo = new DatastoreMO(hyperHost.getContext(), morDs);
|
||||
//restrict VM name to 32 chars, (else snapshot descriptor file name will be truncated to 32 chars of vm name)
|
||||
String workerVMName = UUID.randomUUID().toString().replaceAll("-", "");
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
vmConfig.setName(workerVMName);
|
||||
vmConfig.setMemoryMB((long) 4);
|
||||
vmConfig.setNumCPUs(1);
|
||||
vmConfig.setGuestId(VirtualMachineGuestOsIdentifier._otherGuest.toString());
|
||||
VirtualMachineFileInfo fileInfo = new VirtualMachineFileInfo();
|
||||
fileInfo.setVmPathName(String.format("[%s]", dsMo.getName()));
|
||||
vmConfig.setFiles(fileInfo);
|
||||
|
||||
// Scsi controller
|
||||
VirtualLsiLogicController scsiController = new VirtualLsiLogicController();
|
||||
scsiController.setSharedBus(VirtualSCSISharing.noSharing);
|
||||
scsiController.setBusNumber(0);
|
||||
scsiController.setKey(1);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.add);
|
||||
vmConfig.setDeviceChange(new VirtualDeviceConfigSpec[] { scsiControllerSpec });
|
||||
|
||||
hyperHost.createVm(vmConfig);
|
||||
workerVm = hyperHost.findVmOnHyperHost(workerVMName);
|
||||
if (workerVm == null) {
|
||||
String msg = "Unable to create worker VM to execute CopyVolumeCommand";
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
//attach volume to worker VM
|
||||
String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumePath);
|
||||
workerVm.attachDisk(new String[] { datastoreVolumePath }, morDs);
|
||||
vmMo = workerVm;
|
||||
}
|
||||
|
||||
vmMo.createSnapshot(exportName, "Temporary snapshot for copy-volume command", false, false);
|
||||
|
||||
exportVolumeToSecondaryStroage(vmMo, volumePath, secStorageUrl, "volumes/" + volumeFolder, exportName, workerVmName);
|
||||
return new Pair<String, String>(volumeFolder, exportName);
|
||||
|
||||
} finally {
|
||||
vmMo.removeSnapshot(exportName, false);
|
||||
if (workerVm != null) {
|
||||
//detach volume and destroy worker vm
|
||||
workerVm.detachAllDisks();
|
||||
workerVm.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Pair<String, String> copyVolumeFromSecStorage(VmwareHypervisorHost hyperHost, long volumeId,
|
||||
DatastoreMO dsMo, String secStorageUrl, String exportName) throws Exception {
|
||||
|
||||
String volumeFolder = String.valueOf(volumeId) + "/";
|
||||
String newVolume = UUID.randomUUID().toString().replaceAll("-", "");
|
||||
restoreVolumeFromSecStorage(hyperHost, dsMo, newVolume, secStorageUrl, "volumes/" + volumeFolder, exportName);
|
||||
|
||||
return new Pair<String, String>(volumeFolder, newVolume);
|
||||
}
|
||||
|
||||
private String getOVFFilePath(String srcOVAFileName) {
|
||||
File file = new File(srcOVAFileName);
|
||||
assert(_storage != null);
|
||||
String[] files = _storage.listFiles(file.getParent());
|
||||
if(files != null) {
|
||||
for(String fileName : files) {
|
||||
if(fileName.toLowerCase().endsWith(".ovf")) {
|
||||
File ovfFile = new File(fileName);
|
||||
return file.getParent() + File.separator + ovfFile.getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String getTemplateRelativeDirInSecStorage(long accountId, long templateId) {
|
||||
return "template/tmpl/" + accountId + "/" + templateId;
|
||||
}
|
||||
|
||||
private static String getSnapshotRelativeDirInSecStorage(long accountId, long volumeId) {
|
||||
return "snapshots/" + accountId + "/" + volumeId;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.manager;
|
||||
|
||||
public interface VmwareStorageMount {
|
||||
String getMountPoint(String storageUrl);
|
||||
}
|
||||
193
core/src/com/cloud/hypervisor/vmware/resource/SshHelper.java
Executable file
193
core/src/com/cloud/hypervisor/vmware/resource/SshHelper.java
Executable 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
53
core/src/com/cloud/hypervisor/vmware/resource/VmwareContextFactory.java
Executable file
53
core/src/com/cloud/hypervisor/vmware/resource/VmwareContextFactory.java
Executable 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;
|
||||
}
|
||||
}
|
||||
3747
core/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
Executable file
3747
core/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
Executable file
File diff suppressed because it is too large
Load Diff
715
core/src/com/cloud/storage/resource/CifsSecondaryStorageResource.java
Executable file
715
core/src/com/cloud/storage/resource/CifsSecondaryStorageResource.java
Executable 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";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.storage.resource;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
|
||||
public class PremiumSecondaryStorageResource extends NfsSecondaryStorageResource {
|
||||
|
||||
private static final Logger s_logger = Logger.getLogger(PremiumSecondaryStorageResource.class);
|
||||
|
||||
private Map<Hypervisor.HypervisorType, SecondaryStorageResourceHandler> _handlers = new HashMap<Hypervisor.HypervisorType, SecondaryStorageResourceHandler>();
|
||||
|
||||
private Map<String, String> _activeOutgoingAddresses = new HashMap<String, String>();
|
||||
|
||||
@Override
|
||||
public Answer executeRequest(Command cmd) {
|
||||
String hypervisor = cmd.getContextParam("hypervisor");
|
||||
if(hypervisor != null) {
|
||||
Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.getType(hypervisor);
|
||||
if(hypervisorType == null) {
|
||||
s_logger.error("Unsupported hypervisor type in command context, hypervisor: " + hypervisor);
|
||||
return defaultAction(cmd);
|
||||
}
|
||||
|
||||
SecondaryStorageResourceHandler handler = getHandler(hypervisorType);
|
||||
if(handler == null) {
|
||||
s_logger.error("No handler can be found for hypervisor type in command context, hypervisor: " + hypervisor);
|
||||
return defaultAction(cmd);
|
||||
}
|
||||
|
||||
return handler.executeRequest(cmd);
|
||||
}
|
||||
|
||||
return defaultAction(cmd);
|
||||
}
|
||||
|
||||
public Answer defaultAction(Command cmd) {
|
||||
return super.executeRequest(cmd);
|
||||
}
|
||||
|
||||
public void ensureOutgoingRuleForAddress(String address) {
|
||||
if(address == null || address.isEmpty() || address.startsWith("0.0.0.0")) {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("Drop invalid dynamic route/firewall entry " + address);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean needToSetRule = false;
|
||||
synchronized(_activeOutgoingAddresses) {
|
||||
if(!_activeOutgoingAddresses.containsKey(address)) {
|
||||
_activeOutgoingAddresses.put(address, address);
|
||||
needToSetRule = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(needToSetRule) {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("Add dynamic route/firewall entry for " + address);
|
||||
allowOutgoingOnPrivate(address);
|
||||
}
|
||||
}
|
||||
|
||||
private void registerHandler(Hypervisor.HypervisorType hypervisorType, SecondaryStorageResourceHandler handler) {
|
||||
_handlers.put(hypervisorType, handler);
|
||||
}
|
||||
|
||||
private SecondaryStorageResourceHandler getHandler(Hypervisor.HypervisorType hypervisorType) {
|
||||
return _handlers.get(hypervisorType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
super.configure(name, params);
|
||||
|
||||
if(_inSystemVM) {
|
||||
VmwareSecondaryStorageContextFactory.initFactoryEnvironment();
|
||||
}
|
||||
|
||||
registerHandler(Hypervisor.HypervisorType.VMware, new VmwareSecondaryStorageResourceHandler(this));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.storage.resource;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
|
||||
public interface SecondaryStorageResourceHandler {
|
||||
Answer executeRequest(Command cmd);
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.storage.resource;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.vmware.apputils.version.ExtendedAppUtil;
|
||||
|
||||
public class VmwareSecondaryStorageContextFactory {
|
||||
private static volatile int s_seq = 1;
|
||||
|
||||
private static Map<String, VmwareContext> s_contextMap = new HashMap<String, VmwareContext>();
|
||||
|
||||
public static void initFactoryEnvironment() {
|
||||
System.setProperty("axis.socketSecureFactory", "org.apache.axis.components.net.SunFakeTrustSocketFactory");
|
||||
}
|
||||
|
||||
public static VmwareContext create(String vCenterAddress, String vCenterUserName, String vCenterPassword) throws Exception {
|
||||
assert(vCenterAddress != null);
|
||||
assert(vCenterUserName != null);
|
||||
assert(vCenterPassword != null);
|
||||
|
||||
VmwareContext context = null;
|
||||
|
||||
synchronized(s_contextMap) {
|
||||
context = s_contextMap.get(vCenterAddress);
|
||||
if(context == null) {
|
||||
String serviceUrl = "https://" + vCenterAddress + "/sdk/vimService";
|
||||
String[] params = new String[] {"--url", serviceUrl, "--username", vCenterUserName, "--password", vCenterPassword };
|
||||
ExtendedAppUtil appUtil = ExtendedAppUtil.initialize(vCenterAddress + "-" + s_seq++, params);
|
||||
|
||||
appUtil.connect();
|
||||
context = new VmwareContext(appUtil, vCenterAddress);
|
||||
context.registerStockObject("username", vCenterUserName);
|
||||
context.registerStockObject("password", vCenterPassword);
|
||||
|
||||
s_contextMap.put(vCenterAddress, context);
|
||||
}
|
||||
}
|
||||
|
||||
assert(context != null);
|
||||
return context;
|
||||
}
|
||||
|
||||
public static void invalidate(VmwareContext context) {
|
||||
synchronized(s_contextMap) {
|
||||
for(Map.Entry<String, VmwareContext> entry : s_contextMap.entrySet()) {
|
||||
if(entry.getValue() == context) {
|
||||
s_contextMap.remove(entry.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,292 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.storage.resource;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.BackupSnapshotCommand;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
|
||||
import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
|
||||
import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
|
||||
import com.cloud.agent.api.DeleteSnapshotBackupCommand;
|
||||
import com.cloud.agent.api.DeleteSnapshotsDirCommand;
|
||||
import com.cloud.agent.api.storage.CopyVolumeCommand;
|
||||
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareHostService;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareStorageManager;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareStorageManagerImpl;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareStorageMount;
|
||||
import com.cloud.hypervisor.vmware.mo.ClusterMO;
|
||||
import com.cloud.hypervisor.vmware.mo.HostMO;
|
||||
import com.cloud.hypervisor.vmware.mo.VmwareHostType;
|
||||
import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
|
||||
import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHostNetworkSummary;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareHelper;
|
||||
import com.cloud.serializer.GsonHelper;
|
||||
import com.google.gson.Gson;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
|
||||
public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageResourceHandler, VmwareHostService, VmwareStorageMount {
|
||||
private static final Logger s_logger = Logger.getLogger(VmwareSecondaryStorageResourceHandler.class);
|
||||
|
||||
private final PremiumSecondaryStorageResource _resource;
|
||||
private final VmwareStorageManager _storageMgr;
|
||||
|
||||
private final Gson _gson;
|
||||
|
||||
/*
|
||||
private Map<String, HostMO> _activeHosts = new HashMap<String, HostMO>();
|
||||
*/
|
||||
|
||||
public VmwareSecondaryStorageResourceHandler(PremiumSecondaryStorageResource resource) {
|
||||
_resource = resource;
|
||||
_storageMgr = new VmwareStorageManagerImpl(this);
|
||||
_gson = GsonHelper.getGsonLogger();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer executeRequest(Command cmd) {
|
||||
Answer answer;
|
||||
if (cmd instanceof PrimaryStorageDownloadCommand) {
|
||||
answer = execute((PrimaryStorageDownloadCommand)cmd);
|
||||
} else if(cmd instanceof BackupSnapshotCommand) {
|
||||
answer = execute((BackupSnapshotCommand)cmd);
|
||||
} else if(cmd instanceof DeleteSnapshotsDirCommand) {
|
||||
answer = execute((DeleteSnapshotsDirCommand)cmd);
|
||||
} else if(cmd instanceof DeleteSnapshotBackupCommand) {
|
||||
answer = execute((DeleteSnapshotBackupCommand)cmd);
|
||||
} else if(cmd instanceof CreatePrivateTemplateFromVolumeCommand) {
|
||||
answer = execute((CreatePrivateTemplateFromVolumeCommand)cmd);
|
||||
} else if(cmd instanceof CreatePrivateTemplateFromSnapshotCommand) {
|
||||
answer = execute((CreatePrivateTemplateFromSnapshotCommand)cmd);
|
||||
} else if(cmd instanceof CopyVolumeCommand) {
|
||||
answer = execute((CopyVolumeCommand)cmd);
|
||||
} else if(cmd instanceof CreateVolumeFromSnapshotCommand) {
|
||||
answer = execute((CreateVolumeFromSnapshotCommand)cmd);
|
||||
} else {
|
||||
answer = _resource.defaultAction(cmd);
|
||||
}
|
||||
|
||||
if(cmd.getContextParam("execid") != null) {
|
||||
answer.setContextParam("execid", cmd.getContextParam("execid"));
|
||||
}
|
||||
if(cmd.getContextParam("checkpoint") != null) {
|
||||
answer.setContextParam("checkpoint", cmd.getContextParam("checkpoint"));
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
private Answer execute(PrimaryStorageDownloadCommand cmd) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Executing resource PrimaryStorageDownloadCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
return _storageMgr.execute(this, cmd);
|
||||
}
|
||||
|
||||
private Answer execute(BackupSnapshotCommand cmd) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Executing resource BackupSnapshotCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
return _storageMgr.execute(this, cmd);
|
||||
}
|
||||
|
||||
private Answer execute(DeleteSnapshotsDirCommand cmd) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Executing resource DeleteSnapshotsDirCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
return _storageMgr.execute(this, cmd);
|
||||
}
|
||||
|
||||
private Answer execute(DeleteSnapshotBackupCommand cmd) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Executing resource DeleteSnapshotBackupCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
return _storageMgr.execute(this, cmd);
|
||||
}
|
||||
|
||||
private Answer execute(CreatePrivateTemplateFromVolumeCommand cmd) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Executing resource CreatePrivateTemplateFromVolumeCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
return _storageMgr.execute(this, cmd);
|
||||
}
|
||||
|
||||
private Answer execute(CreatePrivateTemplateFromSnapshotCommand cmd) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Executing resource CreatePrivateTemplateFromVolumeCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
return _storageMgr.execute(this, cmd);
|
||||
}
|
||||
|
||||
private Answer execute(CopyVolumeCommand cmd) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Executing resource CopyVolumeCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
return _storageMgr.execute(this, cmd);
|
||||
}
|
||||
|
||||
private Answer execute(CreateVolumeFromSnapshotCommand cmd) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Executing resource CreateVolumeFromSnapshotCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
|
||||
return _storageMgr.execute(this, cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VmwareContext getServiceContext(Command cmd) {
|
||||
String guid = cmd.getContextParam("guid");
|
||||
if(guid == null || guid.isEmpty()) {
|
||||
s_logger.error("Invalid command context parameter guid");
|
||||
return null;
|
||||
}
|
||||
|
||||
String username = cmd.getContextParam("username");
|
||||
if(username == null || username.isEmpty()) {
|
||||
s_logger.error("Invalid command context parameter username");
|
||||
return null;
|
||||
}
|
||||
|
||||
String password = cmd.getContextParam("password");
|
||||
|
||||
// validate command guid parameter
|
||||
String[] tokens = guid.split("@");
|
||||
if(tokens == null || tokens.length != 2) {
|
||||
s_logger.error("Invalid content in command context parameter guid");
|
||||
return null;
|
||||
}
|
||||
|
||||
String vCenterAddress = tokens[1];
|
||||
String[] hostTokens = tokens[0].split(":");
|
||||
if(hostTokens == null || hostTokens.length != 2) {
|
||||
s_logger.error("Invalid content in command context parameter guid");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
_resource.ensureOutgoingRuleForAddress(vCenterAddress);
|
||||
VmwareContext context = null;
|
||||
|
||||
// cached VmwareContext may be timed out in vCenter, give it a chance to reclaim a new context from factory
|
||||
for(int i = 0; i < 2; i++) {
|
||||
context = VmwareSecondaryStorageContextFactory.create(vCenterAddress, username, password);
|
||||
if(!validateContext(context, cmd)) {
|
||||
invalidateServiceContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
if(context != null) {
|
||||
context.registerStockObject("serviceconsole", cmd.getContextParam("serviceconsole"));
|
||||
context.registerStockObject("manageportgroup", cmd.getContextParam("manageportgroup"));
|
||||
}
|
||||
return context;
|
||||
} catch(Exception e) {
|
||||
s_logger.error("Unexpected exception " + e.toString(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateServiceContext(VmwareContext context) {
|
||||
VmwareSecondaryStorageContextFactory.invalidate(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VmwareHypervisorHost getHyperHost(VmwareContext context, Command cmd) {
|
||||
String guid = cmd.getContextParam("guid");
|
||||
assert(guid != null);
|
||||
|
||||
String[] tokens = guid.split("@");
|
||||
assert(tokens != null && tokens.length == 2);
|
||||
|
||||
ManagedObjectReference morHyperHost = new ManagedObjectReference();
|
||||
String[] hostTokens = tokens[0].split(":");
|
||||
if(hostTokens == null || hostTokens.length != 2) {
|
||||
s_logger.error("Invalid content in command context parameter guid");
|
||||
return null;
|
||||
}
|
||||
|
||||
morHyperHost.setType(hostTokens[0]);
|
||||
morHyperHost.set_value(hostTokens[1]);
|
||||
|
||||
if(morHyperHost.getType().equalsIgnoreCase("HostSystem")) {
|
||||
HostMO hostMo = new HostMO(context, morHyperHost);
|
||||
|
||||
try {
|
||||
VmwareHypervisorHostNetworkSummary netSummary = hostMo.getHyperHostNetworkSummary(
|
||||
hostMo.getHostType() == VmwareHostType.ESXi ? cmd.getContextParam("manageportgroup") : cmd.getContextParam("serviceconsole"));
|
||||
_resource.ensureOutgoingRuleForAddress(netSummary.getHostIp());
|
||||
} catch(Throwable e) {
|
||||
s_logger.warn("Unable to retrive host network information due to exception " + e.toString() + ", host: " + hostTokens[0] + "-" + hostTokens[1]);
|
||||
}
|
||||
|
||||
return hostMo;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return new ClusterMO(context, morHyperHost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorkerName(VmwareContext context, Command cmd) {
|
||||
assert(cmd.getContextParam("worker") != null);
|
||||
return cmd.getContextParam("worker");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMountPoint(String storageUrl) {
|
||||
return _resource.getRootDir(storageUrl);
|
||||
}
|
||||
|
||||
private boolean validateContext(VmwareContext context, Command cmd) {
|
||||
String guid = cmd.getContextParam("guid");
|
||||
assert(guid != null);
|
||||
|
||||
String[] tokens = guid.split("@");
|
||||
assert(tokens != null && tokens.length == 2);
|
||||
|
||||
ManagedObjectReference morHyperHost = new ManagedObjectReference();
|
||||
String[] hostTokens = tokens[0].split(":");
|
||||
assert(hostTokens.length == 2);
|
||||
|
||||
morHyperHost.setType(hostTokens[0]);
|
||||
morHyperHost.set_value(hostTokens[1]);
|
||||
|
||||
if(morHyperHost.getType().equalsIgnoreCase("HostSystem")) {
|
||||
HostMO hostMo = new HostMO(context, morHyperHost);
|
||||
try {
|
||||
VmwareHypervisorHostNetworkSummary netSummary = hostMo.getHyperHostNetworkSummary(
|
||||
hostMo.getHostType() == VmwareHostType.ESXi ? cmd.getContextParam("manageportgroup") : cmd.getContextParam("serviceconsole"));
|
||||
assert(netSummary != null);
|
||||
if(netSummary.getHostIp() != null && !netSummary.getHostIp().isEmpty()) {
|
||||
if(s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Context validation succeeded. Validated via host: " + netSummary.getHostIp() + ", guid: " + guid);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
s_logger.warn("Context validation failed due to invalid host network summary");
|
||||
return false;
|
||||
} catch(Throwable e) {
|
||||
s_logger.warn("Context validation failed due to " + VmwareHelper.getExceptionMessage(e));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.vmware.apputils.version.ExtendedAppUtil;
|
||||
|
||||
public class TestVmwareContextFactory {
|
||||
private static volatile int s_seq = 1;
|
||||
|
||||
static {
|
||||
// skip certificate check
|
||||
System.setProperty("axis.socketSecureFactory", "org.apache.axis.components.net.SunFakeTrustSocketFactory");
|
||||
}
|
||||
|
||||
public static VmwareContext create(String vCenterAddress, String vCenterUserName, String vCenterPassword) throws Exception {
|
||||
assert(vCenterAddress != null);
|
||||
assert(vCenterUserName != null);
|
||||
assert(vCenterPassword != null);
|
||||
|
||||
String serviceUrl = "https://" + vCenterAddress + "/sdk/vimService";
|
||||
String[] params = new String[] {"--url", serviceUrl, "--username", vCenterUserName, "--password", vCenterPassword };
|
||||
ExtendedAppUtil appUtil = ExtendedAppUtil.initialize(vCenterAddress + "-" + s_seq++, params);
|
||||
|
||||
appUtil.connect();
|
||||
VmwareContext context = new VmwareContext(appUtil, vCenterAddress);
|
||||
return context;
|
||||
}
|
||||
}
|
||||
35
core/test/com/cloud/hypervisor/vmware/mo/TestVmwareMO.java
Executable file
35
core/test/com/cloud/hypervisor/vmware/mo/TestVmwareMO.java
Executable 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
96
core/test/com/cloud/hypervisor/vmware/util/TestVmwareUtil.java
Executable file
96
core/test/com/cloud/hypervisor/vmware/util/TestVmwareUtil.java
Executable 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
1128
core/test/com/cloud/vmware/TestVMWare.java
Normal file
1128
core/test/com/cloud/vmware/TestVMWare.java
Normal file
File diff suppressed because it is too large
Load Diff
16
deps/.classpath
vendored
16
deps/.classpath
vendored
@ -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
BIN
deps/vmware-apputils.jar
vendored
Normal file
Binary file not shown.
BIN
deps/vmware-credstore.jar
vendored
Normal file
BIN
deps/vmware-credstore.jar
vendored
Normal file
Binary file not shown.
BIN
deps/vmware-lib-activation.jar
vendored
Normal file
BIN
deps/vmware-lib-activation.jar
vendored
Normal file
Binary file not shown.
BIN
deps/vmware-lib-jaxen-core.jar
vendored
Normal file
BIN
deps/vmware-lib-jaxen-core.jar
vendored
Normal file
Binary file not shown.
BIN
deps/vmware-lib-jaxen-jdom.jar
vendored
Normal file
BIN
deps/vmware-lib-jaxen-jdom.jar
vendored
Normal file
Binary file not shown.
BIN
deps/vmware-lib-jaxrpc.jar
vendored
Normal file
BIN
deps/vmware-lib-jaxrpc.jar
vendored
Normal file
Binary file not shown.
BIN
deps/vmware-lib-jdom.jar
vendored
Normal file
BIN
deps/vmware-lib-jdom.jar
vendored
Normal file
Binary file not shown.
BIN
deps/vmware-lib-mailapi.jar
vendored
Normal file
BIN
deps/vmware-lib-mailapi.jar
vendored
Normal file
Binary file not shown.
BIN
deps/vmware-lib-saxpath.jar
vendored
Normal file
BIN
deps/vmware-lib-saxpath.jar
vendored
Normal file
Binary file not shown.
BIN
deps/vmware-lib-smtp.jar
vendored
Normal file
BIN
deps/vmware-lib-smtp.jar
vendored
Normal file
Binary file not shown.
BIN
deps/vmware-lib-wbem.jar
vendored
Normal file
BIN
deps/vmware-lib-wbem.jar
vendored
Normal file
Binary file not shown.
BIN
deps/vmware-lib-xalan.jar
vendored
Normal file
BIN
deps/vmware-lib-xalan.jar
vendored
Normal file
Binary file not shown.
BIN
deps/vmware-lib-xerces.jar
vendored
Normal file
BIN
deps/vmware-lib-xerces.jar
vendored
Normal file
Binary file not shown.
BIN
deps/vmware-lib-xml-apis.jar
vendored
Normal file
BIN
deps/vmware-lib-xml-apis.jar
vendored
Normal file
Binary file not shown.
BIN
deps/vmware-vim.jar
vendored
Normal file
BIN
deps/vmware-vim.jar
vendored
Normal file
Binary file not shown.
BIN
deps/vmware-vim25.jar
vendored
Normal file
BIN
deps/vmware-vim25.jar
vendored
Normal file
Binary file not shown.
@ -8,5 +8,6 @@
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/api"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/deps"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/tools"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/vmware-base"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
||||
63
server/src/com/cloud/hypervisor/guru/HypervGuru.java
Normal file
63
server/src/com/cloud/hypervisor/guru/HypervGuru.java
Normal 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;
|
||||
}
|
||||
}
|
||||
153
server/src/com/cloud/hypervisor/guru/VMwareGuru.java
Normal file
153
server/src/com/cloud/hypervisor/guru/VMwareGuru.java
Normal 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;
|
||||
}
|
||||
}
|
||||
131
server/src/com/cloud/hypervisor/vmware/VmwareCleanupMaid.java
Normal file
131
server/src/com/cloud/hypervisor/vmware/VmwareCleanupMaid.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
860
server/src/com/cloud/hypervisor/vmware/VmwareManagerImpl.java
Executable file
860
server/src/com/cloud/hypervisor/vmware/VmwareManagerImpl.java
Executable 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;
|
||||
}
|
||||
}
|
||||
250
server/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java
Executable file
250
server/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java
Executable 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
13
server/src/com/cloud/secstorage/CommandExecLogDao.java
Normal file
13
server/src/com/cloud/secstorage/CommandExecLogDao.java
Normal 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);
|
||||
}
|
||||
34
server/src/com/cloud/secstorage/CommandExecLogDaoImpl.java
Normal file
34
server/src/com/cloud/secstorage/CommandExecLogDaoImpl.java
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
99
server/src/com/cloud/secstorage/CommandExecLogVO.java
Normal file
99
server/src/com/cloud/secstorage/CommandExecLogVO.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@ -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
8
vmware-base/.classpath
Normal 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
17
vmware-base/.project
Normal 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>
|
||||
138
vmware-base/src/com/cloud/hypervisor/vmware/mo/BaseMO.java
Normal file
138
vmware-base/src/com/cloud/hypervisor/vmware/mo/BaseMO.java
Normal 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);
|
||||
}
|
||||
}
|
||||
566
vmware-base/src/com/cloud/hypervisor/vmware/mo/ClusterMO.java
Executable file
566
vmware-base/src/com/cloud/hypervisor/vmware/mo/ClusterMO.java
Executable 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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
public interface CustomFieldConstants {
|
||||
public final static String CLOUD_UUID = "cloud.uuid";
|
||||
public final static String CLOUD_GC = "cloud.gc";
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.vmware.vim25.CustomFieldDef;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.PrivilegePolicyDef;
|
||||
|
||||
public class CustomFieldsManagerMO extends BaseMO {
|
||||
|
||||
public CustomFieldsManagerMO(VmwareContext context, ManagedObjectReference mor) {
|
||||
super(context, mor);
|
||||
}
|
||||
|
||||
public CustomFieldsManagerMO(VmwareContext context, String morType, String morValue) {
|
||||
super(context, morType, morValue);
|
||||
}
|
||||
|
||||
public CustomFieldDef addCustomerFieldDef(String fieldName, String morType,
|
||||
PrivilegePolicyDef fieldDefPolicy, PrivilegePolicyDef fieldPolicy) throws Exception {
|
||||
return _context.getService().addCustomFieldDef(getMor(), fieldName, morType, fieldDefPolicy, fieldPolicy);
|
||||
}
|
||||
|
||||
public void removeCustomFieldDef(int key) throws Exception {
|
||||
_context.getService().removeCustomFieldDef(getMor(), key);
|
||||
}
|
||||
|
||||
public void renameCustomFieldDef(int key, String name) throws Exception {
|
||||
_context.getService().renameCustomFieldDef(getMor(), key, name);
|
||||
}
|
||||
|
||||
public void setField(ManagedObjectReference morEntity, int key, String value) throws Exception {
|
||||
_context.getService().setField(getMor(), morEntity, key, value);
|
||||
}
|
||||
|
||||
public CustomFieldDef[] getFields() throws Exception {
|
||||
return (CustomFieldDef[])_context.getServiceUtil().getDynamicProperty(getMor(), "field");
|
||||
}
|
||||
|
||||
public int getCustomFieldKey(String morType, String fieldName) throws Exception {
|
||||
CustomFieldDef[] fields = getFields();
|
||||
if(fields != null) {
|
||||
for(CustomFieldDef field : fields) {
|
||||
if(field.getName().equals(fieldName) && field.getManagedObjectType().equals(morType))
|
||||
return field.getKey();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int ensureCustomFieldDef(String morType, String fieldName) throws Exception {
|
||||
int key = getCustomFieldKey(morType, fieldName);
|
||||
if(key > 0)
|
||||
return key;
|
||||
|
||||
try {
|
||||
CustomFieldDef field = addCustomerFieldDef(fieldName, morType, null, null);
|
||||
return field.getKey();
|
||||
} catch(Exception e) {
|
||||
// assuming that someone is adding it
|
||||
key = getCustomFieldKey(morType, fieldName);
|
||||
}
|
||||
|
||||
if(key == 0)
|
||||
throw new Exception("Unable to setup custom field facility for " + morType + ":" + fieldName);
|
||||
|
||||
return key;
|
||||
}
|
||||
}
|
||||
295
vmware-base/src/com/cloud/hypervisor/vmware/mo/DatacenterMO.java
Executable file
295
vmware-base/src/com/cloud/hypervisor/vmware/mo/DatacenterMO.java
Executable 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);
|
||||
}
|
||||
}
|
||||
125
vmware-base/src/com/cloud/hypervisor/vmware/mo/DatastoreFile.java
Executable file
125
vmware-base/src/com/cloud/hypervisor/vmware/mo/DatastoreFile.java
Executable 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;
|
||||
}
|
||||
}
|
||||
305
vmware-base/src/com/cloud/hypervisor/vmware/mo/DatastoreMO.java
Executable file
305
vmware-base/src/com/cloud/hypervisor/vmware/mo/DatastoreMO.java
Executable 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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
173
vmware-base/src/com/cloud/hypervisor/vmware/mo/HostDatastoreSystemMO.java
Executable file
173
vmware-base/src/com/cloud/hypervisor/vmware/mo/HostDatastoreSystemMO.java
Executable 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 });
|
||||
}
|
||||
}
|
||||
34
vmware-base/src/com/cloud/hypervisor/vmware/mo/HostFirewallSystemMO.java
Executable file
34
vmware-base/src/com/cloud/hypervisor/vmware/mo/HostFirewallSystemMO.java
Executable 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);
|
||||
}
|
||||
}
|
||||
887
vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java
Executable file
887
vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java
Executable 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;
|
||||
}
|
||||
}
|
||||
53
vmware-base/src/com/cloud/hypervisor/vmware/mo/HostNetworkSystemMO.java
Executable file
53
vmware-base/src/com/cloud/hypervisor/vmware/mo/HostNetworkSystemMO.java
Executable 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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
public enum HostVirtualNicType {
|
||||
management,
|
||||
vmotion,
|
||||
faultToleranceLogging
|
||||
}
|
||||
|
||||
145
vmware-base/src/com/cloud/hypervisor/vmware/mo/HttpNfcLeaseMO.java
Executable file
145
vmware-base/src/com/cloud/hypervisor/vmware/mo/HttpNfcLeaseMO.java
Executable 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
538
vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java
Executable file
538
vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java
Executable 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
|
||||
public class NetworkDetails {
|
||||
|
||||
private String _name;
|
||||
private ManagedObjectReference _morNetwork;
|
||||
private ManagedObjectReference[] _morVMsOnNetwork;
|
||||
private String _gcTag;
|
||||
|
||||
public NetworkDetails(String name, ManagedObjectReference morNetwork, ManagedObjectReference[] morVMsOnNetwork, String gcTag) {
|
||||
_name = name;
|
||||
_morNetwork = morNetwork;
|
||||
_morVMsOnNetwork = morVMsOnNetwork;
|
||||
_gcTag = gcTag;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
public ManagedObjectReference getNetworkMor() {
|
||||
return _morNetwork;
|
||||
}
|
||||
|
||||
public ManagedObjectReference[] getVMMorsOnNetwork() {
|
||||
return _morVMsOnNetwork;
|
||||
}
|
||||
|
||||
public String getGCTag() {
|
||||
return _gcTag;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
|
||||
public class NetworkMO extends BaseMO {
|
||||
public NetworkMO(VmwareContext context, ManagedObjectReference morCluster) {
|
||||
super(context, morCluster);
|
||||
}
|
||||
|
||||
public NetworkMO(VmwareContext context, String morType, String morValue) {
|
||||
super(context, morType, morValue);
|
||||
}
|
||||
|
||||
public void destroyNetwork() throws Exception {
|
||||
_context.getService().destroyNetwork(_mor);
|
||||
}
|
||||
|
||||
public ManagedObjectReference[] getVMsOnNetwork() throws Exception {
|
||||
ManagedObjectReference[] vms = (ManagedObjectReference[])_context.getServiceUtil().getDynamicProperty(_mor, "vm");
|
||||
return vms;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.vmware.vim25.PerfCounterInfo;
|
||||
import com.vmware.vim25.PerfSummaryType;
|
||||
|
||||
public class PerfCounterInfoMapper {
|
||||
// map <group name, counter name, list of PerfCounterInfo based on rollupType>
|
||||
Map<String, Map<String, List<PerfCounterInfo>>> _mapCounterInfos =
|
||||
new HashMap<String, Map<String, List<PerfCounterInfo>>>();
|
||||
|
||||
public PerfCounterInfoMapper(PerfCounterInfo[] counterInfos) {
|
||||
if(counterInfos != null) {
|
||||
for(PerfCounterInfo counterInfo : counterInfos) {
|
||||
List<PerfCounterInfo> counterInfoList = getSafeCounterInfoList(
|
||||
counterInfo.getGroupInfo().getKey(), counterInfo.getNameInfo().getKey());
|
||||
counterInfoList.add(counterInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PerfCounterInfo[] lookup(String groupName, String counterName, PerfSummaryType rollupType) {
|
||||
assert(groupName != null);
|
||||
assert(counterName != null);
|
||||
|
||||
Map<String, List<PerfCounterInfo>> groupMap = _mapCounterInfos.get(groupName);
|
||||
if(groupMap == null)
|
||||
return null;
|
||||
|
||||
List<PerfCounterInfo> counterInfoList = groupMap.get(counterName);
|
||||
if(counterInfoList == null)
|
||||
return null;
|
||||
|
||||
if(rollupType == null) {
|
||||
return counterInfoList.toArray(new PerfCounterInfo[0]);
|
||||
}
|
||||
|
||||
for(PerfCounterInfo info : counterInfoList) {
|
||||
if(info.getRollupType() == rollupType)
|
||||
return new PerfCounterInfo[] { info };
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public PerfCounterInfo lookupOne(String groupName, String counterName, PerfSummaryType rollupType) {
|
||||
PerfCounterInfo[] infos = lookup(groupName, counterName, rollupType);
|
||||
if(infos != null && infos.length > 0)
|
||||
return infos[0];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Map<String, List<PerfCounterInfo>> getSafeGroupMap(String groupName) {
|
||||
Map<String, List<PerfCounterInfo>> groupMap = _mapCounterInfos.get(groupName);
|
||||
if(groupMap == null) {
|
||||
groupMap = new HashMap<String, List<PerfCounterInfo>>();
|
||||
_mapCounterInfos.put(groupName, groupMap);
|
||||
}
|
||||
return groupMap;
|
||||
}
|
||||
|
||||
private List<PerfCounterInfo> getSafeCounterInfoList(String groupName, String counterName) {
|
||||
Map<String, List<PerfCounterInfo>> groupMap = getSafeGroupMap(groupName);
|
||||
assert(groupMap != null);
|
||||
|
||||
List<PerfCounterInfo> counterInfoList = groupMap.get(counterName);
|
||||
if(counterInfoList == null) {
|
||||
counterInfoList = new ArrayList<PerfCounterInfo>();
|
||||
groupMap.put(counterName, counterInfoList);
|
||||
}
|
||||
return counterInfoList;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.PerfCompositeMetric;
|
||||
import com.vmware.vim25.PerfCounterInfo;
|
||||
import com.vmware.vim25.PerfEntityMetricBase;
|
||||
import com.vmware.vim25.PerfInterval;
|
||||
import com.vmware.vim25.PerfMetricId;
|
||||
import com.vmware.vim25.PerfProviderSummary;
|
||||
import com.vmware.vim25.PerfQuerySpec;
|
||||
|
||||
public class PerfManagerMO extends BaseMO {
|
||||
public PerfManagerMO(VmwareContext context, ManagedObjectReference mor) {
|
||||
super(context, mor);
|
||||
}
|
||||
|
||||
public PerfManagerMO(VmwareContext context, String morType, String morValue) {
|
||||
super(context, morType, morValue);
|
||||
}
|
||||
|
||||
public void createPerfInterval(PerfInterval interval) throws Exception {
|
||||
_context.getService().createPerfInterval(_mor, interval);
|
||||
}
|
||||
|
||||
public PerfMetricId[] queryAvailablePerfMetric(ManagedObjectReference morEntity, Calendar beginTime,
|
||||
Calendar endTime, Integer intervalId) throws Exception {
|
||||
|
||||
return _context.getService().queryAvailablePerfMetric(_mor, morEntity, beginTime, endTime, intervalId);
|
||||
}
|
||||
|
||||
public PerfCompositeMetric queryPerfComposite(PerfQuerySpec spec) throws Exception {
|
||||
return _context.getService().queryPerfComposite(_mor, spec);
|
||||
}
|
||||
|
||||
public PerfCounterInfo[] queryPerfCounter(int[] counterId) throws Exception {
|
||||
return _context.getService().queryPerfCounter(_mor, counterId);
|
||||
}
|
||||
|
||||
public PerfCounterInfo[] queryPerfCounterByLevel(int level) throws Exception {
|
||||
return _context.getService().queryPerfCounterByLevel(_mor, level);
|
||||
}
|
||||
|
||||
public PerfProviderSummary queryPerfProviderSummary(ManagedObjectReference morEntity) throws Exception {
|
||||
return _context.getService().queryPerfProviderSummary(_mor, morEntity);
|
||||
}
|
||||
|
||||
public PerfEntityMetricBase[] queryPerf(PerfQuerySpec[] specs) throws Exception {
|
||||
return _context.getService().queryPerf(_mor, specs);
|
||||
}
|
||||
|
||||
public void removePerfInterval(int samplePeriod) throws Exception {
|
||||
_context.getService().removePerfInterval(_mor, samplePeriod);
|
||||
}
|
||||
|
||||
public void updatePerfInterval(PerfInterval interval) throws Exception {
|
||||
_context.getService().updatePerfInterval(_mor, interval);
|
||||
}
|
||||
|
||||
public PerfCounterInfo[] getCounterInfo() throws Exception {
|
||||
return (PerfCounterInfo[])_context.getServiceUtil().getDynamicProperty(_mor, "perfCounter");
|
||||
}
|
||||
|
||||
public PerfInterval[] getIntervalInfo() throws Exception {
|
||||
return (PerfInterval[])_context.getServiceUtil().getDynamicProperty(_mor, "historicalInterval");
|
||||
}
|
||||
}
|
||||
260
vmware-base/src/com/cloud/hypervisor/vmware/mo/SnapshotDescriptor.java
Executable file
260
vmware-base/src/com/cloud/hypervisor/vmware/mo/SnapshotDescriptor.java
Executable 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
62
vmware-base/src/com/cloud/hypervisor/vmware/mo/TaskMO.java
Normal file
62
vmware-base/src/com/cloud/hypervisor/vmware/mo/TaskMO.java
Normal 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();
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
145
vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualDiskManagerMO.java
Executable file
145
vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualDiskManagerMO.java
Executable 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);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
public enum VirtualEthernetCardType {
|
||||
E1000, PCNet32, Vmxnet2, Vmxnet3
|
||||
}
|
||||
1912
vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
Executable file
1912
vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
Executable file
File diff suppressed because it is too large
Load Diff
146
vmware-base/src/com/cloud/hypervisor/vmware/mo/VmdkFileDescriptor.java
Executable file
146
vmware-base/src/com/cloud/hypervisor/vmware/mo/VmdkFileDescriptor.java
Executable 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();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
public enum VmwareHostType {
|
||||
ESXi, ESX
|
||||
}
|
||||
57
vmware-base/src/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java
Executable file
57
vmware-base/src/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java
Executable 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;
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
public class VmwareHypervisorHostNetworkSummary {
|
||||
private String hostIp;
|
||||
private String hostNetmask;
|
||||
private String hostMacAddress;
|
||||
|
||||
public VmwareHypervisorHostNetworkSummary() {
|
||||
}
|
||||
|
||||
public String getHostIp() {
|
||||
return hostIp;
|
||||
}
|
||||
|
||||
public void setHostIp(String hostIp) {
|
||||
this.hostIp = hostIp;
|
||||
}
|
||||
|
||||
public String getHostNetmask() {
|
||||
return hostNetmask;
|
||||
}
|
||||
|
||||
public void setHostNetmask(String hostNetmask) {
|
||||
this.hostNetmask = hostNetmask;
|
||||
}
|
||||
|
||||
public String getHostMacAddress() {
|
||||
return hostMacAddress;
|
||||
}
|
||||
|
||||
public void setHostMacAddress(String hostMacAddress) {
|
||||
this.hostMacAddress = hostMacAddress;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Cloud.com, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
public class VmwareHypervisorHostResourceSummary {
|
||||
private long memoryBytes;
|
||||
private long cpuCount;
|
||||
private long cpuSpeed;
|
||||
|
||||
public VmwareHypervisorHostResourceSummary() {
|
||||
}
|
||||
|
||||
public long getMemoryBytes() {
|
||||
return memoryBytes;
|
||||
}
|
||||
|
||||
public void setMemoryBytes(long memoryBytes) {
|
||||
this.memoryBytes = memoryBytes;
|
||||
}
|
||||
|
||||
public long getCpuCount() {
|
||||
return cpuCount;
|
||||
}
|
||||
|
||||
public void setCpuCount(long cpuCount) {
|
||||
this.cpuCount = cpuCount;
|
||||
}
|
||||
|
||||
public long getCpuSpeed() {
|
||||
return cpuSpeed;
|
||||
}
|
||||
|
||||
public void setCpuSpeed(long cpuSpeed) {
|
||||
this.cpuSpeed = cpuSpeed;
|
||||
}
|
||||
}
|
||||
593
vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareContext.java
Executable file
593
vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareContext.java
Executable 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&dsName=NFS%20datastore">Parent Directory</a></td><td> </td><td align="right"> - </td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2da2013465%2ehlog?dcPath=cupertino&dsName=NFS%20datastore">Fedora-clone-test-a2013465.hlog</a></td><td align="right">15-Aug-2010 00:13</td><td align="right">1</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2da2013465%2evswp?dcPath=cupertino&dsName=NFS%20datastore">Fedora-clone-test-a2013465.vswp</a></td><td align="right">14-Aug-2010 23:01</td><td align="right">402653184</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2dflat%2evmdk?dcPath=cupertino&dsName=NFS%20datastore">Fedora-clone-test-flat.vmdk</a></td><td align="right">26-Aug-2010 18:43</td><td align="right">17179869184</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2envram?dcPath=cupertino&dsName=NFS%20datastore">Fedora-clone-test.nvram</a></td><td align="right">15-Aug-2010 00:13</td><td align="right">8684</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2evmdk?dcPath=cupertino&dsName=NFS%20datastore">Fedora-clone-test.vmdk</a></td><td align="right">15-Aug-2010 00:13</td><td align="right">479</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2evmsd?dcPath=cupertino&dsName=NFS%20datastore">Fedora-clone-test.vmsd</a></td><td align="right">14-Aug-2010 16:59</td><td align="right">0</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2evmx?dcPath=cupertino&dsName=NFS%20datastore">Fedora-clone-test.vmx</a></td><td align="right">15-Aug-2010 00:13</td><td align="right">3500</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2evmxf?dcPath=cupertino&dsName=NFS%20datastore">Fedora-clone-test.vmxf</a></td><td align="right">15-Aug-2010 00:13</td><td align="right">272</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/test%2etxt?dcPath=cupertino&dsName=NFS%20datastore">test.txt</a></td><td align="right">24-Aug-2010 01:03</td><td align="right">12</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2d2%2elog?dcPath=cupertino&dsName=NFS%20datastore">vmware-2.log</a></td><td align="right">14-Aug-2010 16:51</td><td align="right">80782</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2d3%2elog?dcPath=cupertino&dsName=NFS%20datastore">vmware-3.log</a></td><td align="right">14-Aug-2010 19:07</td><td align="right">58573</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2d4%2elog?dcPath=cupertino&dsName=NFS%20datastore">vmware-4.log</a></td><td align="right">14-Aug-2010 23:00</td><td align="right">49751</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2d5%2elog?dcPath=cupertino&dsName=NFS%20datastore">vmware-5.log</a></td><td align="right">15-Aug-2010 00:04</td><td align="right">64024</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2d6%2elog?dcPath=cupertino&dsName=NFS%20datastore">vmware-6.log</a></td><td align="right">15-Aug-2010 00:11</td><td align="right">59742</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2d7%2elog?dcPath=cupertino&dsName=NFS%20datastore">vmware-7.log</a></td><td align="right">15-Aug-2010 00:13</td><td align="right">59859</td></tr>
|
||||
<tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2elog?dcPath=cupertino&dsName=NFS%20datastore">vmware.log</a></td><td align="right">15-Aug-2010 00:23</td><td align="right">47157</td></tr>
|
||||
<tr><th colspan="5"><hr></th></tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
*/
|
||||
public String[] listDatastoreDirContent(String urlString) throws Exception {
|
||||
List<String> fileList = new ArrayList<String>();
|
||||
String content = new String(getResourceContent(urlString));
|
||||
String marker = "</a></td><td ";
|
||||
int parsePos = -1;
|
||||
do {
|
||||
parsePos = content.indexOf(marker, parsePos < 0 ? 0 : parsePos);
|
||||
if(parsePos > 0) {
|
||||
int beginPos = content.lastIndexOf('>', parsePos -1);
|
||||
if(beginPos < 0)
|
||||
beginPos = 0;
|
||||
|
||||
fileList.add((content.substring(beginPos + 1, parsePos)));
|
||||
parsePos += marker.length();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while(parsePos > 0);
|
||||
return fileList.toArray(new String[0]);
|
||||
}
|
||||
|
||||
public String composeDatastoreBrowseUrl(String dcName, String fullPath) {
|
||||
DatastoreFile dsFile = new DatastoreFile(fullPath);
|
||||
return composeDatastoreBrowseUrl(dcName, dsFile.getDatastoreName(), dsFile.getRelativePath());
|
||||
}
|
||||
|
||||
public String composeDatastoreBrowseUrl(String dcName, String datastoreName, String relativePath) {
|
||||
assert(relativePath != null);
|
||||
assert(datastoreName != null);
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("https://");
|
||||
sb.append(_serverAddress);
|
||||
sb.append("/folder/");
|
||||
sb.append(relativePath);
|
||||
sb.append("?dcPath=").append(URLEncoder.encode(dcName)).append("&dsName=");
|
||||
sb.append(URLEncoder.encode(datastoreName));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public HttpURLConnection getHTTPConnection(String urlString) throws Exception {
|
||||
return getHTTPConnection(urlString, "GET");
|
||||
}
|
||||
|
||||
public HttpURLConnection getHTTPConnection(String urlString, String httpMethod) throws Exception {
|
||||
String cookieString = getServiceCookie();
|
||||
HostnameVerifier hv = new HostnameVerifier() {
|
||||
public boolean verify(String urlHostName, SSLSession session) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
HttpsURLConnection.setDefaultHostnameVerifier(hv);
|
||||
URL url = new URL(urlString);
|
||||
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
|
||||
|
||||
conn.setDoInput(true);
|
||||
conn.setDoOutput(true);
|
||||
conn.setAllowUserInteraction(true);
|
||||
conn.setRequestProperty(org.apache.axis.transport.http.HTTPConstants.HEADER_COOKIE, cookieString);
|
||||
conn.setRequestMethod(httpMethod);
|
||||
conn.connect();
|
||||
return conn;
|
||||
}
|
||||
|
||||
public HttpURLConnection getRawHTTPConnection(String urlString) throws Exception {
|
||||
HostnameVerifier hv = new HostnameVerifier() {
|
||||
public boolean verify(String urlHostName, SSLSession session) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
HttpsURLConnection.setDefaultHostnameVerifier(hv);
|
||||
URL url = new URL(urlString);
|
||||
return (HttpURLConnection)url.openConnection();
|
||||
}
|
||||
|
||||
private String getServiceCookie() throws Exception {
|
||||
com.vmware.vim25.VimPortType service = getService();
|
||||
org.apache.axis.client.Stub st = (org.apache.axis.client.Stub)service;
|
||||
org.apache.axis.client.Call callObj = st._getCall();
|
||||
org.apache.axis.MessageContext msgContext = callObj.getMessageContext();
|
||||
String cookieString = (String)msgContext.getProperty(org.apache.axis.transport.http.HTTPConstants.HEADER_COOKIE);
|
||||
return cookieString;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
_appUtil.disConnect();
|
||||
} catch(Exception e) {
|
||||
s_logger.warn("Unexpected exception: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TrustAllManager implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager {
|
||||
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isServerTrusted(java.security.cert.X509Certificate[] certs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isClientTrusted(java.security.cert.X509Certificate[] certs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
|
||||
throws java.security.cert.CertificateException {
|
||||
return;
|
||||
}
|
||||
|
||||
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
|
||||
throws java.security.cert.CertificateException {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
97
vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java
Executable file
97
vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java
Executable 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);
|
||||
}
|
||||
}
|
||||
513
vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareHelper.java
Executable file
513
vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareHelper.java
Executable 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()));
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user