diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 8cdfb54ccc2..67942397a7c 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -2610,6 +2610,15 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa s_logger.error(msg); throw new Exception(msg); } + + DatastoreMO dsRootVolumeIsOn = getDatastoreThatRootDiskIsOn(dataStoresDetails, disks); + if(dsRootVolumeIsOn == null) { + String msg = "Unable to locate datastore details of root volume"; + s_logger.error(msg); + throw new Exception(msg); + } + + DatacenterMO dcMo = new DatacenterMO(hyperHost.getContext(), hyperHost.getHyperHostDatacenter()); VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmInternalCSName); if (vmMo != null) { @@ -2657,7 +2666,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa throw new Exception("Failed to find the newly create or relocated VM. vmName: " + vmInternalCSName); } } - + int totalChangeDevices = disks.length + nics.length; DiskTO volIso = null; if (vmSpec.getType() != VirtualMachine.Type.User) { @@ -2823,9 +2832,18 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa Pair volumeDsDetails = dataStoresDetails.get(primaryStore.getUuid()); assert (volumeDsDetails != null); VirtualDevice device; + + datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmName, volumeDsDetails.second(), + volumeTO.getPath()); + device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, new String[] { datastoreDiskPath }, volumeDsDetails.first(), + (controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1); + +/* datastoreDiskPath = String.format("[%s] %s.vmdk", volumeDsDetails.second().getName(), volumeTO.getPath()); + String chainInfo = volumeTO.getChainInfo(); + // chainInfo is no longer in use if (chainInfo != null && !chainInfo.isEmpty()) { String[] diskChain = _gson.fromJson(chainInfo, String[].class); if (diskChain == null || diskChain.length < 1) { @@ -2845,6 +2863,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, new String[] { datastoreDiskPath }, volumeDsDetails.first(), (controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1); } +*/ + deviceConfigSpecArray[i].setDevice(device); deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD); @@ -3110,8 +3130,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa return validatedDetails; } - - private NicTO[] sortNicsByDeviceId(NicTO[] nics) { List listForSort = new ArrayList(); @@ -3181,6 +3199,21 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa return poolMors; } + private DatastoreMO getDatastoreThatRootDiskIsOn(HashMap> dataStoresDetails, + DiskTO disks[]) { + + Pair rootDiskDataStoreDetails = null; + for (DiskTO vol : disks) { + if (vol.getType() == Volume.Type.ROOT) { + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)vol.getData().getDataStore(); + rootDiskDataStoreDetails = dataStoresDetails.get(primaryStore.getUuid()); + } + } + + if(rootDiskDataStoreDetails != null) + return rootDiskDataStoreDetails.second(); + return null; + } private String getPvlanInfo(NicTO nicTo) { if (nicTo.getBroadcastType() == BroadcastDomainType.Pvlan) { @@ -4277,6 +4310,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } DatastoreMO dsMo = new DatastoreMO(getServiceContext(), morDs); + VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dsMo.getOwnerDatacenter().first(), cmd.getVmName(), + dsMo, cmd.getVolumePath()); + String datastoreVolumePath = dsMo.searchFileInSubFolders(cmd.getVolumePath() + ".vmdk", true); assert (datastoreVolumePath != null) : "Virtual disk file must exist in specified datastore for attach/detach operations."; if (datastoreVolumePath == null) { @@ -4292,6 +4328,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa if (cmd.isManaged()) { handleDatastoreAndVmdkDetach(cmd.get_iScsiName(), cmd.getStorageHost(), cmd.getStoragePort()); + } else { + VmwareStorageLayoutHelper.syncVolumeToRootFolder(dsMo.getOwnerDatacenter().first(), dsMo, cmd.getVolumePath()); } } diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageLayoutHelper.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageLayoutHelper.java index f5383928b1d..b41b72a5e32 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageLayoutHelper.java +++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageLayoutHelper.java @@ -16,7 +16,10 @@ // under the License. package com.cloud.storage.resource; +import org.apache.log4j.Logger; + import com.cloud.hypervisor.vmware.mo.DatacenterMO; +import com.cloud.hypervisor.vmware.mo.DatastoreFile; import com.cloud.hypervisor.vmware.mo.DatastoreMO; import com.cloud.utils.Pair; @@ -26,6 +29,7 @@ import com.cloud.utils.Pair; * */ public class VmwareStorageLayoutHelper { + private static final Logger s_logger = Logger.getLogger(VmwareStorageLayoutHelper.class); public static String[] getVmdkFilePairDatastorePath(DatastoreMO dsMo, String vmName, String vmdkName, VmwareStorageLayoutType layoutType, boolean linkedVmdk) throws Exception { @@ -34,21 +38,21 @@ public class VmwareStorageLayoutHelper { switch(layoutType) { case VMWARE : assert(vmName != null && !vmName.isEmpty()); - filePair[0] = String.format("[%s] %s/%s.vmdk", dsMo.getName(), vmName, vmdkName); + filePair[0] = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkName + ".vmdk"); if(linkedVmdk) - filePair[1] = String.format("[%s] %s/%s-delta.vmdk", dsMo.getName(), vmName, vmdkName); + filePair[1] = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkName + "-delta.vmdk"); else - filePair[1] = String.format("[%s] %s/%s-flat.vmdk", dsMo.getName(), vmName, vmdkName); + filePair[1] = getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkName + "-flat.vmdk"); return filePair; case CLOUDSTACK_LEGACY : - filePair[0] = String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName); + filePair[0] = getLegacyDatastorePathFromVmdkFileName(dsMo, vmdkName + ".vmdk"); if(linkedVmdk) - filePair[1] = String.format("[%s] %s-delta.vmdk", dsMo.getName(), vmdkName); + filePair[1] = getLegacyDatastorePathFromVmdkFileName(dsMo, vmdkName + "-delta.vmdk"); else - filePair[1] = String.format("[%s] %s-flat.vmdk", dsMo.getName(), vmdkName); + filePair[1] = getLegacyDatastorePathFromVmdkFileName(dsMo, vmdkName + "-flat.vmdk"); return filePair; default : @@ -60,6 +64,83 @@ public class VmwareStorageLayoutHelper { return null; } + public static String syncVolumeToVmDefaultFolder(DatacenterMO dcMo, String vmName, + DatastoreMO ds, String vmdkName) throws Exception { + + assert(ds != null); + if(!ds.folderExists(String.format("[%s]", ds.getName()), vmName)) { + s_logger.info("VM folder does not exist on target datastore, we will create one. vm: " + vmName + ", datastore: " + ds.getName()); + + ds.makeDirectory(String.format("[%s] %s", ds.getName(), vmName), dcMo.getMor()); + } + + String[] vmdkLinkedCloneModeLegacyPair = getVmdkFilePairDatastorePath(ds, vmName, vmdkName, + VmwareStorageLayoutType.CLOUDSTACK_LEGACY, true); + String[] vmdkFullCloneModeLegacyPair = getVmdkFilePairDatastorePath(ds, vmName, vmdkName, + VmwareStorageLayoutType.CLOUDSTACK_LEGACY, false); + + String[] vmdkLinkedCloneModePair = getVmdkFilePairDatastorePath(ds, vmName, vmdkName, + VmwareStorageLayoutType.VMWARE, true); + String[] vmdkFullCloneModePair = getVmdkFilePairDatastorePath(ds, vmName, vmdkName, + VmwareStorageLayoutType.VMWARE, false); + + if(!ds.fileExists(vmdkLinkedCloneModeLegacyPair[0])) { + // To protect against inconsistency caused by non-atomic datastore file management, detached disk may + // be left over in its previous owner VM. We will do a fixup synchronization here by moving it to root + // again + // + syncVolumeToRootFolder(dcMo, ds, vmdkName); + } + + if(ds.fileExists(vmdkFullCloneModeLegacyPair[1])) { + s_logger.info("sync " + vmdkFullCloneModeLegacyPair[1] + "->" + vmdkFullCloneModePair[1]); + + ds.moveDatastoreFile(vmdkFullCloneModeLegacyPair[1], dcMo.getMor(), ds.getMor(), + vmdkFullCloneModePair[1], dcMo.getMor(), true); + } + + if(ds.fileExists(vmdkLinkedCloneModeLegacyPair[1])) { + s_logger.info("sync " + vmdkLinkedCloneModeLegacyPair[1] + "->" + vmdkLinkedCloneModePair[1]); + + ds.moveDatastoreFile(vmdkLinkedCloneModeLegacyPair[1], dcMo.getMor(), ds.getMor(), + vmdkLinkedCloneModePair[1], dcMo.getMor(), true); + } + + s_logger.info("sync " + vmdkLinkedCloneModeLegacyPair[0] + "->" + vmdkLinkedCloneModePair[0]); + ds.moveDatastoreFile(vmdkLinkedCloneModeLegacyPair[0], dcMo.getMor(), ds.getMor(), + vmdkLinkedCloneModePair[0], dcMo.getMor(), true); + + return vmdkLinkedCloneModePair[0]; + } + + public static void syncVolumeToRootFolder(DatacenterMO dcMo, DatastoreMO ds, String vmdkName) throws Exception { + String fileDsFullPath = ds.searchFileInSubFolders(vmdkName + ".vmdk", false); + if(fileDsFullPath == null) + throw new Exception("Unable to find " + vmdkName + ".vmdk in datastore: " + ds.getName()); + + DatastoreFile srcDsFile = new DatastoreFile(fileDsFullPath); + String companionFilePath = srcDsFile.getCompanionPath(vmdkName + "-flat.vmdk"); + if(ds.fileExists(companionFilePath)) { + String targetPath = getLegacyDatastorePathFromVmdkFileName(ds, vmdkName + "-flat.vmdk"); + + s_logger.info("Fixup folder-synchronization. move " + companionFilePath + " -> " + targetPath); + ds.moveDatastoreFile(companionFilePath, dcMo.getMor(), ds.getMor(), targetPath, dcMo.getMor(), true); + } + + companionFilePath = srcDsFile.getCompanionPath(vmdkName + "-delta.vmdk"); + if(ds.fileExists(companionFilePath)) { + String targetPath = getLegacyDatastorePathFromVmdkFileName(ds, vmdkName + "-delta.vmdk"); + + s_logger.info("Fixup folder-synchronization. move " + companionFilePath + " -> " + targetPath); + ds.moveDatastoreFile(companionFilePath, dcMo.getMor(), ds.getMor(), targetPath, dcMo.getMor(), true); + } + + // move the identity VMDK file the last + String targetPath = getLegacyDatastorePathFromVmdkFileName(ds, vmdkName + ".vmdk"); + s_logger.info("Fixup folder-synchronization. move " + fileDsFullPath + " -> " + targetPath); + ds.moveDatastoreFile(fileDsFullPath, dcMo.getMor(), ds.getMor(), targetPath, dcMo.getMor(), true); + } + public static String getTemplateOnSecStorageFilePath(String secStorageMountPoint, String templateRelativeFolderPath, String templateName, String fileExtension) { @@ -114,13 +195,43 @@ public class VmwareStorageLayoutHelper { } 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); + + String fileName = volumeName + ".vmdk"; + String fileFullPath = getLegacyDatastorePathFromVmdkFileName(dsMo, fileName); + if(!dsMo.fileExists(fileFullPath)) + fileFullPath = dsMo.searchFileInSubFolders(fileName, false); + if(fileFullPath != null) { + dsMo.deleteFile(fileFullPath, dcMo.getMor(), false); + } else { + s_logger.warn("Unable to locate VMDK file: " + fileName); + } + + fileName = volumeName + "-flat.vmdk"; + fileFullPath = getLegacyDatastorePathFromVmdkFileName(dsMo, fileName); + if(!dsMo.fileExists(fileFullPath)) + fileFullPath = dsMo.searchFileInSubFolders(fileName, false); + if(fileFullPath != null) { + dsMo.deleteFile(fileFullPath, dcMo.getMor(), false); + } else { + s_logger.warn("Unable to locate VMDK file: " + fileName); + } + + fileName = volumeName + "-delta.vmdk"; + fileFullPath = getLegacyDatastorePathFromVmdkFileName(dsMo, fileName); + if(!dsMo.fileExists(fileFullPath)) + fileFullPath = dsMo.searchFileInSubFolders(fileName, false); + if(fileFullPath != null) { + dsMo.deleteFile(fileFullPath, dcMo.getMor(), false); + } else { + s_logger.warn("Unable to locate VMDK file: " + fileName); + } + } + + public static String getLegacyDatastorePathFromVmdkFileName(DatastoreMO dsMo, String vmdkFileName) throws Exception { + return String.format("[%s] %s", dsMo.getName(), vmdkFileName); + } + + public static String getVmwareDatastorePathFromVmdkFileName(DatastoreMO dsMo, String vmName, String vmdkFileName) throws Exception { + return String.format("[%s] %s/%s", dsMo.getName(), vmName, vmdkFileName); } } diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java index a0199ce049e..547be4e3a3d 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java +++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java @@ -1148,7 +1148,7 @@ public class VmwareStorageProcessor implements StorageProcessor { } else { morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, isManaged ? VmwareResource.getDatastoreName(iScsiName) : primaryStore.getUuid()); - } + } if (morDs == null) { String msg = "Unable to find the mounted datastore to execute AttachVolumeCommand, vmName: " + vmName; @@ -1157,19 +1157,33 @@ public class VmwareStorageProcessor implements StorageProcessor { } DatastoreMO dsMo = new DatastoreMO(this.hostService.getServiceContext(null), morDs); - String datastoreVolumePath = dsMo.getDatastorePath((isManaged ? dsMo.getName() : volumeTO.getPath()) + ".vmdk"); + String datastoreVolumePath; + if(isAttach) { + if(!isManaged) + datastoreVolumePath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dsMo.getOwnerDatacenter().first(), vmName, + dsMo, volumeTO.getPath()); + else + datastoreVolumePath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk"); + } else { + datastoreVolumePath = VmwareStorageLayoutHelper.getLegacyDatastorePathFromVmdkFileName(dsMo, volumeTO.getPath() + ".vmdk"); + if(!dsMo.fileExists(datastoreVolumePath)) + datastoreVolumePath = VmwareStorageLayoutHelper.getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, volumeTO.getPath() + ".vmdk"); + } + disk.setVdiUuid(datastoreVolumePath); AttachAnswer answer = new AttachAnswer(disk); if (isAttach) { vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs); - } else { + } else { vmMo.removeAllSnapshots(); vmMo.detachDisk(datastoreVolumePath, false); if (isManaged) { - hostService.handleDatastoreAndVmdkDetach(iScsiName, storageHost, storagePort); + this.hostService.handleDatastoreAndVmdkDetach(iScsiName, storageHost, storagePort); + } else { + VmwareStorageLayoutHelper.syncVolumeToRootFolder(dsMo.getOwnerDatacenter().first(), dsMo, volumeTO.getPath()); } } @@ -1428,23 +1442,10 @@ public class VmwareStorageProcessor implements StorageProcessor { } } - if (s_logger.isInfoEnabled()) { + if (s_logger.isInfoEnabled()) s_logger.info("Destroy volume by original name: " + vol.getPath() + ".vmdk"); - } - dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true); - - // root volume may be created via linked-clone, delete the delta disk as well - if (_fullCloneFlag) { - if (s_logger.isInfoEnabled()) { - s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk"); - } - dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true); - } else { - if (s_logger.isInfoEnabled()) { - s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-delta.vmdk"); - } - dsMo.deleteFile(vol.getPath() + "-delta.vmdk", morDc, true); - } + + VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, vol.getPath(), new DatacenterMO(context, morDc)); return new Answer(cmd, true, "Success"); } @@ -1464,41 +1465,8 @@ public class VmwareStorageProcessor implements StorageProcessor { } } - String chainInfo = vol.getChainInfo(); - if (chainInfo != null && !chainInfo.isEmpty()) { - s_logger.info("Destroy volume by chain info: " + chainInfo); - String[] diskChain = _gson.fromJson(chainInfo, String[].class); - - if (diskChain != null && diskChain.length > 0) { - for (String backingName : diskChain) { - if (s_logger.isInfoEnabled()) { - s_logger.info("Delete volume backing file: " + backingName); - } - dsMo.deleteFile(backingName, morDc, true); - } - } else { - if (s_logger.isInfoEnabled()) { - s_logger.info("Empty disk chain info, fall back to try to delete by original backing file name"); - } - dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true); - - if (s_logger.isInfoEnabled()) { - s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk"); - } - dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true); - } - } else { - if (s_logger.isInfoEnabled()) { - s_logger.info("Destroy volume by original name: " + vol.getPath() + ".vmdk"); - } - dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true); - - if (s_logger.isInfoEnabled()) { - s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk"); - } - dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true); - } - + VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, vol.getPath(), new DatacenterMO(context, morDc)); + return new Answer(cmd, true, "Success"); } catch (Throwable e) { if (e instanceof RemoteException) { diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/DatastoreMO.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/DatastoreMO.java index 92a8f053084..4b2ce088ea5 100755 --- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/DatastoreMO.java +++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/DatastoreMO.java @@ -351,17 +351,15 @@ public class DatastoreMO extends BaseMO { s_logger.warn("Multiple files with name " + fileName + " exists in datastore " + datastorePath + ". Trying to choose first file found in search attempt."); } for (HostDatastoreBrowserSearchResults result : results) { - if (result != null) { - List info = result.getFile(); - if (info != null && info.size() > 0) { - for (FileInfo fi : info) { - absoluteFileName = parentFolderPath = result.getFolderPath(); - s_logger.info("Found file " + fileName + " in datastore at " + absoluteFileName); - if(parentFolderPath.endsWith("]")) - absoluteFileName += " "; - absoluteFileName += fi.getPath(); - break; - } + List info = result.getFile(); + if (info != null && info.size() > 0) { + for (FileInfo fi : info) { + absoluteFileName = parentFolderPath = result.getFolderPath(); + s_logger.info("Found file " + fileName + " in datastore at " + absoluteFileName); + if(parentFolderPath.endsWith("]")) + absoluteFileName += " "; + absoluteFileName += fi.getPath(); + break; } } } diff --git a/vmware-base/test/com/cloud/hypervisor/vmware/mo/TestVmwareContextFactory.java b/vmware-base/test/com/cloud/hypervisor/vmware/mo/TestVmwareContextFactory.java new file mode 100644 index 00000000000..aa6506ae999 --- /dev/null +++ b/vmware-base/test/com/cloud/hypervisor/vmware/mo/TestVmwareContextFactory.java @@ -0,0 +1,53 @@ +//Licensed to the Apache Software Foundation (ASF) under one +//or more contributor license agreements. See the NOTICE file +//distributed with this work for additional information +//regarding copyright ownership. The ASF licenses this file +//to you under the Apache License, Version 2.0 (the +//"License"); you may not use this file except in compliance +//with the License. You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, +//software distributed under the License is distributed on an +//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +//KIND, either express or implied. See the License for the +//specific language governing permissions and limitations +//under the License. + +package com.cloud.hypervisor.vmware.mo; + +import org.apache.log4j.Logger; + +import com.cloud.hypervisor.vmware.util.VmwareClient; +import com.cloud.hypervisor.vmware.util.VmwareContext; +import com.cloud.utils.StringUtils; + +public class TestVmwareContextFactory { + + private static final Logger s_logger = Logger.getLogger(TestVmwareContextFactory.class); + + 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"; + + if(s_logger.isDebugEnabled()) + s_logger.debug("initialize VmwareContext. url: " + serviceUrl + ", username: " + vCenterUserName + ", password: " + StringUtils.getMaskedPasswordForDisplay(vCenterPassword)); + + VmwareClient vimClient = new VmwareClient(vCenterAddress + "-" + s_seq++); + vimClient.connect(serviceUrl, vCenterUserName, vCenterPassword); + + VmwareContext context = new VmwareContext(vimClient, vCenterAddress); + return context; + } +}