mirror of https://github.com/apache/cloudstack.git
Merge 6edb407bb8 into 9bbd32a8ef
This commit is contained in:
commit
4906801a8f
|
|
@ -0,0 +1,45 @@
|
|||
// 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 org.apache.cloudstack.storage;
|
||||
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import org.apache.cloudstack.api.Identity;
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public interface DiskControllerMapping extends InternalIdentity, Identity {
|
||||
String getName();
|
||||
|
||||
String getControllerReference();
|
||||
|
||||
String getBusName();
|
||||
|
||||
HypervisorType getHypervisor();
|
||||
|
||||
Integer getMaxDeviceCount();
|
||||
|
||||
Integer getMaxControllerCount();
|
||||
|
||||
String getVmdkAdapterType();
|
||||
|
||||
String getMinHardwareVersion();
|
||||
|
||||
Date getRemoved();
|
||||
|
||||
Date getCreated();
|
||||
}
|
||||
|
|
@ -20,6 +20,9 @@
|
|||
package com.cloud.agent.api;
|
||||
|
||||
import com.cloud.agent.api.LogLevel.Log4jLevel;
|
||||
import org.apache.cloudstack.storage.DiskControllerMappingVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SecStorageVMSetupCommand extends Command {
|
||||
String[] allowedInternalSites = new String[0];
|
||||
|
|
@ -27,6 +30,8 @@ public class SecStorageVMSetupCommand extends Command {
|
|||
@LogLevel(Log4jLevel.Off)
|
||||
String copyPassword;
|
||||
|
||||
private List<DiskControllerMappingVO> supportedDiskControllers;
|
||||
|
||||
public SecStorageVMSetupCommand() {
|
||||
super();
|
||||
}
|
||||
|
|
@ -60,4 +65,11 @@ public class SecStorageVMSetupCommand extends Command {
|
|||
this.copyPassword = copyPassword;
|
||||
}
|
||||
|
||||
public List<DiskControllerMappingVO> getSupportedDiskControllers() {
|
||||
return supportedDiskControllers;
|
||||
}
|
||||
|
||||
public void setSupportedDiskControllers(List<DiskControllerMappingVO> supportedDiskControllers) {
|
||||
this.supportedDiskControllers = supportedDiskControllers;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,205 @@
|
|||
// 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 org.apache.cloudstack.storage;
|
||||
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
import org.apache.cloudstack.util.HypervisorTypeConverter;
|
||||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Convert;
|
||||
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 java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
@Table(name = "disk_controller_mapping")
|
||||
public class DiskControllerMappingVO implements DiskControllerMapping {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id", nullable = false)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "uuid", nullable = false)
|
||||
private String uuid = UUID.randomUUID().toString();
|
||||
|
||||
@Column(name = "name", nullable = false)
|
||||
private String name;
|
||||
|
||||
@Column(name = "controller_reference", nullable = false)
|
||||
private String controllerReference;
|
||||
|
||||
@Column(name = "bus_name", nullable = false)
|
||||
private String busName;
|
||||
|
||||
@Column(name = "hypervisor", nullable = false)
|
||||
@Convert(converter = HypervisorTypeConverter.class)
|
||||
private HypervisorType hypervisor;
|
||||
|
||||
@Column(name = "max_device_count")
|
||||
private Integer maxDeviceCount = null;
|
||||
|
||||
@Column(name = "max_controller_count")
|
||||
private Integer maxControllerCount = null;
|
||||
|
||||
@Column(name = "vmdk_adapter_type")
|
||||
private String vmdkAdapterType = null;
|
||||
|
||||
@Column(name = "min_hardware_version")
|
||||
private String minHardwareVersion = null;
|
||||
|
||||
@Column(name = GenericDao.CREATED_COLUMN, nullable = false)
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date created;
|
||||
|
||||
@Column(name = GenericDao.REMOVED_COLUMN)
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
private Date removed = null;
|
||||
|
||||
public DiskControllerMappingVO() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getControllerReference() {
|
||||
return controllerReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBusName() {
|
||||
return busName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HypervisorType getHypervisor() {
|
||||
return hypervisor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getMaxDeviceCount() {
|
||||
return maxDeviceCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getMaxControllerCount() {
|
||||
return maxControllerCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVmdkAdapterType() {
|
||||
return vmdkAdapterType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMinHardwareVersion() {
|
||||
return minHardwareVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getRemoved() {
|
||||
return removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setUuid(String uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setControllerReference(String controllerReference) {
|
||||
this.controllerReference = controllerReference;
|
||||
}
|
||||
|
||||
public void setBusName(String busName) {
|
||||
this.busName = busName;
|
||||
}
|
||||
|
||||
public void setHypervisor(HypervisorType hypervisor) {
|
||||
this.hypervisor = hypervisor;
|
||||
}
|
||||
|
||||
public void setMaxDeviceCount(Integer maxDeviceCount) {
|
||||
this.maxDeviceCount = maxDeviceCount;
|
||||
}
|
||||
|
||||
public void setMaxControllerCount(Integer maxControllerCount) {
|
||||
this.maxControllerCount = maxControllerCount;
|
||||
}
|
||||
|
||||
public void setVmdkAdapterType(String vmdkAdapterType) {
|
||||
this.vmdkAdapterType = vmdkAdapterType;
|
||||
}
|
||||
|
||||
public void setMinHardwareVersion(String minHardwareVersion) {
|
||||
this.minHardwareVersion = minHardwareVersion;
|
||||
}
|
||||
|
||||
public void setCreated(Date created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
public void setRemoved(Date removed) {
|
||||
this.removed = removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof DiskControllerMappingVO)) {
|
||||
return false;
|
||||
}
|
||||
DiskControllerMappingVO that = (DiskControllerMappingVO) obj;
|
||||
return controllerReference.equals(that.getControllerReference());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "name", "controllerReference",
|
||||
"busName", "hypervisor", "maxDeviceCount", "maxControllerCount", "vmdkAdapterType", "minHardwareVersion");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// 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 org.apache.cloudstack.storage.dao;
|
||||
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import org.apache.cloudstack.storage.DiskControllerMappingVO;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface DiskControllerMappingDao extends GenericDao<DiskControllerMappingVO, Long> {
|
||||
DiskControllerMappingVO findDiskControllerMapping(String name, String classReference, HypervisorType hypervisor);
|
||||
|
||||
List<DiskControllerMappingVO> listForHypervisor(HypervisorType hypervisor);
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
// 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 org.apache.cloudstack.storage.dao;
|
||||
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import org.apache.cloudstack.storage.DiskControllerMappingVO;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class DiskControllerMappingDaoImpl extends GenericDaoBase<DiskControllerMappingVO, Long> implements DiskControllerMappingDao {
|
||||
private SearchBuilder<DiskControllerMappingVO> diskControllerMappingSearch;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
diskControllerMappingSearch = createSearchBuilder();
|
||||
diskControllerMappingSearch.and("name", diskControllerMappingSearch.entity().getName(), SearchCriteria.Op.EQ);
|
||||
diskControllerMappingSearch.and("controllerReference", diskControllerMappingSearch.entity().getControllerReference(), SearchCriteria.Op.EQ);
|
||||
diskControllerMappingSearch.and("hypervisor", diskControllerMappingSearch.entity().getHypervisor(), SearchCriteria.Op.EQ);
|
||||
diskControllerMappingSearch.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiskControllerMappingVO findDiskControllerMapping(String name, String controllerReference, HypervisorType hypervisor) {
|
||||
SearchCriteria<DiskControllerMappingVO> sc = diskControllerMappingSearch.create();
|
||||
sc.setParametersIfNotNull("name", name);
|
||||
sc.setParametersIfNotNull("controllerReference", controllerReference);
|
||||
sc.setParameters("hypervisor", hypervisor);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DiskControllerMappingVO> listForHypervisor(HypervisorType hypervisor) {
|
||||
SearchCriteria<DiskControllerMappingVO> sc = diskControllerMappingSearch.create();
|
||||
sc.setParameters("hypervisor", hypervisor);
|
||||
return listBy(sc);
|
||||
}
|
||||
}
|
||||
|
|
@ -67,6 +67,7 @@
|
|||
<bean id="dataCenterJoinDaoImpl" class="com.cloud.api.query.dao.DataCenterJoinDaoImpl" />
|
||||
<bean id="domainVlanMapDaoImpl" class="com.cloud.dc.dao.DomainVlanMapDaoImpl" />
|
||||
<bean id="engineDcDetailsDaoImpl" class="org.apache.cloudstack.engine.datacenter.entity.api.db.dao.DcDetailsDaoImpl" />
|
||||
<bean id="diskControllerMappingDaoImpl" class="org.apache.cloudstack.storage.dao.DiskControllerMappingDaoImpl" />
|
||||
<bean id="diskOfferingJoinDaoImpl" class="com.cloud.api.query.dao.DiskOfferingJoinDaoImpl" />
|
||||
<bean id="domainDaoImpl" class="com.cloud.domain.dao.DomainDaoImpl" />
|
||||
<bean id="domainDetailsDaoImpl" class="com.cloud.domain.dao.DomainDetailsDaoImpl" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
-- 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.
|
||||
|
||||
DROP PROCEDURE IF EXISTS `cloud`.`ADD_DISK_CONTROLLER_MAPPING`;
|
||||
|
||||
CREATE PROCEDURE `cloud`.`ADD_DISK_CONTROLLER_MAPPING` (
|
||||
IN disk_controller_name varchar(255),
|
||||
IN disk_controller_reference varchar(255),
|
||||
IN disk_controller_bus_name varchar(255),
|
||||
IN disk_controller_hypervisor varchar(40),
|
||||
IN disk_controller_max_device_count bigint unsigned,
|
||||
IN disk_controller_max_controller_count bigint unsigned,
|
||||
IN disk_controller_vmdk_adapter_type varchar(255),
|
||||
IN disk_controller_min_hardware_version varchar(20)
|
||||
)
|
||||
BEGIN
|
||||
INSERT INTO cloud.disk_controller_mapping (uuid, name, controller_reference, bus_name, hypervisor, max_device_count,
|
||||
max_controller_count, vmdk_adapter_type, min_hardware_version, created)
|
||||
SELECT UUID(), disk_controller_name, disk_controller_reference, disk_controller_bus_name, disk_controller_hypervisor,
|
||||
disk_controller_max_device_count, disk_controller_max_controller_count, disk_controller_vmdk_adapter_type,
|
||||
disk_controller_min_hardware_version, now()
|
||||
FROM DUAL
|
||||
WHERE NOT EXISTS (SELECT 1 FROM cloud.disk_controller_mapping WHERE cloud.disk_controller_mapping.name = disk_controller_name
|
||||
AND cloud.disk_controller_mapping.hypervisor = disk_controller_hypervisor)
|
||||
;END;
|
||||
|
|
@ -49,3 +49,32 @@ CREATE TABLE IF NOT EXISTS `cloud`.`webhook_filter` (
|
|||
INDEX `i_webhook_filter__webhook_id`(`webhook_id`),
|
||||
CONSTRAINT `fk_webhook_filter__webhook_id` FOREIGN KEY(`webhook_id`) REFERENCES `webhook`(`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Disk controller mappings
|
||||
CREATE TABLE IF NOT EXISTS `cloud`.`disk_controller_mapping` (
|
||||
`id` bigint(20) unsigned NOT NULL auto_increment,
|
||||
`uuid` varchar(255) UNIQUE NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`controller_reference` varchar(255) NOT NULL,
|
||||
`bus_name` varchar(255) NOT NULL,
|
||||
`hypervisor` varchar(40) NOT NULL,
|
||||
`max_device_count` bigint unsigned DEFAULT NULL,
|
||||
`max_controller_count` bigint unsigned DEFAULT NULL,
|
||||
`vmdk_adapter_type` varchar(255) DEFAULT NULL,
|
||||
`min_hardware_version` varchar(20) DEFAULT NULL,
|
||||
`created` datetime NOT NULL,
|
||||
`removed` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
-- Add VMware's default disk controller mappings
|
||||
CALL `cloud`.`ADD_DISK_CONTROLLER_MAPPING` ('osdefault', 'unused', 'unused', 'VMware', NULL, NULL, NULL, NULL);
|
||||
CALL `cloud`.`ADD_DISK_CONTROLLER_MAPPING` ('ide', 'com.vmware.vim25.VirtualIDEController', 'ide', 'VMware', 2, 2, 'ide', NULL);
|
||||
CALL `cloud`.`ADD_DISK_CONTROLLER_MAPPING` ('scsi', 'com.vmware.vim25.VirtualLsiLogicController', 'scsi', 'VMware', 16, 4, 'lsilogic', NULL);
|
||||
CALL `cloud`.`ADD_DISK_CONTROLLER_MAPPING` ('buslogic', 'com.vmware.vim25.VirtualBusLogicController', 'scsi', 'VMware', 16, 4, 'buslogic', NULL);
|
||||
CALL `cloud`.`ADD_DISK_CONTROLLER_MAPPING` ('lsilogic', 'com.vmware.vim25.VirtualLsiLogicController', 'scsi', 'VMware', 16, 4, 'lsilogic', NULL);
|
||||
CALL `cloud`.`ADD_DISK_CONTROLLER_MAPPING` ('lsisas1068', 'com.vmware.vim25.VirtualLsiLogicSASController', 'scsi', 'VMware', 16, 4, 'lsilogic', NULL);
|
||||
CALL `cloud`.`ADD_DISK_CONTROLLER_MAPPING` ('pvscsi', 'com.vmware.vim25.ParaVirtualSCSIController', 'scsi', 'VMware', 16, 4, 'lsilogic', '7');
|
||||
CALL `cloud`.`ADD_DISK_CONTROLLER_MAPPING` ('sata', 'com.vmware.vim25.VirtualAHCIController', 'sata', 'VMware', 30, 4, 'ide', '10');
|
||||
CALL `cloud`.`ADD_DISK_CONTROLLER_MAPPING` ('ahci', 'com.vmware.vim25.VirtualAHCIController', 'sata', 'VMware', 30, 4, 'ide', '10');
|
||||
CALL `cloud`.`ADD_DISK_CONTROLLER_MAPPING` ('nvme', 'com.vmware.vim25.VirtualNVMEController', 'nvme', 'VMware', 15, 4, 'ide', '13');
|
||||
|
|
|
|||
|
|
@ -322,7 +322,7 @@ class VmwareVmImplementer {
|
|||
}
|
||||
|
||||
if (vm.getType() == VirtualMachine.Type.NetScalerVm) {
|
||||
details.put(VmDetailConstants.ROOT_DISK_CONTROLLER, "scsi");
|
||||
details.put(VmDetailConstants.ROOT_DISK_CONTROLLER, DiskControllerType.scsi.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,9 @@ import org.apache.cloudstack.framework.config.Configurable;
|
|||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.framework.jobs.impl.AsyncJobManagerImpl;
|
||||
import org.apache.cloudstack.management.ManagementServerHost;
|
||||
import org.apache.cloudstack.storage.DiskControllerMappingVO;
|
||||
import org.apache.cloudstack.storage.command.CheckDataStoreStoragePolicyComplianceCommand;
|
||||
import org.apache.cloudstack.storage.dao.DiskControllerMappingDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
import org.apache.cloudstack.utils.identity.ManagementServerNode;
|
||||
|
|
@ -235,6 +237,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
|||
@Inject
|
||||
private VMInstanceDao vmInstanceDao;
|
||||
@Inject
|
||||
private DiskControllerMappingDao diskControllerMappingDao;
|
||||
private UserVmCloneSettingDao cloneSettingDao;
|
||||
@Inject
|
||||
private TemplateManager templateManager;
|
||||
|
|
@ -392,6 +395,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
|||
|
||||
_agentMgr.registerForHostEvents(this, true, true, true);
|
||||
|
||||
List<DiskControllerMappingVO> mappingsInDatabase = diskControllerMappingDao.listForHypervisor(Hypervisor.HypervisorType.VMware);
|
||||
VmwareHelper.configureDiskControllerMappingsInVmwareBaseModule(mappingsInDatabase);
|
||||
|
||||
logger.info("VmwareManagerImpl has been successfully configured");
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,11 +57,15 @@ import com.vmware.vim25.FileQueryFlags;
|
|||
import com.vmware.vim25.FolderFileInfo;
|
||||
import com.vmware.vim25.HostDatastoreBrowserSearchResults;
|
||||
import com.vmware.vim25.HostDatastoreBrowserSearchSpec;
|
||||
import com.vmware.vim25.VirtualCdrom;
|
||||
import com.vmware.vim25.VirtualCdromIsoBackingInfo;
|
||||
import com.vmware.vim25.VirtualController;
|
||||
import com.vmware.vim25.VirtualIDEController;
|
||||
import com.vmware.vim25.VirtualMachineConfigSummary;
|
||||
import com.vmware.vim25.VirtualTPM;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.backup.PrepareForBackupRestorationCommand;
|
||||
import org.apache.cloudstack.storage.DiskControllerMappingVO;
|
||||
import org.apache.cloudstack.storage.command.CopyCommand;
|
||||
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
|
||||
import org.apache.cloudstack.storage.command.browser.ListDataStoreObjectsAnswer;
|
||||
|
|
@ -246,7 +250,6 @@ import com.cloud.hypervisor.vmware.mo.CustomFieldsManagerMO;
|
|||
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
|
||||
import com.cloud.hypervisor.vmware.mo.DatastoreFile;
|
||||
import com.cloud.hypervisor.vmware.mo.DatastoreMO;
|
||||
import com.cloud.hypervisor.vmware.mo.DiskControllerType;
|
||||
import com.cloud.hypervisor.vmware.mo.FeatureKeyConstants;
|
||||
import com.cloud.hypervisor.vmware.mo.HostDatastoreSystemMO;
|
||||
import com.cloud.hypervisor.vmware.mo.HostMO;
|
||||
|
|
@ -374,7 +377,6 @@ import com.vmware.vim25.VirtualMachineRelocateSpecDiskLocator;
|
|||
import com.vmware.vim25.VirtualMachineRuntimeInfo;
|
||||
import com.vmware.vim25.VirtualMachineToolsStatus;
|
||||
import com.vmware.vim25.VirtualMachineVideoCard;
|
||||
import com.vmware.vim25.VirtualSCSIController;
|
||||
import com.vmware.vim25.VirtualUSBController;
|
||||
import com.vmware.vim25.VmConfigInfo;
|
||||
import com.vmware.vim25.VmConfigSpec;
|
||||
|
|
@ -417,7 +419,6 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||
protected boolean _instanceNameFlag = false;
|
||||
|
||||
protected boolean _recycleHungWorker = false;
|
||||
protected DiskControllerType _rootDiskController = DiskControllerType.ide;
|
||||
|
||||
protected ManagedObjectReference _morHyperHost;
|
||||
protected final static ThreadLocal<VmwareContext> s_serviceContext = new ThreadLocal<>();
|
||||
|
|
@ -1973,61 +1974,157 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||
return new ScaleVmAnswer(cmd, true, null);
|
||||
}
|
||||
|
||||
protected void ensureDiskControllers(VirtualMachineMO vmMo, Pair<String, String> controllerInfo) throws Exception {
|
||||
if (vmMo == null) {
|
||||
/**
|
||||
* Validates whether the instance has the required disk controllers, and creates them if it does not.
|
||||
* @param controllerInfo pair containing the root disk and data disk controllers, respectively.
|
||||
* @throws CloudRuntimeException if the instance does not have the required controllers, but this method is unable to create them.
|
||||
*/
|
||||
protected void ensureDiskControllers(VirtualMachineMO vmMo, Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo,
|
||||
boolean isSystemVm) throws Exception {
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> chosenDiskControllers = VmwareHelper.chooseDiskControllers(controllerInfo, vmMo, null, null);
|
||||
Set<DiskControllerMappingVO> requiredDiskControllers = VmwareHelper.getRequiredDiskControllers(chosenDiskControllers, isSystemVm);
|
||||
|
||||
if (vmHasRequiredControllers(vmMo, requiredDiskControllers)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Pair<String, String> chosenDiskControllers = VmwareHelper.chooseRequiredDiskControllers(controllerInfo, vmMo, null, null);
|
||||
String scsiDiskController = HypervisorHostHelper.getScsiController(chosenDiskControllers);
|
||||
if (scsiDiskController == null) {
|
||||
return;
|
||||
}
|
||||
validateRequiredVirtualHardwareVersionForNewDiskControllers(vmMo, requiredDiskControllers);
|
||||
validateNewDiskControllersSupportExistingDisks(vmMo, chosenDiskControllers);
|
||||
teardownAllDiskControllers(vmMo);
|
||||
|
||||
vmMo.getScsiDeviceControllerKeyNoException();
|
||||
// This VM needs SCSI controllers.
|
||||
// Get count of existing scsi controllers. Helps not to attempt to create more than the maximum allowed 4
|
||||
// Get maximum among the bus numbers in use by scsi controllers. Safe to pick maximum, because we always go sequential allocating bus numbers.
|
||||
Ternary<Integer, Integer, DiskControllerType> scsiControllerInfo = vmMo.getScsiControllerInfo();
|
||||
int requiredNumScsiControllers = VmwareHelper.MAX_SCSI_CONTROLLER_COUNT - scsiControllerInfo.first();
|
||||
int availableBusNum = scsiControllerInfo.second() + 1; // method returned current max. bus number
|
||||
|
||||
if (DiskControllerType.getType(scsiDiskController) != scsiControllerInfo.third()) {
|
||||
logger.debug(String.format("Change controller type from: %s to: %s", scsiControllerInfo.third().toString(),
|
||||
scsiDiskController));
|
||||
vmMo.tearDownDevices(new Class<?>[]{VirtualSCSIController.class});
|
||||
vmMo.addScsiDeviceControllers(DiskControllerType.getType(scsiDiskController));
|
||||
return;
|
||||
VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
|
||||
VmwareHelper.addDiskControllersToVmConfigSpec(vmConfigSpec, requiredDiskControllers, isSystemVm);
|
||||
if (!vmMo.configureVm(vmConfigSpec)) {
|
||||
throw new CloudRuntimeException("Unable to configure virtual machine's disk controllers.");
|
||||
}
|
||||
|
||||
if (requiredNumScsiControllers == 0) {
|
||||
return;
|
||||
}
|
||||
if (scsiControllerInfo.first() > 0) {
|
||||
// For VMs which already have a SCSI controller, do NOT attempt to add any more SCSI controllers & return the sub type.
|
||||
// For Legacy VMs would have only 1 LsiLogic Parallel SCSI controller, and doesn't require more.
|
||||
// For VMs created post device ordering support, 4 SCSI subtype controllers are ensured during deployment itself. No need to add more.
|
||||
// For fresh VM deployment only, all required controllers should be ensured.
|
||||
return;
|
||||
}
|
||||
ensureScsiDiskControllers(vmMo, scsiDiskController, requiredNumScsiControllers, availableBusNum);
|
||||
logger.info("Successfully added virtual machine [{}]'s required disk controllers [{}].", vmMo, requiredDiskControllers);
|
||||
}
|
||||
|
||||
private void ensureScsiDiskControllers(VirtualMachineMO vmMo, String scsiDiskController, int requiredNumScsiControllers, int availableBusNum) throws Exception {
|
||||
// Pick the sub type of scsi
|
||||
if (DiskControllerType.getType(scsiDiskController) == DiskControllerType.pvscsi) {
|
||||
if (!vmMo.isPvScsiSupported()) {
|
||||
String msg = "This VM doesn't support Vmware Paravirtual SCSI controller for virtual disks, because the virtual hardware version is less than 7.";
|
||||
throw new Exception(msg);
|
||||
}
|
||||
vmMo.ensurePvScsiDeviceController(requiredNumScsiControllers, availableBusNum);
|
||||
} else if (DiskControllerType.getType(scsiDiskController) == DiskControllerType.lsisas1068) {
|
||||
vmMo.ensureLsiLogicSasDeviceControllers(requiredNumScsiControllers, availableBusNum);
|
||||
} else if (DiskControllerType.getType(scsiDiskController) == DiskControllerType.buslogic) {
|
||||
vmMo.ensureBusLogicDeviceControllers(requiredNumScsiControllers, availableBusNum);
|
||||
} else if (DiskControllerType.getType(scsiDiskController) == DiskControllerType.lsilogic) {
|
||||
vmMo.ensureLsiLogicDeviceControllers(requiredNumScsiControllers, availableBusNum);
|
||||
protected boolean vmHasRequiredControllers(VirtualMachineMO vmMo, Set<DiskControllerMappingVO> requiredDiskControllers) throws Exception {
|
||||
Set<String> requiredDiskControllerClasspaths = requiredDiskControllers.stream()
|
||||
.map(DiskControllerMappingVO::getControllerReference)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
List<VirtualController> existingControllers = vmMo.getControllers();
|
||||
for (VirtualController controller : existingControllers) {
|
||||
String classpath = controller.getClass().getName();
|
||||
requiredDiskControllerClasspaths.remove(classpath);
|
||||
}
|
||||
|
||||
if (requiredDiskControllerClasspaths.isEmpty()) {
|
||||
logger.debug("Virtual machine [{}] has all the required controllers [{}].", vmMo, requiredDiskControllers);
|
||||
return true;
|
||||
}
|
||||
logger.debug("Virtual machine [{}] does not have the following required controllers: [{}].", vmMo, requiredDiskControllerClasspaths);
|
||||
return false;
|
||||
}
|
||||
|
||||
/***
|
||||
* Validates if the provided <code>VirtualMachineMO</code>'s virtual hardware version supports the required disk controllers.
|
||||
* @throws CloudRuntimeException if one of the disk controllers requires a version greater than the instance's virtual
|
||||
* hardware version.
|
||||
*/
|
||||
protected void validateRequiredVirtualHardwareVersionForNewDiskControllers(VirtualMachineMO vmMo, Set<DiskControllerMappingVO> requiredDiskControllers) throws Exception {
|
||||
int hardwareVersion = vmMo.getVirtualHardwareVersion();
|
||||
List<DiskControllerMappingVO> unsupportedDiskControllers = new ArrayList<>();
|
||||
|
||||
for (DiskControllerMappingVO diskController : requiredDiskControllers) {
|
||||
if (diskController.getMinHardwareVersion() == null) {
|
||||
continue;
|
||||
}
|
||||
Integer requiredVersion = Integer.parseInt(diskController.getMinHardwareVersion());
|
||||
if (hardwareVersion < requiredVersion) {
|
||||
unsupportedDiskControllers.add(diskController);
|
||||
}
|
||||
}
|
||||
|
||||
if (!unsupportedDiskControllers.isEmpty()) {
|
||||
String names = unsupportedDiskControllers.stream().map(DiskControllerMappingVO::getName).collect(Collectors.joining(", "));
|
||||
String requiredVersions = unsupportedDiskControllers.stream().map(DiskControllerMappingVO::getMinHardwareVersion).collect(Collectors.joining(", "));
|
||||
logger.debug("Virtual machine [{}] does not support disk controllers [{}], as its virtual hardware version is [{}] but the controllers require, respectfully, versions [{}].",
|
||||
vmMo, names, hardwareVersion, requiredVersions);
|
||||
throw new CloudRuntimeException(String.format("Disk controllers [%s] are not supported.", names));
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* Validates if the provided disk controllers have enough device nodes to support all the existing disks.
|
||||
* @param controllerInfo pair containing the root disk and data disk controllers, respectively.
|
||||
* @throws CloudRuntimeException if the instance has more disks than the amount supported by the controllers.
|
||||
*/
|
||||
protected void validateNewDiskControllersSupportExistingDisks(VirtualMachineMO vmMo, Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo) throws Exception {
|
||||
DiskControllerMappingVO rootDiskController = controllerInfo.first();
|
||||
DiskControllerMappingVO dataDiskController = controllerInfo.second();
|
||||
|
||||
List<VirtualDisk> disks = vmMo.getVirtualDisks();
|
||||
VirtualCdrom cdrom = (VirtualCdrom) vmMo.getIsoDevice();
|
||||
|
||||
if (rootDiskController == dataDiskController) {
|
||||
int maxDevicesInBus = getMaxSupportedDevicesInBus(rootDiskController);
|
||||
int devicesInBus = disks.size();
|
||||
|
||||
if (cdrom != null && Class.forName(rootDiskController.getControllerReference()) == VirtualIDEController.class) {
|
||||
devicesInBus++;
|
||||
}
|
||||
|
||||
if (maxDevicesInBus < devicesInBus) {
|
||||
throw new CloudRuntimeException(String.format("Virtual machine [%s] has [%s] virtual disks (including cdrom), but the new disk controllers only support [%s] devices.",
|
||||
vmMo.getName(), devicesInBus, maxDevicesInBus));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int maxDevicesInRootDiskBus = getMaxSupportedDevicesInBus(rootDiskController);
|
||||
int maxDevicesInDataDiskBus = getMaxSupportedDevicesInBus(dataDiskController);
|
||||
int devicesInRootDiskBus = 1;
|
||||
int devicesInDataDiskBus = disks.size() - 1;
|
||||
|
||||
if (cdrom != null) {
|
||||
if (Class.forName(rootDiskController.getControllerReference()) == VirtualIDEController.class) {
|
||||
devicesInRootDiskBus++;
|
||||
} else if (Class.forName(dataDiskController.getControllerReference()) == VirtualIDEController.class) {
|
||||
devicesInDataDiskBus++;
|
||||
}
|
||||
}
|
||||
|
||||
if (maxDevicesInRootDiskBus < devicesInRootDiskBus || maxDevicesInDataDiskBus < devicesInDataDiskBus) {
|
||||
throw new CloudRuntimeException(String.format("Virtual machine [%s] has [%s] devices in the root disk's bus and [%s] in the data disks' bus, " +
|
||||
"but these buses only support [%s] and [%s] devices.", vmMo.getName(), devicesInRootDiskBus, devicesInDataDiskBus,
|
||||
maxDevicesInRootDiskBus, maxDevicesInDataDiskBus));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total amount of disks that the instance can have using the provided disk controller type, considering
|
||||
* that the instance has the maximum amount of that disk controller type created.
|
||||
*/
|
||||
protected int getMaxSupportedDevicesInBus(DiskControllerMappingVO mapping) {
|
||||
int devicesPerController = mapping.getMaxDeviceCount();
|
||||
if (VmwareHelper.isControllerScsi(mapping)) {
|
||||
devicesPerController--;
|
||||
}
|
||||
return devicesPerController * mapping.getMaxControllerCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all disk controllers from the virtual machine.
|
||||
*/
|
||||
protected void teardownAllDiskControllers(VirtualMachineMO vmMo) throws Exception {
|
||||
List<DiskControllerMappingVO> allMappings = VmwareHelper.getAllSupportedDiskControllerMappingsExceptOsDefault();
|
||||
Set<Class<?>> classesToTeardown = new HashSet<>();
|
||||
|
||||
for (DiskControllerMappingVO mapping : allMappings) {
|
||||
try {
|
||||
Class<?> diskControllerClass = Class.forName(mapping.getControllerReference());
|
||||
if (diskControllerClass != VirtualIDEController.class) {
|
||||
classesToTeardown.add(diskControllerClass);
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
logger.debug("Could not find class for controller reference [{}]; ignoring it on teardown.", mapping.getControllerReference());
|
||||
}
|
||||
}
|
||||
|
||||
vmMo.tearDownDevices(classesToTeardown.toArray(new Class<?>[0]));
|
||||
}
|
||||
|
||||
protected StartAnswer execute(StartCommand cmd) {
|
||||
|
|
@ -2051,7 +2148,7 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||
String vmNameOnVcenter = names.second();
|
||||
DiskTO rootDiskTO = null;
|
||||
String bootMode = getBootModeFromVmSpec(vmSpec, deployAsIs);
|
||||
Pair<String, String> controllerInfo = getControllerInfoFromVmSpec(vmSpec);
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = getControllerInfoFromVmSpec(vmSpec);
|
||||
|
||||
Boolean systemVm = vmSpec.getType().isUsedBySystem();
|
||||
// Thus, vmInternalCSName always holds i-x-y, the cloudstack generated internal VM name.
|
||||
|
|
@ -2087,9 +2184,6 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||
|
||||
VirtualMachineDiskInfoBuilder diskInfoBuilder = null;
|
||||
VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmInternalCSName);
|
||||
DiskControllerType systemVmScsiControllerType = DiskControllerType.lsilogic;
|
||||
int firstScsiControllerBusNum = 0;
|
||||
int numScsiControllerForSystemVm = 1;
|
||||
boolean hasSnapshot = false;
|
||||
|
||||
List<Pair<Integer, ManagedObjectReference>> diskDatastores = null;
|
||||
|
|
@ -2104,8 +2198,7 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||
hasSnapshot = vmMo.hasSnapshot();
|
||||
|
||||
tearDownVmDevices(vmMo, hasSnapshot, deployAsIs);
|
||||
ensureDiskControllersInternal(vmMo, systemVm, controllerInfo, systemVmScsiControllerType,
|
||||
numScsiControllerForSystemVm, firstScsiControllerBusNum, deployAsIs);
|
||||
ensureDiskControllersInternal(vmMo, systemVm, controllerInfo, deployAsIs);
|
||||
} else {
|
||||
ManagedObjectReference morDc = hyperHost.getHyperHostDatacenter();
|
||||
assert (morDc != null);
|
||||
|
|
@ -2128,8 +2221,7 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||
diskDatastores = vmMo.getAllDiskDatastores();
|
||||
|
||||
tearDownVmDevices(vmMo, hasSnapshot, deployAsIs);
|
||||
ensureDiskControllersInternal(vmMo, systemVm, controllerInfo, systemVmScsiControllerType,
|
||||
numScsiControllerForSystemVm, firstScsiControllerBusNum, deployAsIs);
|
||||
ensureDiskControllersInternal(vmMo, systemVm, controllerInfo, deployAsIs);
|
||||
}
|
||||
} else {
|
||||
// If a VM with the same name is found in a different cluster in the DC, unregister the old VM and configure a new VM (cold-migration).
|
||||
|
|
@ -2225,10 +2317,6 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||
VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
|
||||
|
||||
int i = 0;
|
||||
int ideUnitNumber = !deployAsIs ? 0 : vmMo.getNextIDEDeviceNumber();
|
||||
int scsiUnitNumber = !deployAsIs ? 0 : vmMo.getNextScsiDiskDeviceNumber();
|
||||
int ideControllerKey = vmMo.getIDEDeviceControllerKey();
|
||||
int scsiControllerKey = vmMo.getScsiDeviceControllerKeyNoException();
|
||||
VirtualDeviceConfigSpec[] deviceConfigSpecArray = new VirtualDeviceConfigSpec[totalChangeDevices];
|
||||
DiskTO[] sortedDisks = sortVolumesByDeviceId(disks);
|
||||
VmwareHelper.setBasicVmConfig(vmConfigSpec, vmSpec.getCpus(), vmSpec.getMaxSpeed(), getReservedCpuMHZ(vmSpec), (int) (vmSpec.getMaxRam() / (1024 * 1024)),
|
||||
|
|
@ -2270,8 +2358,12 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||
//
|
||||
// Setup ISO device
|
||||
//
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> chosenDiskControllers = VmwareHelper.chooseDiskControllers(controllerInfo, vmMo, null, null);
|
||||
Map<String, Integer> diskControllerCurrentUnitNumbers = createDiskControllerUnitNumberMap(vmMo, chosenDiskControllers, deployAsIs);
|
||||
|
||||
// prepare systemvm patch ISO
|
||||
String ideClasspath = VirtualIDEController.class.getName();
|
||||
int ideUnitNumber = diskControllerCurrentUnitNumbers.get(ideClasspath);
|
||||
if (vmSpec.getType() != VirtualMachine.Type.User) {
|
||||
// attach ISO (for patching of system VM)
|
||||
Pair<String, Long> secStoreUrlAndId = mgr.getSecondaryStorageStoreUrlAndId(Long.parseLong(_dcId));
|
||||
|
|
@ -2290,8 +2382,9 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||
DatastoreMO secDsMo = new DatastoreMO(hyperHost.getContext(), morSecDs);
|
||||
|
||||
deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
|
||||
Pair<VirtualDevice, Boolean> isoInfo = VmwareHelper.prepareIsoDevice(vmMo,
|
||||
null, secDsMo.getMor(), true, true, ideUnitNumber++, i + 1);
|
||||
Pair<VirtualDevice, Boolean> isoInfo = VmwareHelper.prepareIsoDevice(vmMo, null, secDsMo.getMor(),
|
||||
true, true, ideUnitNumber++, i + 1);
|
||||
diskControllerCurrentUnitNumbers.replace(ideClasspath, ideUnitNumber);
|
||||
deviceConfigSpecArray[i].setDevice(isoInfo.first());
|
||||
if (isoInfo.second()) {
|
||||
if (logger.isDebugEnabled())
|
||||
|
|
@ -2309,12 +2402,14 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||
for (DiskTO vol : disks) {
|
||||
if (vol.getType() == Volume.Type.ISO) {
|
||||
configureIso(hyperHost, vmMo, vol, deviceConfigSpecArray, ideUnitNumber++, i);
|
||||
diskControllerCurrentUnitNumbers.replace(ideClasspath, ideUnitNumber);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
|
||||
Pair<VirtualDevice, Boolean> isoInfo = VmwareHelper.prepareIsoDevice(vmMo, null, null, true, true, ideUnitNumber++, i + 1);
|
||||
diskControllerCurrentUnitNumbers.replace(ideClasspath, ideUnitNumber);
|
||||
deviceConfigSpecArray[i].setDevice(isoInfo.first());
|
||||
if (isoInfo.second()) {
|
||||
if (logger.isDebugEnabled())
|
||||
|
|
@ -2331,9 +2426,6 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||
}
|
||||
}
|
||||
|
||||
int controllerKey;
|
||||
Pair<String, String> chosenDiskControllers = VmwareHelper.chooseRequiredDiskControllers(controllerInfo,vmMo, null, null);
|
||||
|
||||
//
|
||||
// Setup ROOT/DATA disk devices
|
||||
//
|
||||
|
|
@ -2345,6 +2437,7 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||
if (vol.getType() == Volume.Type.ISO) {
|
||||
if (deployAsIs) {
|
||||
configureIso(hyperHost, vmMo, vol, deviceConfigSpecArray, ideUnitNumber++, i);
|
||||
diskControllerCurrentUnitNumbers.replace(ideClasspath, ideUnitNumber);
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
|
|
@ -2360,48 +2453,23 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||
continue;
|
||||
}
|
||||
|
||||
String diskController = getDiskController(vmMo, matchingExistingDisk, vol, chosenDiskControllers, deployAsIs);
|
||||
if (DiskControllerType.getType(diskController) == DiskControllerType.ide) {
|
||||
controllerKey = vmMo.getIDEControllerKey(ideUnitNumber);
|
||||
if (vol.getType() == Volume.Type.DATADISK) {
|
||||
// Could be result of flip due to user configured setting or "osdefault" for data disks
|
||||
// Ensure maximum of 2 data volumes over IDE controller, 3 includeing root volume
|
||||
if (vmMo.getNumberOfVirtualDisks() > 3) {
|
||||
throw new CloudRuntimeException("Found more than 3 virtual disks attached to this VM [" + vmMo.getVmName() + "]. Unable to implement the disks over "
|
||||
+ diskController + " controller, as maximum number of devices supported over IDE controller is 4 including CDROM device.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (VmwareHelper.isReservedScsiDeviceNumber(scsiUnitNumber)) {
|
||||
scsiUnitNumber++;
|
||||
}
|
||||
DiskControllerMappingVO diskController = getControllerForDisk(vmMo, matchingExistingDisk, vol, chosenDiskControllers, deployAsIs);
|
||||
int unitNumber = diskControllerCurrentUnitNumbers.get(diskController.getControllerReference());
|
||||
|
||||
controllerKey = vmMo.getScsiDiskControllerKeyNoException(diskController, scsiUnitNumber);
|
||||
if (controllerKey == -1) {
|
||||
// This may happen for ROOT legacy VMs which doesn't have recommended disk controller when global configuration parameter 'vmware.root.disk.controller' is set to "osdefault"
|
||||
// Retrieve existing controller and use.
|
||||
Ternary<Integer, Integer, DiskControllerType> vmScsiControllerInfo = vmMo.getScsiControllerInfo();
|
||||
DiskControllerType existingControllerType = vmScsiControllerInfo.third();
|
||||
controllerKey = vmMo.getScsiDiskControllerKeyNoException(existingControllerType.toString(), scsiUnitNumber);
|
||||
}
|
||||
}
|
||||
if (!hasSnapshot) {
|
||||
int diskControllerNumber = unitNumber / diskController.getMaxDeviceCount();
|
||||
VirtualController diskControllerDevice = (VirtualController) vmMo.getNthDevice(diskController.getControllerReference(), diskControllerNumber);
|
||||
vmMo.validateDiskControllerIsAvailable(diskControllerDevice, diskController); // This may be unnecessary, as a validation of whether the controllers support all disks was already performed.
|
||||
int deviceNumber = unitNumber % diskController.getMaxDeviceCount();
|
||||
|
||||
deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
|
||||
|
||||
String[] diskChain = syncDiskChain(dcMo, vmMo, vol, matchingExistingDisk, volumeDsDetails.second());
|
||||
|
||||
int deviceNumber;
|
||||
if (controllerKey == vmMo.getIDEControllerKey(ideUnitNumber)) {
|
||||
deviceNumber = ideUnitNumber % VmwareHelper.MAX_ALLOWED_DEVICES_IDE_CONTROLLER;
|
||||
ideUnitNumber++;
|
||||
} else {
|
||||
deviceNumber = scsiUnitNumber % VmwareHelper.MAX_ALLOWED_DEVICES_SCSI_CONTROLLER;
|
||||
scsiUnitNumber++;
|
||||
}
|
||||
|
||||
VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData();
|
||||
Long maxIops = volumeTO.getIopsWriteRate() + volumeTO.getIopsReadRate();
|
||||
VirtualDevice device = VmwareHelper.prepareDiskDevice(vmMo, null, controllerKey, diskChain, volumeDsDetails.first(), deviceNumber, i + 1, maxIops);
|
||||
VirtualDevice device = VmwareHelper.prepareDiskDevice(vmMo, null, diskControllerDevice.getKey(), diskChain,
|
||||
volumeDsDetails.first(), deviceNumber, i + 1, maxIops);
|
||||
logger.debug(LogUtils.logGsonWithoutException("The following definitions will be used to start the VM: virtual device [%s], volume [%s].", device, volumeTO));
|
||||
|
||||
diskStoragePolicyId = volumeTO.getvSphereStoragePolicyId();
|
||||
|
|
@ -2425,11 +2493,14 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||
logger.debug("Prepare volume at new device " + _gson.toJson(device));
|
||||
|
||||
i++;
|
||||
} else {
|
||||
if (controllerKey == vmMo.getIDEControllerKey(ideUnitNumber))
|
||||
ideUnitNumber++;
|
||||
else
|
||||
scsiUnitNumber++;
|
||||
}
|
||||
|
||||
diskControllerCurrentUnitNumbers.replace(diskController.getControllerReference(), unitNumber + 1);
|
||||
if (VmwareHelper.isControllerScsi(diskController)) {
|
||||
int scsiUnitNumber = diskControllerCurrentUnitNumbers.get(diskController.getControllerReference());
|
||||
if (VmwareHelper.isReservedScsiDeviceNumber(scsiUnitNumber)) {
|
||||
diskControllerCurrentUnitNumbers.replace(diskController.getControllerReference(), scsiUnitNumber + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2673,6 +2744,38 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash-map with keys being the classpath of existing disk controllers, and values representing the next available
|
||||
* unit number for the disk controller type. This hash-map is used in the virtual machine start workflow to associate
|
||||
* the disks with their respective controller.
|
||||
* @param controllerInfo pair containing the root disk and data disk controllers, respectively.
|
||||
* @param deployAsIs if false, all values will be initialized as 0; otherwise, they will be initialized to the next available unit number for each of the controller types.
|
||||
* @throws CloudRuntimeException if the template is deploy-as-is and no disk controller for one of the required controller types is found.
|
||||
*/
|
||||
protected Map<String, Integer> createDiskControllerUnitNumberMap(VirtualMachineMO vmMo, Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo,
|
||||
boolean deployAsIs) throws Exception {
|
||||
Set<DiskControllerMappingVO> existingDiskControllers = new HashSet<>();
|
||||
existingDiskControllers.add(controllerInfo.first());
|
||||
existingDiskControllers.add(controllerInfo.second());
|
||||
existingDiskControllers.add(VmwareHelper.getDiskControllerMapping(null, VirtualIDEController.class.getName()));
|
||||
|
||||
Map<String, Integer> currentUnitNumberMap = new HashMap<>();
|
||||
for (DiskControllerMappingVO diskController : existingDiskControllers) {
|
||||
String classpath = diskController.getControllerReference();
|
||||
if (!deployAsIs) {
|
||||
currentUnitNumberMap.put(classpath, 0);
|
||||
continue;
|
||||
}
|
||||
Pair<Integer, Integer> nextAvailableControllerKeyAndUnitNumber = vmMo.getNextAvailableControllerKeyAndDeviceNumberForType(diskController);
|
||||
if (nextAvailableControllerKeyAndUnitNumber == null) {
|
||||
throw new CloudRuntimeException(String.format("Unable to find an available disk controller of the required type: [%s].",
|
||||
diskController.getName()));
|
||||
}
|
||||
currentUnitNumberMap.put(diskController.getControllerReference(), nextAvailableControllerKeyAndUnitNumber.second());
|
||||
}
|
||||
return currentUnitNumberMap;
|
||||
}
|
||||
|
||||
private Pair<ManagedObjectReference, DatastoreMO> getVolumeDatastoreDetails(DiskTO vol, HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> dataStoresDetails) throws Exception {
|
||||
boolean managed = false;
|
||||
String iScsiName = null;
|
||||
|
|
@ -2839,15 +2942,10 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||
|
||||
}
|
||||
|
||||
private void ensureDiskControllersInternal(VirtualMachineMO vmMo, Boolean systemVm,
|
||||
Pair<String, String> controllerInfo,
|
||||
DiskControllerType systemVmScsiControllerType,
|
||||
int numScsiControllerForSystemVm,
|
||||
int firstScsiControllerBusNum, boolean deployAsIs) throws Exception {
|
||||
if (systemVm) {
|
||||
ensureScsiDiskControllers(vmMo, systemVmScsiControllerType.toString(), numScsiControllerForSystemVm, firstScsiControllerBusNum);
|
||||
} else if (!deployAsIs) {
|
||||
ensureDiskControllers(vmMo, controllerInfo);
|
||||
protected void ensureDiskControllersInternal(VirtualMachineMO vmMo, Boolean systemVm, Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo,
|
||||
boolean deployAsIs) throws Exception {
|
||||
if (systemVm || !deployAsIs) {
|
||||
ensureDiskControllers(vmMo, controllerInfo, systemVm);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2871,11 +2969,11 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||
return translateGuestOsIdentifier(vmSpec.getArch(), vmSpec.getOs(), vmSpec.getPlatformEmulator()).value();
|
||||
}
|
||||
|
||||
private Pair<String, String> getControllerInfoFromVmSpec(VirtualMachineTO vmSpec) throws CloudRuntimeException {
|
||||
protected Pair<DiskControllerMappingVO, DiskControllerMappingVO> getControllerInfoFromVmSpec(VirtualMachineTO vmSpec) throws CloudRuntimeException {
|
||||
boolean isSystemVm = vmSpec.getType().isUsedBySystem();
|
||||
String rootDiskControllerDetail = vmSpec.getDetails().get(VmDetailConstants.ROOT_DISK_CONTROLLER);
|
||||
String dataDiskControllerDetail = vmSpec.getDetails().get(VmDetailConstants.DATA_DISK_CONTROLLER);
|
||||
VmwareHelper.validateDiskControllerDetails(rootDiskControllerDetail, dataDiskControllerDetail);
|
||||
return new Pair<>(rootDiskControllerDetail, dataDiskControllerDetail);
|
||||
return VmwareHelper.getDiskControllersFromVmSettings(rootDiskControllerDetail, dataDiskControllerDetail, isSystemVm);
|
||||
}
|
||||
|
||||
private String getBootModeFromVmSpec(VirtualMachineTO vmSpec, boolean deployAsIs) {
|
||||
|
|
@ -3655,23 +3753,32 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||
return getMatchingExistingDiskWithVolumeDetails(diskInfoBuilder, volume.getPath(), chainInfo, isManaged, iScsiName, datastoreUUID, hyperHost, context);
|
||||
}
|
||||
|
||||
private String getDiskController(VirtualMachineMO vmMo, VirtualMachineDiskInfo matchingExistingDisk, DiskTO vol, Pair<String, String> controllerInfo, boolean deployAsIs) throws Exception {
|
||||
DiskControllerType controllerType = DiskControllerType.none;
|
||||
/**
|
||||
* Returns the disk controller mapping that should be used for the disk. If the instance uses a deploy-as-is template
|
||||
* and the disk already exists, tries to choose based on the current bus name first, but chooses any available disk controller
|
||||
* if unable to choose a type based on the bus name; if the instance does not use a deploy-as-is template or the disk
|
||||
* does not exist, chooses based on <code>controllerInfo</code>.
|
||||
* @param controllerInfo pair containing the root disk and data disk controllers, respectively. Ignored if the instance uses a deploy-as-is template and the disk already exists.
|
||||
* @throws CloudRuntimeException if the instance uses a deploy-as-is template, but no disk controller is available.
|
||||
*/
|
||||
protected DiskControllerMappingVO getControllerForDisk(VirtualMachineMO vmMo, VirtualMachineDiskInfo matchingExistingDisk,
|
||||
DiskTO vol, Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo,
|
||||
boolean deployAsIs) throws Exception {
|
||||
if (deployAsIs && matchingExistingDisk != null) {
|
||||
String currentBusName = matchingExistingDisk.getDiskDeviceBusName();
|
||||
if (currentBusName != null) {
|
||||
logger.info("Chose disk controller based on existing information: " + currentBusName);
|
||||
if (currentBusName.startsWith("ide")) {
|
||||
controllerType = DiskControllerType.ide;
|
||||
} else if (currentBusName.startsWith("scsi")) {
|
||||
controllerType = DiskControllerType.scsi;
|
||||
Set<DiskControllerMappingVO> mappingsForExistingDiskControllers = vmMo.getMappingsForExistingDiskControllers();
|
||||
for (DiskControllerMappingVO mapping : mappingsForExistingDiskControllers) {
|
||||
if (currentBusName.startsWith(mapping.getBusName())) {
|
||||
logger.debug("Choosing disk controller [{}] for virtual machine [{}] based on current bus name [{}].", mapping.getName(), vmMo, currentBusName);
|
||||
return mapping;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controllerType == DiskControllerType.scsi || controllerType == DiskControllerType.none) {
|
||||
Ternary<Integer, Integer, DiskControllerType> vmScsiControllerInfo = vmMo.getScsiControllerInfo();
|
||||
controllerType = vmScsiControllerInfo.third();
|
||||
}
|
||||
return controllerType.toString();
|
||||
DiskControllerMappingVO existingAvailableDiskController = vmMo.getAnyExistingAvailableDiskController();
|
||||
logger.debug("Falling back to existing disk controller [{}] for virtual machine [{}] as no matching controller was found based on the current bus name [{}].",
|
||||
existingAvailableDiskController, vmMo, currentBusName);
|
||||
return existingAvailableDiskController;
|
||||
}
|
||||
|
||||
return VmwareHelper.getControllerBasedOnDiskType(controllerInfo, vol);
|
||||
|
|
@ -6979,14 +7086,6 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
|
|||
if (value != null && value.equalsIgnoreCase("true"))
|
||||
_recycleHungWorker = true;
|
||||
|
||||
value = (String) params.get("vmware.root.disk.controller");
|
||||
if (value != null && value.equalsIgnoreCase("scsi"))
|
||||
_rootDiskController = DiskControllerType.scsi;
|
||||
else if (value != null && value.equalsIgnoreCase("ide"))
|
||||
_rootDiskController = DiskControllerType.ide;
|
||||
else
|
||||
_rootDiskController = DiskControllerType.osdefault;
|
||||
|
||||
Integer intObj = (Integer) params.get("ports.per.dvportgroup");
|
||||
if (intObj != null)
|
||||
_portsPerDvPortGroup = intObj;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package com.cloud.storage.resource;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.agent.api.SecStorageVMSetupCommand;
|
||||
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
|
||||
import org.apache.cloudstack.storage.resource.SecondaryStorageResourceHandler;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
|
@ -114,6 +115,8 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe
|
|||
answer = storageSubsystemHandler.handleStorageCommands((StorageSubSystemCommand)cmd);
|
||||
} else if (cmd instanceof CreateEntityDownloadURLCommand) {
|
||||
answer = execute((CreateEntityDownloadURLCommand)cmd);
|
||||
} else if (cmd instanceof SecStorageVMSetupCommand) {
|
||||
answer = execute((SecStorageVMSetupCommand) cmd);
|
||||
} else {
|
||||
answer = _resource.defaultAction(cmd);
|
||||
}
|
||||
|
|
@ -183,6 +186,11 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe
|
|||
return _storageMgr.execute(this, cmd);
|
||||
}
|
||||
|
||||
private Answer execute(SecStorageVMSetupCommand cmd) {
|
||||
VmwareHelper.configureDiskControllerMappingsInVmwareBaseModule(cmd.getSupportedDiskControllers());
|
||||
return _resource.defaultAction(cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VmwareContext getServiceContext(Command cmd) {
|
||||
String guid = cmd.getContextParam("guid");
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import java.util.concurrent.Executors;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.cloudstack.agent.directdownload.DirectDownloadCommand;
|
||||
import org.apache.cloudstack.storage.DiskControllerMappingVO;
|
||||
import org.apache.cloudstack.storage.command.AttachAnswer;
|
||||
import org.apache.cloudstack.storage.command.AttachCommand;
|
||||
import org.apache.cloudstack.storage.command.CheckDataStoreStoragePolicyComplianceCommand;
|
||||
|
|
@ -76,7 +77,6 @@ import com.cloud.hypervisor.vmware.mo.CustomFieldConstants;
|
|||
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
|
||||
import com.cloud.hypervisor.vmware.mo.DatastoreFile;
|
||||
import com.cloud.hypervisor.vmware.mo.DatastoreMO;
|
||||
import com.cloud.hypervisor.vmware.mo.DiskControllerType;
|
||||
import com.cloud.hypervisor.vmware.mo.HostDatastoreSystemMO;
|
||||
import com.cloud.hypervisor.vmware.mo.HostMO;
|
||||
import com.cloud.hypervisor.vmware.mo.HostStorageSystemMO;
|
||||
|
|
@ -2102,18 +2102,19 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
|||
AttachAnswer answer = new AttachAnswer(disk);
|
||||
|
||||
if (isAttach) {
|
||||
String rootDiskControllerDetail = DiskControllerType.ide.toString();
|
||||
if (controllerInfo != null && StringUtils.isNotEmpty(controllerInfo.get(VmDetailConstants.ROOT_DISK_CONTROLLER))) {
|
||||
rootDiskControllerDetail = controllerInfo.get(VmDetailConstants.ROOT_DISK_CONTROLLER);
|
||||
}
|
||||
String dataDiskControllerDetail = getLegacyVmDataDiskController();
|
||||
if (controllerInfo != null && StringUtils.isNotEmpty(controllerInfo.get(VmDetailConstants.DATA_DISK_CONTROLLER))) {
|
||||
dataDiskControllerDetail = controllerInfo.get(VmDetailConstants.DATA_DISK_CONTROLLER);
|
||||
}
|
||||
|
||||
VmwareHelper.validateDiskControllerDetails(rootDiskControllerDetail, dataDiskControllerDetail);
|
||||
Pair<String, String> chosenDiskControllers = VmwareHelper.chooseRequiredDiskControllers(new Pair<>(rootDiskControllerDetail, dataDiskControllerDetail), vmMo, null, null);
|
||||
String diskController = VmwareHelper.getControllerBasedOnDiskType(chosenDiskControllers, disk);
|
||||
// Let's first find which disk controller should be used for the volume being attached.
|
||||
//
|
||||
// `controllerInfo` can not be null here. It is always defined when creating the `AttachComand` in
|
||||
// `com.cloud.storage.VolumeApiServiceImpl#sendAttachVolumeCommand`.
|
||||
//
|
||||
// If `VmDetailConstants.ROOT_DISK_CONTROLLER` or `VmDetailConstants.DATA_DISK_CONTROLLER` are not present
|
||||
// in `controllerInfo`, `com.cloud.hypervisor.vmware.util.VmwareHelper#getDiskControllersFromVmSettings`
|
||||
// will return default values.
|
||||
String rootDiskControllerDetail = controllerInfo.get(VmDetailConstants.ROOT_DISK_CONTROLLER);
|
||||
String dataDiskControllerDetail = controllerInfo.get(VmDetailConstants.DATA_DISK_CONTROLLER);
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> specifiedDiskControllers = VmwareHelper.getDiskControllersFromVmSettings(rootDiskControllerDetail, dataDiskControllerDetail, false);
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> chosenDiskControllers = VmwareHelper.chooseDiskControllers(specifiedDiskControllers, vmMo, null, null);
|
||||
DiskControllerMappingVO diskController = VmwareHelper.getControllerBasedOnDiskType(chosenDiskControllers, disk);
|
||||
|
||||
vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs, diskController, storagePolicyId, volumeTO.getIopsReadRate() + volumeTO.getIopsWriteRate());
|
||||
VirtualMachineDiskInfoBuilder diskInfoBuilder = vmMo.getDiskInfoBuilder();
|
||||
|
|
@ -3751,10 +3752,6 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
|||
return templateUuid;
|
||||
}
|
||||
|
||||
private String getLegacyVmDataDiskController() throws Exception {
|
||||
return DiskControllerType.lsilogic.toString();
|
||||
}
|
||||
|
||||
void setNfsVersion(String nfsVersion){
|
||||
this._nfsVersion = nfsVersion;
|
||||
logger.debug("VmwareProcessor instance now using NFS version: " + nfsVersion);
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd;
|
|||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.storage.dao.DiskControllerMappingDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
|
|
@ -495,6 +496,11 @@ public class VmwareDatacenterApiUnitTest {
|
|||
return Mockito.mock(VsphereStoragePolicyDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DiskControllerMappingDao diskControllerMappingDao() {
|
||||
return Mockito.mock(DiskControllerMappingDao.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public StorageManager storageManager() {
|
||||
return Mockito.mock(StorageManager.class);
|
||||
|
|
|
|||
|
|
@ -38,24 +38,40 @@ import java.util.Collections;
|
|||
import java.util.Date;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.ScaleVmAnswer;
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
import com.cloud.hypervisor.vmware.mo.DatastoreMO;
|
||||
import com.cloud.hypervisor.vmware.mo.HostDatastoreBrowserMO;
|
||||
import com.cloud.hypervisor.vmware.mo.HypervisorHostHelper;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareHelper;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.vmware.vim25.FileInfo;
|
||||
import com.vmware.vim25.HostDatastoreBrowserSearchResults;
|
||||
import com.vmware.vim25.HostDatastoreBrowserSearchSpec;
|
||||
import com.vmware.vim25.ParaVirtualSCSIController;
|
||||
import com.vmware.vim25.VirtualAHCIController;
|
||||
import com.vmware.vim25.VirtualCdrom;
|
||||
import com.vmware.vim25.VirtualDisk;
|
||||
import com.vmware.vim25.VirtualIDEController;
|
||||
import com.vmware.vim25.VirtualLsiLogicController;
|
||||
import com.vmware.vim25.VirtualNVMEController;
|
||||
import com.vmware.vim25.VirtualTPM;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.storage.DiskControllerMappingVO;
|
||||
import org.apache.cloudstack.storage.command.CopyCommand;
|
||||
import org.apache.cloudstack.storage.command.browser.ListDataStoreObjectsAnswer;
|
||||
import org.apache.cloudstack.storage.command.browser.ListDataStoreObjectsCommand;
|
||||
import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
|
||||
|
||||
import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
|
@ -144,6 +160,8 @@ public class VmwareResourceTest {
|
|||
@Mock
|
||||
VirtualMachineTO vmSpec;
|
||||
@Mock
|
||||
DiskTO diskTo;
|
||||
@Mock
|
||||
VmwareHypervisorHost hyperHost;
|
||||
@Mock
|
||||
VirtualMachineMO vmMo;
|
||||
|
|
@ -186,8 +204,11 @@ public class VmwareResourceTest {
|
|||
@Mock
|
||||
HostCapability hostCapability;
|
||||
@Mock
|
||||
VirtualMachineDiskInfo virtualMachineDiskInfo;
|
||||
@Mock
|
||||
ManagedObjectReference _morHyperHost;
|
||||
|
||||
|
||||
CopyCommand storageCmd;
|
||||
EnumMap<VmwareStorageProcessorConfigurableFields, Object> params = new EnumMap<VmwareStorageProcessorConfigurableFields,Object>(VmwareStorageProcessorConfigurableFields.class);
|
||||
|
||||
|
|
@ -232,6 +253,8 @@ public class VmwareResourceTest {
|
|||
when(context.getService()).thenReturn(vimService);
|
||||
when(vimService.queryTargetCapabilities(envRef, hostRef)).thenReturn(hostCapability);
|
||||
when(hostCapability.isNestedHVSupported()).thenReturn(true);
|
||||
|
||||
configureSupportedDiskControllersForTests();
|
||||
}
|
||||
|
||||
//Test successful scaling up the vm
|
||||
|
|
@ -838,6 +861,361 @@ public class VmwareResourceTest {
|
|||
assertEquals(Collections.singletonList(date.getTime()), answer.getLastModified());
|
||||
}
|
||||
|
||||
private void configureSupportedDiskControllersForTests() {
|
||||
DiskControllerMappingVO osdefaultMapping = new DiskControllerMappingVO();
|
||||
osdefaultMapping.setName("osdefault");
|
||||
osdefaultMapping.setControllerReference("osdefault");
|
||||
|
||||
DiskControllerMappingVO ideMapping = new DiskControllerMappingVO();
|
||||
ideMapping.setName("ide");
|
||||
ideMapping.setControllerReference(VirtualIDEController.class.getName());
|
||||
ideMapping.setBusName("ide");
|
||||
ideMapping.setMaxDeviceCount(2);
|
||||
ideMapping.setMaxControllerCount(2);
|
||||
|
||||
DiskControllerMappingVO lsilogicMapping = new DiskControllerMappingVO();
|
||||
lsilogicMapping.setName("lsilogic");
|
||||
lsilogicMapping.setControllerReference(VirtualLsiLogicController.class.getName());
|
||||
lsilogicMapping.setBusName("scsi");
|
||||
lsilogicMapping.setMaxDeviceCount(16);
|
||||
lsilogicMapping.setMaxControllerCount(4);
|
||||
|
||||
DiskControllerMappingVO pvscsiMapping = new DiskControllerMappingVO();
|
||||
pvscsiMapping.setName("pvscsi");
|
||||
pvscsiMapping.setControllerReference(ParaVirtualSCSIController.class.getName());
|
||||
pvscsiMapping.setBusName("scsi");
|
||||
pvscsiMapping.setMaxDeviceCount(16);
|
||||
pvscsiMapping.setMaxControllerCount(4);
|
||||
pvscsiMapping.setMinHardwareVersion("7");
|
||||
|
||||
DiskControllerMappingVO sataMapping = new DiskControllerMappingVO();
|
||||
sataMapping.setName("sata");
|
||||
sataMapping.setControllerReference(VirtualAHCIController.class.getName());
|
||||
sataMapping.setBusName("sata");
|
||||
sataMapping.setMaxDeviceCount(30);
|
||||
sataMapping.setMaxControllerCount(4);
|
||||
sataMapping.setMinHardwareVersion("10");
|
||||
|
||||
DiskControllerMappingVO nvmeMapping = new DiskControllerMappingVO();
|
||||
nvmeMapping.setName("nvme");
|
||||
nvmeMapping.setControllerReference(VirtualNVMEController.class.getName());
|
||||
nvmeMapping.setBusName("nvme");
|
||||
nvmeMapping.setMaxDeviceCount(15);
|
||||
nvmeMapping.setMaxControllerCount(4);
|
||||
nvmeMapping.setMinHardwareVersion("13");
|
||||
|
||||
VmwareHelper.setSupportedDiskControllers(List.of(osdefaultMapping, ideMapping, lsilogicMapping, pvscsiMapping, sataMapping, nvmeMapping));
|
||||
}
|
||||
|
||||
private Set<DiskControllerMappingVO> getRequiredDiskControllersForValidateRequiredVirtualHardwareVersionForNewDiskControllersTests() {
|
||||
DiskControllerMappingVO lsilogicMapping = VmwareHelper.getDiskControllerMapping("lsilogic", null);
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
Set<DiskControllerMappingVO> requiredDiskControllers = new HashSet<>();
|
||||
requiredDiskControllers.add(lsilogicMapping);
|
||||
requiredDiskControllers.add(nvmeMapping);
|
||||
return requiredDiskControllers;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateRequiredVirtualHardwareVersionForNewDiskControllersTestDoesNothingWhenControllerWithSupportedVirtualHardwareVersionIsRequired() throws Exception {
|
||||
Set<DiskControllerMappingVO> requiredDiskControllers = getRequiredDiskControllersForValidateRequiredVirtualHardwareVersionForNewDiskControllersTests();
|
||||
Mockito.when(vmMo.getVirtualHardwareVersion()).thenReturn(13);
|
||||
|
||||
vmwareResource.validateRequiredVirtualHardwareVersionForNewDiskControllers(vmMo, requiredDiskControllers);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void validateRequiredVirtualHardwareVersionForNewDiskControllersTestThrowsExceptionWhenControllerWithGreaterVirtualHardwareVersionIsRequired() throws Exception {
|
||||
Set<DiskControllerMappingVO> requiredDiskControllers = getRequiredDiskControllersForValidateRequiredVirtualHardwareVersionForNewDiskControllersTests();
|
||||
Mockito.when(vmMo.getVirtualHardwareVersion()).thenReturn(8);
|
||||
|
||||
vmwareResource.validateRequiredVirtualHardwareVersionForNewDiskControllers(vmMo, requiredDiskControllers);
|
||||
}
|
||||
|
||||
private void createDisksForValidateNewDiskControllersSupportExistingDisksTests(int numberOfDisks) throws Exception {
|
||||
List<VirtualDisk> virtualDisks = new ArrayList<>();
|
||||
for (int i = 0; i < numberOfDisks; i++) {
|
||||
virtualDisks.add(new VirtualDisk());
|
||||
}
|
||||
Mockito.when(vmMo.getVirtualDisks()).thenReturn(virtualDisks);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateNewDiskControllersSupportExistingDisksTestDoesNothingWhenBothControllersAreTheSameAndMaximumDevicesAreOnTheBus() throws Exception {
|
||||
DiskControllerMappingVO ideMapping = VmwareHelper.getDiskControllerMapping("ide", null);
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(ideMapping, ideMapping);
|
||||
createDisksForValidateNewDiskControllersSupportExistingDisksTests(4);
|
||||
|
||||
vmwareResource.validateNewDiskControllersSupportExistingDisks(vmMo, controllerInfo);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void validateNewDiskControllersSupportExistingDisksTestThrowsExceptionWhenBothControllersAreTheSameAndMoreThanMaximumDevicesAreOnTheBus() throws Exception {
|
||||
DiskControllerMappingVO ideMapping = VmwareHelper.getDiskControllerMapping("ide", null);
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(ideMapping, ideMapping);
|
||||
Mockito.when(vmMo.getIsoDevice()).thenReturn(new VirtualCdrom());
|
||||
createDisksForValidateNewDiskControllersSupportExistingDisksTests(4);
|
||||
|
||||
vmwareResource.validateNewDiskControllersSupportExistingDisks(vmMo, controllerInfo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateNewDiskControllersSupportExistingDisksTestDoesNothingWhenControllersAreNotTheSameAndMaximumDevicesAreOnDataDiskBus() throws Exception {
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
DiskControllerMappingVO ideMapping = VmwareHelper.getDiskControllerMapping("ide", null);
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(nvmeMapping, ideMapping);
|
||||
createDisksForValidateNewDiskControllersSupportExistingDisksTests(5);
|
||||
|
||||
vmwareResource.validateNewDiskControllersSupportExistingDisks(vmMo, controllerInfo);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void validateNewDiskControllersSupportExistingDisksTestThrowsExceptionWhenBothControllersAreNotTheSameAndMoreThanMaximumDevicesAreOnDataDiskBus() throws Exception {
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
DiskControllerMappingVO ideMapping = VmwareHelper.getDiskControllerMapping("ide", null);
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(nvmeMapping, ideMapping);
|
||||
Mockito.when(vmMo.getIsoDevice()).thenReturn(new VirtualCdrom());
|
||||
createDisksForValidateNewDiskControllersSupportExistingDisksTests(5);
|
||||
|
||||
vmwareResource.validateNewDiskControllersSupportExistingDisks(vmMo, controllerInfo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMaxSupportedDevicesInBusTestExpectedValueWhenBusIsNotScsi() {
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
|
||||
int result = vmwareResource.getMaxSupportedDevicesInBus(nvmeMapping);
|
||||
|
||||
Assert.assertEquals(nvmeMapping.getMaxControllerCount() * nvmeMapping.getMaxDeviceCount(), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMaxSupportedDevicesInBusTestExpectedValueWhenBusIsScsi() {
|
||||
DiskControllerMappingVO lsilogicMapping = VmwareHelper.getDiskControllerMapping("lsilogic", null);
|
||||
|
||||
int result = vmwareResource.getMaxSupportedDevicesInBus(lsilogicMapping);
|
||||
|
||||
Assert.assertEquals(lsilogicMapping.getMaxControllerCount() * (lsilogicMapping.getMaxDeviceCount() - 1), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void teardownAllDiskControllersTestTearsdownAllControllersWithValidMappings() throws Exception {
|
||||
vmwareResource.teardownAllDiskControllers(vmMo);
|
||||
|
||||
int numberOfConfiguredDiskControllersToTeardown = VmwareHelper.getAllSupportedDiskControllerMappingsExceptOsDefault().size() - 1;
|
||||
Mockito.verify(vmMo, Mockito.times(1)).tearDownDevices(Mockito.argThat((Class<?>[] c) -> c.length == numberOfConfiguredDiskControllersToTeardown));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createDiskControllerUnitNumberMapTestInitializesValuesAsZeroWhenTemplateIsNotDeployAsIs() throws Exception {
|
||||
DiskControllerMappingVO ideMapping = VmwareHelper.getDiskControllerMapping("ide", null);
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
DiskControllerMappingVO lsilogicMapping = VmwareHelper.getDiskControllerMapping("lsilogic", null);
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(nvmeMapping, lsilogicMapping);
|
||||
|
||||
Map<String, Integer> result = vmwareResource.createDiskControllerUnitNumberMap(vmMo, controllerInfo, false);
|
||||
|
||||
Assert.assertEquals(0, (int) result.get(ideMapping.getControllerReference()));
|
||||
Assert.assertEquals(0, (int) result.get(nvmeMapping.getControllerReference()));
|
||||
Assert.assertEquals(0, (int) result.get(lsilogicMapping.getControllerReference()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createDiskControllerUnitNumberMapTestInitializesValuesAtNextAvailableUnitNumberWhenTemplateIsNotDeployAsIs() throws Exception {
|
||||
DiskControllerMappingVO ideMapping = VmwareHelper.getDiskControllerMapping("ide", null);
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
DiskControllerMappingVO lsilogicMapping = VmwareHelper.getDiskControllerMapping("lsilogic", null);
|
||||
Mockito.doReturn(new Pair<>(100, 10)).when(vmMo).getNextAvailableControllerKeyAndDeviceNumberForType(ideMapping);
|
||||
Mockito.doReturn(new Pair<>(200, 11)).when(vmMo).getNextAvailableControllerKeyAndDeviceNumberForType(nvmeMapping);
|
||||
Mockito.doReturn(new Pair<>(300, 12)).when(vmMo).getNextAvailableControllerKeyAndDeviceNumberForType(lsilogicMapping);
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(nvmeMapping, lsilogicMapping);
|
||||
|
||||
Map<String, Integer> result = vmwareResource.createDiskControllerUnitNumberMap(vmMo, controllerInfo, true);
|
||||
|
||||
Assert.assertEquals(10, (int) result.get(ideMapping.getControllerReference()));
|
||||
Assert.assertEquals(11, (int) result.get(nvmeMapping.getControllerReference()));
|
||||
Assert.assertEquals(12, (int) result.get(lsilogicMapping.getControllerReference()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureDiskControllersInternalTestCallsEnsureDiskControllersWhenInstanceIsSystemVm() throws Exception {
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(new DiskControllerMappingVO(), new DiskControllerMappingVO());
|
||||
Mockito.doNothing().when(vmwareResource).ensureDiskControllers(Mockito.any(), Mockito.any(), Mockito.anyBoolean());
|
||||
|
||||
vmwareResource.ensureDiskControllersInternal(vmMo, true, controllerInfo, true);
|
||||
|
||||
Mockito.verify(vmwareResource, Mockito.times(1)).ensureDiskControllers(vmMo, controllerInfo, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureDiskControllersInternalTestCallsEnsureDiskControllersWhenTemplateIsNotDeployAsIs() throws Exception {
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(new DiskControllerMappingVO(), new DiskControllerMappingVO());
|
||||
Mockito.doNothing().when(vmwareResource).ensureDiskControllers(Mockito.any(), Mockito.any(), Mockito.anyBoolean());
|
||||
|
||||
vmwareResource.ensureDiskControllersInternal(vmMo, false, controllerInfo, false);
|
||||
|
||||
Mockito.verify(vmwareResource, Mockito.times(1)).ensureDiskControllers(vmMo, controllerInfo, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureDiskControllersInternalTestDoesNotCallEnsureDiskControllersWhenInstanceIsNotSystemVmAndTemplateIsDeployAsIs() throws Exception {
|
||||
vmwareResource.ensureDiskControllersInternal(vmMo, false, new Pair<>(new DiskControllerMappingVO(), new DiskControllerMappingVO()), true);
|
||||
|
||||
Mockito.verify(vmwareResource, Mockito.never()).ensureDiskControllers(Mockito.any(), Mockito.any(), Mockito.anyBoolean());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureDiskControllersTestVmIsConfiguredWhenRequiredDiskControllersDoNotExist() throws Exception {
|
||||
boolean isSystemVm = false;
|
||||
DiskControllerMappingVO osdefaultMapping = VmwareHelper.getDiskControllerMapping("osdefault", null);
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(osdefaultMapping, osdefaultMapping);
|
||||
|
||||
try (MockedStatic<VmwareHelper> vmwareHelperMock = Mockito.mockStatic(VmwareHelper.class)) {
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> chosenDiskControllers = new Pair<>(nvmeMapping, nvmeMapping);
|
||||
vmwareHelperMock.when(() -> VmwareHelper.chooseDiskControllers(controllerInfo, vmMo, null, null)).thenReturn(chosenDiskControllers);
|
||||
Set<DiskControllerMappingVO> requiredDiskControllers = new HashSet<>();
|
||||
requiredDiskControllers.add(nvmeMapping);
|
||||
vmwareHelperMock.when(() -> VmwareHelper.getRequiredDiskControllers(chosenDiskControllers, isSystemVm)).thenReturn(requiredDiskControllers);
|
||||
Mockito.doReturn(false).when(vmwareResource).vmHasRequiredControllers(vmMo, requiredDiskControllers);
|
||||
Mockito.doNothing().when(vmwareResource).validateRequiredVirtualHardwareVersionForNewDiskControllers(vmMo, requiredDiskControllers);
|
||||
Mockito.doNothing().when(vmwareResource).validateNewDiskControllersSupportExistingDisks(vmMo, chosenDiskControllers);
|
||||
Mockito.doNothing().when(vmwareResource).teardownAllDiskControllers(vmMo);
|
||||
Mockito.doReturn(true).when(vmMo).configureVm(Mockito.any(VirtualMachineConfigSpec.class));
|
||||
|
||||
vmwareResource.ensureDiskControllers(vmMo, controllerInfo, isSystemVm);
|
||||
|
||||
Mockito.verify(vmwareResource, Mockito.times(1)).vmHasRequiredControllers(vmMo, requiredDiskControllers);
|
||||
Mockito.verify(vmwareResource, Mockito.times(1)).validateRequiredVirtualHardwareVersionForNewDiskControllers(vmMo, requiredDiskControllers);
|
||||
Mockito.verify(vmwareResource, Mockito.times(1)).validateNewDiskControllersSupportExistingDisks(vmMo, chosenDiskControllers);
|
||||
Mockito.verify(vmwareResource, Mockito.times(1)).teardownAllDiskControllers(vmMo);
|
||||
vmwareHelperMock.verify(() -> VmwareHelper.addDiskControllersToVmConfigSpec(Mockito.any(), Mockito.any(), Mockito.anyBoolean()), Mockito.times(1));
|
||||
Mockito.verify(vmMo, Mockito.times(1)).configureVm(Mockito.any(VirtualMachineConfigSpec.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureDiskControllersTestVmIsNotConfiguredWhenRequiredDiskControllersExist() throws Exception {
|
||||
boolean isSystemVm = false;
|
||||
DiskControllerMappingVO osdefaultMapping = VmwareHelper.getDiskControllerMapping("osdefault", null);
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(osdefaultMapping, osdefaultMapping);
|
||||
|
||||
try (MockedStatic<VmwareHelper> vmwareHelperMock = Mockito.mockStatic(VmwareHelper.class)) {
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> chosenDiskControllers = new Pair<>(nvmeMapping, nvmeMapping);
|
||||
vmwareHelperMock.when(() -> VmwareHelper.chooseDiskControllers(controllerInfo, vmMo, null, null)).thenReturn(chosenDiskControllers);
|
||||
Set<DiskControllerMappingVO> requiredDiskControllers = new HashSet<>();
|
||||
requiredDiskControllers.add(nvmeMapping);
|
||||
vmwareHelperMock.when(() -> VmwareHelper.getRequiredDiskControllers(chosenDiskControllers, isSystemVm)).thenReturn(requiredDiskControllers);
|
||||
Mockito.doReturn(true).when(vmwareResource).vmHasRequiredControllers(vmMo, requiredDiskControllers);
|
||||
|
||||
vmwareResource.ensureDiskControllers(vmMo, controllerInfo, isSystemVm);
|
||||
|
||||
Mockito.verify(vmwareResource, Mockito.times(1)).vmHasRequiredControllers(vmMo, requiredDiskControllers);
|
||||
Mockito.verify(vmwareResource, Mockito.never()).validateRequiredVirtualHardwareVersionForNewDiskControllers(vmMo, requiredDiskControllers);
|
||||
Mockito.verify(vmwareResource, Mockito.never()).validateNewDiskControllersSupportExistingDisks(vmMo, chosenDiskControllers);
|
||||
Mockito.verify(vmwareResource, Mockito.never()).teardownAllDiskControllers(vmMo);
|
||||
vmwareHelperMock.verify(() -> VmwareHelper.addDiskControllersToVmConfigSpec(Mockito.any(), Mockito.any(), Mockito.anyBoolean()), Mockito.never());
|
||||
Mockito.verify(vmMo, Mockito.never()).configureVm(Mockito.any(VirtualMachineConfigSpec.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void vmHasRequiredControllersTestReturnsTrueWhenInstanceHasAllTheRequiredControllers() throws Exception {
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
DiskControllerMappingVO lsilogicMapping = VmwareHelper.getDiskControllerMapping("lsilogic", null);
|
||||
Set<DiskControllerMappingVO> requiredControllers = new HashSet<>();
|
||||
requiredControllers.add(nvmeMapping);
|
||||
requiredControllers.add(lsilogicMapping);
|
||||
VirtualNVMEController firstExistingController = new VirtualNVMEController();
|
||||
VirtualLsiLogicController secondExistingController = new VirtualLsiLogicController();
|
||||
Mockito.when(vmMo.getControllers()).thenReturn(List.of(firstExistingController, secondExistingController));
|
||||
|
||||
boolean result = vmwareResource.vmHasRequiredControllers(vmMo, requiredControllers);
|
||||
|
||||
Assert.assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void vmHasRequiredControllersTestReturnsFalseWhenInstanceDoesNotHaveAllTheRequiredControllers() throws Exception {
|
||||
DiskControllerMappingVO sataMapping = VmwareHelper.getDiskControllerMapping("sata", null);
|
||||
DiskControllerMappingVO pvscsiMapping = VmwareHelper.getDiskControllerMapping("pvscsi", null);
|
||||
Set<DiskControllerMappingVO> requiredControllers = new HashSet<>();
|
||||
requiredControllers.add(sataMapping);
|
||||
requiredControllers.add(pvscsiMapping);
|
||||
VirtualAHCIController firstExistingController = new VirtualAHCIController();
|
||||
VirtualLsiLogicController secondExistingController = new VirtualLsiLogicController();
|
||||
Mockito.when(vmMo.getControllers()).thenReturn(List.of(firstExistingController, secondExistingController));
|
||||
|
||||
boolean result = vmwareResource.vmHasRequiredControllers(vmMo, requiredControllers);
|
||||
|
||||
Assert.assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getControllerInfoFromVmSpecTestExpectedValues() {
|
||||
String rootDiskControllerDetail = "nvme";
|
||||
String dataDiskControllerDetail = "sata";
|
||||
Map<String, String> details = new HashMap<>();
|
||||
details.put(VmDetailConstants.ROOT_DISK_CONTROLLER, rootDiskControllerDetail);
|
||||
details.put(VmDetailConstants.DATA_DISK_CONTROLLER, dataDiskControllerDetail);
|
||||
Mockito.when(vmSpec.getDetails()).thenReturn(details);
|
||||
Mockito.when(vmSpec.getType()).thenReturn(VirtualMachine.Type.SecondaryStorageVm);
|
||||
|
||||
DiskControllerMappingVO expectedMapping = new DiskControllerMappingVO();
|
||||
expectedMapping.setControllerReference("expected");
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> expectedResult = new Pair<>(expectedMapping, expectedMapping);
|
||||
|
||||
try (MockedStatic<VmwareHelper> vmwareHelperMock = Mockito.mockStatic(VmwareHelper.class)) {
|
||||
vmwareHelperMock.when(() -> VmwareHelper.getDiskControllersFromVmSettings(rootDiskControllerDetail, dataDiskControllerDetail, true)).thenReturn(expectedResult);
|
||||
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> result = vmwareResource.getControllerInfoFromVmSpec(vmSpec);
|
||||
|
||||
Assert.assertEquals(expectedResult, result);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getControllerForDiskTestChoosesControllerFromControllerInfoWhenTemplateIsNotDeployAsIs() throws Exception {
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(new DiskControllerMappingVO(), new DiskControllerMappingVO());
|
||||
|
||||
try (MockedStatic<VmwareHelper> vmwareHelperMock = Mockito.mockStatic(VmwareHelper.class)) {
|
||||
DiskControllerMappingVO expectedResult = new DiskControllerMappingVO();
|
||||
expectedResult.setControllerReference("expected");
|
||||
vmwareHelperMock.when(() -> VmwareHelper.getControllerBasedOnDiskType(controllerInfo, diskTo)).thenReturn(expectedResult);
|
||||
|
||||
DiskControllerMappingVO result = vmwareResource.getControllerForDisk(vmMo, null, diskTo, controllerInfo, false);
|
||||
|
||||
Assert.assertEquals(expectedResult, result);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getControllerForDiskTestChoosesControllerFromCurrentBusNameWhenTemplateIsDeployAsIsAndCurrentBusNameIsValid() throws Exception {
|
||||
Mockito.when(virtualMachineDiskInfo.getDiskDeviceBusName()).thenReturn("nvme1:3");
|
||||
Mockito.when(vmMo.getMappingsForExistingDiskControllers()).thenReturn(new HashSet<>(VmwareHelper.getAllSupportedDiskControllerMappingsExceptOsDefault()));
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(new DiskControllerMappingVO(), new DiskControllerMappingVO());
|
||||
|
||||
DiskControllerMappingVO result = vmwareResource.getControllerForDisk(vmMo, virtualMachineDiskInfo, diskTo, controllerInfo, true);
|
||||
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
Assert.assertEquals(nvmeMapping, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getControllerForDiskTestChoosesAnyControllerWhenTemplateIsDeployAsIsAndBusNameIsInvalid() throws Exception {
|
||||
Mockito.when(virtualMachineDiskInfo.getDiskDeviceBusName()).thenReturn("unmapped1:3");
|
||||
Mockito.when(vmMo.getMappingsForExistingDiskControllers()).thenReturn(new HashSet<>(VmwareHelper.getAllSupportedDiskControllerMappingsExceptOsDefault()));
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(new DiskControllerMappingVO(), new DiskControllerMappingVO());
|
||||
DiskControllerMappingVO expectedResult = new DiskControllerMappingVO();
|
||||
expectedResult.setControllerReference("expected");
|
||||
Mockito.when(vmMo.getAnyExistingAvailableDiskController()).thenReturn(expectedResult);
|
||||
|
||||
DiskControllerMappingVO result = vmwareResource.getControllerForDisk(vmMo, virtualMachineDiskInfo, diskTo, controllerInfo, true);
|
||||
|
||||
Assert.assertEquals(expectedResult, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddVirtualTPMDevice() throws Exception {
|
||||
VirtualMachineMO vmMo = Mockito.mock(VirtualMachineMO.class);
|
||||
|
|
|
|||
|
|
@ -170,6 +170,8 @@ import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
|
|||
import org.apache.cloudstack.secstorage.HeuristicVO;
|
||||
import org.apache.cloudstack.secstorage.dao.SecondaryStorageHeuristicDao;
|
||||
import org.apache.cloudstack.secstorage.heuristics.Heuristic;
|
||||
import org.apache.cloudstack.storage.DiskControllerMappingVO;
|
||||
import org.apache.cloudstack.storage.dao.DiskControllerMappingDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ObjectStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ObjectStoreVO;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
|
|
@ -625,6 +627,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||
@Inject
|
||||
ManagementServerHostPeerJoinDao mshostPeerJoinDao;
|
||||
|
||||
@Inject
|
||||
private DiskControllerMappingDao diskControllerMappingDao;
|
||||
|
||||
@Inject
|
||||
private AsyncJobManager jobManager;
|
||||
|
||||
|
|
@ -5433,8 +5438,12 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||
|
||||
if (HypervisorType.VMware.equals(hypervisorType)) {
|
||||
options.put(VmDetailConstants.NIC_ADAPTER, Arrays.asList("E1000", "PCNet32", "Vmxnet2", "Vmxnet3"));
|
||||
options.put(VmDetailConstants.ROOT_DISK_CONTROLLER, Arrays.asList("osdefault", "ide", "scsi", "lsilogic", "lsisas1068", "buslogic", "pvscsi"));
|
||||
options.put(VmDetailConstants.DATA_DISK_CONTROLLER, Arrays.asList("osdefault", "ide", "scsi", "lsilogic", "lsisas1068", "buslogic", "pvscsi"));
|
||||
List<String> availableDiskControllers = diskControllerMappingDao.listForHypervisor(HypervisorType.VMware).stream()
|
||||
.map(DiskControllerMappingVO::getName)
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
options.put(VmDetailConstants.ROOT_DISK_CONTROLLER, availableDiskControllers);
|
||||
options.put(VmDetailConstants.DATA_DISK_CONTROLLER, availableDiskControllers);
|
||||
options.put(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG, Arrays.asList("true", "false"));
|
||||
options.put(VmDetailConstants.SVGA_VRAM_SIZE, Collections.emptyList());
|
||||
options.put(VmDetailConstants.RAM_RESERVATION, Collections.emptyList());
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ import org.apache.cloudstack.framework.config.ConfigKey;
|
|||
import org.apache.cloudstack.framework.config.Configurable;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.framework.security.keystore.KeystoreManager;
|
||||
import org.apache.cloudstack.storage.DiskControllerMappingVO;
|
||||
import org.apache.cloudstack.storage.dao.DiskControllerMappingDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
|
||||
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
|
||||
|
|
@ -252,6 +254,8 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
|
|||
@Inject
|
||||
VolumeDataStoreDao _volumeStoreDao;
|
||||
@Inject
|
||||
DiskControllerMappingDao diskControllerMappingDao;
|
||||
@Inject
|
||||
private ImageStoreDetailsUtil imageStoreDetailsUtil;
|
||||
@Inject
|
||||
private IndirectAgentLB indirectAgentLB;
|
||||
|
|
@ -382,6 +386,12 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
|
|||
setupCmd.setCopyPassword(copyPasswd);
|
||||
setupCmd.setCopyUserName(TemplateConstants.DEFAULT_HTTP_AUTH_USER);
|
||||
|
||||
List<DiskControllerMappingVO> mappingsInDatabase = diskControllerMappingDao.listForHypervisor(HypervisorType.VMware);
|
||||
if (!CollectionUtils.isEmpty(mappingsInDatabase)) {
|
||||
setupCmd.setSupportedDiskControllers(mappingsInDatabase);
|
||||
setupCmd.setContextParam("hypervisor", HypervisorType.VMware.toString());
|
||||
}
|
||||
|
||||
Answer answer = _agentMgr.easySend(ssAHostId, setupCmd);
|
||||
if (answer != null && answer.getResult()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
|
|
|||
|
|
@ -47,6 +47,11 @@
|
|||
<artifactId>cloud-engine-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-engine-schema</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
|
|
|
|||
|
|
@ -51,6 +51,9 @@ public class BaseMO {
|
|||
|
||||
private String _name;
|
||||
|
||||
protected BaseMO() {
|
||||
}
|
||||
|
||||
public BaseMO(VmwareContext context, ManagedObjectReference mor) {
|
||||
assert (context != null);
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import java.util.Arrays;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.storage.DiskControllerMappingVO;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
|
|
@ -403,7 +404,7 @@ public class ClusterMO extends BaseMO implements VmwareHypervisorHost {
|
|||
|
||||
@Override
|
||||
public boolean createBlankVm(String vmName, String vmInternalCSName, int cpuCount, int cpuSpeedMHz, int cpuReservedMHz, boolean limitCpuUse, int memoryMB,
|
||||
int memoryReserveMB, String guestOsIdentifier, ManagedObjectReference morDs, boolean snapshotDirToParent, Pair<String, String> controllerInfo, Boolean systemVm) throws Exception {
|
||||
int memoryReserveMB, String guestOsIdentifier, ManagedObjectReference morDs, boolean snapshotDirToParent, Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo, Boolean systemVm) throws Exception {
|
||||
|
||||
if (logger.isTraceEnabled())
|
||||
logger.trace("vCenter API trace - createBlankVm(). target MOR: " + _mor.getValue() + ", vmName: " + vmName + ", cpuCount: " + cpuCount + ", cpuSpeedMhz: " +
|
||||
|
|
|
|||
|
|
@ -17,36 +17,12 @@
|
|||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
public enum DiskControllerType {
|
||||
// These enums are used only for default values and validations.
|
||||
// To add support for a new disk controller, create a new disk controller mapping instead.
|
||||
osdefault,
|
||||
ide,
|
||||
scsi,
|
||||
osdefault,
|
||||
lsilogic,
|
||||
lsisas1068,
|
||||
buslogic,
|
||||
pvscsi,
|
||||
none;
|
||||
public static DiskControllerType getType(String diskController) {
|
||||
if (diskController == null || diskController.equalsIgnoreCase("osdefault")) {
|
||||
return DiskControllerType.osdefault;
|
||||
} else if (diskController.equalsIgnoreCase("vim.vm.device.VirtualLsiLogicSASController") || diskController.equalsIgnoreCase("VirtualLsiLogicSASController")
|
||||
|| diskController.equalsIgnoreCase(ScsiDiskControllerType.LSILOGIC_SAS_1068)
|
||||
|| diskController.equalsIgnoreCase(ScsiDiskControllerType.LSILOGIC_SAS)) {
|
||||
return DiskControllerType.lsisas1068;
|
||||
} else if (diskController.equalsIgnoreCase("vim.vm.device.VirtualLsiLogicController") || diskController.equalsIgnoreCase("VirtualLsiLogicController")
|
||||
|| diskController.equalsIgnoreCase(ScsiDiskControllerType.LSILOGIC_PARALLEL) || diskController.equalsIgnoreCase("scsi")) {
|
||||
return DiskControllerType.lsilogic;
|
||||
} else if (diskController.equalsIgnoreCase("vim.vm.device.VirtualIDEController") || diskController.equalsIgnoreCase("VirtualIDEController")
|
||||
|| diskController.equalsIgnoreCase("ide")) {
|
||||
return DiskControllerType.ide;
|
||||
} else if (diskController.equalsIgnoreCase("vim.vm.device.ParaVirtualSCSIController") || diskController.equalsIgnoreCase("ParaVirtualSCSIController")
|
||||
|| diskController.equalsIgnoreCase(ScsiDiskControllerType.VMWARE_PARAVIRTUAL)
|
||||
|| diskController.equalsIgnoreCase(ScsiDiskControllerType.VIRTUAL_SCSI)) {
|
||||
return DiskControllerType.pvscsi;
|
||||
} else if (diskController.equalsIgnoreCase("vim.vm.device.VirtualBusLogicController") || diskController.equalsIgnoreCase("VirtualBusLogicController")
|
||||
|| diskController.equalsIgnoreCase(ScsiDiskControllerType.BUSLOGIC)) {
|
||||
return DiskControllerType.buslogic;
|
||||
} else {
|
||||
return DiskControllerType.none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.cloudstack.storage.DiskControllerMappingVO;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
|
|
@ -672,7 +673,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
|||
ObjectContent[] ocs = getDatastorePropertiesOnHyperHost(new String[] {"name", "summary"});
|
||||
if (ocs != null) {
|
||||
for (ObjectContent oc : ocs) {
|
||||
DatastoreSummary dsSummary = (DatastoreSummary)VmwareHelper.getPropValue(oc, "summary");
|
||||
DatastoreSummary dsSummary = (DatastoreSummary) VmwareHelper.getPropValue(oc, "summary");
|
||||
if (dsSummary.isMultipleHostAccess() == false && dsSummary.isAccessible() && dsSummary.getType().equalsIgnoreCase("vmfs")) {
|
||||
ManagedObjectReference morDs = oc.getObj();
|
||||
String name = (String)VmwareHelper.getPropValue(oc, "name");
|
||||
|
|
@ -697,7 +698,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
|||
|
||||
@Override
|
||||
public boolean createBlankVm(String vmName, String vmInternalCSName, int cpuCount, int cpuSpeedMHz, int cpuReservedMHz, boolean limitCpuUse, int memoryMB,
|
||||
int memoryReserveMB, String guestOsIdentifier, ManagedObjectReference morDs, boolean snapshotDirToParent, Pair<String, String> controllerInfo, Boolean systemVm) throws Exception {
|
||||
int memoryReserveMB, String guestOsIdentifier, ManagedObjectReference morDs, boolean snapshotDirToParent, Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo, Boolean systemVm) throws Exception {
|
||||
|
||||
if (logger.isTraceEnabled())
|
||||
logger.trace("vCenter API trace - createBlankVm(). target MOR: " + _mor.getValue() + ", vmName: " + vmName + ", cpuCount: " + cpuCount + ", cpuSpeedMhz: " +
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import java.util.Arrays;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -40,6 +41,7 @@ import javax.xml.transform.dom.DOMSource;
|
|||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
import org.apache.cloudstack.storage.DiskControllerMappingVO;
|
||||
import org.apache.cloudstack.utils.security.ParserUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
|
@ -119,7 +121,6 @@ import com.vmware.vim25.OvfCreateImportSpecParams;
|
|||
import com.vmware.vim25.OvfCreateImportSpecResult;
|
||||
import com.vmware.vim25.OvfFile;
|
||||
import com.vmware.vim25.OvfFileItem;
|
||||
import com.vmware.vim25.ParaVirtualSCSIController;
|
||||
import com.vmware.vim25.RuntimeFaultFaultMsg;
|
||||
import com.vmware.vim25.TaskInProgressFaultMsg;
|
||||
import com.vmware.vim25.VMwareDVSConfigSpec;
|
||||
|
|
@ -127,15 +128,12 @@ import com.vmware.vim25.VMwareDVSPortSetting;
|
|||
import com.vmware.vim25.VMwareDVSPortgroupPolicy;
|
||||
import com.vmware.vim25.VMwareDVSPvlanConfigSpec;
|
||||
import com.vmware.vim25.VMwareDVSPvlanMapEntry;
|
||||
import com.vmware.vim25.VirtualBusLogicController;
|
||||
import com.vmware.vim25.VirtualController;
|
||||
import com.vmware.vim25.VirtualDevice;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpec;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
|
||||
import com.vmware.vim25.VirtualDisk;
|
||||
import com.vmware.vim25.VirtualIDEController;
|
||||
import com.vmware.vim25.VirtualLsiLogicController;
|
||||
import com.vmware.vim25.VirtualLsiLogicSASController;
|
||||
import com.vmware.vim25.VirtualMachineConfigSpec;
|
||||
import com.vmware.vim25.VirtualMachineFileInfo;
|
||||
import com.vmware.vim25.VirtualMachineGuestOsIdentifier;
|
||||
|
|
@ -1569,12 +1567,11 @@ public class HypervisorHostHelper {
|
|||
|
||||
public static boolean createBlankVm(VmwareHypervisorHost host, String vmName, String vmInternalCSName, int cpuCount, int cpuSpeedMHz, int cpuReservedMHz,
|
||||
boolean limitCpuUse, int memoryMB, int memoryReserveMB, String guestOsIdentifier, ManagedObjectReference morDs, boolean snapshotDirToParent,
|
||||
Pair<String, String> controllerInfo, Boolean systemVm) throws Exception {
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo, Boolean systemVm) throws Exception {
|
||||
|
||||
if (LOGGER.isInfoEnabled())
|
||||
LOGGER.info("Create blank VM. cpuCount: " + cpuCount + ", cpuSpeed(MHz): " + cpuSpeedMHz + ", mem(Mb): " + memoryMB);
|
||||
|
||||
VirtualDeviceConfigSpec controllerSpec = null;
|
||||
// VM config basics
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
vmConfig.setName(vmName);
|
||||
|
|
@ -1583,23 +1580,9 @@ public class HypervisorHostHelper {
|
|||
|
||||
VmwareHelper.setBasicVmConfig(vmConfig, cpuCount, cpuSpeedMHz, cpuReservedMHz, memoryMB, memoryReserveMB, guestOsIdentifier, limitCpuUse, false);
|
||||
|
||||
Pair<String, String> chosenDiskControllers = VmwareHelper.chooseRequiredDiskControllers(controllerInfo, null, host, guestOsIdentifier);
|
||||
String scsiDiskController = HypervisorHostHelper.getScsiController(chosenDiskControllers);
|
||||
// If there is requirement for a SCSI controller, ensure to create those.
|
||||
if (scsiDiskController != null) {
|
||||
int busNum = 0;
|
||||
int maxControllerCount = VmwareHelper.MAX_SCSI_CONTROLLER_COUNT;
|
||||
if (systemVm) {
|
||||
maxControllerCount = 1;
|
||||
}
|
||||
while (busNum < maxControllerCount) {
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec = getControllerSpec(DiskControllerType.getType(scsiDiskController).toString(), busNum);
|
||||
|
||||
vmConfig.getDeviceChange().add(scsiControllerSpec);
|
||||
busNum++;
|
||||
}
|
||||
}
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> chosenDiskControllers = VmwareHelper.chooseDiskControllers(controllerInfo, null, host, guestOsIdentifier);
|
||||
Set<DiskControllerMappingVO> requiredDiskControllers = VmwareHelper.getRequiredDiskControllers(chosenDiskControllers, systemVm);
|
||||
VmwareHelper.addDiskControllersToVmConfigSpec(vmConfig, requiredDiskControllers, systemVm);
|
||||
|
||||
if (guestOsIdentifier.startsWith("darwin")) { //Mac OS
|
||||
LOGGER.debug("Add USB Controller device for blank Mac OS VM " + vmName);
|
||||
|
|
@ -1698,34 +1681,6 @@ public class HypervisorHostHelper {
|
|||
return version;
|
||||
}
|
||||
|
||||
private static VirtualDeviceConfigSpec getControllerSpec(String diskController, int busNum) {
|
||||
VirtualDeviceConfigSpec controllerSpec = new VirtualDeviceConfigSpec();
|
||||
VirtualController controller = null;
|
||||
|
||||
if (diskController.equalsIgnoreCase(DiskControllerType.ide.toString())) {
|
||||
controller = new VirtualIDEController();
|
||||
} else if (DiskControllerType.pvscsi == DiskControllerType.getType(diskController)) {
|
||||
controller = new ParaVirtualSCSIController();
|
||||
} else if (DiskControllerType.lsisas1068 == DiskControllerType.getType(diskController)) {
|
||||
controller = new VirtualLsiLogicSASController();
|
||||
} else if (DiskControllerType.buslogic == DiskControllerType.getType(diskController)) {
|
||||
controller = new VirtualBusLogicController();
|
||||
} else if (DiskControllerType.lsilogic == DiskControllerType.getType(diskController)) {
|
||||
controller = new VirtualLsiLogicController();
|
||||
}
|
||||
|
||||
if (!diskController.equalsIgnoreCase(DiskControllerType.ide.toString())) {
|
||||
((VirtualSCSIController)controller).setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
}
|
||||
|
||||
controller.setBusNumber(busNum);
|
||||
controller.setKey(busNum - VmwareHelper.MAX_SCSI_CONTROLLER_COUNT);
|
||||
|
||||
controllerSpec.setDevice(controller);
|
||||
controllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
|
||||
return controllerSpec;
|
||||
}
|
||||
public static VirtualMachineMO createWorkerVM(VmwareHypervisorHost hyperHost, DatastoreMO dsMo, String vmName, String vmxFormattedHardwareVersion) throws Exception {
|
||||
|
||||
// Allow worker VM to float within cluster so that we will have better chance to
|
||||
|
|
@ -2258,35 +2213,6 @@ public class HypervisorHostHelper {
|
|||
return morHyperHost;
|
||||
}
|
||||
|
||||
public static String getScsiController(Pair<String, String> controllerInfo) {
|
||||
String rootDiskController = controllerInfo.first();
|
||||
String dataDiskController = controllerInfo.second();
|
||||
|
||||
String scsiDiskController; //If any of the controller provided is SCSI then return it's sub-type.
|
||||
if (isIdeController(rootDiskController) && isIdeController(dataDiskController)) {
|
||||
//Default controllers would exist
|
||||
return null;
|
||||
} else if (isIdeController(rootDiskController) || isIdeController(dataDiskController)) {
|
||||
// Only one of the controller types is IDE. Pick the other controller type to create controller.
|
||||
if (isIdeController(rootDiskController)) {
|
||||
scsiDiskController = dataDiskController;
|
||||
} else {
|
||||
scsiDiskController = rootDiskController;
|
||||
}
|
||||
} else if (DiskControllerType.getType(rootDiskController) != DiskControllerType.getType(dataDiskController)) {
|
||||
// Both ROOT and DATA controllers are SCSI controllers but different sub-types, then prefer ROOT controller
|
||||
scsiDiskController = rootDiskController;
|
||||
} else {
|
||||
// Both are SCSI controllers.
|
||||
scsiDiskController = rootDiskController;
|
||||
}
|
||||
return scsiDiskController;
|
||||
}
|
||||
|
||||
public static boolean isIdeController(String controller) {
|
||||
return DiskControllerType.getType(controller) == DiskControllerType.ide;
|
||||
}
|
||||
|
||||
public static void createBaseFolder(DatastoreMO dsMo, VmwareHypervisorHost hyperHost, StoragePoolType poolType) throws Exception {
|
||||
if (poolType != null && poolType == StoragePoolType.DatastoreCluster) {
|
||||
StoragepodMO storagepodMO = new StoragepodMO(hyperHost.getContext(), dsMo.getMor());
|
||||
|
|
|
|||
|
|
@ -31,7 +31,9 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
|
@ -46,6 +48,7 @@ import com.vmware.vim25.RuntimeFaultFaultMsg;
|
|||
import com.vmware.vim25.TaskInfo;
|
||||
import com.vmware.vim25.TaskInfoState;
|
||||
import com.vmware.vim25.VirtualMachineTicket;
|
||||
import org.apache.cloudstack.storage.DiskControllerMappingVO;
|
||||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
|
@ -78,11 +81,9 @@ import com.vmware.vim25.OptionValue;
|
|||
import com.vmware.vim25.OvfCreateDescriptorParams;
|
||||
import com.vmware.vim25.OvfCreateDescriptorResult;
|
||||
import com.vmware.vim25.OvfFile;
|
||||
import com.vmware.vim25.ParaVirtualSCSIController;
|
||||
import com.vmware.vim25.PropertyFilterSpec;
|
||||
import com.vmware.vim25.PropertySpec;
|
||||
import com.vmware.vim25.TraversalSpec;
|
||||
import com.vmware.vim25.VirtualBusLogicController;
|
||||
import com.vmware.vim25.VirtualCdrom;
|
||||
import com.vmware.vim25.VirtualCdromIsoBackingInfo;
|
||||
import com.vmware.vim25.VirtualCdromRemotePassthroughBackingInfo;
|
||||
|
|
@ -106,7 +107,6 @@ import com.vmware.vim25.VirtualEthernetCardDistributedVirtualPortBackingInfo;
|
|||
import com.vmware.vim25.VirtualHardwareOption;
|
||||
import com.vmware.vim25.VirtualIDEController;
|
||||
import com.vmware.vim25.VirtualLsiLogicController;
|
||||
import com.vmware.vim25.VirtualLsiLogicSASController;
|
||||
import com.vmware.vim25.VirtualMachineCloneSpec;
|
||||
import com.vmware.vim25.VirtualMachineConfigInfo;
|
||||
import com.vmware.vim25.VirtualMachineConfigOption;
|
||||
|
|
@ -146,6 +146,10 @@ public class VirtualMachineMO extends BaseMO {
|
|||
this.internalCSName = internalVMName;
|
||||
}
|
||||
|
||||
protected VirtualMachineMO() {
|
||||
super();
|
||||
}
|
||||
|
||||
public VirtualMachineMO(VmwareContext context, ManagedObjectReference morVm) {
|
||||
super(context, morVm);
|
||||
}
|
||||
|
|
@ -1370,13 +1374,11 @@ public class VirtualMachineMO extends BaseMO {
|
|||
_context.waitForTaskProgressDone(morTask);
|
||||
}
|
||||
|
||||
public void updateVmdkAdapter(String vmdkFileName, String diskController) throws Exception {
|
||||
|
||||
DiskControllerType diskControllerType = DiskControllerType.getType(diskController);
|
||||
VmdkAdapterType vmdkAdapterType = VmdkAdapterType.getAdapterType(diskControllerType);
|
||||
public void updateVmdkAdapter(String vmdkFileName, DiskControllerMappingVO diskController) throws Exception {
|
||||
VmdkAdapterType vmdkAdapterType = VmdkAdapterType.getType(diskController.getVmdkAdapterType());
|
||||
if (vmdkAdapterType == VmdkAdapterType.none) {
|
||||
String message = "Failed to attach disk due to invalid vmdk adapter type for vmdk file [" +
|
||||
vmdkFileName + "] with controller : " + diskControllerType;
|
||||
vmdkFileName + "] with controller : " + diskController.getName();
|
||||
logger.debug(message);
|
||||
throw new Exception(message);
|
||||
}
|
||||
|
|
@ -1430,45 +1432,40 @@ public class VirtualMachineMO extends BaseMO {
|
|||
attachDisk(vmdkDatastorePathChain, morDs, null, null);
|
||||
}
|
||||
|
||||
public void attachDisk(String[] vmdkDatastorePathChain, ManagedObjectReference morDs, String diskController, String vSphereStoragePolicyId) throws Exception {
|
||||
public void attachDisk(String[] vmdkDatastorePathChain, ManagedObjectReference morDs, DiskControllerMappingVO diskController, String vSphereStoragePolicyId) throws Exception {
|
||||
attachDisk(vmdkDatastorePathChain, morDs, diskController, vSphereStoragePolicyId, null);
|
||||
}
|
||||
|
||||
public void attachDisk(String[] vmdkDatastorePathChain, ManagedObjectReference morDs, String diskController, String vSphereStoragePolicyId, Long maxIops) throws Exception {
|
||||
if(logger.isTraceEnabled())
|
||||
logger.trace("vCenter API trace - attachDisk(). target MOR: " + _mor.getValue() + ", vmdkDatastorePath: "
|
||||
+ GSON.toJson(vmdkDatastorePathChain) + ", datastore: " + morDs.getValue());
|
||||
int controllerKey = 0;
|
||||
int unitNumber = 0;
|
||||
public void attachDisk(String[] vmdkDatastorePathChain, ManagedObjectReference morDs, DiskControllerMappingVO diskController, String vSphereStoragePolicyId, Long maxIops) throws Exception {
|
||||
logger.trace("vCenter API trace - attachDisk(). target MOR: {}, vmdkDatastorePath: {}, datastore: {}", _mor.getValue(),
|
||||
GSON.toJson(vmdkDatastorePathChain), morDs.getValue());
|
||||
|
||||
if (DiskControllerType.getType(diskController) == DiskControllerType.ide) {
|
||||
if (diskController == null) {
|
||||
logger.debug("Provided disk controller is null; therefore, we will choose any existing disk controller to use.");
|
||||
diskController = getAnyExistingAvailableDiskController();
|
||||
}
|
||||
|
||||
if (VirtualIDEController.class.getName().equals(diskController.getControllerReference())) {
|
||||
// IDE virtual disk cannot be added if VM is running
|
||||
if (getPowerState() == VirtualMachinePowerState.POWERED_ON) {
|
||||
throw new Exception("Adding a virtual disk over IDE controller is not supported while instance is running in VMware hypervisor. Please re-try when instance is not running.");
|
||||
}
|
||||
// Get next available unit number and controller key
|
||||
int ideDeviceCount = getNumberOfIDEDevices();
|
||||
if (ideDeviceCount >= VmwareHelper.MAX_IDE_CONTROLLER_COUNT * VmwareHelper.MAX_ALLOWED_DEVICES_IDE_CONTROLLER) {
|
||||
throw new Exception("Maximum limit of devices supported on IDE controllers [" + VmwareHelper.MAX_IDE_CONTROLLER_COUNT
|
||||
* VmwareHelper.MAX_ALLOWED_DEVICES_IDE_CONTROLLER + "] is reached.");
|
||||
}
|
||||
controllerKey = getIDEControllerKey(ideDeviceCount);
|
||||
unitNumber = getFreeUnitNumberOnIDEController(controllerKey);
|
||||
} else {
|
||||
if (StringUtils.isNotBlank(diskController)) {
|
||||
controllerKey = getScsiDiskControllerKey(diskController);
|
||||
} else {
|
||||
controllerKey = getScsiDeviceControllerKey();
|
||||
}
|
||||
unitNumber = -1;
|
||||
}
|
||||
|
||||
Pair<Integer, Integer> controllerKeyAndUnitNumber = getNextAvailableControllerKeyAndDeviceNumberForType(diskController);
|
||||
if (controllerKeyAndUnitNumber == null) {
|
||||
throw new CloudRuntimeException(String.format("Unable to find an available disk controller of the required type: [%s]. " +
|
||||
"If the disk controller being used has been changed, please restart your virtual machine so that CloudStack creates the required controllers. " +
|
||||
"Otherwise, the maximum number of disks for the bus has been reached.",
|
||||
diskController.getName()));
|
||||
}
|
||||
|
||||
synchronized (_mor.getValue().intern()) {
|
||||
VirtualDevice newDisk = VmwareHelper.prepareDiskDevice(this, null, controllerKey, vmdkDatastorePathChain, morDs, unitNumber, 1, maxIops);
|
||||
if (StringUtils.isNotBlank(diskController)) {
|
||||
String vmdkFileName = vmdkDatastorePathChain[0];
|
||||
updateVmdkAdapter(vmdkFileName, diskController);
|
||||
}
|
||||
VirtualDevice newDisk = VmwareHelper.prepareDiskDevice(this, null, controllerKeyAndUnitNumber.first(),
|
||||
vmdkDatastorePathChain, morDs, controllerKeyAndUnitNumber.second(), 1, maxIops);
|
||||
String vmdkFileName = vmdkDatastorePathChain[0];
|
||||
updateVmdkAdapter(vmdkFileName, diskController);
|
||||
|
||||
VirtualMachineConfigSpec reConfigSpec = new VirtualMachineConfigSpec();
|
||||
VirtualDeviceConfigSpec deviceConfigSpec = new VirtualDeviceConfigSpec();
|
||||
|
||||
|
|
@ -2381,97 +2378,6 @@ public class VirtualMachineMO extends BaseMO {
|
|||
return false;
|
||||
}
|
||||
|
||||
public int getPvScsiDeviceControllerKeyNoException() throws Exception {
|
||||
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
|
||||
getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
if (devices != null && devices.size() > 0) {
|
||||
for (VirtualDevice device : devices) {
|
||||
if (device instanceof ParaVirtualSCSIController) {
|
||||
return device.getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getPvScsiDeviceControllerKey() throws Exception {
|
||||
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
|
||||
getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
if (devices != null && devices.size() > 0) {
|
||||
for (VirtualDevice device : devices) {
|
||||
if (device instanceof ParaVirtualSCSIController) {
|
||||
return device.getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert (false);
|
||||
throw new Exception("VMware Paravirtual SCSI Controller Not Found");
|
||||
}
|
||||
|
||||
protected VirtualSCSIController getScsiController(DiskControllerType type) {
|
||||
switch (type) {
|
||||
case pvscsi:
|
||||
return new ParaVirtualSCSIController();
|
||||
case lsisas1068:
|
||||
return new VirtualLsiLogicSASController();
|
||||
case buslogic:
|
||||
return new VirtualBusLogicController();
|
||||
default:
|
||||
return new VirtualLsiLogicController();
|
||||
}
|
||||
}
|
||||
|
||||
public void addScsiDeviceControllers(DiskControllerType type) throws Exception {
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
int busNum = 0;
|
||||
while (busNum < VmwareHelper.MAX_SCSI_CONTROLLER_COUNT) {
|
||||
VirtualSCSIController scsiController = getScsiController(type);
|
||||
scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
scsiController.setBusNumber(busNum);
|
||||
scsiController.setKey(busNum - VmwareHelper.MAX_SCSI_CONTROLLER_COUNT);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
vmConfig.getDeviceChange().add(scsiControllerSpec);
|
||||
busNum++;
|
||||
}
|
||||
|
||||
if (configureVm(vmConfig)) {
|
||||
logger.info("Successfully added SCSI controllers.");
|
||||
} else {
|
||||
throw new Exception("Unable to add Scsi controllers to the instance " + getName());
|
||||
}
|
||||
}
|
||||
|
||||
public void ensurePvScsiDeviceController(int requiredNumScsiControllers, int availableBusNum) throws Exception {
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
|
||||
int busNum = availableBusNum;
|
||||
while (busNum < requiredNumScsiControllers) {
|
||||
ParaVirtualSCSIController scsiController = new ParaVirtualSCSIController();
|
||||
|
||||
scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
scsiController.setBusNumber(busNum);
|
||||
scsiController.setKey(busNum - VmwareHelper.MAX_SCSI_CONTROLLER_COUNT);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
|
||||
vmConfig.getDeviceChange().add(scsiControllerSpec);
|
||||
busNum++;
|
||||
}
|
||||
|
||||
if (configureVm(vmConfig)) {
|
||||
throw new Exception("Unable to add Scsi controllers to the instance " + getName());
|
||||
} else {
|
||||
logger.info("Successfully added " + requiredNumScsiControllers + " SCSI controllers.");
|
||||
}
|
||||
}
|
||||
|
||||
public String getRecommendedDiskController(String guestOsId) throws Exception {
|
||||
String recommendedController;
|
||||
GuestOsDescriptor guestOsDescriptor = getGuestOsDescriptor(guestOsId);
|
||||
|
|
@ -2479,100 +2385,6 @@ public class VirtualMachineMO extends BaseMO {
|
|||
return recommendedController;
|
||||
}
|
||||
|
||||
public boolean isPvScsiSupported() throws Exception {
|
||||
int virtualHardwareVersion;
|
||||
|
||||
virtualHardwareVersion = getVirtualHardwareVersion();
|
||||
|
||||
// Check if virtual machine is using hardware version 7 or later.
|
||||
if (virtualHardwareVersion < 7) {
|
||||
logger.error("The virtual hardware version of the Instance is " + virtualHardwareVersion
|
||||
+ ", which doesn't support PV SCSI controller type for virtual harddisks. Please upgrade this Instance's virtual hardware version to 7 or later.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Would be useful if there exists multiple sub types of SCSI controllers per VM are supported in CloudStack f
|
||||
public int getScsiDiskControllerKey(String diskController) throws Exception {
|
||||
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
if (CollectionUtils.isNotEmpty(devices)) {
|
||||
DiskControllerType diskControllerType = DiskControllerType.getType(diskController);
|
||||
for (VirtualDevice device : devices) {
|
||||
if ((diskControllerType == DiskControllerType.lsilogic || diskControllerType == DiskControllerType.scsi)
|
||||
&& device instanceof VirtualLsiLogicController && isValidScsiDiskController((VirtualLsiLogicController)device)) {
|
||||
return ((VirtualLsiLogicController)device).getKey();
|
||||
} else if ((diskControllerType == DiskControllerType.lsisas1068 || diskControllerType == DiskControllerType.scsi)
|
||||
&& device instanceof VirtualLsiLogicSASController && isValidScsiDiskController((VirtualLsiLogicSASController)device)) {
|
||||
return ((VirtualLsiLogicSASController)device).getKey();
|
||||
} else if ((diskControllerType == DiskControllerType.pvscsi || diskControllerType == DiskControllerType.scsi)
|
||||
&& device instanceof ParaVirtualSCSIController && isValidScsiDiskController((ParaVirtualSCSIController)device)) {
|
||||
return ((ParaVirtualSCSIController)device).getKey();
|
||||
} else if ((diskControllerType == DiskControllerType.buslogic || diskControllerType == DiskControllerType.scsi)
|
||||
&& device instanceof VirtualBusLogicController && isValidScsiDiskController((VirtualBusLogicController)device)) {
|
||||
return ((VirtualBusLogicController)device).getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert (false);
|
||||
throw new IllegalStateException("Scsi disk controller of type " + diskController + " not found among configured devices.");
|
||||
}
|
||||
|
||||
public int getScsiDiskControllerKeyNoException(String diskController, int scsiUnitNumber) throws Exception {
|
||||
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
if (CollectionUtils.isNotEmpty(devices) && scsiUnitNumber >= 0) {
|
||||
int requiredScsiController = scsiUnitNumber / VmwareHelper.MAX_ALLOWED_DEVICES_SCSI_CONTROLLER;
|
||||
int scsiControllerDeviceCount = 0;
|
||||
DiskControllerType diskControllerType = DiskControllerType.getType(diskController);
|
||||
for (VirtualDevice device : devices) {
|
||||
if ((diskControllerType == DiskControllerType.lsilogic || diskControllerType == DiskControllerType.scsi) && device instanceof VirtualLsiLogicController) {
|
||||
if (scsiControllerDeviceCount == requiredScsiController) {
|
||||
if (isValidScsiDiskController((VirtualLsiLogicController)device)) {
|
||||
return ((VirtualLsiLogicController)device).getKey();
|
||||
}
|
||||
break;
|
||||
}
|
||||
scsiControllerDeviceCount++;
|
||||
} else if ((diskControllerType == DiskControllerType.lsisas1068 || diskControllerType == DiskControllerType.scsi) && device instanceof VirtualLsiLogicSASController) {
|
||||
if (scsiControllerDeviceCount == requiredScsiController) {
|
||||
if (isValidScsiDiskController((VirtualLsiLogicSASController)device)) {
|
||||
return ((VirtualLsiLogicSASController)device).getKey();
|
||||
}
|
||||
break;
|
||||
}
|
||||
scsiControllerDeviceCount++;
|
||||
} else if ((diskControllerType == DiskControllerType.pvscsi || diskControllerType == DiskControllerType.scsi) && device instanceof ParaVirtualSCSIController) {
|
||||
if (scsiControllerDeviceCount == requiredScsiController) {
|
||||
if (isValidScsiDiskController((ParaVirtualSCSIController)device)) {
|
||||
return ((ParaVirtualSCSIController)device).getKey();
|
||||
}
|
||||
break;
|
||||
}
|
||||
scsiControllerDeviceCount++;
|
||||
} else if ((diskControllerType == DiskControllerType.buslogic || diskControllerType == DiskControllerType.scsi) && device instanceof VirtualBusLogicController) {
|
||||
if (scsiControllerDeviceCount == requiredScsiController) {
|
||||
if (isValidScsiDiskController((VirtualBusLogicController)device)) {
|
||||
return ((VirtualBusLogicController)device).getKey();
|
||||
}
|
||||
break;
|
||||
}
|
||||
scsiControllerDeviceCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getNextScsiDiskDeviceNumber() throws Exception {
|
||||
int scsiControllerKey = getScsiDeviceControllerKey();
|
||||
int deviceNumber = getNextDeviceNumber(scsiControllerKey);
|
||||
|
||||
return deviceNumber;
|
||||
}
|
||||
|
||||
public int getScsiDeviceControllerKey() throws Exception {
|
||||
List<VirtualDevice> devices = _context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
|
|
@ -2602,47 +2414,6 @@ public class VirtualMachineMO extends BaseMO {
|
|||
return -1;
|
||||
}
|
||||
|
||||
public void ensureLsiLogicDeviceControllers(int count, int availableBusNum) throws Exception {
|
||||
int scsiControllerKey = getLsiLogicDeviceControllerKeyNoException();
|
||||
if (scsiControllerKey < 0) {
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
|
||||
int busNum = availableBusNum;
|
||||
while (busNum < count) {
|
||||
VirtualLsiLogicController scsiController = new VirtualLsiLogicController();
|
||||
scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
scsiController.setBusNumber(busNum);
|
||||
scsiController.setKey(busNum - VmwareHelper.MAX_SCSI_CONTROLLER_COUNT);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
|
||||
vmConfig.getDeviceChange().add(scsiControllerSpec);
|
||||
busNum++;
|
||||
}
|
||||
if (configureVm(vmConfig)) {
|
||||
throw new Exception("Unable to add Lsi Logic controllers to the instance " + getName());
|
||||
} else {
|
||||
logger.info("Successfully added " + count + " LsiLogic Parallel SCSI controllers.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getLsiLogicDeviceControllerKeyNoException() throws Exception {
|
||||
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
|
||||
getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
if (devices != null && devices.size() > 0) {
|
||||
for (VirtualDevice device : devices) {
|
||||
if (device instanceof VirtualLsiLogicController) {
|
||||
return device.getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void ensureScsiDeviceController() throws Exception {
|
||||
int scsiControllerKey = getScsiDeviceControllerKeyNoException();
|
||||
if (scsiControllerKey < 0) {
|
||||
|
|
@ -2664,32 +2435,6 @@ public class VirtualMachineMO extends BaseMO {
|
|||
}
|
||||
}
|
||||
|
||||
public void ensureScsiDeviceControllers(int count, int availableBusNum) throws Exception {
|
||||
int scsiControllerKey = getScsiDeviceControllerKeyNoException();
|
||||
if (scsiControllerKey < 0) {
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
|
||||
int busNum = availableBusNum;
|
||||
while (busNum < count) {
|
||||
VirtualLsiLogicController scsiController = new VirtualLsiLogicController();
|
||||
scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
scsiController.setBusNumber(busNum);
|
||||
scsiController.setKey(busNum - VmwareHelper.MAX_SCSI_CONTROLLER_COUNT);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
|
||||
vmConfig.getDeviceChange().add(scsiControllerSpec);
|
||||
busNum++;
|
||||
}
|
||||
if (configureVm(vmConfig)) {
|
||||
throw new Exception("Unable to add Scsi controllers to the instance " + getName());
|
||||
} else {
|
||||
logger.info("Successfully added " + count + " SCSI controllers.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidScsiDiskController(VirtualSCSIController scsiDiskController) {
|
||||
if (scsiDiskController == null) {
|
||||
return false;
|
||||
|
|
@ -3003,19 +2748,24 @@ public class VirtualMachineMO extends BaseMO {
|
|||
return pathList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a virtual disk's numbering. For example, if the disk uses the second SCSI controller's third device node,
|
||||
* then "scsi1:2" will be returned.
|
||||
* @param allDevices a list containing all the instance's devices.
|
||||
* @param theDevice the virtual disk.
|
||||
* @throws Exception if the disk's controller is not found in <code>allDevices</code> or its type does not have an
|
||||
* equivalent mapping.
|
||||
*/
|
||||
public String getDeviceBusName(List<VirtualDevice> allDevices, VirtualDevice theDevice) throws Exception {
|
||||
for (VirtualDevice device : allDevices) {
|
||||
if (device.getKey() == theDevice.getControllerKey().intValue()) {
|
||||
if (device instanceof VirtualIDEController) {
|
||||
return String.format("ide%d:%d", ((VirtualIDEController)device).getBusNumber(), theDevice.getUnitNumber());
|
||||
} else if (device instanceof VirtualSCSIController) {
|
||||
return String.format("scsi%d:%d", ((VirtualSCSIController)device).getBusNumber(), theDevice.getUnitNumber());
|
||||
} else {
|
||||
throw new Exception("Device controller is not supported yet");
|
||||
}
|
||||
if (device.getKey() != theDevice.getControllerKey()) {
|
||||
continue;
|
||||
}
|
||||
DiskControllerMappingVO mapping = VmwareHelper.getDiskControllerMapping(null, device.getClass().getName());
|
||||
return String.format("%s%d:%d", mapping.getBusName(), ((VirtualController) device).getBusNumber(),
|
||||
theDevice.getUnitNumber());
|
||||
}
|
||||
throw new Exception("Unable to find device controller");
|
||||
throw new Exception("Unable to find device controller.");
|
||||
}
|
||||
|
||||
public List<VirtualDisk> getVirtualDisks() throws Exception {
|
||||
|
|
@ -3106,19 +2856,6 @@ public class VirtualMachineMO extends BaseMO {
|
|||
return deviceList.toArray(new VirtualDisk[0]);
|
||||
}
|
||||
|
||||
public VirtualDisk getDiskDeviceByBusName(List<VirtualDevice> allDevices, String busName) throws Exception {
|
||||
for (VirtualDevice device : allDevices) {
|
||||
if (device instanceof VirtualDisk) {
|
||||
VirtualDisk disk = (VirtualDisk)device;
|
||||
String diskBusName = getDeviceBusName(allDevices, disk);
|
||||
if (busName.equalsIgnoreCase(diskBusName))
|
||||
return disk;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public VirtualDisk[] getAllIndependentDiskDevice() throws Exception {
|
||||
List<VirtualDisk> independentDisks = new ArrayList<>();
|
||||
VirtualDisk[] allDisks = getAllDiskDevice();
|
||||
|
|
@ -3175,70 +2912,6 @@ public class VirtualMachineMO extends BaseMO {
|
|||
throw new Exception("IDE Controller Not Found");
|
||||
}
|
||||
|
||||
public int getIDEControllerKey(int ideUnitNumber) throws Exception {
|
||||
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
|
||||
getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
int requiredIdeController = ideUnitNumber / VmwareHelper.MAX_IDE_CONTROLLER_COUNT;
|
||||
|
||||
int ideControllerCount = 0;
|
||||
if(devices != null && !devices.isEmpty()) {
|
||||
for(VirtualDevice device : devices) {
|
||||
if(device instanceof VirtualIDEController) {
|
||||
if (ideControllerCount == requiredIdeController) {
|
||||
return ((VirtualIDEController)device).getKey();
|
||||
}
|
||||
ideControllerCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw new Exception("IDE Controller Not Found");
|
||||
}
|
||||
|
||||
public int getNumberOfIDEDevices() throws Exception {
|
||||
int ideDeviceCount = 0;
|
||||
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
|
||||
getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
if (devices != null && !devices.isEmpty()) {
|
||||
for (VirtualDevice device : devices) {
|
||||
if (device instanceof VirtualIDEController) {
|
||||
ideDeviceCount += ((VirtualIDEController)device).getDevice().size();
|
||||
}
|
||||
}
|
||||
}
|
||||
return ideDeviceCount;
|
||||
}
|
||||
|
||||
public int getFreeUnitNumberOnIDEController(int controllerKey) throws Exception {
|
||||
int freeUnitNumber = 0;
|
||||
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
|
||||
getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
int deviceCount = 0;
|
||||
int ideDeviceUnitNumber = -1;
|
||||
if (devices != null) {
|
||||
for (VirtualDevice device : devices) {
|
||||
if (device.getControllerKey() == null || device.getControllerKey() != controllerKey) {
|
||||
continue;
|
||||
}
|
||||
if (device instanceof VirtualDisk || device instanceof VirtualCdrom) {
|
||||
deviceCount++;
|
||||
ideDeviceUnitNumber = device.getUnitNumber();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (deviceCount == 1) {
|
||||
if (ideDeviceUnitNumber == 0) {
|
||||
freeUnitNumber = 1;
|
||||
} // else freeUnitNumber is already initialized to 0
|
||||
} else if (deviceCount == 2) {
|
||||
throw new Exception("IDE controller with key [" + controllerKey + "] already has 2 device attached. Cannot attach more than the limit of 2.");
|
||||
}
|
||||
return freeUnitNumber;
|
||||
}
|
||||
public int getNextIDEDeviceNumber() throws Exception {
|
||||
int controllerKey = getIDEDeviceControllerKey();
|
||||
return getNextDeviceNumber(controllerKey);
|
||||
|
|
@ -3648,135 +3321,6 @@ public class VirtualMachineMO extends BaseMO {
|
|||
}
|
||||
return guestOsSupportsMemoryHotAdd && virtualHardwareSupportsMemoryHotAdd;
|
||||
}
|
||||
public void ensureLsiLogicSasDeviceControllers(int count, int availableBusNum) throws Exception {
|
||||
int scsiControllerKey = getLsiLogicSasDeviceControllerKeyNoException();
|
||||
if (scsiControllerKey < 0) {
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
|
||||
int busNum = availableBusNum;
|
||||
while (busNum < count) {
|
||||
VirtualLsiLogicSASController scsiController = new VirtualLsiLogicSASController();
|
||||
scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
scsiController.setBusNumber(busNum);
|
||||
scsiController.setKey(busNum - VmwareHelper.MAX_SCSI_CONTROLLER_COUNT);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
|
||||
vmConfig.getDeviceChange().add(scsiControllerSpec);
|
||||
busNum++;
|
||||
}
|
||||
if (configureVm(vmConfig)) {
|
||||
throw new Exception("Unable to add Scsi controller of type LsiLogic SAS.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private int getLsiLogicSasDeviceControllerKeyNoException() throws Exception {
|
||||
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
|
||||
getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
if (devices != null && !devices.isEmpty()) {
|
||||
for (VirtualDevice device : devices) {
|
||||
if (device instanceof VirtualLsiLogicSASController) {
|
||||
return device.getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void ensureBusLogicDeviceControllers(int count, int availableBusNum) throws Exception {
|
||||
int scsiControllerKey = getBusLogicDeviceControllerKeyNoException();
|
||||
if (scsiControllerKey < 0) {
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
|
||||
int busNum = availableBusNum;
|
||||
while (busNum < count) {
|
||||
VirtualBusLogicController scsiController = new VirtualBusLogicController();
|
||||
|
||||
scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
scsiController.setBusNumber(busNum);
|
||||
scsiController.setKey(busNum - VmwareHelper.MAX_SCSI_CONTROLLER_COUNT);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
|
||||
vmConfig.getDeviceChange().add(scsiControllerSpec);
|
||||
busNum++;
|
||||
}
|
||||
|
||||
if (configureVm(vmConfig)) {
|
||||
throw new Exception("Unable to add Scsi BusLogic controllers to the instance " + getName());
|
||||
} else {
|
||||
logger.info("Successfully added " + count + " SCSI BusLogic controllers.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getBusLogicDeviceControllerKeyNoException() throws Exception {
|
||||
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
|
||||
getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
if (devices != null && !devices.isEmpty()) {
|
||||
for (VirtualDevice device : devices) {
|
||||
if (device instanceof VirtualBusLogicController) {
|
||||
return device.getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public Ternary<Integer, Integer, DiskControllerType> getScsiControllerInfo() throws Exception {
|
||||
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
|
||||
getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
int scsiControllerCount = 0;
|
||||
int busNum = -1;
|
||||
DiskControllerType controllerType = DiskControllerType.lsilogic;
|
||||
if (devices != null && !devices.isEmpty()) {
|
||||
for (VirtualDevice device : devices) {
|
||||
if (device instanceof VirtualSCSIController) {
|
||||
scsiControllerCount++;
|
||||
int deviceBus = ((VirtualSCSIController)device).getBusNumber();
|
||||
if (busNum < deviceBus) {
|
||||
busNum = deviceBus;
|
||||
}
|
||||
if (device instanceof VirtualLsiLogicController) {
|
||||
controllerType = DiskControllerType.lsilogic;
|
||||
} else if (device instanceof VirtualLsiLogicSASController) {
|
||||
controllerType = DiskControllerType.lsisas1068;
|
||||
} else if (device instanceof VirtualBusLogicController) {
|
||||
controllerType = DiskControllerType.buslogic;
|
||||
} else if (device instanceof ParaVirtualSCSIController) {
|
||||
controllerType = DiskControllerType.pvscsi;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Ternary<>(scsiControllerCount, busNum, controllerType);
|
||||
}
|
||||
|
||||
public int getNumberOfVirtualDisks() throws Exception {
|
||||
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
logger.info("Counting disk devices attached to Instance " + getVmName());
|
||||
int count = 0;
|
||||
|
||||
if (devices != null && !devices.isEmpty()) {
|
||||
for (VirtualDevice device : devices) {
|
||||
if (device instanceof VirtualDisk) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public String getExternalDiskUUID(String datastoreVolumePath) throws Exception{
|
||||
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
|
@ -3901,4 +3445,169 @@ public class VirtualMachineMO extends BaseMO {
|
|||
public String toString() {
|
||||
return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "internalCSName");
|
||||
}
|
||||
|
||||
public List<VirtualController> getControllers() throws Exception {
|
||||
List<VirtualController> controllers = new ArrayList<>();
|
||||
|
||||
List<VirtualDevice> devices = _context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
|
||||
for (VirtualDevice device : devices) {
|
||||
if (device instanceof VirtualController) {
|
||||
controllers.add((VirtualController) device);
|
||||
}
|
||||
}
|
||||
|
||||
return controllers;
|
||||
}
|
||||
|
||||
public Set<DiskControllerMappingVO> getMappingsForExistingDiskControllers() throws Exception {
|
||||
Set<DiskControllerMappingVO> mappingsForExistingControllers = new HashSet<>();
|
||||
|
||||
List<VirtualDevice> devices = _context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
|
||||
for (VirtualDevice device : devices) {
|
||||
if (!(device instanceof VirtualController)) {
|
||||
continue;
|
||||
}
|
||||
String classpath = device.getClass().getName();
|
||||
try {
|
||||
DiskControllerMappingVO mapping = VmwareHelper.getDiskControllerMapping(null, classpath);
|
||||
mappingsForExistingControllers.add(mapping);
|
||||
} catch (CloudRuntimeException e) {
|
||||
logger.debug("No disk controller mapping found for existing controller [{}]; ignoring it.", classpath);
|
||||
}
|
||||
}
|
||||
|
||||
return mappingsForExistingControllers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for a disk controller that has available device nodes, and returns its type's equivalent mapping. <br>
|
||||
* This function prioritizes choosing disk controllers different than <code>VirtualIDEController</code>. If no other
|
||||
* disk controller type is available, but a <code>VirtualIDEController</code> is, then the IDE will be chosen.
|
||||
* @throws CloudRuntimeException if no disk controller is available.
|
||||
*/
|
||||
public DiskControllerMappingVO getAnyExistingAvailableDiskController() throws Exception {
|
||||
Set<String> validDiskControllerClasspaths = VmwareHelper.getAllSupportedDiskControllerMappingsExceptOsDefault().stream()
|
||||
.map(DiskControllerMappingVO::getControllerReference)
|
||||
.collect(Collectors.toSet());
|
||||
Set<String> unavailableControllerClasspaths = new HashSet<>();
|
||||
|
||||
List<VirtualDevice> devices = _context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
|
||||
for (VirtualDevice device : devices) {
|
||||
String deviceClasspath = device.getClass().getName();
|
||||
if (VirtualIDEController.class.getName().equals(deviceClasspath)) {
|
||||
// Prioritize choosing controllers different from IDE
|
||||
continue;
|
||||
}
|
||||
if (!validDiskControllerClasspaths.contains(deviceClasspath) || unavailableControllerClasspaths.contains(deviceClasspath)) {
|
||||
continue;
|
||||
}
|
||||
DiskControllerMappingVO diskController = VmwareHelper.getDiskControllerMapping(null, deviceClasspath);
|
||||
Pair<Integer, Integer> nextAvailableControllerKeyAndUnitNumber = getNextAvailableControllerKeyAndDeviceNumberForType(diskController);
|
||||
if (nextAvailableControllerKeyAndUnitNumber != null) {
|
||||
return diskController;
|
||||
}
|
||||
unavailableControllerClasspaths.add(deviceClasspath);
|
||||
}
|
||||
|
||||
DiskControllerMappingVO ideMapping = VmwareHelper.getDiskControllerMapping(null, VirtualIDEController.class.getName());
|
||||
Pair<Integer, Integer> nextAvailableControllerKeyAndUnitNumber = getNextAvailableControllerKeyAndDeviceNumberForType(ideMapping);
|
||||
if (nextAvailableControllerKeyAndUnitNumber != null) {
|
||||
return ideMapping;
|
||||
}
|
||||
throw new CloudRuntimeException("Unable to find an available disk controller in the virtual machine.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for disk controllers matching the provided mapping, and returns a pair containing, respectively, the first
|
||||
* found available controller's key and its next available device node number. If no disk controller matching the mapping
|
||||
* is found, returns <code>null</code>.
|
||||
*/
|
||||
public Pair<Integer, Integer> getNextAvailableControllerKeyAndDeviceNumberForType(DiskControllerMappingVO mapping) throws Exception {
|
||||
List<VirtualDevice> devices = _context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
|
||||
for (VirtualDevice device : devices) {
|
||||
if (!mapping.getControllerReference().equals(device.getClass().getName())) {
|
||||
continue;
|
||||
}
|
||||
VirtualController controller = (VirtualController) device;
|
||||
if (controller.getBusNumber() >= mapping.getMaxControllerCount()) {
|
||||
continue;
|
||||
}
|
||||
int nextAvailableDeviceNumber = getNextAvailableDeviceNumberForController(controller, mapping);
|
||||
if (nextAvailableDeviceNumber >= 0) {
|
||||
return new Pair<>(controller.getKey(), nextAvailableDeviceNumber);
|
||||
}
|
||||
}
|
||||
logger.debug("No available disk controller of class [{}] found.", mapping.getControllerReference());
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next available device node number for the provided disk controller. If no node is available, returns -1.
|
||||
* @param mapping mapping that represents the provided disk controller's type.
|
||||
*/
|
||||
protected int getNextAvailableDeviceNumberForController(VirtualController diskController, DiskControllerMappingVO mapping) throws Exception {
|
||||
List<VirtualDevice> devices = _context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
Set<Integer> usedUnitNumbers = new HashSet<>();
|
||||
for (VirtualDevice device : devices) {
|
||||
if (device.getControllerKey() == null || device.getControllerKey() != diskController.getKey()) {
|
||||
continue;
|
||||
}
|
||||
if (device instanceof VirtualDisk || device instanceof VirtualCdrom) {
|
||||
usedUnitNumbers.add(device.getUnitNumber());
|
||||
}
|
||||
}
|
||||
if (VmwareHelper.isControllerScsi(mapping)) {
|
||||
usedUnitNumbers.add(7);
|
||||
}
|
||||
|
||||
int unitNumber = 0;
|
||||
while (unitNumber < mapping.getMaxDeviceCount()) {
|
||||
if (!usedUnitNumbers.contains(unitNumber)) {
|
||||
return unitNumber;
|
||||
}
|
||||
unitNumber++;
|
||||
}
|
||||
logger.debug("Disk controller [{}] does not have an available device number.", diskController.getKey());
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches all the instance's devices for devices with a class represented by <code>classpath</code>, and returns the
|
||||
* nth (specified by <code>number</code>) device found.
|
||||
* @throws CloudRuntimeException if the device is not found.
|
||||
*/
|
||||
public VirtualDevice getNthDevice(String classpath, int number) throws Exception {
|
||||
int currentNumber = 0;
|
||||
|
||||
List<VirtualDevice> devices = _context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
|
||||
for (VirtualDevice device : devices) {
|
||||
if (classpath.equals(device.getClass().getName())) {
|
||||
if (currentNumber == number) {
|
||||
return device;
|
||||
}
|
||||
currentNumber++;
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug("Unable to find a device with classpath [{}] and number [{}] in the virtual machine.", classpath, number);
|
||||
throw new CloudRuntimeException("Unable to find the required device in the virtual machine.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates (i) if the provided disk controller has a valid bus number and (ii) if it has an available device node number.
|
||||
* @param mapping mapping that represents the provided disk controller's type.
|
||||
* @throws CloudRuntimeException if it does not.
|
||||
*/
|
||||
public void validateDiskControllerIsAvailable(VirtualController diskController, DiskControllerMappingVO mapping) throws Exception {
|
||||
if (diskController.getBusNumber() >= mapping.getMaxControllerCount()) {
|
||||
logger.debug("Disk controller [{}] has an invalid bus number [{}].", diskController.getKey(), diskController.getBusNumber());
|
||||
throw new CloudRuntimeException("Virtual machine does not have an available disk controller device.");
|
||||
}
|
||||
|
||||
int nextUnconfiguredDeviceNumber = getNextAvailableDeviceNumberForController(diskController, mapping);
|
||||
if (nextUnconfiguredDeviceNumber == -1) {
|
||||
throw new CloudRuntimeException("Virtual machine does not have an available disk controller device.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,18 +22,6 @@ public enum VmdkAdapterType {
|
|||
buslogic,
|
||||
none;
|
||||
|
||||
public static VmdkAdapterType getAdapterType(DiskControllerType diskControllerType) {
|
||||
if (diskControllerType == DiskControllerType.ide) {
|
||||
return VmdkAdapterType.ide;
|
||||
} else if (diskControllerType == DiskControllerType.buslogic) {
|
||||
return VmdkAdapterType.buslogic;
|
||||
} else if (diskControllerType == DiskControllerType.lsilogic || diskControllerType == DiskControllerType.pvscsi || diskControllerType == DiskControllerType.lsisas1068) {
|
||||
return VmdkAdapterType.lsilogic;
|
||||
} else {
|
||||
return VmdkAdapterType.none;
|
||||
}
|
||||
}
|
||||
|
||||
public static VmdkAdapterType getType(String vmdkAdapterType) {
|
||||
if (vmdkAdapterType == null)
|
||||
return VmdkAdapterType.none;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import com.vmware.vim25.VirtualMachineConfigSpec;
|
|||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.cloud.utils.Pair;
|
||||
import org.apache.cloudstack.storage.DiskControllerMappingVO;
|
||||
|
||||
/**
|
||||
* Interface to consolidate ESX(i) hosts and HA/FT clusters into a common interface used by CloudStack Hypervisor resources
|
||||
|
|
@ -64,7 +65,7 @@ public interface VmwareHypervisorHost {
|
|||
|
||||
boolean createBlankVm(String vmName, String vmInternalCSName, int cpuCount, int cpuSpeedMHz, int cpuReservedMHz, boolean limitCpuUse, int memoryMB,
|
||||
int memoryReserveMB, String guestOsIdentifier, ManagedObjectReference morDs, boolean snapshotDirToParent,
|
||||
Pair<String, String> controllerInfo, Boolean systemVm) throws Exception;
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo, Boolean systemVm) throws Exception;
|
||||
|
||||
void importVmFromOVF(String ovfFilePath, String vmName, DatastoreMO dsMo, String diskOption, String configurationId) throws Exception;
|
||||
|
||||
|
|
|
|||
|
|
@ -31,9 +31,12 @@ import java.util.Comparator;
|
|||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.xml.datatype.DatatypeConfigurationException;
|
||||
|
|
@ -56,20 +59,28 @@ import com.vmware.vim25.GuestInfo;
|
|||
import com.vmware.vim25.GuestNicInfo;
|
||||
import com.vmware.vim25.HostPortGroupSpec;
|
||||
import com.vmware.vim25.NasDatastoreInfo;
|
||||
import com.vmware.vim25.ParaVirtualSCSIController;
|
||||
import com.vmware.vim25.VMwareDVSPortSetting;
|
||||
import com.vmware.vim25.VirtualController;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpec;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
|
||||
import com.vmware.vim25.VirtualDeviceFileBackingInfo;
|
||||
import com.vmware.vim25.VirtualIDEController;
|
||||
import com.vmware.vim25.VirtualLsiLogicController;
|
||||
import com.vmware.vim25.VirtualMachineBootOptions;
|
||||
import com.vmware.vim25.VirtualMachineConfigInfo;
|
||||
import com.vmware.vim25.VirtualMachineConfigSummary;
|
||||
import com.vmware.vim25.VirtualMachineGuestOsIdentifier;
|
||||
import com.vmware.vim25.VirtualMachineToolsStatus;
|
||||
import com.vmware.vim25.VirtualSCSIController;
|
||||
import com.vmware.vim25.VirtualSCSISharing;
|
||||
import com.vmware.vim25.VmwareDistributedVirtualSwitchPvlanSpec;
|
||||
import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec;
|
||||
import org.apache.cloudstack.storage.DiskControllerMappingVO;
|
||||
import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo;
|
||||
import org.apache.cloudstack.vm.UnmanagedInstanceTO;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
|
@ -126,17 +137,20 @@ public class VmwareHelper {
|
|||
protected static Logger LOGGER = LogManager.getLogger(VmwareHelper.class);
|
||||
|
||||
public static final int MAX_SCSI_CONTROLLER_COUNT = 4;
|
||||
public static final int MAX_IDE_CONTROLLER_COUNT = 2;
|
||||
public static final int MAX_ALLOWED_DEVICES_IDE_CONTROLLER = 2;
|
||||
public static final int MAX_ALLOWED_DEVICES_SCSI_CONTROLLER = 16;
|
||||
public static final int MAX_SUPPORTED_DEVICES_SCSI_CONTROLLER = MAX_ALLOWED_DEVICES_SCSI_CONTROLLER - 1; // One device node is unavailable for hard disks or SCSI devices
|
||||
public static final int MAX_USABLE_SCSI_CONTROLLERS = 2;
|
||||
public static final String MIN_VERSION_UEFI_LEGACY = "5.5";
|
||||
public static final String MIN_VERSION_VMFS6 = "6.5";
|
||||
|
||||
private static List<DiskControllerMappingVO> supportedDiskControllers;
|
||||
|
||||
public static void setSupportedDiskControllers(List<DiskControllerMappingVO> controllers) {
|
||||
supportedDiskControllers = controllers;
|
||||
}
|
||||
|
||||
public static boolean isReservedScsiDeviceNumber(int deviceNumber) {
|
||||
// The SCSI controller is assigned to virtual device node (z:7), so that device node is unavailable for hard disks or SCSI devices.
|
||||
return (deviceNumber % VmwareHelper.MAX_ALLOWED_DEVICES_SCSI_CONTROLLER) == 7;
|
||||
return (deviceNumber % MAX_ALLOWED_DEVICES_SCSI_CONTROLLER) == 7;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
|
@ -748,13 +762,11 @@ public class VmwareHelper {
|
|||
}
|
||||
|
||||
public static String getRecommendedDiskControllerFromDescriptor(GuestOsDescriptor guestOsDescriptor) throws Exception {
|
||||
String recommendedController;
|
||||
|
||||
recommendedController = guestOsDescriptor.getRecommendedDiskController();
|
||||
String recommendedController = guestOsDescriptor.getRecommendedDiskController();
|
||||
|
||||
// By-pass auto detected PVSCSI controller to use LsiLogic Parallel instead
|
||||
if (DiskControllerType.getType(recommendedController) == DiskControllerType.pvscsi) {
|
||||
recommendedController = DiskControllerType.lsilogic.toString();
|
||||
if (ParaVirtualSCSIController.class.getSimpleName().equals(recommendedController)) {
|
||||
return VirtualLsiLogicController.class.getSimpleName();
|
||||
}
|
||||
|
||||
return recommendedController;
|
||||
|
|
@ -771,8 +783,18 @@ public class VmwareHelper {
|
|||
return name;
|
||||
}
|
||||
|
||||
public static boolean isControllerOsRecommended(String dataDiskController) {
|
||||
return DiskControllerType.getType(dataDiskController) == DiskControllerType.osdefault;
|
||||
/**
|
||||
* Returns true if the provided mapping's name is "osdefault".
|
||||
*/
|
||||
public static boolean isControllerOsRecommended(DiskControllerMappingVO mapping) {
|
||||
return DiskControllerType.osdefault.toString().equals(mapping.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the provided mapping's bus name is "scsi".
|
||||
*/
|
||||
public static boolean isControllerScsi(DiskControllerMappingVO mapping) {
|
||||
return DiskControllerType.scsi.toString().equals(mapping.getBusName());
|
||||
}
|
||||
|
||||
public static XMLGregorianCalendar getXMLGregorianCalendar(final Date date, final int offsetSeconds) throws DatatypeConfigurationException {
|
||||
|
|
@ -892,18 +914,18 @@ public class VmwareHelper {
|
|||
instanceDisk.setChainInfo(GsonHelper.getGsonLogger().toJson(diskInfo));
|
||||
}
|
||||
for (VirtualDevice device : vmMo.getAllDeviceList()) {
|
||||
if (diskDevice.getControllerKey() == device.getKey()) {
|
||||
if (device instanceof VirtualIDEController) {
|
||||
instanceDisk.setController(DiskControllerType.getType(device.getClass().getSimpleName()).toString());
|
||||
instanceDisk.setControllerUnit(((VirtualIDEController) device).getBusNumber());
|
||||
} else if (device instanceof VirtualSCSIController) {
|
||||
instanceDisk.setController(DiskControllerType.getType(device.getClass().getSimpleName()).toString());
|
||||
instanceDisk.setControllerUnit(((VirtualSCSIController) device).getBusNumber());
|
||||
} else {
|
||||
instanceDisk.setController(DiskControllerType.none.toString());
|
||||
}
|
||||
break;
|
||||
if (diskDevice.getControllerKey() != device.getKey()) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
DiskControllerMappingVO diskController = VmwareHelper.getDiskControllerMapping(null, device.getClass().getName());
|
||||
instanceDisk.setController(diskController.getName());
|
||||
instanceDisk.setControllerUnit(((VirtualController) device).getBusNumber());
|
||||
} catch (CloudRuntimeException e) {
|
||||
LOGGER.debug("Unable to find a disk controller mapping for class [{}]; defaulting disk controller to 'none'.", device.getClass().getName());
|
||||
instanceDisk.setController(DiskControllerType.none.toString());
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (disk.getBacking() instanceof VirtualDeviceFileBackingInfo) {
|
||||
VirtualDeviceFileBackingInfo diskBacking = (VirtualDeviceFileBackingInfo) disk.getBacking();
|
||||
|
|
@ -1083,45 +1105,127 @@ public class VmwareHelper {
|
|||
}
|
||||
|
||||
/**
|
||||
* Validates an instance's <code>rootDiskController</code> and <code>dataDiskController</code> details. Throws a
|
||||
* <code>CloudRuntimeException</code> if they are invalid.
|
||||
* Returns a disk controller mapping that has the provided name or the provided controller reference.
|
||||
* @throws CloudRuntimeException if there is no configured disk controller matching the provided params.
|
||||
*/
|
||||
public static void validateDiskControllerDetails(String rootDiskControllerDetail, String dataDiskControllerDetail) {
|
||||
rootDiskControllerDetail = DiskControllerType.getType(rootDiskControllerDetail).toString();
|
||||
if (DiskControllerType.getType(rootDiskControllerDetail) == DiskControllerType.none) {
|
||||
throw new CloudRuntimeException(String.format("[%s] is not a valid root disk controller", rootDiskControllerDetail));
|
||||
public static DiskControllerMappingVO getDiskControllerMapping(String name, String controllerReference) {
|
||||
for (DiskControllerMappingVO mapping : getAllSupportedDiskControllerMappings()) {
|
||||
if (mapping.getName().equals(name) || mapping.getControllerReference().equals(controllerReference)) {
|
||||
return mapping;
|
||||
}
|
||||
}
|
||||
dataDiskControllerDetail = DiskControllerType.getType(dataDiskControllerDetail).toString();
|
||||
if (DiskControllerType.getType(dataDiskControllerDetail) == DiskControllerType.none) {
|
||||
throw new CloudRuntimeException(String.format("[%s] is not a valid data disk controller", dataDiskControllerDetail));
|
||||
LOGGER.debug("No corresponding disk controller mapping found for name [{}] and controller reference [{}].", name, controllerReference);
|
||||
throw new CloudRuntimeException("Specified disk controller is invalid.");
|
||||
}
|
||||
|
||||
public static List<DiskControllerMappingVO> getAllSupportedDiskControllerMappings() {
|
||||
return supportedDiskControllers;
|
||||
}
|
||||
|
||||
public static List<DiskControllerMappingVO> getAllSupportedDiskControllerMappingsExceptOsDefault() {
|
||||
return getAllSupportedDiskControllerMappings().stream()
|
||||
.filter(c -> !isControllerOsRecommended(c))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set containing the disk controllers an instance should have based on the provided params.
|
||||
* @param controllerInfo pair containing the root disk and data disk controllers, respectively.
|
||||
* @param isSystemVm if true, only the root disk controller is required; otherwise, both controllers are required.
|
||||
*/
|
||||
public static Set<DiskControllerMappingVO> getRequiredDiskControllers(Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo,
|
||||
boolean isSystemVm) {
|
||||
Set<DiskControllerMappingVO> requiredDiskControllers = new HashSet<>();
|
||||
requiredDiskControllers.add(controllerInfo.first());
|
||||
if (!isSystemVm) {
|
||||
requiredDiskControllers.add(controllerInfo.second());
|
||||
}
|
||||
return requiredDiskControllers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the provided <code>VirtualMachineConfigSpec</code> to create the disk controllers contained in <code>requiredDiskControllers</code>.
|
||||
* @param isSystemVm if true, only one disk controller of each type will be created; otherwise, the maximum amount of each controller will be created.
|
||||
* @throws Exception if a disk controller mapping has an invalid controller reference.
|
||||
*/
|
||||
public static void addDiskControllersToVmConfigSpec(VirtualMachineConfigSpec vmConfigSpec, Set<DiskControllerMappingVO> requiredDiskControllers,
|
||||
boolean isSystemVm) throws Exception {
|
||||
int currentKey = -1;
|
||||
|
||||
for (DiskControllerMappingVO diskController : requiredDiskControllers) {
|
||||
Class<?> controllerClass = Class.forName(diskController.getControllerReference());
|
||||
if (controllerClass == VirtualIDEController.class) {
|
||||
continue;
|
||||
}
|
||||
for (int bus = 0; bus < diskController.getMaxControllerCount(); bus++) {
|
||||
VirtualController controller = (VirtualController) controllerClass.newInstance();
|
||||
controller.setBusNumber(bus);
|
||||
controller.setKey(currentKey);
|
||||
currentKey--;
|
||||
|
||||
if (controller instanceof VirtualSCSIController) {
|
||||
((VirtualSCSIController) controller).setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
}
|
||||
|
||||
VirtualDeviceConfigSpec controllerConfigSpec = new VirtualDeviceConfigSpec();
|
||||
controllerConfigSpec.setDevice(controller);
|
||||
controllerConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
vmConfigSpec.getDeviceChange().add(controllerConfigSpec);
|
||||
|
||||
if (isSystemVm) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on an instance's <code>rootDiskController</code> and <code>dataDiskController</code> details, returns a pair
|
||||
* containing the disk controllers that should be used for root disk and the data disks, respectively.
|
||||
*
|
||||
* @param controllerInfo pair containing the root disk and data disk controllers, respectively.
|
||||
* @param vmMo virtual machine to derive the recommended disk controllers from. If not null, <code>host</code> and <code>guestOsIdentifier</code> will be ignored.
|
||||
* @param host host to derive the recommended disk controllers from. Must be provided with <code>guestOsIdentifier</code>.
|
||||
* @param guestOsIdentifier used to derive the recommended disk controllers from the host.
|
||||
* containing the disk controller mappings that should be used for root disk and the data disks, respectively.
|
||||
* @param isSystemVm if true, the root disk controller detail will be ignored, and the chosen root disk controller will be <code>lsilogic</code>.
|
||||
*/
|
||||
public static Pair<String, String> chooseRequiredDiskControllers(Pair<String, String> controllerInfo, VirtualMachineMO vmMo,
|
||||
VmwareHypervisorHost host, String guestOsIdentifier) throws Exception {
|
||||
String recommendedDiskControllerClassName = vmMo != null ? vmMo.getRecommendedDiskController(null) : host.getRecommendedDiskController(guestOsIdentifier);
|
||||
String recommendedDiskController = DiskControllerType.getType(recommendedDiskControllerClassName).toString();
|
||||
public static Pair<DiskControllerMappingVO, DiskControllerMappingVO> getDiskControllersFromVmSettings(String rootDiskControllerDetail,
|
||||
String dataDiskControllerDetail,
|
||||
boolean isSystemVm) {
|
||||
String updatedRootDiskControllerDetail = isSystemVm ? DiskControllerType.lsilogic.toString() : ObjectUtils.defaultIfNull(rootDiskControllerDetail, DiskControllerType.osdefault.toString());
|
||||
String updatedDataDiskControllerDetail = ObjectUtils.defaultIfNull(dataDiskControllerDetail, updatedRootDiskControllerDetail);
|
||||
|
||||
String convertedRootDiskController = controllerInfo.first();
|
||||
DiskControllerMappingVO specifiedRootDiskController = getDiskControllerMapping(updatedRootDiskControllerDetail, null);
|
||||
DiskControllerMappingVO specifiedDataDiskController = getDiskControllerMapping(updatedDataDiskControllerDetail, null);
|
||||
|
||||
return new Pair<>(specifiedRootDiskController, specifiedDataDiskController);
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on an instance's <code>rootDiskController</code> and <code>dataDiskController</code> details, returns a pair
|
||||
* containing the disk controllers that should be used for root disk and the data disks, respectively.
|
||||
* @param controllerInfo pair containing the root disk and data disk controllers, respectively.
|
||||
* @param vmMo virtual machine to derive the recommended disk controllers from. If not null, <code>host</code> and <code>guestOsIdentifier</code> will be ignored.
|
||||
* @param host host to derive the recommended disk controllers from. Must be provided with <code>guestOsIdentifier</code>.
|
||||
* @param guestOsIdentifier used to derive the recommended disk controllers from the host.
|
||||
* @throws Exception if no disk controller mapping matching the recommended disk controller exists.
|
||||
*/
|
||||
public static Pair<DiskControllerMappingVO, DiskControllerMappingVO> chooseDiskControllers(Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo,
|
||||
VirtualMachineMO vmMo,
|
||||
VmwareHypervisorHost host,
|
||||
String guestOsIdentifier) throws Exception {
|
||||
String recommendedDiskControllerClassName = vmMo != null ? vmMo.getRecommendedDiskController(null) : host.getRecommendedDiskController(guestOsIdentifier);
|
||||
DiskControllerMappingVO recommendedDiskController = getAllSupportedDiskControllerMappingsExceptOsDefault().stream()
|
||||
.filter(c -> c.getControllerReference().contains(recommendedDiskControllerClassName))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new CloudRuntimeException("Recommended disk controller is not mapped."));
|
||||
|
||||
DiskControllerMappingVO convertedRootDiskController = controllerInfo.first();
|
||||
if (isControllerOsRecommended(convertedRootDiskController)) {
|
||||
convertedRootDiskController = recommendedDiskController;
|
||||
}
|
||||
|
||||
String convertedDataDiskController = controllerInfo.second();
|
||||
DiskControllerMappingVO convertedDataDiskController = controllerInfo.second();
|
||||
if (isControllerOsRecommended(convertedDataDiskController)) {
|
||||
convertedDataDiskController = recommendedDiskController;
|
||||
}
|
||||
|
||||
if (diskControllersShareTheSameBusType(convertedRootDiskController, convertedDataDiskController)) {
|
||||
if (convertedRootDiskController.getBusName().equals(convertedDataDiskController.getBusName())) {
|
||||
LOGGER.debug("Root and data disk controllers share the same bus type; therefore, we will only use the controllers specified for the root disk.");
|
||||
return new Pair<>(convertedRootDiskController, convertedRootDiskController);
|
||||
}
|
||||
|
|
@ -1129,28 +1233,40 @@ public class VmwareHelper {
|
|||
return new Pair<>(convertedRootDiskController, convertedDataDiskController);
|
||||
}
|
||||
|
||||
protected static boolean diskControllersShareTheSameBusType(String rootDiskController, String dataDiskController) {
|
||||
DiskControllerType rootDiskControllerType = DiskControllerType.getType(rootDiskController);
|
||||
DiskControllerType dataDiskControllerType = DiskControllerType.getType(dataDiskController);
|
||||
if (rootDiskControllerType.equals(dataDiskControllerType)) {
|
||||
return true;
|
||||
}
|
||||
List<DiskControllerType> scsiDiskControllers = List.of(DiskControllerType.scsi, DiskControllerType.lsilogic, DiskControllerType.lsisas1068,
|
||||
DiskControllerType.buslogic ,DiskControllerType.pvscsi);
|
||||
return scsiDiskControllers.contains(rootDiskControllerType) && scsiDiskControllers.contains(dataDiskControllerType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies whether the disk is a root or data disk, and returns the controller from the provided pair that should
|
||||
* be used for the disk.
|
||||
* @param controllerInfo pair containing the root disk and data disk controllers, respectively.
|
||||
*/
|
||||
public static String getControllerBasedOnDiskType(Pair<String, String> controllerInfo, DiskTO disk) {
|
||||
public static DiskControllerMappingVO getControllerBasedOnDiskType(Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo,
|
||||
DiskTO disk) {
|
||||
if (disk.getType() == Volume.Type.ROOT || disk.getDiskSeq() == 0) {
|
||||
LOGGER.debug(String.format("Choosing disk controller [%s] for the root disk.", controllerInfo.first()));
|
||||
LOGGER.debug("Choosing disk controller [{}] for the root disk.", controllerInfo.first());
|
||||
return controllerInfo.first();
|
||||
}
|
||||
LOGGER.debug(String.format("Choosing disk controller [%s] for the data disks.", controllerInfo.second()));
|
||||
LOGGER.debug("Choosing disk controller [{}] for the data disks.", controllerInfo.second());
|
||||
return controllerInfo.second();
|
||||
}
|
||||
|
||||
public static void configureDiskControllerMappingsInVmwareBaseModule(List<DiskControllerMappingVO> mappings) {
|
||||
List<DiskControllerMappingVO> validMappings = new ArrayList<>();
|
||||
|
||||
for (DiskControllerMappingVO mapping : mappings) {
|
||||
try {
|
||||
if (!DiskControllerType.osdefault.toString().equals(mapping.getName())) {
|
||||
Class.forName(mapping.getControllerReference());
|
||||
}
|
||||
LOGGER.debug("Adding disk controller mapping with name [{}] and controller reference [{}] to the list of available disk controllers.",
|
||||
mapping.getName(), mapping.getControllerReference());
|
||||
validMappings.add(mapping);
|
||||
} catch (ClassNotFoundException e) {
|
||||
LOGGER.debug("Disk controller mapping with name [{}] and controller reference [{}] is invalid; ignoring it.",
|
||||
mapping.getName(), mapping.getControllerReference());
|
||||
}
|
||||
}
|
||||
|
||||
setSupportedDiskControllers(validMappings);
|
||||
LOGGER.info("Configured the available disk controller mappings on the 'vmware-base' module. To add support for a new controller, " +
|
||||
"it is necessary to restart the management servers.");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,10 +19,19 @@ package com.cloud.hypervisor.vmware.mo;
|
|||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareClient;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareHelper;
|
||||
import com.vmware.vim25.VirtualCdrom;
|
||||
import com.vmware.vim25.VirtualDisk;
|
||||
import com.vmware.vim25.VirtualE1000;
|
||||
import com.vmware.vim25.VirtualIDEController;
|
||||
import com.vmware.vim25.VirtualLsiLogicController;
|
||||
import com.vmware.vim25.VirtualNVMEController;
|
||||
import org.apache.cloudstack.storage.DiskControllerMappingVO;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.VirtualController;
|
||||
import com.vmware.vim25.VirtualDevice;
|
||||
import com.vmware.vim25.VirtualLsiLogicController;
|
||||
import com.vmware.vim25.VirtualLsiLogicSASController;
|
||||
import com.vmware.vim25.VirtualSCSIController;
|
||||
import com.vmware.vim25.VirtualSCSISharing;
|
||||
|
|
@ -34,11 +43,14 @@ import org.junit.BeforeClass;
|
|||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
|
|
@ -53,6 +65,10 @@ public class VirtualMachineMOTest {
|
|||
VmwareClient client;
|
||||
@Mock
|
||||
ManagedObjectReference mor;
|
||||
@Mock
|
||||
VirtualController virtualControllerMock;
|
||||
@Spy
|
||||
VirtualMachineMO vmMoSpy;
|
||||
|
||||
VirtualMachineMO vmMo;
|
||||
|
||||
|
|
@ -81,6 +97,40 @@ public class VirtualMachineMOTest {
|
|||
closeable = MockitoAnnotations.openMocks(this);
|
||||
vmMo = new VirtualMachineMO(context, mor);
|
||||
when(context.getVimClient()).thenReturn(client);
|
||||
|
||||
configureSupportedDiskControllersForTests();
|
||||
vmMoSpy._context = context;
|
||||
vmMoSpy._mor = mor;
|
||||
}
|
||||
|
||||
private void configureSupportedDiskControllersForTests() {
|
||||
DiskControllerMappingVO osdefaultMapping = new DiskControllerMappingVO();
|
||||
osdefaultMapping.setName("osdefault");
|
||||
osdefaultMapping.setControllerReference("osdefault");
|
||||
|
||||
DiskControllerMappingVO ideMapping = new DiskControllerMappingVO();
|
||||
ideMapping.setName("ide");
|
||||
ideMapping.setControllerReference(VirtualIDEController.class.getName());
|
||||
ideMapping.setBusName("ide");
|
||||
ideMapping.setMaxDeviceCount(2);
|
||||
ideMapping.setMaxControllerCount(2);
|
||||
|
||||
DiskControllerMappingVO lsilogicMapping = new DiskControllerMappingVO();
|
||||
lsilogicMapping.setName("lsilogic");
|
||||
lsilogicMapping.setControllerReference(VirtualLsiLogicController.class.getName());
|
||||
lsilogicMapping.setBusName("scsi");
|
||||
lsilogicMapping.setMaxDeviceCount(16);
|
||||
lsilogicMapping.setMaxControllerCount(4);
|
||||
|
||||
DiskControllerMappingVO nvmeMapping = new DiskControllerMappingVO();
|
||||
nvmeMapping.setName("nvme");
|
||||
nvmeMapping.setControllerReference(VirtualNVMEController.class.getName());
|
||||
nvmeMapping.setBusName("nvme");
|
||||
nvmeMapping.setMaxDeviceCount(15);
|
||||
nvmeMapping.setMaxControllerCount(4);
|
||||
nvmeMapping.setMinHardwareVersion("13");
|
||||
|
||||
VmwareHelper.setSupportedDiskControllers(List.of(osdefaultMapping, ideMapping, lsilogicMapping, nvmeMapping));
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
|
|
@ -107,18 +157,6 @@ public class VirtualMachineMOTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestEnsureLsiLogicDeviceControllers() {
|
||||
try {
|
||||
when(client.getDynamicProperty(any(ManagedObjectReference.class), any(String.class))).thenReturn(getVirtualScSiDeviceList(VirtualLsiLogicController.class));
|
||||
vmMo.ensureLsiLogicDeviceControllers(1, 0);
|
||||
}
|
||||
catch (Exception e) {
|
||||
fail("Received exception when success expected: " + e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetVmxFormattedVirtualHardwareVersionOneDigit() {
|
||||
String vmxHwVersion = VirtualMachineMO.getVmxFormattedVirtualHardwareVersion(8);
|
||||
|
|
@ -135,4 +173,216 @@ public class VirtualMachineMOTest {
|
|||
public void testGetVmxFormattedVirtualHardwareVersionInvalid() {
|
||||
VirtualMachineMO.getVmxFormattedVirtualHardwareVersion(-1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDeviceBusNameTestReturnsValue() throws Exception {
|
||||
List<VirtualDevice> virtualDevices = new ArrayList<>();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
VirtualLsiLogicController controller = new VirtualLsiLogicController();
|
||||
controller.setKey(100 + i);
|
||||
controller.setBusNumber(i);
|
||||
virtualDevices.add(controller);
|
||||
}
|
||||
VirtualDisk disk = new VirtualDisk();
|
||||
disk.setControllerKey(101);
|
||||
disk.setUnitNumber(3);
|
||||
|
||||
String result = vmMoSpy.getDeviceBusName(virtualDevices, disk);
|
||||
|
||||
Assert.assertEquals("scsi1:3", result);
|
||||
}
|
||||
|
||||
private List<VirtualDevice> configureDevicesForTests() throws Exception {
|
||||
List<VirtualDevice> devices = new ArrayList<>();
|
||||
devices.add(new VirtualE1000());
|
||||
devices.add(new VirtualCdrom());
|
||||
devices.add(new VirtualDisk());
|
||||
devices.add(new VirtualIDEController());
|
||||
devices.add(new VirtualIDEController());
|
||||
VirtualNVMEController nvmeController = new VirtualNVMEController();
|
||||
nvmeController.setKey(111);
|
||||
nvmeController.setBusNumber(3);
|
||||
devices.add(nvmeController);
|
||||
Mockito.doReturn(devices).when(client).getDynamicProperty(mor, "config.hardware.device");
|
||||
return devices;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getControllersTestReturnsValue() throws Exception {
|
||||
List<VirtualDevice> devices = configureDevicesForTests();
|
||||
|
||||
List<VirtualController> result = vmMoSpy.getControllers();
|
||||
|
||||
for (VirtualDevice device : devices) {
|
||||
if (!(device instanceof VirtualController)) {
|
||||
continue;
|
||||
}
|
||||
Assert.assertTrue(result.contains(device));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMappingsForExistingDiskControllersTestReturnsValue() throws Exception {
|
||||
configureDevicesForTests();
|
||||
|
||||
Set<DiskControllerMappingVO> result = vmMoSpy.getMappingsForExistingDiskControllers();
|
||||
|
||||
DiskControllerMappingVO ideMapping = VmwareHelper.getDiskControllerMapping("ide", null);
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
Assert.assertTrue(result.contains(ideMapping));
|
||||
Assert.assertTrue(result.contains(nvmeMapping));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnyExistingAvailableDiskControllerTestReturnsNonIdeControllerWhenNonIdeControllerIsAvailable() throws Exception {
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
DiskControllerMappingVO ideMapping = VmwareHelper.getDiskControllerMapping("ide", null);
|
||||
Mockito.doReturn(new Pair<>(1, 2)).when(vmMoSpy).getNextAvailableControllerKeyAndDeviceNumberForType(nvmeMapping);
|
||||
Mockito.lenient().doReturn(new Pair<>(3, 4)).when(vmMoSpy).getNextAvailableControllerKeyAndDeviceNumberForType(ideMapping);
|
||||
configureDevicesForTests();
|
||||
|
||||
DiskControllerMappingVO result = vmMoSpy.getAnyExistingAvailableDiskController();
|
||||
|
||||
|
||||
Assert.assertEquals(nvmeMapping, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnyExistingAvailableDiskControllerTestReturnsIdeControllerWhenNonIdeControllerIsNotAvailable() throws Exception {
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
DiskControllerMappingVO ideMapping = VmwareHelper.getDiskControllerMapping("ide", null);
|
||||
Mockito.doReturn(null).when(vmMoSpy).getNextAvailableControllerKeyAndDeviceNumberForType(nvmeMapping);
|
||||
Mockito.doReturn(new Pair<>(1, 2)).when(vmMoSpy).getNextAvailableControllerKeyAndDeviceNumberForType(ideMapping);
|
||||
configureDevicesForTests();
|
||||
|
||||
DiskControllerMappingVO result = vmMoSpy.getAnyExistingAvailableDiskController();
|
||||
|
||||
Assert.assertEquals(ideMapping, result);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void getAnyExistingAvailableDiskControllerTestThrowsExceptionWhenNoDiskControllerIsAvailable() throws Exception {
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
DiskControllerMappingVO ideMapping = VmwareHelper.getDiskControllerMapping("ide", null);
|
||||
Mockito.doReturn(null).when(vmMoSpy).getNextAvailableControllerKeyAndDeviceNumberForType(nvmeMapping);
|
||||
Mockito.doReturn(null).when(vmMoSpy).getNextAvailableControllerKeyAndDeviceNumberForType(ideMapping);
|
||||
configureDevicesForTests();
|
||||
|
||||
vmMoSpy.getAnyExistingAvailableDiskController();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNextAvailableControllerKeyAndDeviceNumberForTypeTestReturnsValueWhenControllerIsAvailable() throws Exception {
|
||||
Mockito.doReturn(0).when(vmMoSpy).getNextAvailableDeviceNumberForController(Mockito.any(VirtualNVMEController.class), Mockito.any());
|
||||
configureDevicesForTests();
|
||||
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
Pair<Integer, Integer> result = vmMoSpy.getNextAvailableControllerKeyAndDeviceNumberForType(nvmeMapping);
|
||||
|
||||
Assert.assertEquals(111, (int) result.first());
|
||||
Assert.assertEquals(0, (int) result.second());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNextAvailableControllerKeyAndDeviceNumberForTypeTestReturnsNullWhenNoControllerIsAvailable() throws Exception {
|
||||
Mockito.doReturn(-1).when(vmMoSpy).getNextAvailableDeviceNumberForController(Mockito.any(), Mockito.any());
|
||||
configureDevicesForTests();
|
||||
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
Pair<Integer, Integer> result = vmMoSpy.getNextAvailableControllerKeyAndDeviceNumberForType(nvmeMapping);
|
||||
|
||||
Assert.assertNull(result);
|
||||
}
|
||||
|
||||
private Pair<VirtualController, DiskControllerMappingVO> configureScsiControllersAndDisksForGetNextAvailableDeviceNumberForControllerTests(int numberOfDevices) throws Exception {
|
||||
List<VirtualDevice> devices = new ArrayList<>();
|
||||
|
||||
devices.add(new VirtualIDEController());
|
||||
devices.add(new VirtualIDEController());
|
||||
|
||||
int firstScsiKey = 1;
|
||||
VirtualLsiLogicController firstScsiController = new VirtualLsiLogicController();
|
||||
firstScsiController.setKey(firstScsiKey);
|
||||
firstScsiController.setBusNumber(0);
|
||||
VirtualLsiLogicController secondScsiController = new VirtualLsiLogicController();
|
||||
secondScsiController.setKey(firstScsiKey + 1);
|
||||
secondScsiController.setBusNumber(1);
|
||||
|
||||
int currentDeviceNumber = 0;
|
||||
for (int i = 0; i < numberOfDevices; i++) {
|
||||
VirtualDevice device = i == 0 ? new VirtualCdrom() : new VirtualDisk();
|
||||
device.setControllerKey(firstScsiKey);
|
||||
device.setUnitNumber(currentDeviceNumber);
|
||||
devices.add(device);
|
||||
|
||||
currentDeviceNumber++;
|
||||
if (VmwareHelper.isReservedScsiDeviceNumber(currentDeviceNumber)) {
|
||||
currentDeviceNumber++;
|
||||
}
|
||||
}
|
||||
|
||||
Mockito.doReturn(devices).when(client).getDynamicProperty(mor, "config.hardware.device");
|
||||
|
||||
DiskControllerMappingVO lsilogicMapping = VmwareHelper.getDiskControllerMapping("lsilogic", null);
|
||||
return new Pair<>(firstScsiController, lsilogicMapping);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNextAvailableDeviceNumberForControllerTestValueWhenDeviceNumberIsAvailable() throws Exception {
|
||||
int numberOfDevices = 14;
|
||||
Pair<VirtualController, DiskControllerMappingVO> config = configureScsiControllersAndDisksForGetNextAvailableDeviceNumberForControllerTests(numberOfDevices);
|
||||
|
||||
int result = vmMoSpy.getNextAvailableDeviceNumberForController(config.first(), config.second());
|
||||
|
||||
Assert.assertEquals(numberOfDevices + 1, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNextAvailableDeviceNumberForControllerTestValueWhenNoDeviceNumberIsAvailable() throws Exception {
|
||||
Pair<VirtualController, DiskControllerMappingVO> config = configureScsiControllersAndDisksForGetNextAvailableDeviceNumberForControllerTests(15);
|
||||
|
||||
int result = vmMoSpy.getNextAvailableDeviceNumberForController(config.first(), config.second());
|
||||
|
||||
Assert.assertEquals(-1, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNthDeviceTestReturnsDeviceWhenDeviceExists() throws Exception {
|
||||
configureDevicesForTests();
|
||||
|
||||
vmMoSpy.getNthDevice(VirtualIDEController.class.getName(), 1);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void getNthDeviceTestThrowsExceptionWhenDeviceDoesNotExist() throws Exception {
|
||||
configureDevicesForTests();
|
||||
|
||||
vmMoSpy.getNthDevice(VirtualIDEController.class.getName(), 2);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void validateDiskControllerIsAvailableTestThrowsExceptionWhenBusNumberIsInvalid() throws Exception {
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
Mockito.when(virtualControllerMock.getBusNumber()).thenReturn(4);
|
||||
|
||||
vmMo.validateDiskControllerIsAvailable(virtualControllerMock, nvmeMapping);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void validateDiskControllerIsAvailableTestThrowsExceptionWhenNoAvailableDeviceNumberExists() throws Exception {
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
Mockito.when(virtualControllerMock.getBusNumber()).thenReturn(3);
|
||||
Mockito.doReturn(-1).when(vmMoSpy).getNextAvailableDeviceNumberForController(virtualControllerMock, nvmeMapping);
|
||||
|
||||
vmMoSpy.validateDiskControllerIsAvailable(virtualControllerMock, nvmeMapping);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateDiskControllerIsAvailableTestDoesNothingWhenBusNumberIsValidAndAvailableDeviceNumberExists() throws Exception {
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
Mockito.when(virtualControllerMock.getBusNumber()).thenReturn(3);
|
||||
Mockito.doReturn(14).when(vmMoSpy).getNextAvailableDeviceNumberForController(virtualControllerMock, nvmeMapping);
|
||||
|
||||
vmMoSpy.validateDiskControllerIsAvailable(virtualControllerMock, nvmeMapping);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,10 +20,27 @@ package com.cloud.hypervisor.vmware.util;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.vmware.vim25.DatastoreInfo;
|
||||
import com.vmware.vim25.Description;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.ParaVirtualSCSIController;
|
||||
import com.vmware.vim25.VirtualAHCIController;
|
||||
import com.vmware.vim25.VirtualController;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpec;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
|
||||
import com.vmware.vim25.VirtualDiskFlatVer2BackingInfo;
|
||||
import com.vmware.vim25.VirtualIDEController;
|
||||
import com.vmware.vim25.VirtualLsiLogicController;
|
||||
import com.vmware.vim25.VirtualMachineConfigSpec;
|
||||
import com.vmware.vim25.VirtualNVMEController;
|
||||
import com.vmware.vim25.VirtualSCSIController;
|
||||
import com.vmware.vim25.VirtualSCSISharing;
|
||||
import org.apache.cloudstack.storage.DiskControllerMappingVO;
|
||||
import org.apache.cloudstack.vm.UnmanagedInstanceTO;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
|
|
@ -36,12 +53,21 @@ import org.mockito.junit.MockitoJUnitRunner;
|
|||
import com.cloud.hypervisor.vmware.mo.VirtualMachineMO;
|
||||
import com.vmware.vim25.VirtualDisk;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class VmwareHelperTest {
|
||||
@Mock
|
||||
private VirtualMachineMO virtualMachineMO;
|
||||
@Mock
|
||||
private VmwareHypervisorHost vmwareHypervisorHostMock;
|
||||
@Mock
|
||||
private VirtualMachineConfigSpec virtualMachineConfigSpecMock;
|
||||
|
||||
private static final String diskLabel = "disk1";
|
||||
private static final String diskFileBaseName = "xyz.vmdk";
|
||||
|
|
@ -73,6 +99,43 @@ public class VmwareHelperTest {
|
|||
Mockito.when(context.getVimClient()).thenReturn(client);
|
||||
Mockito.when(virtualMachineMO.getContext()).thenReturn(context);
|
||||
Mockito.when(virtualMachineMO.getName()).thenReturn(vmName);
|
||||
|
||||
DiskControllerMappingVO osdefaultMapping = new DiskControllerMappingVO();
|
||||
osdefaultMapping.setName("osdefault");
|
||||
osdefaultMapping.setControllerReference("osdefault");
|
||||
DiskControllerMappingVO ideMapping = new DiskControllerMappingVO();
|
||||
ideMapping.setName("ide");
|
||||
ideMapping.setControllerReference(VirtualIDEController.class.getName());
|
||||
ideMapping.setBusName("ide");
|
||||
ideMapping.setMaxDeviceCount(2);
|
||||
ideMapping.setMaxControllerCount(2);
|
||||
DiskControllerMappingVO lsilogicMapping = new DiskControllerMappingVO();
|
||||
lsilogicMapping.setName("lsilogic");
|
||||
lsilogicMapping.setControllerReference(VirtualLsiLogicController.class.getName());
|
||||
lsilogicMapping.setBusName("scsi");
|
||||
lsilogicMapping.setMaxDeviceCount(16);
|
||||
lsilogicMapping.setMaxControllerCount(4);
|
||||
DiskControllerMappingVO pvscsiMapping = new DiskControllerMappingVO();
|
||||
pvscsiMapping.setName("pvscsi");
|
||||
pvscsiMapping.setControllerReference(ParaVirtualSCSIController.class.getName());
|
||||
pvscsiMapping.setBusName("scsi");
|
||||
pvscsiMapping.setMaxDeviceCount(16);
|
||||
pvscsiMapping.setMaxControllerCount(4);
|
||||
DiskControllerMappingVO sataMapping = new DiskControllerMappingVO();
|
||||
sataMapping.setName("sata");
|
||||
sataMapping.setControllerReference(VirtualAHCIController.class.getName());
|
||||
sataMapping.setBusName("sata");
|
||||
sataMapping.setMaxDeviceCount(30);
|
||||
sataMapping.setMaxControllerCount(4);
|
||||
DiskControllerMappingVO nvmeMapping = new DiskControllerMappingVO();
|
||||
nvmeMapping.setName("nvme");
|
||||
nvmeMapping.setControllerReference(VirtualNVMEController.class.getName());
|
||||
nvmeMapping.setBusName("nvme");
|
||||
nvmeMapping.setMaxDeviceCount(15);
|
||||
nvmeMapping.setMaxControllerCount(4);
|
||||
VmwareHelper.setSupportedDiskControllers(List.of(osdefaultMapping, ideMapping, lsilogicMapping, pvscsiMapping, sataMapping, nvmeMapping));
|
||||
|
||||
Mockito.when(virtualMachineConfigSpecMock.getDeviceChange()).thenReturn(new ArrayList<>());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -105,4 +168,304 @@ public class VmwareHelperTest {
|
|||
Assert.assertEquals(diskFileBaseName, disk.getFileBaseName());
|
||||
Assert.assertEquals(dataStoreName, disk.getDatastoreName());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void isControllerOsRecommendedTestControllerIsOsRecommendedReturnsTrue() {
|
||||
DiskControllerMappingVO mapping = new DiskControllerMappingVO();
|
||||
mapping.setName("osdefault");
|
||||
|
||||
boolean result = VmwareHelper.isControllerOsRecommended(mapping);
|
||||
|
||||
Assert.assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isControllerOsRecommendedTestControllerIsNotOsRecommendedReturnsFalse() {
|
||||
DiskControllerMappingVO mapping = new DiskControllerMappingVO();
|
||||
mapping.setName("lsilogic");
|
||||
|
||||
boolean result = VmwareHelper.isControllerOsRecommended(mapping);
|
||||
|
||||
Assert.assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isControllerScsiTestControllerIsScsiReturnsTrue() {
|
||||
DiskControllerMappingVO mapping = new DiskControllerMappingVO();
|
||||
mapping.setBusName("scsi");
|
||||
|
||||
boolean result = VmwareHelper.isControllerScsi(mapping);
|
||||
|
||||
Assert.assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isControllerScsiTestControllerIsNotScsiReturnsFalse() {
|
||||
DiskControllerMappingVO mapping = new DiskControllerMappingVO();
|
||||
mapping.setBusName("nvme");
|
||||
|
||||
boolean result = VmwareHelper.isControllerScsi(mapping);
|
||||
|
||||
Assert.assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDiskControllerMappingTestSearchByExistingNameReturnsObject() {
|
||||
String name = "lsilogic";
|
||||
|
||||
DiskControllerMappingVO mapping = VmwareHelper.getDiskControllerMapping(name, null);
|
||||
|
||||
Assert.assertEquals(name, mapping.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDiskControllerMappingTestSearchByExistingControllerReferenceReturnsObject() {
|
||||
String classpath = VirtualLsiLogicController.class.getName();
|
||||
|
||||
DiskControllerMappingVO mapping = VmwareHelper.getDiskControllerMapping(null, classpath);
|
||||
|
||||
Assert.assertEquals(classpath, mapping.getControllerReference());
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void getDiskControllerMappingTestThrowsExceptionWhenNoMatches() {
|
||||
VmwareHelper.getDiskControllerMapping("invalid", "invalid");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAllDiskControllerMappingsExceptOsDefaultTestReturnDoesNotContainOsDefaultMapping() {
|
||||
List<DiskControllerMappingVO> result = VmwareHelper.getAllSupportedDiskControllerMappingsExceptOsDefault();
|
||||
|
||||
DiskControllerMappingVO osdefaultMapping = VmwareHelper.getDiskControllerMapping("osdefault", null);
|
||||
Assert.assertFalse(result.contains(osdefaultMapping));
|
||||
Assert.assertFalse(result.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequiredDiskControllersTestRequiresAllControllersWhenInstanceIsNotSystemVm() {
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(new DiskControllerMappingVO(), new DiskControllerMappingVO());
|
||||
|
||||
Set<DiskControllerMappingVO> result = VmwareHelper.getRequiredDiskControllers(controllerInfo, false);
|
||||
|
||||
Assert.assertTrue(result.contains(controllerInfo.first()));
|
||||
Assert.assertTrue(result.contains(controllerInfo.second()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequiredDiskControllersTestRequiresOnlyRootDiskControllerWhenInstanceIsSystemVm() {
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(new DiskControllerMappingVO(), new DiskControllerMappingVO());
|
||||
|
||||
Set<DiskControllerMappingVO> result = VmwareHelper.getRequiredDiskControllers(controllerInfo, true);
|
||||
|
||||
Assert.assertTrue(result.contains(controllerInfo.first()));
|
||||
Assert.assertFalse(result.contains(controllerInfo.second()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void chooseDiskControllersDiskControllersTestControllersAreNotOsRecommendedReturnsProvidedControllers() throws Exception {
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
DiskControllerMappingVO sataMapping = VmwareHelper.getDiskControllerMapping("sata", null);
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(nvmeMapping, sataMapping);
|
||||
Mockito.doReturn("VirtualLsiLogicController").when(virtualMachineMO).getRecommendedDiskController(null);
|
||||
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> result = VmwareHelper.chooseDiskControllers(controllerInfo, virtualMachineMO, null, null);
|
||||
|
||||
Assert.assertEquals(nvmeMapping, result.first());
|
||||
Assert.assertEquals(sataMapping, result.second());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void chooseDiskControllersTestControllersAreOsRecommendedAndVmMoIsProvidedReturnsConvertedControllersBasedOnVmMo() throws Exception {
|
||||
DiskControllerMappingVO osdefaultMapping = VmwareHelper.getDiskControllerMapping("osdefault", null);
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(osdefaultMapping, osdefaultMapping);
|
||||
Mockito.doReturn("VirtualLsiLogicController").when(virtualMachineMO).getRecommendedDiskController(null);
|
||||
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> result = VmwareHelper.chooseDiskControllers(controllerInfo, virtualMachineMO, null, null);
|
||||
|
||||
DiskControllerMappingVO lsilogicMapping = VmwareHelper.getDiskControllerMapping("lsilogic", null);
|
||||
Assert.assertEquals(lsilogicMapping, result.first());
|
||||
Assert.assertEquals(lsilogicMapping, result.second());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void chooseDiskControllersTestControllersAreOsRecommendedAndHostIsProvidedReturnsConvertedControllersBasedOnHost() throws Exception {
|
||||
DiskControllerMappingVO osdefaultMapping = VmwareHelper.getDiskControllerMapping("osdefault", null);
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(osdefaultMapping, osdefaultMapping);
|
||||
String guestOsId = "guestOsId";
|
||||
Mockito.doReturn("VirtualLsiLogicController").when(vmwareHypervisorHostMock).getRecommendedDiskController(guestOsId);
|
||||
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> result = VmwareHelper.chooseDiskControllers(controllerInfo, null, vmwareHypervisorHostMock, guestOsId);
|
||||
|
||||
DiskControllerMappingVO lsilogicMapping = VmwareHelper.getDiskControllerMapping("lsilogic", null);
|
||||
Assert.assertEquals(lsilogicMapping, result.first());
|
||||
Assert.assertEquals(lsilogicMapping, result.second());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void chooseDiskControllersTestControllersShareTheSameBusTypeReturnsRootDiskController() throws Exception {
|
||||
DiskControllerMappingVO osdefaultMapping = VmwareHelper.getDiskControllerMapping("osdefault", null);
|
||||
DiskControllerMappingVO pvscsiMapping = VmwareHelper.getDiskControllerMapping("pvscsi", null);
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(osdefaultMapping, pvscsiMapping);
|
||||
Mockito.doReturn("VirtualLsiLogicController").when(virtualMachineMO).getRecommendedDiskController(null);
|
||||
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> result = VmwareHelper.chooseDiskControllers(controllerInfo, virtualMachineMO, null, null);
|
||||
|
||||
DiskControllerMappingVO lsilogicMapping = VmwareHelper.getDiskControllerMapping("lsilogic", null);
|
||||
Assert.assertEquals(lsilogicMapping, result.first());
|
||||
Assert.assertEquals(lsilogicMapping, result.second());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addDiskControllersToVmConfigSpecTestDoesNotAddIdeControllers() throws Exception {
|
||||
DiskControllerMappingVO ideMapping = VmwareHelper.getDiskControllerMapping("ide", null);
|
||||
Set<DiskControllerMappingVO> requiredControllers = new HashSet<>();
|
||||
requiredControllers.add(ideMapping);
|
||||
|
||||
VmwareHelper.addDiskControllersToVmConfigSpec(virtualMachineConfigSpecMock, requiredControllers, false);
|
||||
|
||||
Assert.assertEquals(0, virtualMachineConfigSpecMock.getDeviceChange().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addDiskControllersToVmConfigSpecTestMaximumAmmountOfControllersIsAdded() throws Exception {
|
||||
DiskControllerMappingVO nvmeMapping = VmwareHelper.getDiskControllerMapping("nvme", null);
|
||||
DiskControllerMappingVO sataMapping = VmwareHelper.getDiskControllerMapping("sata", null);
|
||||
Set<DiskControllerMappingVO> requiredControllers = new HashSet<>();
|
||||
requiredControllers.add(nvmeMapping);
|
||||
requiredControllers.add(sataMapping);
|
||||
|
||||
VmwareHelper.addDiskControllersToVmConfigSpec(virtualMachineConfigSpecMock, requiredControllers, false);
|
||||
|
||||
int expectedControllerAmmount = nvmeMapping.getMaxControllerCount() + sataMapping.getMaxControllerCount();
|
||||
Assert.assertEquals(expectedControllerAmmount, virtualMachineConfigSpecMock.getDeviceChange().size());
|
||||
|
||||
Set<Integer> usedKeys = new HashSet<>();
|
||||
Map<String, Set<Integer>> usedBusNumbers = new HashMap<>();
|
||||
usedBusNumbers.put(nvmeMapping.getControllerReference(), new HashSet<>());
|
||||
usedBusNumbers.put(sataMapping.getControllerReference(), new HashSet<>());
|
||||
for (VirtualDeviceConfigSpec virtualDeviceConfigSpec : virtualMachineConfigSpecMock.getDeviceChange()) {
|
||||
Assert.assertEquals(VirtualDeviceConfigSpecOperation.ADD, virtualDeviceConfigSpec.getOperation());
|
||||
VirtualController controller = (VirtualController) virtualDeviceConfigSpec.getDevice();
|
||||
usedKeys.add(controller.getKey());
|
||||
usedBusNumbers.get(controller.getClass().getName()).add(controller.getBusNumber());
|
||||
}
|
||||
Assert.assertEquals(expectedControllerAmmount, usedKeys.size());
|
||||
Assert.assertEquals((int) nvmeMapping.getMaxControllerCount(), usedBusNumbers.get(nvmeMapping.getControllerReference()).size());
|
||||
Assert.assertEquals((int) sataMapping.getMaxControllerCount(), usedBusNumbers.get(sataMapping.getControllerReference()).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addDiskControllersToVmConfigSpecTestAddedScsiControllersDoNotShareBus() throws Exception {
|
||||
DiskControllerMappingVO lsilogicMapping = VmwareHelper.getDiskControllerMapping("lsilogic", null);
|
||||
Set<DiskControllerMappingVO> requiredControllers = new HashSet<>();
|
||||
requiredControllers.add(lsilogicMapping);
|
||||
|
||||
VmwareHelper.addDiskControllersToVmConfigSpec(virtualMachineConfigSpecMock, requiredControllers, false);
|
||||
|
||||
for (VirtualDeviceConfigSpec virtualDeviceConfigSpec : virtualMachineConfigSpecMock.getDeviceChange()) {
|
||||
Assert.assertEquals(VirtualSCSISharing.NO_SHARING, ((VirtualSCSIController) virtualDeviceConfigSpec.getDevice()).getSharedBus());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addDiskControllersToVmConfigSpecTestInstanceIsSystemVmAddsOneController() throws Exception {
|
||||
DiskControllerMappingVO lsilogicMapping = VmwareHelper.getDiskControllerMapping("lsilogic", null);
|
||||
Set<DiskControllerMappingVO> requiredControllers = new HashSet<>();
|
||||
requiredControllers.add(lsilogicMapping);
|
||||
|
||||
VmwareHelper.addDiskControllersToVmConfigSpec(virtualMachineConfigSpecMock, requiredControllers, true);
|
||||
|
||||
Assert.assertEquals(1, virtualMachineConfigSpecMock.getDeviceChange().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDiskControllersFromVmSettingsTestReturnsSpecifiedControllersWhenInstanceIsNotSystemVm() {
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = VmwareHelper.getDiskControllersFromVmSettings("nvme", "sata", false);
|
||||
|
||||
Assert.assertEquals("nvme", controllerInfo.first().getName());
|
||||
Assert.assertEquals("sata", controllerInfo.second().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDiskControllersFromVmSettingsTestReturnsLsiLogicForRootDiskWhenInstanceIsSystemVm() {
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = VmwareHelper.getDiskControllersFromVmSettings("nvme", "sata", true);
|
||||
|
||||
Assert.assertEquals("lsilogic", controllerInfo.first().getName());
|
||||
Assert.assertEquals("sata", controllerInfo.second().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getControllerBasedOnDiskTypeTestReturnsRootDiskControllerWhenVolumeTypeIsRoot() {
|
||||
DiskControllerMappingVO rootDiskController = new DiskControllerMappingVO();
|
||||
rootDiskController.setControllerReference("root");
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(rootDiskController, new DiskControllerMappingVO());
|
||||
DiskTO disk = new DiskTO();
|
||||
disk.setType(Volume.Type.ROOT);
|
||||
|
||||
DiskControllerMappingVO result = VmwareHelper.getControllerBasedOnDiskType(controllerInfo, disk);
|
||||
|
||||
Assert.assertEquals(rootDiskController, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getControllerBasedOnDiskTypeTestReturnsRootDiskControllerWhenVolumeDiskSeqIsZero() {
|
||||
DiskControllerMappingVO rootDiskController = new DiskControllerMappingVO();
|
||||
rootDiskController.setControllerReference("root");
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(rootDiskController, new DiskControllerMappingVO());
|
||||
DiskTO disk = new DiskTO();
|
||||
disk.setDiskSeq(0L);
|
||||
|
||||
DiskControllerMappingVO result = VmwareHelper.getControllerBasedOnDiskType(controllerInfo, disk);
|
||||
|
||||
Assert.assertEquals(rootDiskController, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getControllerBasedOnDiskTypeTestReturnsDataDiskControllerWhenVolumeTypeIsNotRootAndDiskSeqIsNotZero() {
|
||||
DiskControllerMappingVO dataDiskController = new DiskControllerMappingVO();
|
||||
dataDiskController.setControllerReference("data");
|
||||
Pair<DiskControllerMappingVO, DiskControllerMappingVO> controllerInfo = new Pair<>(new DiskControllerMappingVO(), dataDiskController);
|
||||
DiskTO disk = new DiskTO();
|
||||
disk.setType(Volume.Type.DATADISK);
|
||||
disk.setDiskSeq(1L);
|
||||
|
||||
DiskControllerMappingVO result = VmwareHelper.getControllerBasedOnDiskType(controllerInfo, disk);
|
||||
|
||||
Assert.assertEquals(dataDiskController, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureDiskControllerMappingsInVmwareBaseModuleTestOsdefaultIsConfigured() {
|
||||
DiskControllerMappingVO osdefaultMappingVo = new DiskControllerMappingVO();
|
||||
osdefaultMappingVo.setName("osdefault");
|
||||
osdefaultMappingVo.setControllerReference("osdefault");
|
||||
|
||||
VmwareHelper.configureDiskControllerMappingsInVmwareBaseModule(List.of(osdefaultMappingVo));
|
||||
|
||||
Assert.assertEquals(List.of(osdefaultMappingVo), VmwareHelper.getAllSupportedDiskControllerMappings());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureDiskControllerMappingsInVmwareBaseModuleTestLsiLogicIsConfigured() {
|
||||
DiskControllerMappingVO lsilogicMappingVo = new DiskControllerMappingVO();
|
||||
lsilogicMappingVo.setName("lsilogic");
|
||||
lsilogicMappingVo.setControllerReference(VirtualLsiLogicController.class.getName());
|
||||
|
||||
VmwareHelper.configureDiskControllerMappingsInVmwareBaseModule(List.of(lsilogicMappingVo));
|
||||
|
||||
Assert.assertEquals(List.of(lsilogicMappingVo), VmwareHelper.getAllSupportedDiskControllerMappings());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureDiskControllerMappingsInVmwareBaseModuleTestInvalidMappingIsNotConfigured() {
|
||||
DiskControllerMappingVO invalidMappingVo = new DiskControllerMappingVO();
|
||||
invalidMappingVo.setName("invalid");
|
||||
invalidMappingVo.setControllerReference("invalid");
|
||||
|
||||
VmwareHelper.configureDiskControllerMappingsInVmwareBaseModule(List.of(invalidMappingVo));
|
||||
|
||||
Assert.assertEquals(0, VmwareHelper.getAllSupportedDiskControllerMappings().size());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue