From f0aee9b39f83bdb2d2c3bbaab53ccfdf1f7616ae Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 2 Aug 2019 13:17:29 +0530 Subject: [PATCH 01/61] VM ingestion feature allows CloudStack to discover, on-board, import existing VMs in an infra. The feature currently works only for VMware, with a hypervisor agnostic framework which may be extended for KVM and XenServer in future. Two new APIs have been added, listUnmanagedInstances and importUnmanagedInstance. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit listUnmanagedInstances API will list all unmanaged virtual machine for a give cluster. Optionally, name for an existing unmanaged virtual machine can be given to retrieve VM details. API request params - clusterid(UUID of cluster) name(instance name) Response - clusterid hostid name osdisplayname memory powerstate cpuCoresPerSocket cpunumber cpuspeed disk - id - capacity - controller - controllerunit - imagepath - position nic - id - macaddress - networkname - vlanid - pcislot - ipaddress(Only with VMware Tools installed on VM for VMware) importUnmanagedInstance API will import an exisitng unmanaged virtual machine into CloudStack for a given cluster and virtual machine name. Service offering for the VM, disk offerings for volumes and networks for NICs of the VM can be mapped. Some optional parameters like projectid, domainid, hostname, details, etc can also be given. Appropritate networks, service offering and disk offerings need to be present before import and cannot be created on the fly during the API call. API request params - clusterid(UUID of cluster) name(instance name) displayname hostname domainid projectid templateid serviceofferingid diskofferingid(UUID of disk offering for root disk) nicnetworklist(Map for NIC ID and corresponding Network UUID) nicipaddresslist(Map for NIC ID and corresponding IP address) datadiskofferinglist(Map for disk ID and corresponding disk offering UUID) details(Map for VM details) migrateAllowed(VM and its volumes are allowed to migrate to different host/pool when offerings passed are incompatible with current host/pool) Response - Same response as that of deployVirtualMachine API A python 3 based script (scripts/vm/hypervisor/vmware/discover_networks.py) has been created to aid migrations. It leverages VMware’s pyvmomi library (https://github.com/vmware/pyvmomi) and allows listing all networks for a vCenter host or cluster. This script can take following arguments, -h, --help show this help message and exit -s HOST, --host HOST vSpehre service to connect to -o PORT, --port PORT Port to connect on -u USER, --user USER User name to use -p PASSWORD, --password PASSWORD Password to use -c CLUSTER, --cluster CLUSTER Cluster for which discover networks -S, --disable_ssl_verification Disable ssl host certificate verification -d, --debug Debug log messages Signed-off-by: Abhishek Kumar --- .../main/java/com/cloud/event/EventTypes.java | 15 +- .../main/java/com/cloud/vm/UserVmService.java | 4 + .../java/com/cloud/vm/VmDetailConstants.java | 7 + .../apache/cloudstack/api/ApiConstants.java | 11 + .../admin/vm/ImportUnmanagedInstanceCmd.java | 306 +++++++ .../admin/vm/ListUnmanagedInstancesCmd.java | 113 +++ .../api/response/DomainRouterResponse.java | 7 +- .../cloudstack/api/response/NicResponse.java | 21 +- .../UnmanagedInstanceDiskResponse.java | 111 +++ .../response/UnmanagedInstanceResponse.java | 178 ++++ .../cloudstack/vm/UnmanagedInstance.java | 263 ++++++ .../apache/cloudstack/vm/VmImportService.java | 31 + .../api/GetUnmanagedInstancesAnswer.java | 58 ++ .../api/GetUnmanagedInstancesCommand.java | 67 ++ .../service/NetworkOrchestrationService.java | 2 + .../service/VolumeOrchestrationService.java | 20 + .../orchestration/NetworkOrchestrator.java | 43 + .../orchestration/VolumeOrchestrator.java | 61 +- .../cloud/service/dao/ServiceOfferingDao.java | 2 +- .../service/dao/ServiceOfferingDaoImpl.java | 6 +- .../vmware/resource/VmwareResource.java | 727 ++++++++++------ .../vm/hypervisor/vmware/discover_networks.py | 252 ++++++ .../cloud/server/ManagementServerImpl.java | 2 +- .../java/com/cloud/vm/UserVmManagerImpl.java | 117 ++- .../cloudstack/vm/VmImportManagerImpl.java | 811 ++++++++++++++++++ .../spring-server-compute-context.xml | 2 + .../com/cloud/vpc/MockNetworkManagerImpl.java | 5 + .../vm/VmImportManagerImplTest.java | 279 ++++++ tools/apidoc/gen_toc.py | 1 + .../cloud/hypervisor/vmware/mo/ClusterMO.java | 13 + .../cloud/hypervisor/vmware/mo/HostMO.java | 12 + .../vmware/mo/VmwareHypervisorHost.java | 4 + 32 files changed, 3258 insertions(+), 293 deletions(-) create mode 100644 api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java create mode 100644 api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListUnmanagedInstancesCmd.java create mode 100644 api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceDiskResponse.java create mode 100644 api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java create mode 100644 api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java create mode 100644 api/src/main/java/org/apache/cloudstack/vm/VmImportService.java create mode 100644 core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesAnswer.java create mode 100644 core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesCommand.java create mode 100755 scripts/vm/hypervisor/vmware/discover_networks.py create mode 100644 server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java create mode 100644 server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java diff --git a/api/src/main/java/com/cloud/event/EventTypes.java b/api/src/main/java/com/cloud/event/EventTypes.java index a30518aaf176..59c4d689af1c 100644 --- a/api/src/main/java/com/cloud/event/EventTypes.java +++ b/api/src/main/java/com/cloud/event/EventTypes.java @@ -19,6 +19,13 @@ import java.util.HashMap; import java.util.Map; +import org.apache.cloudstack.acl.Role; +import org.apache.cloudstack.acl.RolePermission; +import org.apache.cloudstack.annotation.Annotation; +import org.apache.cloudstack.config.Configuration; +import org.apache.cloudstack.ha.HAConfig; +import org.apache.cloudstack.usage.Usage; + import com.cloud.dc.DataCenter; import com.cloud.dc.Pod; import com.cloud.dc.StorageNetworkIpRange; @@ -69,12 +76,6 @@ import com.cloud.vm.Nic; import com.cloud.vm.NicSecondaryIp; import com.cloud.vm.VirtualMachine; -import org.apache.cloudstack.acl.Role; -import org.apache.cloudstack.acl.RolePermission; -import org.apache.cloudstack.annotation.Annotation; -import org.apache.cloudstack.config.Configuration; -import org.apache.cloudstack.ha.HAConfig; -import org.apache.cloudstack.usage.Usage; public class EventTypes { @@ -96,6 +97,7 @@ public class EventTypes { public static final String EVENT_VM_MOVE = "VM.MOVE"; public static final String EVENT_VM_RESTORE = "VM.RESTORE"; public static final String EVENT_VM_EXPUNGE = "VM.EXPUNGE"; + public static final String EVENT_VM_IMPORT = "VM.IMPORT"; // Domain Router public static final String EVENT_ROUTER_CREATE = "ROUTER.CREATE"; @@ -594,6 +596,7 @@ public class EventTypes { entityEventDetails.put(EVENT_VM_MOVE, VirtualMachine.class); entityEventDetails.put(EVENT_VM_RESTORE, VirtualMachine.class); entityEventDetails.put(EVENT_VM_EXPUNGE, VirtualMachine.class); + entityEventDetails.put(EVENT_VM_IMPORT, VirtualMachine.class); entityEventDetails.put(EVENT_ROUTER_CREATE, VirtualRouter.class); entityEventDetails.put(EVENT_ROUTER_DESTROY, VirtualRouter.class); diff --git a/api/src/main/java/com/cloud/vm/UserVmService.java b/api/src/main/java/com/cloud/vm/UserVmService.java index 99eb827c1227..8349e00d7054 100644 --- a/api/src/main/java/com/cloud/vm/UserVmService.java +++ b/api/src/main/java/com/cloud/vm/UserVmService.java @@ -513,4 +513,8 @@ UserVm upgradeVirtualMachine(ScaleVMCmd cmd) throws ResourceUnavailableException void collectVmNetworkStatistics (UserVm userVm); + UserVm importVM(final DataCenter zone, final Host host, final VirtualMachineTemplate template, final String instanceName, final String displayName, final Account owner, final String userData, final Account caller, final Boolean isDisplayVm, final String keyboard, + final long accountId, final long userId, final ServiceOffering serviceOffering, final DiskOffering rootDiskOffering, final String sshPublicKey, + final String hostName, final HypervisorType hypervisorType, final Map customParameters, final VirtualMachine.PowerState powerState) throws InsufficientCapacityException; + } diff --git a/api/src/main/java/com/cloud/vm/VmDetailConstants.java b/api/src/main/java/com/cloud/vm/VmDetailConstants.java index 84de8c9ebac8..35c7485d2ebb 100644 --- a/api/src/main/java/com/cloud/vm/VmDetailConstants.java +++ b/api/src/main/java/com/cloud/vm/VmDetailConstants.java @@ -54,4 +54,11 @@ public interface VmDetailConstants { String SSH_PUBLIC_KEY = "SSH.PublicKey"; String PASSWORD = "password"; String ENCRYPTED_PASSWORD = "Encrypted.Password"; + + // VM import with nic, disk and custom params for custom compute offering + String NIC = "nic"; + String NETWORK = "network"; + String IP_ADDRESS = "ipAddress"; + String DISK = "disk"; + String DISK_OFFERING = "diskOffering"; } diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index fb44a8a11f48..f51050c43f5f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -43,6 +43,7 @@ public class ApiConstants { public static final String BYTES_WRITE_RATE_MAX = "byteswriteratemax"; public static final String BYTES_WRITE_RATE_MAX_LENGTH = "byteswriteratemaxlength"; public static final String BYPASS_VLAN_OVERLAP_CHECK = "bypassvlanoverlapcheck"; + public static final String CAPACITY = "capacity"; public static final String CATEGORY = "category"; public static final String CAN_REVERT = "canrevert"; public static final String CA_CERTIFICATES = "cacertificates"; @@ -50,6 +51,8 @@ public class ApiConstants { public static final String CERTIFICATE_CHAIN = "certchain"; public static final String CERTIFICATE_FINGERPRINT = "fingerprint"; public static final String CERTIFICATE_ID = "certid"; + public static final String CONTROLLER = "controller"; + public static final String CONTROLLER_UNIT = "controllerunit"; public static final String COPY_IMAGE_TAGS = "copyimagetags"; public static final String CSR = "csr"; public static final String PRIVATE_KEY = "privatekey"; @@ -69,6 +72,7 @@ public class ApiConstants { public static final String COMMAND = "command"; public static final String CMD_EVENT_TYPE = "cmdeventtype"; public static final String COMPONENT = "component"; + public static final String CPU_CORE_PER_SOCKET = "cpucorepersocket"; public static final String CPU_NUMBER = "cpunumber"; public static final String CPU_SPEED = "cpuspeed"; public static final String CREATED = "created"; @@ -90,6 +94,7 @@ public class ApiConstants { public static final String DETAILS = "details"; public static final String DEVICE_ID = "deviceid"; public static final String DIRECT_DOWNLOAD = "directdownload"; + public static final String DISK = "disk"; public static final String DISK_OFFERING_ID = "diskofferingid"; public static final String NEW_DISK_OFFERING_ID = "newdiskofferingid"; public static final String DISK_KBS_READ = "diskkbsread"; @@ -169,6 +174,7 @@ public class ApiConstants { public static final String PREVIOUS_ACL_RULE_ID = "previousaclruleid"; public static final String NEXT_ACL_RULE_ID = "nextaclruleid"; public static final String MOVE_ACL_CONSISTENCY_HASH = "aclconsistencyhash"; + public static final String IMAGE_PATH = "imagepath"; public static final String INTERNAL_DNS1 = "internaldns1"; public static final String INTERNAL_DNS2 = "internaldns2"; public static final String INTERVAL_TYPE = "intervaltype"; @@ -222,6 +228,9 @@ public class ApiConstants { public static final String NETWORK_DOMAIN = "networkdomain"; public static final String NETMASK = "netmask"; public static final String NEW_NAME = "newname"; + public static final String NIC = "nic"; + public static final String NIC_NETWORK_LIST = "nicnetworklist"; + public static final String NIC_IP_ADDRESS_LIST = "nicipaddresslist"; public static final String NUM_RETRIES = "numretries"; public static final String OFFER_HA = "offerha"; public static final String IS_SYSTEM_OFFERING = "issystem"; @@ -253,6 +262,7 @@ public class ApiConstants { public static final String PORTAL = "portal"; public static final String PORTABLE_IP_ADDRESS = "portableipaddress"; public static final String PORT_FORWARDING_SERVICE_ID = "portforwardingserviceid"; + public static final String POSITION = "position"; public static final String POST_URL = "postURL"; public static final String POWER_STATE = "powerstate"; public static final String PRIVATE_INTERFACE = "privateinterface"; @@ -526,6 +536,7 @@ public class ApiConstants { public static final String CUSTOM_DISK_OFF_MAX_SIZE = "customdiskofferingmaxsize"; public static final String DEFAULT_ZONE_ID = "defaultzoneid"; public static final String LIVE_MIGRATE = "livemigrate"; + public static final String MIGRATE_ALLOWED = "migrateallowed"; public static final String MIGRATE_TO = "migrateto"; public static final String GUID = "guid"; public static final String VSWITCH_TYPE_GUEST_TRAFFIC = "guestvswitchtype"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java new file mode 100644 index 000000000000..1a012ee50b3e --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java @@ -0,0 +1,306 @@ +// 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.api.command.admin.vm; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import javax.inject.Inject; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.ClusterResponse; +import org.apache.cloudstack.api.response.DiskOfferingResponse; +import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.api.response.ProjectResponse; +import org.apache.cloudstack.api.response.ServiceOfferingResponse; +import org.apache.cloudstack.api.response.TemplateResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.vm.VmImportService; +import org.apache.commons.collections.MapUtils; +import org.apache.log4j.Logger; + +import com.cloud.event.EventTypes; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.Network; +import com.cloud.offering.DiskOffering; +import com.cloud.user.Account; +import com.cloud.utils.net.NetUtils; +import com.cloud.vm.VmDetailConstants; +import com.google.common.base.Strings; + +@APICommand(name = ImportUnmanagedInstanceCmd.API_NAME, + description = "Import unmanaged virtual machine from a given cluster.", + responseObject = UserVmResponse.class, + responseView = ResponseObject.ResponseView.Full, + requestHasSensitiveInfo = false, + responseHasSensitiveInfo = true, + authorized = {RoleType.Admin}, + since = "4.14.0") +public class ImportUnmanagedInstanceCmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(ImportUnmanagedInstanceCmd.class); + public static final String API_NAME = "importUnmanagedInstance"; + + @Inject + public VmImportService vmImportService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.CLUSTER_ID, + type = CommandType.UUID, + entityType = ClusterResponse.class, + required = true, + description = "the cluster ID") + private Long clusterId; + + @Parameter(name = ApiConstants.NAME, + type = CommandType.STRING, + required = true, + description = "the hypervisor name of the instance") + private String name; + + @Parameter(name = ApiConstants.DISPLAY_NAME, + type = CommandType.STRING, + description = "the display name of the instance") + private String displayName; + + @Parameter(name = ApiConstants.HOST_NAME, + type = CommandType.STRING, + description = "the host name of the instance") + private String hostName; + + @Parameter(name = ApiConstants.ACCOUNT, + type = CommandType.STRING, + description = "an optional account for the virtual machine. Must be used with domainId.") + private String accountName; + + @Parameter(name = ApiConstants.DOMAIN_ID, + type = CommandType.UUID, + entityType = DomainResponse.class, + description = "import instance to the domain specified") + private Long domainId; + + @Parameter(name = ApiConstants.PROJECT_ID, + type = CommandType.UUID, + entityType = ProjectResponse.class, + description = "import instance for the project") + private Long projectId; + + @Parameter(name = ApiConstants.TEMPLATE_ID, + type = CommandType.UUID, + entityType = TemplateResponse.class, + required = true, + description = "the ID of the template for the virtual machine") + private Long templateId; + + @Parameter(name = ApiConstants.SERVICE_OFFERING_ID, + type = CommandType.UUID, + entityType = ServiceOfferingResponse.class, + required = true, + description = "the ID of the service offering for the virtual machine") + private Long serviceOfferingId; + + @Parameter(name = ApiConstants.DISK_OFFERING_ID, + type = CommandType.UUID, + entityType = DiskOfferingResponse.class, + required = true, + description = "the ID of the root disk offering for the virtual machine") + private Long diskOfferingId; + + @Parameter(name = ApiConstants.NIC_NETWORK_LIST, + type = CommandType.MAP, + description = "VM nic to network id mapping using keys nic and network") + private Map nicNetworkList; + + @Parameter(name = ApiConstants.NIC_IP_ADDRESS_LIST, + type = CommandType.MAP, + description = "VM nic to ip address mapping using keys nic and ipAddress") + private Map nicIpAddressList; + + @Parameter(name = ApiConstants.DATADISK_OFFERING_LIST, + type = CommandType.MAP, + description = "datadisk template to disk-offering mapping using keys disk and diskOffering") + private Map dataDiskToDiskOfferingList; + + @Parameter(name = ApiConstants.DETAILS, + type = CommandType.MAP, + description = "used to specify the custom parameters.") + private Map details; + + @Parameter(name = ApiConstants.MIGRATE_ALLOWED, + type = CommandType.BOOLEAN, + description = "vm and its volumes are allowed to migrate to different host/pool when offerings passed are incompatible with current host/pool") + private Boolean migrateAllowed; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getClusterId() { + return clusterId; + } + + public String getName() { + return name; + } + + public String getDisplayName() { + return displayName; + } + + public String getHostName() { + return hostName; + } + + public String getAccountName() { + return accountName; + } + + public Long getDomainId() { + return domainId; + } + + public Long getTemplateId() { + return templateId; + } + + public Long getProjectId() { + return projectId; + } + + public Long getServiceOfferingId() { + return serviceOfferingId; + } + + public Long getDiskOfferingId() { + return diskOfferingId; + } + + public Map getNicNetworkList() { + Map nicNetworkMap = new HashMap<>(); + if (MapUtils.isNotEmpty(nicNetworkList)) { + for (Map entry : (Collection>)nicNetworkList.values()) { + String nic = entry.get(VmDetailConstants.NIC); + String networkUuid = entry.get(VmDetailConstants.NETWORK); + if (Strings.isNullOrEmpty(nic) || Strings.isNullOrEmpty(networkUuid) || _entityMgr.findByUuid(Network.class, networkUuid) == null) { + throw new InvalidParameterValueException(String.format("Network ID: %s for NIC ID: %s is invalid", networkUuid, nic)); + } + nicNetworkMap.put(nic, _entityMgr.findByUuid(Network.class, networkUuid).getId()); + } + } + return nicNetworkMap; + } + + public Map getNicIpAddressList() { + Map nicIpAddressMap = new HashMap<>(); + if (MapUtils.isNotEmpty(nicIpAddressList)) { + for (Map entry : (Collection>)nicIpAddressList.values()) { + String nic = entry.get(VmDetailConstants.NIC); + String ipAddress = entry.get(VmDetailConstants.IP_ADDRESS); + if (Strings.isNullOrEmpty(nic) || Strings.isNullOrEmpty(ipAddress) || !NetUtils.isValidIp4(ipAddress)) { + throw new InvalidParameterValueException(String.format("IP Address: %s for NIC ID: %s is invalid", ipAddress, nic)); + } + nicIpAddressMap.put(nic, ipAddress); + } + } + return nicIpAddressMap; + } + + public Map getDataDiskToDiskOfferingList() { + Map dataDiskToDiskOfferingMap = new HashMap<>(); + if (MapUtils.isNotEmpty(dataDiskToDiskOfferingList)) { + for (Map entry : (Collection>)dataDiskToDiskOfferingList.values()) { + String nic = entry.get(VmDetailConstants.DISK); + String offeringUuid = entry.get(VmDetailConstants.DISK_OFFERING); + if (Strings.isNullOrEmpty(nic) || Strings.isNullOrEmpty(offeringUuid) || _entityMgr.findByUuid(DiskOffering.class, offeringUuid) == null) { + throw new InvalidParameterValueException(String.format("Disk offering ID: %s for disk ID: %s is invalid", offeringUuid, nic)); + } + dataDiskToDiskOfferingMap.put(nic, _entityMgr.findByUuid(DiskOffering.class, offeringUuid).getId()); + } + } + return dataDiskToDiskOfferingMap; + } + + public Map getDetails() { + if (MapUtils.isEmpty(details)) { + return new HashMap(); + } + + Collection paramsCollection = details.values(); + Map params = (Map) (paramsCollection.toArray())[0]; + return params; + } + + public Boolean getMigrateAllowed() { + return migrateAllowed == Boolean.TRUE; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_VM_IMPORT; + } + + @Override + public String getEventDescription() { + return "Importing unmanaged VM"; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + UserVmResponse response = vmImportService.importUnmanagedInstance(this); + response.setResponseName(getCommandName()); + setResponseObject(response); + } + + @Override + public String getCommandName() { + return API_NAME.toLowerCase() + BaseAsyncCmd.RESPONSE_SUFFIX; + } + + @Override + public long getEntityOwnerId() { + Long accountId = _accountService.finalyzeAccountId(accountName, domainId, projectId, true); + if (accountId == null) { + Account account = CallContext.current().getCallingAccount(); + if (account != null) { + accountId = account.getId(); + } else { + accountId = Account.ACCOUNT_ID_SYSTEM; + } + } + return accountId; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListUnmanagedInstancesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListUnmanagedInstancesCmd.java new file mode 100644 index 000000000000..aced2c621101 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListUnmanagedInstancesCmd.java @@ -0,0 +1,113 @@ +// 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.api.command.admin.vm; + +import javax.inject.Inject; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.ClusterResponse; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.UnmanagedInstanceResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.vm.UnmanagedInstance; +import org.apache.cloudstack.vm.VmImportService; +import org.apache.log4j.Logger; + +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.user.Account; + +@APICommand(name = ListUnmanagedInstancesCmd.API_NAME, + description = "Lists unmanaged virtual machines for a given cluster.", + responseObject = UnmanagedInstanceResponse.class, + responseView = ResponseObject.ResponseView.Full, + entityType = {UnmanagedInstance.class}, + requestHasSensitiveInfo = false, + responseHasSensitiveInfo = true, + authorized = {RoleType.Admin}, + since = "4.14.0") +public class ListUnmanagedInstancesCmd extends BaseListCmd { + public static final Logger s_logger = Logger.getLogger(ListUnmanagedInstancesCmd.class.getName()); + public static final String API_NAME = "listUnmanagedInstances"; + + @Inject + public VmImportService vmImportService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.CLUSTER_ID, + type = CommandType.UUID, + entityType = ClusterResponse.class, + required = true, + description = "the cluster ID") + private Long clusterId; + + @Parameter(name = ApiConstants.NAME, + type = CommandType.STRING, + description = "the hypervisor name of the instance") + private String name; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getClusterId() { + return clusterId; + } + + public String getName() { + return name; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + ListResponse response = vmImportService.listUnmanagedInstances(this); + response.setResponseName(getCommandName()); + setResponseObject(response); + } + + @Override + public String getCommandName() { + return API_NAME.toLowerCase() + BaseAsyncCmd.RESPONSE_SUFFIX; + } + + @Override + public long getEntityOwnerId() { + Account account = CallContext.current().getCallingAccount(); + if (account != null) { + return account.getId(); + } + return Account.ACCOUNT_ID_SYSTEM; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/DomainRouterResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/DomainRouterResponse.java index 131e3e1de7ed..f69f0153dae3 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/DomainRouterResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/DomainRouterResponse.java @@ -20,8 +20,6 @@ import java.util.LinkedHashSet; import java.util.Set; -import com.google.gson.annotations.SerializedName; - import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; @@ -29,6 +27,7 @@ import com.cloud.serializer.Param; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; +import com.google.gson.annotations.SerializedName; @EntityReference(value = VirtualMachine.class) @SuppressWarnings("unused") @@ -258,6 +257,10 @@ public void setGateway(String gateway) { this.gateway = gateway; } + public String getName() { + return name; + } + public void setName(String name) { this.name = name; } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java index 5c3fd7a75a67..e9cf952d942c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java @@ -16,14 +16,15 @@ // under the License. package org.apache.cloudstack.api.response; -import com.cloud.serializer.Param; -import com.cloud.vm.Nic; -import com.google.gson.annotations.SerializedName; +import java.util.List; + import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; -import java.util.List; +import com.cloud.serializer.Param; +import com.cloud.vm.Nic; +import com.google.gson.annotations.SerializedName; @SuppressWarnings("unused") @EntityReference(value = Nic.class) @@ -113,6 +114,10 @@ public class NicResponse extends BaseResponse { @Param(description = "Id of the NSX Logical Switch Port (if NSX based), null otherwise", since="4.6.0") private String nsxLogicalSwitchPort; + @SerializedName(ApiConstants.VLAN_ID) + @Param(description = "ID of the VLAN/VNI if available", since="4.14.0") + private Integer vlanId; + public void setVmId(String vmId) { this.vmId = vmId; } @@ -303,4 +308,12 @@ public String getNsxLogicalSwitch() { public String getNsxLogicalSwitchPort() { return nsxLogicalSwitchPort; } + + public Integer getVlanId() { + return vlanId; + } + + public void setVlanId(Integer vlanId) { + this.vlanId = vlanId; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceDiskResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceDiskResponse.java new file mode 100644 index 000000000000..f9b506a6fcb4 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceDiskResponse.java @@ -0,0 +1,111 @@ +// 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.api.response; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +public class UnmanagedInstanceDiskResponse extends BaseResponse { + + @SerializedName(ApiConstants.ID) + @Param(description = "the ID of the disk") + private String diskId; + + @SerializedName(ApiConstants.LABEL) + @Param(description = "the label of the disk") + private String label; + + @SerializedName(ApiConstants.CAPACITY) + @Param(description = "the capacity in KB of the disk") + private Long capacity; + + @SerializedName(ApiConstants.IMAGE_PATH) + @Param(description = "the file path of the disk image") + private String imagePath; + + @SerializedName(ApiConstants.CONTROLLER) + @Param(description = "the controller of the disk") + private String controller; + + @SerializedName(ApiConstants.CONTROLLER_UNIT) + @Param(description = "the controller unit of the disk") + private Integer controllerUnit; + + @SerializedName(ApiConstants.POSITION) + @Param(description = "the position of the disk") + private Integer position; + + public String getDiskId() { + return diskId; + } + + public void setDiskId(String diskId) { + this.diskId = diskId; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public Long getCapacity() { + return capacity; + } + + public void setCapacity(Long capacity) { + this.capacity = capacity; + } + + public String getImagePath() { + return imagePath; + } + + public void setImagePath(String imagePath) { + this.imagePath = imagePath; + } + + public String getController() { + return controller; + } + + public void setController(String controller) { + this.controller = controller; + } + + public Integer getControllerUnit() { + return controllerUnit; + } + + public void setControllerUnit(Integer controllerUnit) { + this.controllerUnit = controllerUnit; + } + + public Integer getPosition() { + return position; + } + + public void setPosition(Integer position) { + this.position = position; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java new file mode 100644 index 000000000000..cd3f7a8f8259 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java @@ -0,0 +1,178 @@ +// 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.api.response; + +import java.util.LinkedHashSet; +import java.util.Set; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; +import org.apache.cloudstack.vm.UnmanagedInstance; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +@EntityReference(value = UnmanagedInstance.class) +public class UnmanagedInstanceResponse extends BaseResponse { + + @SerializedName(ApiConstants.NAME) + @Param(description = "the name of the virtual machine") + private String name; + + @SerializedName(ApiConstants.CLUSTER_ID) + @Param(description = "the ID of the cluster to which virtual machine belongs") + private String clusterId; + + @SerializedName(ApiConstants.HOST_ID) + @Param(description = "the ID of the host to which virtual machine belongs") + private String hostId; + + @SerializedName(ApiConstants.POWER_STATE) + @Param(description = "the power state of the virtual machine") + private String powerState; + + @SerializedName(ApiConstants.CPU_NUMBER) + @Param(description = "the CPU cores of the virtual machine") + private Integer cpuCores; + + @SerializedName(ApiConstants.CPU_CORE_PER_SOCKET) + @Param(description = "the CPU cores per socket for the virtual machine. VMware specific") + private Integer cpuCoresPerSocket; + + @SerializedName(ApiConstants.CPU_SPEED) + @Param(description = "the CPU speed of the virtual machine") + private Integer cpuSpeed; + + @SerializedName(ApiConstants.MEMORY) + @Param(description = "the memory of the virtual machine in MB") + private Integer memory; + + @SerializedName(ApiConstants.OS_DISPLAY_NAME) + @Param(description = "the operating system of the virtual machine") + private String operatingSystem; + + @SerializedName(ApiConstants.DISK) + @Param(description = "the list of disks associated with the virtual machine", responseObject = UnmanagedInstanceDiskResponse.class) + private Set disks; + + @SerializedName(ApiConstants.NIC) + @Param(description = "the list of nics associated with the virtual machine", responseObject = NicResponse.class) + private Set nics; + + public UnmanagedInstanceResponse() { + disks = new LinkedHashSet(); + nics = new LinkedHashSet(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getClusterId() { + return clusterId; + } + + public void setClusterId(String clusterId) { + this.clusterId = clusterId; + } + + public String getHostId() { + return hostId; + } + + public void setHostId(String hostId) { + this.hostId = hostId; + } + + public String getPowerState() { + return powerState; + } + + public void setPowerState(String powerState) { + this.powerState = powerState; + } + + public Integer getCpuCores() { + return cpuCores; + } + + public void setCpuCores(Integer cpuCores) { + this.cpuCores = cpuCores; + } + + public Integer getCpuCoresPerSocket() { + return cpuCoresPerSocket; + } + + public void setCpuCoresPerSocket(Integer cpuCoresPerSocket) { + this.cpuCoresPerSocket = cpuCoresPerSocket; + } + + public Integer getCpuSpeed() { + return cpuSpeed; + } + + public void setCpuSpeed(Integer cpuSpeed) { + this.cpuSpeed = cpuSpeed; + } + + public Integer getMemory() { + return memory; + } + + public void setMemory(Integer memory) { + this.memory = memory; + } + + public String getOperatingSystem() { + return operatingSystem; + } + + public void setOperatingSystem(String operatingSystem) { + this.operatingSystem = operatingSystem; + } + + public Set getDisks() { + return disks; + } + + public void setDisks(Set disks) { + this.disks = disks; + } + + public void addDisk(UnmanagedInstanceDiskResponse disk) { + this.disks.add(disk); + } + + public Set getNics() { + return nics; + } + + public void setNics(Set nics) { + this.nics = nics; + } + + public void addNic(NicResponse nic) { + this.nics.add(nic); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java new file mode 100644 index 000000000000..43e2fa6e8887 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java @@ -0,0 +1,263 @@ +// 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.vm; + +import java.util.List; + +public class UnmanagedInstance { + + public enum PowerState { + PowerUnknown, + PowerOn, + PowerOff + } + + private String name; + + private PowerState powerState; + + private Integer cpuCores; + + private Integer cpuCoresPerSocket; + + private Integer memory; + + private Integer cpuSpeed; + + private String operatingSystem; + + private List disks; + + private List nics; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public PowerState getPowerState() { + return powerState; + } + + public void setPowerState(PowerState powerState) { + this.powerState = powerState; + } + + public Integer getCpuCores() { + return cpuCores; + } + + public void setCpuCores(Integer cpuCores) { + this.cpuCores = cpuCores; + } + + public Integer getCpuCoresPerSocket() { + return cpuCoresPerSocket; + } + + public void setCpuCoresPerSocket(Integer cpuCoresPerSocket) { + this.cpuCoresPerSocket = cpuCoresPerSocket; + } + + public Integer getMemory() { + return memory; + } + + public void setMemory(Integer memory) { + this.memory = memory; + } + + public Integer getCpuSpeed() { + return cpuSpeed; + } + + public void setCpuSpeed(Integer cpuSpeed) { + this.cpuSpeed = cpuSpeed; + } + + public String getOperatingSystem() { + return operatingSystem; + } + + public void setOperatingSystem(String operatingSystem) { + this.operatingSystem = operatingSystem; + } + + public List getDisks() { + return disks; + } + + public void setDisks(List disks) { + this.disks = disks; + } + + public List getNics() { + return nics; + } + + public void setNics(List nics) { + this.nics = nics; + } + + public static class Disk { + private String diskId; + + private String label; + + private Long capacity; + + private String imagePath; + + private String controller; + + private Integer controllerUnit; + + private Integer position; + + public String getDiskId() { + return diskId; + } + + public void setDiskId(String diskId) { + this.diskId = diskId; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public Long getCapacity() { + return capacity; + } + + public void setCapacity(Long capacity) { + this.capacity = capacity; + } + + public String getImagePath() { + return imagePath; + } + + public void setImagePath(String imagePath) { + this.imagePath = imagePath; + } + + public String getController() { + return controller; + } + + public void setController(String controller) { + this.controller = controller; + } + + public Integer getControllerUnit() { + return controllerUnit; + } + + public void setControllerUnit(Integer controllerUnit) { + this.controllerUnit = controllerUnit; + } + + public Integer getPosition() { + return position; + } + + public void setPosition(Integer position) { + this.position = position; + } + } + + public static class Nic { + private String nicId; + + private String adapterType; + + private String macAddress; + + private String network; + + private Integer vlan; + + private String ipAddress; + + private String pciSlot; + + public String getNicId() { + return nicId; + } + + public void setNicId(String nicId) { + this.nicId = nicId; + } + + public String getAdapterType() { + return adapterType; + } + + public void setAdapterType(String adapterType) { + this.adapterType = adapterType; + } + + public String getMacAddress() { + return macAddress; + } + + public void setMacAddress(String macAddress) { + this.macAddress = macAddress; + } + + public String getNetwork() { + return network; + } + + public void setNetwork(String network) { + this.network = network; + } + + public Integer getVlan() { + return vlan; + } + + public void setVlan(Integer vlan) { + this.vlan = vlan; + } + + public String getIpAddress() { + return ipAddress; + } + + public void setIpAddress(String ipAddress) { + this.ipAddress = ipAddress; + } + + public String getPciSlot() { + return pciSlot; + } + + public void setPciSlot(String pciSlot) { + this.pciSlot = pciSlot; + } + } +} diff --git a/api/src/main/java/org/apache/cloudstack/vm/VmImportService.java b/api/src/main/java/org/apache/cloudstack/vm/VmImportService.java new file mode 100644 index 000000000000..783a5d295eed --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/vm/VmImportService.java @@ -0,0 +1,31 @@ +// 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.vm; + +import org.apache.cloudstack.api.command.admin.vm.ImportUnmanagedInstanceCmd; +import org.apache.cloudstack.api.command.admin.vm.ListUnmanagedInstancesCmd; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.UnmanagedInstanceResponse; +import org.apache.cloudstack.api.response.UserVmResponse; + +import com.cloud.utils.component.PluggableService; + +public interface VmImportService extends PluggableService { + ListResponse listUnmanagedInstances(ListUnmanagedInstancesCmd cmd); + UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd); +} diff --git a/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesAnswer.java b/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesAnswer.java new file mode 100644 index 000000000000..682af8479c6e --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesAnswer.java @@ -0,0 +1,58 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package com.cloud.agent.api; + +import java.util.HashMap; + +import org.apache.cloudstack.vm.UnmanagedInstance; + +@LogLevel(LogLevel.Log4jLevel.Trace) +public class GetUnmanagedInstancesAnswer extends Answer { + + private String instanceName; + private HashMap unmanagedInstances; + + GetUnmanagedInstancesAnswer() { + } + + public GetUnmanagedInstancesAnswer(GetUnmanagedInstancesCommand cmd, String details, HashMap unmanagedInstances) { + super(cmd, true, details); + this.instanceName = cmd.getInstanceName(); + this.unmanagedInstances = unmanagedInstances; + } + + public String getInstanceName() { + return instanceName; + } + + public void setInstanceName(String instanceName) { + this.instanceName = instanceName; + } + + public HashMap getUnmanagedInstances() { + return unmanagedInstances; + } + + public void setUnmanagedInstances(HashMap unmanagedInstances) { + this.unmanagedInstances = unmanagedInstances; + } + + public String getString() { + return "GetUnmanagedInstancesAnswer [instanceName=" + instanceName + "]"; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesCommand.java b/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesCommand.java new file mode 100644 index 000000000000..68b136dd196a --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesCommand.java @@ -0,0 +1,67 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package com.cloud.agent.api; + +import java.util.List; + +@LogLevel(LogLevel.Log4jLevel.Trace) +public class GetUnmanagedInstancesCommand extends Command { + + String instanceName; + + List managedInstancesNames; + + public GetUnmanagedInstancesCommand() { + } + + public GetUnmanagedInstancesCommand(String instanceName) { + this.instanceName = instanceName; + } + + public String getInstanceName() { + return instanceName; + } + + public void setInstanceName(String instanceName) { + this.instanceName = instanceName; + } + + public List getManagedInstancesNames() { + return managedInstancesNames; + } + + public void setManagedInstancesNames(List managedInstancesNames) { + this.managedInstancesNames = managedInstancesNames; + } + + public boolean hasManagedInstance(String name) { + if (managedInstancesNames!=null && !managedInstancesNames.isEmpty()) { + return managedInstancesNames.contains(name); + } + return false; + } + + @Override + public boolean executeInSequence() { + return false; + } + + public String getString() { + return "GetUnmanagedInstancesCommand [instanceName=" + instanceName + "]"; + } +} diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java index 94a4259a6897..c0c82ea70f64 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java @@ -313,4 +313,6 @@ void implementNetworkElementsAndResources(DeployDestination dest, ReservationCon * Remove entry from /etc/dhcphosts and /etc/hosts on virtual routers */ void cleanupNicDhcpDnsEntry(Network network, VirtualMachineProfile vmProfile, NicProfile nicProfile); + + Pair importNic(final String macAddress, int deviceId, final Network network, final Boolean isDefaultNic, final VirtualMachine vm, final String ipAddress); } diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java index fa6f2c6fb9d4..f21b0f0c574e 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java @@ -127,4 +127,24 @@ DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering offerin StoragePool findStoragePool(DiskProfile dskCh, DataCenter dc, Pod pod, Long clusterId, Long hostId, VirtualMachine vm, Set avoid); void updateVolumeDiskChain(long volumeId, String path, String chainInfo); + + /** + * Imports an existing volume for a VM into database. Useful while ingesting an unmanaged VM. + * @param type Type of the volume - ROOT, DATADISK, etc + * @param name Name of the volume + * @param offering DiskOffering for the volume + * @param size DiskOffering for the volume + * @param minIops minimum IOPS for the disk, if not passed DiskOffering value will be used + * @param maxIops maximum IOPS for the disk, if not passed DiskOffering value will be used + * @param vm VirtualMachine this volume is attached to + * @param template Template of the VM of the volume + * @param owner owner Account for the volume + * @param deviceId device ID of the virtual disk + * @param poolId ID of pool in which volume is stored + * @param path image path of the volume + * @param chainInfo chain info for the volume. Hypervisor specific. + * @return DiskProfile of imported volume + */ + DiskProfile importVolume(Type type, String name, DiskOffering offering, Long size, Long minIops, Long maxIops, VirtualMachine vm, VirtualMachineTemplate template, + Account owner, Long deviceId, Long poolId, String path, String chainInfo); } diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index 51b71d911ce9..6ed770046fed 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -3941,6 +3941,49 @@ public NicVO savePlaceholderNic(final Network network, final String ip4Address, return _nicDao.persist(nic); } + @DB + @Override + public Pair importNic(final String macAddress, int deviceId, final Network network, final Boolean isDefaultNic, final VirtualMachine vm, final String ipAddress) + throws ConcurrentOperationException { + s_logger.debug("Allocating nic for vm " + vm.getUuid() + " in network " + network + " during ingestion"); + + NicVO vo = Transaction.execute(new TransactionCallback() { + @Override + public NicVO doInTransaction(TransactionStatus status) { + NicVO vo = new NicVO(network.getGuruName(), vm.getId(), network.getId(), vm.getType()); + vo.setMacAddress(macAddress); + vo.setAddressFormat(Networks.AddressFormat.Ip4); + vo.setIPv4Address(ipAddress); + if (!Strings.isNullOrEmpty(ipAddress)) { + vo.setIPv4Address(ipAddress); + } + if (!Strings.isNullOrEmpty(network.getGateway())) { + vo.setIPv4Gateway(network.getGateway()); + } + if (!Strings.isNullOrEmpty(network.getCidr())) { + vo.setIPv4Netmask(NetUtils.cidr2Netmask(network.getCidr())); + } + vo.setBroadcastUri(network.getBroadcastUri()); + vo.setMode(network.getMode()); + vo.setState(Nic.State.Reserved); + vo.setReservationStrategy(ReservationStrategy.Start); + vo.setReservationId(UUID.randomUUID().toString()); + vo.setDeviceId(deviceId); + vo.setIsolationUri(network.getBroadcastUri()); + vo.setDeviceId(deviceId); + vo.setDefaultNic(isDefaultNic); + vo = _nicDao.persist(vo); + return vo; + } + }); + + final Integer networkRate = _networkModel.getNetworkRate(network.getId(), vm.getId()); + final NicProfile vmNic = new NicProfile(vo, network, vo.getBroadcastUri(), vo.getIsolationUri(), networkRate, _networkModel.isSecurityGroupSupportedInNetwork(network), + _networkModel.getNetworkTag(vm.getHypervisorType(), network)); + + return new Pair(vmNic, Integer.valueOf(deviceId)); + } + @Override public String getConfigComponentName() { return NetworkOrchestrationService.class.getSimpleName(); diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java index 6e71864c4473..afba2baecd00 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java @@ -30,7 +30,6 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.storage.VolumeApiService; import org.apache.cloudstack.api.command.admin.vm.MigrateVMCmd; import org.apache.cloudstack.api.command.admin.volume.MigrateVolumeCmdByAdmin; import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd; @@ -106,6 +105,7 @@ import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.Volume; import com.cloud.storage.Volume.Type; +import com.cloud.storage.VolumeApiService; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.VolumeDao; @@ -1626,4 +1626,63 @@ public void updateVolumeDiskChain(long volumeId, String path, String chainInfo) _volsDao.update(volumeId, vol); } } + + @Override + public DiskProfile importVolume(Type type, String name, DiskOffering offering, Long size, Long minIops, Long maxIops, + VirtualMachine vm, VirtualMachineTemplate template, Account owner, + Long deviceId, Long poolId, String path, String chainInfo) { + if (size == null) { + size = offering.getDiskSize(); + } else { + size = (size * 1024 * 1024 * 1024); + } + + minIops = minIops != null ? minIops : offering.getMinIops(); + maxIops = maxIops != null ? maxIops : offering.getMaxIops(); + + VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterId(), owner.getDomainId(), owner.getId(), offering.getId(), offering.getProvisioningType(), size, minIops, maxIops, null); + if (vm != null) { + vol.setInstanceId(vm.getId()); + } + + if (deviceId != null) { + vol.setDeviceId(deviceId); + } else if (type.equals(Type.ROOT)) { + vol.setDeviceId(0l); + } else { + vol.setDeviceId(1l); + } + if (template.getFormat() == ImageFormat.ISO) { + vol.setIsoId(template.getId()); + } else if (template.getTemplateType().equals(Storage.TemplateType.DATADISK)) { + vol.setTemplateId(template.getId()); + } + + if (type == Type.ROOT) { + vol.setTemplateId(template.getId()); + } + + // display flag matters only for the User vms + if (vm.getType() == VirtualMachine.Type.User) { + UserVmVO userVm = _userVmDao.findById(vm.getId()); + vol.setDisplayVolume(userVm.isDisplayVm()); + } + + vol.setFormat(getSupportedImageFormatForCluster(vm.getHypervisorType())); + vol.setPoolId(poolId); + vol.setPath(path); + vol.setChainInfo(chainInfo); + vol.setState(Volume.State.Ready); + vol = _volsDao.persist(vol); + + // Save usage event and update resource count for user vm volumes + if (vm.getType() == VirtualMachine.Type.User) { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, vol.getAccountId(), vol.getDataCenterId(), vol.getId(), vol.getName(), offering.getId(), null, size, + Volume.class.getName(), vol.getUuid(), vol.isDisplayVolume()); + + _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.volume, vol.isDisplayVolume()); + _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.primary_storage, vol.isDisplayVolume(), new Long(vol.getSize())); + } + return toDiskProfile(vol, offering); + } } diff --git a/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDao.java b/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDao.java index 74728f826ce5..8ac44b99c1d5 100644 --- a/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDao.java +++ b/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDao.java @@ -48,7 +48,7 @@ List createSystemServiceOfferings(String name, String uniqueN boolean isDynamic(long serviceOfferingId); - ServiceOfferingVO getcomputeOffering(ServiceOfferingVO serviceOffering, Map customParameters); + ServiceOfferingVO getComputeOffering(ServiceOfferingVO serviceOffering, Map customParameters); ServiceOfferingVO findDefaultSystemOffering(String offeringName, Boolean useLocalStorage); } diff --git a/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDaoImpl.java b/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDaoImpl.java index 96b0c350a741..76e867b8f538 100644 --- a/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDaoImpl.java @@ -161,7 +161,7 @@ public ServiceOfferingVO findById(Long vmId, long serviceOfferingId) { throw new CloudRuntimeException("missing argument vmId"); } Map dynamicOffering = userVmDetailsDao.listDetailsKeyPairs(vmId); - return getcomputeOffering(offering, dynamicOffering); + return getComputeOffering(offering, dynamicOffering); } return offering; } @@ -175,7 +175,7 @@ public ServiceOfferingVO findByIdIncludingRemoved(Long vmId, long serviceOfferin throw new CloudRuntimeException("missing argument vmId"); } Map dynamicOffering = userVmDetailsDao.listDetailsKeyPairs(vmId); - return getcomputeOffering(offering, dynamicOffering); + return getComputeOffering(offering, dynamicOffering); } return offering; } @@ -187,7 +187,7 @@ public boolean isDynamic(long serviceOfferingId) { } @Override - public ServiceOfferingVO getcomputeOffering(ServiceOfferingVO serviceOffering, Map customParameters) { + public ServiceOfferingVO getComputeOffering(ServiceOfferingVO serviceOffering, Map customParameters) { ServiceOfferingVO dummyoffering = new ServiceOfferingVO(serviceOffering); dummyoffering.setDynamicFlag(true); if (customParameters.containsKey(UsageEventVO.DynamicParameters.cpuNumber.name())) { diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 02f758ba844b..4d14f0727119 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -44,20 +44,8 @@ import javax.naming.ConfigurationException; import javax.xml.datatype.XMLGregorianCalendar; -import com.cloud.agent.api.storage.OVFPropertyTO; -import com.cloud.utils.crypt.DBEncryptionUtil; -import com.vmware.vim25.ArrayUpdateOperation; -import com.vmware.vim25.VAppOvfSectionInfo; -import com.vmware.vim25.VAppOvfSectionSpec; -import com.vmware.vim25.VAppProductInfo; -import com.vmware.vim25.VAppProductSpec; -import com.vmware.vim25.VAppPropertyInfo; -import com.vmware.vim25.VAppPropertySpec; -import com.vmware.vim25.VmConfigInfo; -import com.vmware.vim25.VmConfigSpec; -import org.apache.commons.collections.CollectionUtils; - import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.vm.UnmanagedInstance; import org.apache.cloudstack.storage.command.CopyCommand; import org.apache.cloudstack.storage.command.StorageSubSystemCommand; import org.apache.cloudstack.storage.configdrive.ConfigDrive; @@ -66,6 +54,7 @@ import org.apache.cloudstack.storage.to.TemplateObjectTO; import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.log4j.Logger; @@ -101,6 +90,8 @@ import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.GetStorageStatsAnswer; import com.cloud.agent.api.GetStorageStatsCommand; +import com.cloud.agent.api.GetUnmanagedInstancesAnswer; +import com.cloud.agent.api.GetUnmanagedInstancesCommand; import com.cloud.agent.api.GetVmDiskStatsAnswer; import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmIpAddressCommand; @@ -184,6 +175,7 @@ import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.storage.MigrateVolumeAnswer; import com.cloud.agent.api.storage.MigrateVolumeCommand; +import com.cloud.agent.api.storage.OVFPropertyTO; import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; import com.cloud.agent.api.storage.ResizeVolumeAnswer; @@ -255,6 +247,7 @@ import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; import com.cloud.utils.Ternary; +import com.cloud.utils.crypt.DBEncryptionUtil; import com.cloud.utils.db.DB; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.ExceptionUtil; @@ -268,8 +261,10 @@ import com.cloud.vm.VirtualMachine.PowerState; import com.cloud.vm.VirtualMachineName; import com.cloud.vm.VmDetailConstants; +import com.google.common.base.Strings; import com.google.gson.Gson; import com.vmware.vim25.AboutInfo; +import com.vmware.vim25.ArrayUpdateOperation; import com.vmware.vim25.BoolPolicy; import com.vmware.vim25.ComputeResourceSummary; import com.vmware.vim25.CustomFieldStringValue; @@ -282,9 +277,11 @@ import com.vmware.vim25.DistributedVirtualSwitchPortCriteria; import com.vmware.vim25.DynamicProperty; import com.vmware.vim25.GuestInfo; +import com.vmware.vim25.GuestNicInfo; import com.vmware.vim25.HostCapability; import com.vmware.vim25.HostHostBusAdapter; import com.vmware.vim25.HostInternetScsiHba; +import com.vmware.vim25.HostPortGroupSpec; import com.vmware.vim25.ManagedObjectReference; import com.vmware.vim25.ObjectContent; import com.vmware.vim25.OptionValue; @@ -297,6 +294,12 @@ import com.vmware.vim25.PerfQuerySpec; import com.vmware.vim25.RuntimeFaultFaultMsg; import com.vmware.vim25.ToolsUnavailableFaultMsg; +import com.vmware.vim25.VAppOvfSectionInfo; +import com.vmware.vim25.VAppOvfSectionSpec; +import com.vmware.vim25.VAppProductInfo; +import com.vmware.vim25.VAppProductSpec; +import com.vmware.vim25.VAppPropertyInfo; +import com.vmware.vim25.VAppPropertySpec; import com.vmware.vim25.VMwareDVSPortSetting; import com.vmware.vim25.VimPortType; import com.vmware.vim25.VirtualDevice; @@ -309,6 +312,7 @@ import com.vmware.vim25.VirtualEthernetCardDistributedVirtualPortBackingInfo; import com.vmware.vim25.VirtualEthernetCardNetworkBackingInfo; import com.vmware.vim25.VirtualEthernetCardOpaqueNetworkBackingInfo; +import com.vmware.vim25.VirtualIDEController; import com.vmware.vim25.VirtualMachineConfigSpec; import com.vmware.vim25.VirtualMachineFileInfo; import com.vmware.vim25.VirtualMachineFileLayoutEx; @@ -320,7 +324,10 @@ 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; import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec; public class VmwareResource implements StoragePoolResource, ServerResource, VmwareHostService, VirtualRouterDeployer { @@ -378,6 +385,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa protected VirtualRoutingResource _vrResource; protected final static HashMap s_powerStatesTable = new HashMap(); + static { s_powerStatesTable.put(VirtualMachinePowerState.POWERED_ON, PowerState.PowerOn); s_powerStatesTable.put(VirtualMachinePowerState.POWERED_OFF, PowerState.PowerOff); @@ -430,118 +438,120 @@ public Answer executeRequest(Command cmd) { Class clz = cmd.getClass(); if (cmd instanceof NetworkElementCommand) { - return _vrResource.executeRequest((NetworkElementCommand)cmd); + return _vrResource.executeRequest((NetworkElementCommand) cmd); } else if (clz == ReadyCommand.class) { - answer = execute((ReadyCommand)cmd); + answer = execute((ReadyCommand) cmd); } else if (clz == GetHostStatsCommand.class) { - answer = execute((GetHostStatsCommand)cmd); + answer = execute((GetHostStatsCommand) cmd); } else if (clz == GetVmStatsCommand.class) { - answer = execute((GetVmStatsCommand)cmd); + answer = execute((GetVmStatsCommand) cmd); } else if (clz == GetVmNetworkStatsCommand.class) { answer = execute((GetVmNetworkStatsCommand) cmd); } else if (clz == GetVmDiskStatsCommand.class) { - answer = execute((GetVmDiskStatsCommand)cmd); + answer = execute((GetVmDiskStatsCommand) cmd); } else if (cmd instanceof GetVolumeStatsCommand) { - return execute((GetVolumeStatsCommand)cmd); + return execute((GetVolumeStatsCommand) cmd); } else if (clz == CheckHealthCommand.class) { - answer = execute((CheckHealthCommand)cmd); + answer = execute((CheckHealthCommand) cmd); } else if (clz == StopCommand.class) { - answer = execute((StopCommand)cmd); + answer = execute((StopCommand) cmd); } else if (clz == RebootRouterCommand.class) { - answer = execute((RebootRouterCommand)cmd); + answer = execute((RebootRouterCommand) cmd); } else if (clz == RebootCommand.class) { - answer = execute((RebootCommand)cmd); + answer = execute((RebootCommand) cmd); } else if (clz == CheckVirtualMachineCommand.class) { - answer = execute((CheckVirtualMachineCommand)cmd); + answer = execute((CheckVirtualMachineCommand) cmd); } else if (clz == PrepareForMigrationCommand.class) { - answer = execute((PrepareForMigrationCommand)cmd); + answer = execute((PrepareForMigrationCommand) cmd); } else if (clz == MigrateCommand.class) { - answer = execute((MigrateCommand)cmd); + answer = execute((MigrateCommand) cmd); } else if (clz == MigrateVmToPoolCommand.class) { - answer = execute((MigrateVmToPoolCommand)cmd); + answer = execute((MigrateVmToPoolCommand) cmd); } else if (clz == MigrateWithStorageCommand.class) { - answer = execute((MigrateWithStorageCommand)cmd); + answer = execute((MigrateWithStorageCommand) cmd); } else if (clz == MigrateVolumeCommand.class) { - answer = execute((MigrateVolumeCommand)cmd); + answer = execute((MigrateVolumeCommand) cmd); } else if (clz == DestroyCommand.class) { - answer = execute((DestroyCommand)cmd); + answer = execute((DestroyCommand) cmd); } else if (clz == CreateStoragePoolCommand.class) { - return execute((CreateStoragePoolCommand)cmd); + return execute((CreateStoragePoolCommand) cmd); } else if (clz == ModifyTargetsCommand.class) { - answer = execute((ModifyTargetsCommand)cmd); + answer = execute((ModifyTargetsCommand) cmd); } else if (clz == ModifyStoragePoolCommand.class) { - answer = execute((ModifyStoragePoolCommand)cmd); + answer = execute((ModifyStoragePoolCommand) cmd); } else if (clz == DeleteStoragePoolCommand.class) { - answer = execute((DeleteStoragePoolCommand)cmd); + answer = execute((DeleteStoragePoolCommand) cmd); } else if (clz == CopyVolumeCommand.class) { - answer = execute((CopyVolumeCommand)cmd); + answer = execute((CopyVolumeCommand) cmd); } else if (clz == AttachIsoCommand.class) { - answer = execute((AttachIsoCommand)cmd); + answer = execute((AttachIsoCommand) cmd); } else if (clz == ValidateSnapshotCommand.class) { - answer = execute((ValidateSnapshotCommand)cmd); + answer = execute((ValidateSnapshotCommand) cmd); } else if (clz == ManageSnapshotCommand.class) { - answer = execute((ManageSnapshotCommand)cmd); + answer = execute((ManageSnapshotCommand) cmd); } else if (clz == BackupSnapshotCommand.class) { - answer = execute((BackupSnapshotCommand)cmd); + answer = execute((BackupSnapshotCommand) cmd); } else if (clz == CreateVolumeFromSnapshotCommand.class) { - answer = execute((CreateVolumeFromSnapshotCommand)cmd); + answer = execute((CreateVolumeFromSnapshotCommand) cmd); } else if (clz == CreatePrivateTemplateFromVolumeCommand.class) { - answer = execute((CreatePrivateTemplateFromVolumeCommand)cmd); + answer = execute((CreatePrivateTemplateFromVolumeCommand) cmd); } else if (clz == CreatePrivateTemplateFromSnapshotCommand.class) { - answer = execute((CreatePrivateTemplateFromSnapshotCommand)cmd); + answer = execute((CreatePrivateTemplateFromSnapshotCommand) cmd); } else if (clz == UpgradeSnapshotCommand.class) { - answer = execute((UpgradeSnapshotCommand)cmd); + answer = execute((UpgradeSnapshotCommand) cmd); } else if (clz == GetStorageStatsCommand.class) { - answer = execute((GetStorageStatsCommand)cmd); + answer = execute((GetStorageStatsCommand) cmd); } else if (clz == PrimaryStorageDownloadCommand.class) { - answer = execute((PrimaryStorageDownloadCommand)cmd); + answer = execute((PrimaryStorageDownloadCommand) cmd); } else if (clz == GetVncPortCommand.class) { - answer = execute((GetVncPortCommand)cmd); + answer = execute((GetVncPortCommand) cmd); } else if (clz == SetupCommand.class) { - answer = execute((SetupCommand)cmd); + answer = execute((SetupCommand) cmd); } else if (clz == MaintainCommand.class) { - answer = execute((MaintainCommand)cmd); + answer = execute((MaintainCommand) cmd); } else if (clz == PingTestCommand.class) { - answer = execute((PingTestCommand)cmd); + answer = execute((PingTestCommand) cmd); } else if (clz == CheckOnHostCommand.class) { - answer = execute((CheckOnHostCommand)cmd); + answer = execute((CheckOnHostCommand) cmd); } else if (clz == ModifySshKeysCommand.class) { - answer = execute((ModifySshKeysCommand)cmd); + answer = execute((ModifySshKeysCommand) cmd); } else if (clz == NetworkUsageCommand.class) { - answer = execute((NetworkUsageCommand)cmd); + answer = execute((NetworkUsageCommand) cmd); } else if (clz == StartCommand.class) { - answer = execute((StartCommand)cmd); + answer = execute((StartCommand) cmd); } else if (clz == CheckSshCommand.class) { - answer = execute((CheckSshCommand)cmd); + answer = execute((CheckSshCommand) cmd); } else if (clz == CheckNetworkCommand.class) { - answer = execute((CheckNetworkCommand)cmd); + answer = execute((CheckNetworkCommand) cmd); } else if (clz == PlugNicCommand.class) { - answer = execute((PlugNicCommand)cmd); + answer = execute((PlugNicCommand) cmd); } else if (clz == ReplugNicCommand.class) { - answer = execute((ReplugNicCommand)cmd); + answer = execute((ReplugNicCommand) cmd); } else if (clz == UnPlugNicCommand.class) { - answer = execute((UnPlugNicCommand)cmd); + answer = execute((UnPlugNicCommand) cmd); } else if (cmd instanceof CreateVMSnapshotCommand) { - return execute((CreateVMSnapshotCommand)cmd); + return execute((CreateVMSnapshotCommand) cmd); } else if (cmd instanceof DeleteVMSnapshotCommand) { - return execute((DeleteVMSnapshotCommand)cmd); + return execute((DeleteVMSnapshotCommand) cmd); } else if (cmd instanceof RevertToVMSnapshotCommand) { - return execute((RevertToVMSnapshotCommand)cmd); + return execute((RevertToVMSnapshotCommand) cmd); } else if (clz == ResizeVolumeCommand.class) { - return execute((ResizeVolumeCommand)cmd); + return execute((ResizeVolumeCommand) cmd); } else if (clz == UnregisterVMCommand.class) { - return execute((UnregisterVMCommand)cmd); + return execute((UnregisterVMCommand) cmd); } else if (cmd instanceof StorageSubSystemCommand) { - checkStorageProcessorAndHandlerNfsVersionAttribute((StorageSubSystemCommand)cmd); - return storageHandler.handleStorageCommands((StorageSubSystemCommand)cmd); + checkStorageProcessorAndHandlerNfsVersionAttribute((StorageSubSystemCommand) cmd); + return storageHandler.handleStorageCommands((StorageSubSystemCommand) cmd); } else if (clz == ScaleVmCommand.class) { - return execute((ScaleVmCommand)cmd); + return execute((ScaleVmCommand) cmd); } else if (clz == PvlanSetupCommand.class) { - return execute((PvlanSetupCommand)cmd); + return execute((PvlanSetupCommand) cmd); } else if (clz == GetVmIpAddressCommand.class) { - return execute((GetVmIpAddressCommand)cmd); + return execute((GetVmIpAddressCommand) cmd); } else if (clz == UnregisterNicCommand.class) { - answer = execute((UnregisterNicCommand)cmd); + answer = execute((UnregisterNicCommand) cmd); + } else if (clz == GetUnmanagedInstancesCommand.class) { + answer = execute((GetUnmanagedInstancesCommand) cmd); } else { answer = Answer.createUnsupportedCommandAnswer(cmd); } @@ -587,6 +597,7 @@ public Answer executeRequest(Command cmd) { * If _storageNfsVersion is not null -> nothing to do, version already set.
* If _storageNfsVersion is null -> examine StorageSubSystemCommand to get NFS version and set it * to the storage processor and storage handler. + * * @param cmd command to execute */ protected void checkStorageProcessorAndHandlerNfsVersionAttribute(StorageSubSystemCommand cmd) { @@ -595,18 +606,19 @@ protected void checkStorageProcessorAndHandlerNfsVersionAttribute(StorageSubSyst if (cmd instanceof CopyCommand) { EnumMap params = new EnumMap( VmwareStorageProcessorConfigurableFields.class); - examineStorageSubSystemCommandNfsVersion((CopyCommand)cmd, params); - params = examineStorageSubSystemCommandFullCloneFlagForVmware((CopyCommand)cmd, params); + examineStorageSubSystemCommandNfsVersion((CopyCommand) cmd, params); + params = examineStorageSubSystemCommandFullCloneFlagForVmware((CopyCommand) cmd, params); reconfigureProcessorByHandler(params); } } /** * Reconfigure processor by handler + * * @param params params */ protected void reconfigureProcessorByHandler(EnumMap params) { - VmwareStorageSubsystemCommandHandler handler = (VmwareStorageSubsystemCommandHandler)storageHandler; + VmwareStorageSubsystemCommandHandler handler = (VmwareStorageSubsystemCommandHandler) storageHandler; boolean success = handler.reconfigureStorageProcessor(params); if (success) { s_logger.info("VmwareStorageProcessor and VmwareStorageSubsystemCommandHandler successfully reconfigured"); @@ -617,18 +629,19 @@ protected void reconfigureProcessorByHandler(EnumMap examineStorageSubSystemCommandFullCloneFlagForVmware(CopyCommand cmd, - EnumMap params) { + EnumMap params) { EnumMap paramsCopy = new EnumMap(params); HypervisorType hypervisor = cmd.getDestTO().getHypervisorType(); if (hypervisor != null && hypervisor.equals(HypervisorType.VMware)) { DataStoreTO destDataStore = cmd.getDestTO().getDataStore(); if (destDataStore instanceof PrimaryDataStoreTO) { - PrimaryDataStoreTO dest = (PrimaryDataStoreTO)destDataStore; + PrimaryDataStoreTO dest = (PrimaryDataStoreTO) destDataStore; if (dest.isFullCloneFlag() != null) { paramsCopy.put(VmwareStorageProcessorConfigurableFields.FULL_CLONE_FLAG, dest.isFullCloneFlag().booleanValue()); } @@ -639,7 +652,8 @@ protected EnumMap examineStora /** * Examine StorageSubSystem command to get storage NFS version, if provided - * @param cmd command to execute + * + * @param cmd command to execute * @param params params */ protected void examineStorageSubSystemCommandNfsVersion(CopyCommand cmd, EnumMap params) { @@ -647,7 +661,7 @@ protected void examineStorageSubSystemCommandNfsVersion(CopyCommand cmd, EnumMap boolean nfsVersionFound = false; if (srcDataStore instanceof NfsTO) { - nfsVersionFound = getStorageNfsVersionFromNfsTO((NfsTO)srcDataStore); + nfsVersionFound = getStorageNfsVersionFromNfsTO((NfsTO) srcDataStore); } if (nfsVersionFound) { @@ -657,6 +671,7 @@ protected void examineStorageSubSystemCommandNfsVersion(CopyCommand cmd, EnumMap /** * Get storage NFS version from NfsTO + * * @param nfsTO nfsTO * @return true if NFS version was found and not null, false in other case */ @@ -743,7 +758,7 @@ private Answer execute(ResizeVolumeCommand cmd) { // OfflineVmwareMigration: 3. attach the disk to the worker vmdkDataStorePath = VmwareStorageLayoutHelper.getLegacyDatastorePathFromVmdkFileName(dsMo, path + VMDK_EXTENSION); - vmMo.attachDisk(new String[] { vmdkDataStorePath }, morDS); + vmMo.attachDisk(new String[]{vmdkDataStorePath}, morDS); } } @@ -773,7 +788,7 @@ private Answer execute(ResizeVolumeCommand cmd) { // IDE virtual disk cannot be re-sized if VM is running if (vdisk.second() != null && vdisk.second().contains("ide")) { throw new Exception("Re-sizing a virtual disk over an IDE controller is not supported in the VMware hypervisor. " + - "Please re-try when virtual disk is attached to a VM using a SCSI controller."); + "Please re-try when virtual disk is attached to a VM using a SCSI controller."); } if (cmd.isManaged()) { @@ -799,16 +814,14 @@ private Answer execute(ResizeVolumeCommand cmd) { _storageProcessor.expandDatastore(hostDatastoreSystem, dsMo); } - if (vdisk.second() != null && !vdisk.second().toLowerCase().startsWith("scsi")) - { - s_logger.error("Unsupported disk device bus "+ vdisk.second()); - throw new Exception("Unsupported disk device bus "+ vdisk.second()); + if (vdisk.second() != null && !vdisk.second().toLowerCase().startsWith("scsi")) { + s_logger.error("Unsupported disk device bus " + vdisk.second()); + throw new Exception("Unsupported disk device bus " + vdisk.second()); } VirtualDisk disk = vdisk.first(); - if ((VirtualDiskFlatVer2BackingInfo)disk.getBacking() != null && ((VirtualDiskFlatVer2BackingInfo)disk.getBacking()).getParent() != null) - { - s_logger.error("Resize is not supported because Disk device has Parent "+ ((VirtualDiskFlatVer2BackingInfo)disk.getBacking()).getParent().getUuid()); - throw new Exception("Resize is not supported because Disk device has Parent "+ ((VirtualDiskFlatVer2BackingInfo)disk.getBacking()).getParent().getUuid()); + if ((VirtualDiskFlatVer2BackingInfo) disk.getBacking() != null && ((VirtualDiskFlatVer2BackingInfo) disk.getBacking()).getParent() != null) { + s_logger.error("Resize is not supported because Disk device has Parent " + ((VirtualDiskFlatVer2BackingInfo) disk.getBacking()).getParent().getUuid()); + throw new Exception("Resize is not supported because Disk device has Parent " + ((VirtualDiskFlatVer2BackingInfo) disk.getBacking()).getParent().getUuid()); } String vmdkAbsFile = getAbsoluteVmdkFile(disk); @@ -946,15 +959,15 @@ public ExecutionResult prepareCommand(NetworkElementCommand cmd) { assert cmd.getRouterAccessIp() != null; if (cmd instanceof IpAssocVpcCommand) { - return prepareNetworkElementCommand((IpAssocVpcCommand)cmd); + return prepareNetworkElementCommand((IpAssocVpcCommand) cmd); } else if (cmd instanceof IpAssocCommand) { - return prepareNetworkElementCommand((IpAssocCommand)cmd); + return prepareNetworkElementCommand((IpAssocCommand) cmd); } else if (cmd instanceof SetSourceNatCommand) { - return prepareNetworkElementCommand((SetSourceNatCommand)cmd); + return prepareNetworkElementCommand((SetSourceNatCommand) cmd); } else if (cmd instanceof SetupGuestNetworkCommand) { - return prepareNetworkElementCommand((SetupGuestNetworkCommand)cmd); + return prepareNetworkElementCommand((SetupGuestNetworkCommand) cmd); } else if (cmd instanceof SetNetworkACLCommand) { - return prepareNetworkElementCommand((SetNetworkACLCommand)cmd); + return prepareNetworkElementCommand((SetNetworkACLCommand) cmd); } return new ExecutionResult(true, null); } @@ -1027,7 +1040,7 @@ private VirtualDevice findVirtualNicDevice(VirtualMachineMO vmMo, String mac) th VirtualDevice[] nics = vmMo.getNicDevices(); for (VirtualDevice nic : nics) { if (nic instanceof VirtualEthernetCard) { - if (((VirtualEthernetCard)nic).getMacAddress().equals(mac)) + if (((VirtualEthernetCard) nic).getMacAddress().equals(mac)) return nic; } } @@ -1125,7 +1138,7 @@ private PlugNicAnswer execute(PlugNicCommand cmd) { if (vmMo == null) { if (hyperHost instanceof HostMO) { - ClusterMO clusterMo = new ClusterMO(hyperHost.getContext(), ((HostMO)hyperHost).getParentMor()); + ClusterMO clusterMo = new ClusterMO(hyperHost.getContext(), ((HostMO) hyperHost).getParentMor()); vmMo = clusterMo.findVmOnHyperHost(vmName); } } @@ -1147,7 +1160,7 @@ private PlugNicAnswer execute(PlugNicCommand cmd) { VirtualEthernetCardType nicDeviceType = VirtualEthernetCardType.E1000; Map details = cmd.getDetails(); if (details != null) { - nicDeviceType = VirtualEthernetCardType.valueOf((String)details.get("nicAdapter")); + nicDeviceType = VirtualEthernetCardType.valueOf((String) details.get("nicAdapter")); } // find a usable device number in VMware environment @@ -1209,7 +1222,7 @@ private ReplugNicAnswer execute(ReplugNicCommand cmd) { if (vmMo == null) { if (hyperHost instanceof HostMO) { - ClusterMO clusterMo = new ClusterMO(hyperHost.getContext(), ((HostMO)hyperHost).getParentMor()); + ClusterMO clusterMo = new ClusterMO(hyperHost.getContext(), ((HostMO) hyperHost).getParentMor()); vmMo = clusterMo.findVmOnHyperHost(vmName); } } @@ -1288,7 +1301,7 @@ private UnPlugNicAnswer execute(UnPlugNicCommand cmd) { if (vmMo == null) { if (hyperHost instanceof HostMO) { - ClusterMO clusterMo = new ClusterMO(hyperHost.getContext(), ((HostMO)hyperHost).getParentMor()); + ClusterMO clusterMo = new ClusterMO(hyperHost.getContext(), ((HostMO) hyperHost).getParentMor()); vmMo = clusterMo.findVmOnHyperHost(vmName); } } @@ -1353,7 +1366,7 @@ private void plugPublicNic(VirtualMachineMO vmMo, final String vlanId, final IpA try { VirtualDevice[] nicDevices = vmMo.getNicDevices(); - VirtualEthernetCard device = (VirtualEthernetCard)nicDevices[nicIndex]; + VirtualEthernetCard device = (VirtualEthernetCard) nicDevices[nicIndex]; if (VirtualSwitchType.StandardVirtualSwitch == vSwitchType) { VirtualEthernetCardNetworkBackingInfo nicBacking = new VirtualEthernetCardNetworkBackingInfo(); @@ -1423,7 +1436,7 @@ private ExecutionResult prepareNetworkElementCommand(IpAssocCommand cmd) { // the check and will try to find it within cluster if (vmMo == null) { if (hyperHost instanceof HostMO) { - ClusterMO clusterMo = new ClusterMO(hyperHost.getContext(), ((HostMO)hyperHost).getParentMor()); + ClusterMO clusterMo = new ClusterMO(hyperHost.getContext(), ((HostMO) hyperHost).getParentMor()); vmMo = clusterMo.findVmOnHyperHost(routerName); } } @@ -1549,13 +1562,13 @@ private DiskTO[] validateDisks(DiskTO[] disks) { for (DiskTO vol : disks) { if (vol.getType() != Volume.Type.ISO) { - VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData(); + VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData(); DataStoreTO primaryStore = volumeTO.getDataStore(); if (primaryStore.getUuid() != null && !primaryStore.getUuid().isEmpty()) { validatedDisks.add(vol); } } else if (vol.getType() == Volume.Type.ISO) { - TemplateObjectTO templateTO = (TemplateObjectTO)vol.getData(); + TemplateObjectTO templateTO = (TemplateObjectTO) vol.getData(); if (templateTO.getPath() != null && !templateTO.getPath().isEmpty()) { validatedDisks.add(vol); } @@ -1612,7 +1625,7 @@ protected ScaleVmAnswer execute(ScaleVmCommand cmd) { // Check if license supports the feature VmwareHelper.isFeatureLicensed(hyperHost, FeatureKeyConstants.HOTPLUG); - VmwareHelper.setVmScaleUpConfig(vmConfigSpec, vmSpec.getCpus(), vmSpec.getMaxSpeed(), vmSpec.getMinSpeed(), (int)requestedMaxMemoryInMb, ramMb, + VmwareHelper.setVmScaleUpConfig(vmConfigSpec, vmSpec.getCpus(), vmSpec.getMaxSpeed(), vmSpec.getMinSpeed(), (int) requestedMaxMemoryInMb, ramMb, vmSpec.getLimitCpuUse()); if (!vmMo.configureVm(vmConfigSpec)) { @@ -1772,9 +1785,9 @@ protected StartAnswer execute(StartCommand cmd) { diskInfoBuilder = vmMo.getDiskInfoBuilder(); hasSnapshot = vmMo.hasSnapshot(); if (!hasSnapshot) - vmMo.tearDownDevices(new Class[] {VirtualDisk.class, VirtualEthernetCard.class}); + vmMo.tearDownDevices(new Class[]{VirtualDisk.class, VirtualEthernetCard.class}); else - vmMo.tearDownDevices(new Class[] {VirtualEthernetCard.class}); + vmMo.tearDownDevices(new Class[]{VirtualEthernetCard.class}); if (systemVm) { ensureScsiDiskControllers(vmMo, systemVmScsiControllerType.toString(), numScsiControllerForSystemVm, firstScsiControllerBusNum); } else { @@ -1798,9 +1811,9 @@ protected StartAnswer execute(StartCommand cmd) { diskInfoBuilder = vmMo.getDiskInfoBuilder(); hasSnapshot = vmMo.hasSnapshot(); if (!hasSnapshot) - vmMo.tearDownDevices(new Class[] {VirtualDisk.class, VirtualEthernetCard.class}); + vmMo.tearDownDevices(new Class[]{VirtualDisk.class, VirtualEthernetCard.class}); else - vmMo.tearDownDevices(new Class[] {VirtualEthernetCard.class}); + vmMo.tearDownDevices(new Class[]{VirtualEthernetCard.class}); if (systemVm) { // System volumes doesn't require more than 1 SCSI controller as there is no requirement for data volumes. @@ -1855,7 +1868,7 @@ protected StartAnswer execute(StartCommand cmd) { } tearDownVm(vmMo); } else if (!hyperHost.createBlankVm(vmNameOnVcenter, vmInternalCSName, vmSpec.getCpus(), vmSpec.getMaxSpeed().intValue(), getReservedCpuMHZ(vmSpec), - vmSpec.getLimitCpuUse(), (int)(vmSpec.getMaxRam() / ResourceType.bytesToMiB), getReservedMemoryMb(vmSpec), guestOsId, rootDiskDataStoreDetails.first(), false, + vmSpec.getLimitCpuUse(), (int) (vmSpec.getMaxRam() / ResourceType.bytesToMiB), getReservedMemoryMb(vmSpec), guestOsId, rootDiskDataStoreDetails.first(), false, controllerInfo, systemVm)) { throw new Exception("Failed to create VM. vmName: " + vmInternalCSName); } @@ -1881,7 +1894,7 @@ protected StartAnswer execute(StartCommand cmd) { VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec(); - VmwareHelper.setBasicVmConfig(vmConfigSpec, vmSpec.getCpus(), vmSpec.getMaxSpeed(), getReservedCpuMHZ(vmSpec), (int)(vmSpec.getMaxRam() / (1024 * 1024)), + VmwareHelper.setBasicVmConfig(vmConfigSpec, vmSpec.getCpus(), vmSpec.getMaxSpeed(), getReservedCpuMHZ(vmSpec), (int) (vmSpec.getMaxRam() / (1024 * 1024)), getReservedMemoryMb(vmSpec), guestOsId, vmSpec.getLimitCpuUse()); // Check for multi-cores per socket settings @@ -1899,7 +1912,7 @@ protected StartAnswer execute(StartCommand cmd) { // Check for hotadd settings vmConfigSpec.setMemoryHotAddEnabled(vmMo.isMemoryHotAddSupported(guestOsId)); - String hostApiVersion = ((HostMO)hyperHost).getHostAboutInfo().getApiVersion(); + String hostApiVersion = ((HostMO) hyperHost).getHostAboutInfo().getApiVersion(); if (numCoresPerSocket > 1 && hostApiVersion.compareTo("5.0") < 0) { s_logger.warn("Dynamic scaling of CPU is not supported for Virtual Machines with multi-core vCPUs in case of ESXi hosts 4.1 and prior. Hence CpuHotAdd will not be" + " enabled for Virtual Machine: " + vmInternalCSName); @@ -2012,7 +2025,6 @@ protected StartAnswer execute(StartCommand cmd) { } - // // Setup ROOT/DATA disk devices // @@ -2051,7 +2063,7 @@ protected StartAnswer execute(StartCommand cmd) { if (!hasSnapshot) { deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec(); - VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData(); + VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData(); DataStoreTO primaryStore = volumeTO.getDataStore(); Map details = vol.getDetails(); boolean managed = false; @@ -2097,7 +2109,7 @@ protected StartAnswer execute(StartCommand cmd) { // Setup USB devices // if (guestOsId.startsWith("darwin")) { //Mac OS - VirtualDevice[] devices = vmMo.getMatchedDevices(new Class[] {VirtualUSBController.class}); + VirtualDevice[] devices = vmMo.getMatchedDevices(new Class[]{VirtualUSBController.class}); if (devices.length == 0) { s_logger.debug("No USB Controller device on VM Start. Add USB Controller device for Mac OS VM " + vmInternalCSName); @@ -2140,7 +2152,7 @@ protected StartAnswer execute(StartCommand cmd) { for (int nicIndex = nics.length - extraPublicNics; nicIndex < nics.length; nicIndex++) { VirtualDevice nicDevice = peerVmMo.getNicDeviceByIndex(nics[nicIndex].getDeviceId()); if (nicDevice != null) { - String mac = ((VirtualEthernetCard)nicDevice).getMacAddress(); + String mac = ((VirtualEthernetCard) nicDevice).getMacAddress(); if (mac != null) { s_logger.info("Use same MAC as previous RvR, the MAC is " + mac + " for extra NIC with device id: " + nics[nicIndex].getDeviceId()); nics[nicIndex].setMac(mac); @@ -2413,8 +2425,8 @@ protected List copyVAppConfigProductSectionFromOVF(VmConfigInfo * and seting properties values from ovfProperties */ protected void copyVAppConfigsFromTemplate(VmConfigInfo vAppConfig, - List ovfProperties, - VirtualMachineConfigSpec vmConfig) throws Exception { + List ovfProperties, + VirtualMachineConfigSpec vmConfig) throws Exception { VmConfigSpec vmConfigSpec = new VmConfigSpec(); vmConfigSpec.getEula().addAll(vAppConfig.getEula()); vmConfigSpec.setInstallBootStopDelay(vAppConfig.getInstallBootStopDelay()); @@ -2437,10 +2449,10 @@ private String appendFileType(String path, String fileType) { private void resizeRootDiskOnVMStart(VirtualMachineMO vmMo, DiskTO rootDiskTO, VmwareHypervisorHost hyperHost, VmwareContext context) throws Exception { final Pair vdisk = getVirtualDiskInfo(vmMo, appendFileType(rootDiskTO.getPath(), VMDK_EXTENSION)); - assert(vdisk != null); + assert (vdisk != null); Long reqSize = 0L; - final VolumeObjectTO volumeTO = ((VolumeObjectTO)rootDiskTO.getData()); + final VolumeObjectTO volumeTO = ((VolumeObjectTO) rootDiskTO.getData()); if (volumeTO != null) { reqSize = volumeTO.getSize() / 1024; } @@ -2452,7 +2464,7 @@ private void resizeRootDiskOnVMStart(VirtualMachineMO vmMo, DiskTO rootDiskTO, V if (diskChain != null && diskChain.length > 1) { s_logger.warn("Disk chain length for the VM is greater than one, this is not supported"); - throw new CloudRuntimeException("Unsupported VM disk chain length: "+ diskChain.length); + throw new CloudRuntimeException("Unsupported VM disk chain length: " + diskChain.length); } boolean resizingSupported = false; @@ -2462,7 +2474,7 @@ private void resizeRootDiskOnVMStart(VirtualMachineMO vmMo, DiskTO rootDiskTO, V } if (!resizingSupported) { s_logger.warn("Resizing of root disk is only support for scsi device/bus, the provide VM's disk device bus name is " + diskInfo.getDiskDeviceBusName()); - throw new CloudRuntimeException("Unsupported VM root disk device bus: "+ diskInfo.getDiskDeviceBusName()); + throw new CloudRuntimeException("Unsupported VM root disk device bus: " + diskInfo.getDiskDeviceBusName()); } disk.setCapacityInKB(reqSize); @@ -2512,8 +2524,9 @@ protected String replaceNicsMacSequenceInBootArgs(String oldMacSequence, String * Sets video card memory to the one provided in detail svga.vramSize (if provided) on {@code vmConfigSpec}. * 64MB was always set before. * Size must be in KB. - * @param vmMo virtual machine mo - * @param vmSpec virtual machine specs + * + * @param vmMo virtual machine mo + * @param vmSpec virtual machine specs * @param vmConfigSpec virtual machine config spec * @throws Exception exception */ @@ -2531,14 +2544,15 @@ protected void configureVideoCard(VirtualMachineMO vmMo, VirtualMachineTO vmSpec /** * Search for vm video card iterating through vm device list - * @param vmMo virtual machine mo + * + * @param vmMo virtual machine mo * @param svgaVmramSize new svga vram size (in KB) - * @param vmConfigSpec virtual machine config spec + * @param vmConfigSpec virtual machine config spec */ protected void setNewVRamSizeVmVideoCard(VirtualMachineMO vmMo, long svgaVmramSize, VirtualMachineConfigSpec vmConfigSpec) throws Exception { for (VirtualDevice device : vmMo.getAllDeviceList()) { if (device instanceof VirtualMachineVideoCard) { - VirtualMachineVideoCard videoCard = (VirtualMachineVideoCard)device; + VirtualMachineVideoCard videoCard = (VirtualMachineVideoCard) device; modifyVmVideoCardVRamSize(videoCard, vmMo, svgaVmramSize, vmConfigSpec); } } @@ -2546,10 +2560,11 @@ protected void setNewVRamSizeVmVideoCard(VirtualMachineMO vmMo, long svgaVmramSi /** * Modifies vm vram size if it was set to a different size to the one provided in svga.vramSize (user_vm_details or template_vm_details) on {@code vmConfigSpec} - * @param videoCard vm's video card device - * @param vmMo virtual machine mo + * + * @param videoCard vm's video card device + * @param vmMo virtual machine mo * @param svgaVmramSize new svga vram size (in KB) - * @param vmConfigSpec virtual machine config spec + * @param vmConfigSpec virtual machine config spec */ protected void modifyVmVideoCardVRamSize(VirtualMachineVideoCard videoCard, VirtualMachineMO vmMo, long svgaVmramSize, VirtualMachineConfigSpec vmConfigSpec) { if (videoCard.getVideoRamSizeInKB().longValue() != svgaVmramSize) { @@ -2560,9 +2575,10 @@ protected void modifyVmVideoCardVRamSize(VirtualMachineVideoCard videoCard, Virt /** * Add edit spec on {@code vmConfigSpec} to modify svga vram size - * @param videoCard video card device to edit providing the svga vram size + * + * @param videoCard video card device to edit providing the svga vram size * @param svgaVmramSize new svga vram size (in KB) - * @param vmConfigSpec virtual machine spec + * @param vmConfigSpec virtual machine spec */ protected void configureSpecVideoCardNewVRamSize(VirtualMachineVideoCard videoCard, long svgaVmramSize, VirtualMachineConfigSpec vmConfigSpec) { videoCard.setVideoRamSizeInKB(svgaVmramSize); @@ -2583,15 +2599,15 @@ private void tearDownVm(VirtualMachineMO vmMo) throws Exception { boolean hasSnapshot = false; hasSnapshot = vmMo.hasSnapshot(); if (!hasSnapshot) - vmMo.tearDownDevices(new Class[] {VirtualDisk.class, VirtualEthernetCard.class}); + vmMo.tearDownDevices(new Class[]{VirtualDisk.class, VirtualEthernetCard.class}); else - vmMo.tearDownDevices(new Class[] {VirtualEthernetCard.class}); + vmMo.tearDownDevices(new Class[]{VirtualEthernetCard.class}); vmMo.ensureScsiDeviceController(); } int getReservedMemoryMb(VirtualMachineTO vmSpec) { if (vmSpec.getDetails().get(VMwareGuru.VmwareReserveMemory.key()).equalsIgnoreCase("true")) { - return (int)(vmSpec.getMinRam() / ResourceType.bytesToMiB); + return (int) (vmSpec.getMinRam() / ResourceType.bytesToMiB); } return 0; } @@ -2605,9 +2621,9 @@ int getReservedCpuMHZ(VirtualMachineTO vmSpec) { // return the finalized disk chain for startup, from top to bottom private String[] syncDiskChain(DatacenterMO dcMo, VirtualMachineMO vmMo, VirtualMachineTO vmSpec, DiskTO vol, VirtualMachineDiskInfo diskInfo, - HashMap> dataStoresDetails) throws Exception { + HashMap> dataStoresDetails) throws Exception { - VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData(); + VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData(); DataStoreTO primaryStore = volumeTO.getDataStore(); Map details = vol.getDetails(); boolean isManaged = false; @@ -2653,8 +2669,7 @@ private String[] syncDiskChain(DatacenterMO dcMo, VirtualMachineMO vmMo, Virtual } datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, vmdkPath); - } - else { + } else { if (vmdkPath == null) { vmdkPath = dsMo.getName(); } @@ -2669,7 +2684,7 @@ private String[] syncDiskChain(DatacenterMO dcMo, VirtualMachineMO vmMo, Virtual s_logger.warn("Volume " + volumeTO.getId() + " does not seem to exist on datastore, out of sync? path: " + datastoreDiskPath); } - return new String[] {datastoreDiskPath}; + return new String[]{datastoreDiskPath}; } // Pair @@ -2773,7 +2788,7 @@ private static void postNvpConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachi VirtualDeviceBackingInfo backing = nicVirtualDevice.getBacking(); if (backing instanceof VirtualEthernetCardDistributedVirtualPortBackingInfo) { // This NIC is connected to a Distributed Virtual Switch - VirtualEthernetCardDistributedVirtualPortBackingInfo portInfo = (VirtualEthernetCardDistributedVirtualPortBackingInfo)backing; + VirtualEthernetCardDistributedVirtualPortBackingInfo portInfo = (VirtualEthernetCardDistributedVirtualPortBackingInfo) backing; DistributedVirtualSwitchPortConnection port = portInfo.getPort(); String portKey = port.getPortKey(); String portGroupKey = port.getPortgroupKey(); @@ -2797,8 +2812,8 @@ private static void postNvpConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachi if (portKey.equals(dvPort.getKey())) { vmDvPort = dvPort; } - VMwareDVSPortSetting settings = (VMwareDVSPortSetting)dvPort.getConfig().getSetting(); - VmwareDistributedVirtualSwitchVlanIdSpec vlanId = (VmwareDistributedVirtualSwitchVlanIdSpec)settings.getVlan(); + VMwareDVSPortSetting settings = (VMwareDVSPortSetting) dvPort.getConfig().getSetting(); + VmwareDistributedVirtualSwitchVlanIdSpec vlanId = (VmwareDistributedVirtualSwitchVlanIdSpec) settings.getVlan(); s_logger.trace("Found port " + dvPort.getKey() + " with vlan " + vlanId.getVlanId()); if (vlanId.getVlanId() > 0 && vlanId.getVlanId() < 4095) { usedVlans.add(vlanId.getVlanId()); @@ -2810,9 +2825,9 @@ private static void postNvpConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachi } DVPortConfigInfo dvPortConfigInfo = vmDvPort.getConfig(); - VMwareDVSPortSetting settings = (VMwareDVSPortSetting)dvPortConfigInfo.getSetting(); + VMwareDVSPortSetting settings = (VMwareDVSPortSetting) dvPortConfigInfo.getSetting(); - VmwareDistributedVirtualSwitchVlanIdSpec vlanId = (VmwareDistributedVirtualSwitchVlanIdSpec)settings.getVlan(); + VmwareDistributedVirtualSwitchVlanIdSpec vlanId = (VmwareDistributedVirtualSwitchVlanIdSpec) settings.getVlan(); BoolPolicy blocked = settings.getBlocked(); if (blocked.isValue() == Boolean.TRUE) { s_logger.trace("Port is blocked, set a vlanid and unblock"); @@ -2864,7 +2879,7 @@ private static void postNvpConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachi private VirtualMachineDiskInfo getMatchingExistingDisk(VirtualMachineDiskInfoBuilder diskInfoBuilder, DiskTO vol, VmwareHypervisorHost hyperHost, VmwareContext context) throws Exception { if (diskInfoBuilder != null) { - VolumeObjectTO volume = (VolumeObjectTO)vol.getData(); + VolumeObjectTO volume = (VolumeObjectTO) vol.getData(); String dsName = null; String diskBackingFileBaseName = null; @@ -2993,14 +3008,14 @@ private String getDiskController(VirtualMachineMO vmMo, VirtualMachineDiskInfo m } private void postDiskConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachineTO vmSpec, DiskTO[] sortedDisks, int ideControllerKey, - int scsiControllerKey, Map> iqnToData, VmwareHypervisorHost hyperHost, VmwareContext context) throws Exception { + int scsiControllerKey, Map> iqnToData, VmwareHypervisorHost hyperHost, VmwareContext context) throws Exception { VirtualMachineDiskInfoBuilder diskInfoBuilder = vmMo.getDiskInfoBuilder(); for (DiskTO vol : sortedDisks) { if (vol.getType() == Volume.Type.ISO) continue; - VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData(); + VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData(); VirtualMachineDiskInfo diskInfo = getMatchingExistingDisk(diskInfoBuilder, vol, hyperHost, context); assert (diskInfo != null); @@ -3185,14 +3200,14 @@ public String getVmdkPath(String path) { } private HashMap> inferDatastoreDetailsFromDiskInfo(VmwareHypervisorHost hyperHost, VmwareContext context, - DiskTO[] disks, Command cmd) throws Exception { + DiskTO[] disks, Command cmd) throws Exception { HashMap> mapIdToMors = new HashMap<>(); assert (hyperHost != null) && (context != null); for (DiskTO vol : disks) { if (vol.getType() != Volume.Type.ISO) { - VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData(); + VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData(); DataStoreTO primaryStore = volumeTO.getDataStore(); String poolUuid = primaryStore.getUuid(); @@ -3227,8 +3242,7 @@ private HashMap> inferDatastor if (vmdkPath != null) { datastoreVolumePath = dsMo.getDatastorePath(vmdkPath + VMDK_EXTENSION); - } - else { + } else { datastoreVolumePath = dsMo.getDatastorePath(dsMo.getName() + VMDK_EXTENSION); } @@ -3237,8 +3251,7 @@ private HashMap> inferDatastor } mapIdToMors.put(datastoreName, new Pair<>(morDatastore, new DatastoreMO(context, morDatastore))); - } - else { + } else { ManagedObjectReference morDatastore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, poolUuid); if (morDatastore == null) { @@ -3350,8 +3363,7 @@ private Pair prepareNetworkFromNicInfo(HostMO ho networkInfo = HypervisorHostHelper.prepareNetwork(switchName, namePrefix, hostMo, getVlanInfo(nicTo, vlanToken), nicTo.getNetworkRateMbps(), nicTo.getNetworkRateMulticastMbps(), _opsTimeout, true, nicTo.getBroadcastType(), nicTo.getUuid(), nicTo.getDetails()); - } - else { + } else { String vlanId = getVlanInfo(nicTo, vlanToken); String svlanId = null; boolean pvlannetwork = (getPvlanInfo(nicTo) == null) ? false : true; @@ -3372,7 +3384,7 @@ private Pair prepareNetworkFromNicInfo(HostMO ho // return Ternary private Ternary getTargetSwitch(NicTO nicTo) throws CloudException { - TrafficType[] supportedTrafficTypes = new TrafficType[] {TrafficType.Guest, TrafficType.Public, TrafficType.Control, TrafficType.Management, TrafficType.Storage}; + TrafficType[] supportedTrafficTypes = new TrafficType[]{TrafficType.Guest, TrafficType.Public, TrafficType.Control, TrafficType.Management, TrafficType.Storage}; TrafficType trafficType = nicTo.getType(); if (!Arrays.asList(supportedTrafficTypes).contains(trafficType)) { @@ -3471,7 +3483,7 @@ private Pair getIsoDatastoreInfo(VmwareHyperviso int templateRootPos = isoUrl.indexOf("template/tmpl"); templateRootPos = (templateRootPos < 0 ? isoUrl.indexOf(ConfigDrive.CONFIGDRIVEDIR) : templateRootPos); - if (templateRootPos < 0 ) { + if (templateRootPos < 0) { throw new Exception("Invalid ISO path info"); } @@ -3653,7 +3665,7 @@ protected Answer execute(GetVmDiskStatsCommand cmd) { if (!(perfValue instanceof PerfEntityMetric)) { continue; } - final List values = ((PerfEntityMetric)perfValue).getValue(); + final List values = ((PerfEntityMetric) perfValue).getValue(); if (values == null || values.isEmpty()) { continue; } @@ -3661,7 +3673,7 @@ protected Answer execute(GetVmDiskStatsCommand cmd) { if (!(value instanceof PerfMetricIntSeries) || !value.getId().getInstance().equals(diskBusName)) { continue; } - final List perfStats = ((PerfMetricIntSeries)value).getValue(); + final List perfStats = ((PerfMetricIntSeries) value).getValue(); if (perfStats.size() > 0) { long sum = 0; for (long val : perfStats) { @@ -3711,7 +3723,7 @@ protected GetVolumeStatsAnswer execute(GetVolumeStatsCommand cmd) { DatacenterMO dcMo = new DatacenterMO(getServiceContext(), dcMor); HashMap statEntry = new HashMap(); - for (String chainInfo : cmd.getVolumeUuids()){ + for (String chainInfo : cmd.getVolumeUuids()) { if (chainInfo != null) { VirtualMachineDiskInfo infoInChain = _gson.fromJson(chainInfo, VirtualMachineDiskInfo.class); if (infoInChain != null) { @@ -3838,7 +3850,7 @@ protected Answer execute(RebootRouterCommand cmd) { s_logger.info("Executing resource RebootRouterCommand: " + _gson.toJson(cmd)); } - RebootAnswer answer = (RebootAnswer)execute((RebootCommand)cmd); + RebootAnswer answer = (RebootAnswer) execute((RebootCommand) cmd); if (answer.getResult()) { String connectResult = connect(cmd.getVmName(), cmd.getPrivateIpAddress()); @@ -4037,7 +4049,7 @@ protected Answer execute(MigrateVmToPoolCommand cmd) { return new Answer(cmd, (Exception) e); } if (s_logger.isDebugEnabled()) { - s_logger.debug("problem" , e); + s_logger.debug("problem", e); } s_logger.error(e.getLocalizedMessage()); return new Answer(cmd, false, "unknown problem: " + e.getLocalizedMessage()); @@ -4051,7 +4063,7 @@ private Answer migrateAndAnswer(VirtualMachineMO vmMo, String poolUuid, VmwareHy // OfflineVmwareMigration: getVolumesFromCommand(cmd); Map volumeDeviceKey = getVolumesFromCommand(vmMo, cmd); if (s_logger.isTraceEnabled()) { - for (Integer diskId: volumeDeviceKey.keySet()) { + for (Integer diskId : volumeDeviceKey.keySet()) { s_logger.trace(String.format("disk to migrate has disk id %d and volumeId %d", diskId, volumeDeviceKey.get(diskId))); } } @@ -4071,12 +4083,12 @@ private Answer migrateAndAnswer(VirtualMachineMO vmMo, String poolUuid, VmwareHy } catch (Exception e) { String msg = "change data store for VM " + vmMo.getVmName() + " failed"; s_logger.error(msg + ": " + e.getLocalizedMessage()); - throw new CloudRuntimeException(msg,e); + throw new CloudRuntimeException(msg, e); } } Answer createAnswerForCmd(VirtualMachineMO vmMo, String poolUuid, Command cmd, Map volumeDeviceKey) throws Exception { - List volumeToList = new ArrayList<>(); + List volumeToList = new ArrayList<>(); VirtualMachineDiskInfoBuilder diskInfoBuilder = vmMo.getDiskInfoBuilder(); VirtualDisk[] disks = vmMo.getAllDiskDevice(); Answer answer; @@ -4099,7 +4111,7 @@ Answer createAnswerForCmd(VirtualMachineMO vmMo, String poolUuid, Command cmd, M newVol.setChainInfo(_gson.toJson(diskInfo)); volumeToList.add(newVol); } - return new MigrateVmToPoolAnswer((MigrateVmToPoolCommand)cmd, volumeToList); + return new MigrateVmToPoolAnswer((MigrateVmToPoolCommand) cmd, volumeToList); } return new Answer(cmd, false, null); } @@ -4107,12 +4119,12 @@ Answer createAnswerForCmd(VirtualMachineMO vmMo, String poolUuid, Command cmd, M private Map getVolumesFromCommand(VirtualMachineMO vmMo, Command cmd) throws Exception { Map volumeDeviceKey = new HashMap(); if (cmd instanceof MigrateVmToPoolCommand) { - MigrateVmToPoolCommand mcmd = (MigrateVmToPoolCommand)cmd; + MigrateVmToPoolCommand mcmd = (MigrateVmToPoolCommand) cmd; for (VolumeTO volume : mcmd.getVolumes()) { addVolumeDiskmapping(vmMo, volumeDeviceKey, volume.getPath(), volume.getId()); } } else if (cmd instanceof MigrateVolumeCommand) { - MigrateVolumeCommand mcmd = (MigrateVolumeCommand)cmd; + MigrateVolumeCommand mcmd = (MigrateVolumeCommand) cmd; addVolumeDiskmapping(vmMo, volumeDeviceKey, mcmd.getVolumePath(), mcmd.getVolumeId()); } return volumeDeviceKey; @@ -4134,7 +4146,7 @@ private void addVolumeDiskmapping(VirtualMachineMO vmMo, Map volu private ManagedObjectReference getTargetDatastoreMOReference(String destinationPool, VmwareHypervisorHost hyperHost) { ManagedObjectReference morDs; try { - if(s_logger.isDebugEnabled()) { + if (s_logger.isDebugEnabled()) { s_logger.debug(String.format("finding datastore %s", destinationPool)); } morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, destinationPool); @@ -4262,7 +4274,7 @@ protected Answer execute(MigrateWithStorageCommand cmd) { throw new CloudRuntimeException(msg); } VmwareManager mgr = tgtHyperHost.getContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME); - String srcHostApiVersion = ((HostMO)srcHyperHost).getHostAboutInfo().getApiVersion(); + String srcHostApiVersion = ((HostMO) srcHyperHost).getHostAboutInfo().getApiVersion(); // find VM through datacenter (VM is not at the target host yet) vmMo = srcHyperHost.findVmOnPeerHyperHost(vmName); @@ -4449,7 +4461,7 @@ protected Answer execute(MigrateWithStorageCommand cmd) { String msg = "MigrationCommand failed due to " + VmwareHelper.getExceptionMessage(e); s_logger.warn(msg, e); - return new MigrateWithStorageAnswer(cmd, (Exception)e); + return new MigrateWithStorageAnswer(cmd, (Exception) e); } finally { // Cleanup datastores mounted on source host for (String mountedDatastore : mountedDatastoresAtSource) { @@ -4482,15 +4494,15 @@ private Answer migrateVolume(MigrateVolumeCommand cmd) { // we need to spawn a worker VM to attach the volume to and move it vmName = getWorkerName(getServiceContext(), cmd, 0); - // OfflineVmwareMigration: refactor for re-use - // OfflineVmwareMigration: 1. find data(store) + // OfflineVmwareMigration: refactor for re-use + // OfflineVmwareMigration: 1. find data(store) // OfflineVmwareMigration: more robust would be to find the store given the volume as it might have been moved out of band or due to error // example: DatastoreMO existingVmDsMo = new DatastoreMO(dcMo.getContext(), dcMo.findDatastore(fileInDatastore.getDatastoreName())); morSourceDS = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, cmd.getSourcePool().getUuid()); dsMo = new DatastoreMO(hyperHost.getContext(), morSourceDS); s_logger.info("Create worker VM " + vmName); - // OfflineVmwareMigration: 2. create the worker with access to the data(store) + // OfflineVmwareMigration: 2. create the worker with access to the data(store) vmMo = HypervisorHostHelper.createWorkerVM(hyperHost, dsMo, vmName); if (vmMo == null) { // OfflineVmwareMigration: don't throw a general Exception but think of a specific one @@ -4502,21 +4514,21 @@ private Answer migrateVolume(MigrateVolumeCommand cmd) { String vmdkFileName = path + VMDK_EXTENSION; vmdkDataStorePath = VmwareStorageLayoutHelper.getLegacyDatastorePathFromVmdkFileName(dsMo, vmdkFileName); if (!dsMo.fileExists(vmdkDataStorePath)) { - if(s_logger.isDebugEnabled()) { + if (s_logger.isDebugEnabled()) { s_logger.debug(String.format("path not found (%s), trying under '%s'", vmdkFileName, path)); } vmdkDataStorePath = VmwareStorageLayoutHelper.getVmwareDatastorePathFromVmdkFileName(dsMo, path, vmdkFileName); } if (!dsMo.fileExists(vmdkDataStorePath)) { - if(s_logger.isDebugEnabled()) { + if (s_logger.isDebugEnabled()) { s_logger.debug(String.format("path not found (%s), trying under '%s'", vmdkFileName, vmName)); } vmdkDataStorePath = VmwareStorageLayoutHelper.getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, vmdkFileName); } - if(s_logger.isDebugEnabled()) { + if (s_logger.isDebugEnabled()) { s_logger.debug(String.format("attaching %s to %s for migration", vmdkDataStorePath, vmMo.getVmName())); } - vmMo.attachDisk(new String[] { vmdkDataStorePath }, morSourceDS); + vmMo.attachDisk(new String[]{vmdkDataStorePath}, morSourceDS); } // OfflineVmwareMigration: 4. find the (worker-) VM @@ -4532,7 +4544,7 @@ private Answer migrateVolume(MigrateVolumeCommand cmd) { VirtualDisk[] disks = vmMo.getAllDiskDevice(); String format = "disk %d is attached as %s"; for (VirtualDisk disk : disks) { - s_logger.trace(String.format(format,disk.getKey(),vmMo.getVmdkFileBaseName(disk))); + s_logger.trace(String.format(format, disk.getKey(), vmMo.getVmdkFileBaseName(disk))); } } @@ -4579,7 +4591,7 @@ private Answer migrateVolume(MigrateVolumeCommand cmd) { } } if (answer instanceof MigrateVolumeAnswer) { - String newPath = ((MigrateVolumeAnswer)answer).getVolumePath(); + String newPath = ((MigrateVolumeAnswer) answer).getVolumePath(); String vmdkFileName = newPath + VMDK_EXTENSION; try { VmwareStorageLayoutHelper.syncVolumeToRootFolder(dsMo.getOwnerDatacenter().first(), dsMo, newPath, vmName); @@ -4726,7 +4738,7 @@ private VmwareHypervisorHost getTargetHyperHost(DatacenterMO dcMo, String destIp VmwareManager mgr = dcMo.getContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME); - List ocs = dcMo.getHostPropertiesOnDatacenterHostFolder(new String[] {"name", "parent"}); + List ocs = dcMo.getHostPropertiesOnDatacenterHostFolder(new String[]{"name", "parent"}); if (ocs != null && ocs.size() > 0) { for (ObjectContent oc : ocs) { HostMO hostMo = new HostMO(dcMo.getContext(), oc.getObj()); @@ -4774,15 +4786,13 @@ protected Answer execute(ModifyTargetsCommand cmd) { hostMOs.add(hostMO); } - } - catch (Exception ex) { + } catch (Exception ex) { s_logger.error(ex.getMessage(), ex); throw new CloudRuntimeException(ex.getMessage(), ex); } - } - else { - hostMOs.add((HostMO)hyperHost); + } else { + hostMOs.add((HostMO) hyperHost); } handleTargets(cmd.getAdd(), cmd.getTargetTypeToRemove(), cmd.isRemoveAsync(), cmd.getTargets(), hostMOs); @@ -4844,8 +4854,7 @@ private void handleTargets(boolean add, ModifyTargetsCommand.TargetTypeToRemove if (targets != null && targets.size() > 0) { try { _storageProcessor.handleTargets(add, targetTypeToRemove, isRemoveAsync, targets, hosts); - } - catch (Exception ex) { + } catch (Exception ex) { s_logger.warn(ex.getMessage()); } } @@ -5262,7 +5271,7 @@ protected Answer execute(GetVncPortCommand cmd) { } } - Pair portInfo = vmMo.getVncPort(mgr.getManagementPortGroupByHost((HostMO)hyperHost)); + Pair portInfo = vmMo.getVncPort(mgr.getManagementPortGroupByHost((HostMO) hyperHost)); if (s_logger.isTraceEnabled()) { s_logger.trace("Found vnc port info. vm: " + cmd.getName() + " host: " + portInfo.first() + ", vnc port: " + portInfo.second()); @@ -5317,7 +5326,7 @@ protected Answer execute(PingTestCommand cmd) { VmwareHypervisorHost hyperHost = getHyperHost(context); try { - HostMO hostMo = (HostMO)hyperHost; + HostMO hostMo = (HostMO) hyperHost; ClusterMO clusterMo = new ClusterMO(context, hostMo.getHyperHostCluster()); VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME); @@ -5419,7 +5428,7 @@ public PrimaryStorageDownloadAnswer execute(PrimaryStorageDownloadCommand cmd) { try { VmwareContext context = getServiceContext(); VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME); - return (PrimaryStorageDownloadAnswer)mgr.getStorageManager().execute(this, cmd); + return (PrimaryStorageDownloadAnswer) mgr.getStorageManager().execute(this, cmd); } catch (Throwable e) { if (e instanceof RemoteException) { s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context"); @@ -5512,7 +5521,7 @@ protected Answer execute(UnregisterNicCommand cmd) { // Get a list of all the hosts in this cluster @SuppressWarnings("unchecked") - List hosts = (List)context.getVimClient().getDynamicProperty(clusterMO, "host"); + List hosts = (List) context.getVimClient().getDynamicProperty(clusterMO, "host"); if (hosts == null) { return new Answer(cmd, false, "No hosts in cluster, which is pretty weird"); } @@ -5557,7 +5566,7 @@ public CopyVolumeAnswer execute(CopyVolumeCommand cmd) { try { VmwareContext context = getServiceContext(); VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME); - return (CopyVolumeAnswer)mgr.getStorageManager().execute(this, cmd); + return (CopyVolumeAnswer) mgr.getStorageManager().execute(this, cmd); } catch (Throwable e) { if (e instanceof RemoteException) { s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context"); @@ -5611,13 +5620,13 @@ private void gcAndKillHungWorkerVMs() { s_logger.info("Scan hung worker VM to recycle"); - int workerKey = ((HostMO)hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_WORKER); - int workerTagKey = ((HostMO)hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_WORKER_TAG); + int workerKey = ((HostMO) hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_WORKER); + int workerTagKey = ((HostMO) hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_WORKER_TAG); String workerPropName = String.format("value[%d]", workerKey); String workerTagPropName = String.format("value[%d]", workerTagKey); // GC worker that has been running for too long - ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(new String[] {"name", "config.template", workerPropName, workerTagPropName,}); + ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(new String[]{"name", "config.template", workerPropName, workerTagPropName,}); if (ocs != null) { for (ObjectContent oc : ocs) { List props = oc.getPropSet(); @@ -5628,13 +5637,13 @@ private void gcAndKillHungWorkerVMs() { for (DynamicProperty prop : props) { if (prop.getName().equals("config.template")) { - template = (Boolean)prop.getVal(); + template = (Boolean) prop.getVal(); } else if (prop.getName().equals(workerPropName)) { - CustomFieldStringValue val = (CustomFieldStringValue)prop.getVal(); + CustomFieldStringValue val = (CustomFieldStringValue) prop.getVal(); if (val != null && val.getValue() != null && val.getValue().equalsIgnoreCase("true")) isWorker = true; } else if (prop.getName().equals(workerTagPropName)) { - CustomFieldStringValue val = (CustomFieldStringValue)prop.getVal(); + CustomFieldStringValue val = (CustomFieldStringValue) prop.getVal(); workerTag = val.getValue(); } } @@ -5680,14 +5689,14 @@ public StartupCommand[] initialize() { try { VmwareHypervisorHost hyperHost = getHyperHost(context); assert (hyperHost instanceof HostMO); - if (!((HostMO)hyperHost).isHyperHostConnected()) { + if (!((HostMO) hyperHost).isHyperHostConnected()) { s_logger.info("Host " + hyperHost.getHyperHostName() + " is not in connected state"); return null; } - ((HostMO)hyperHost).enableVncOnHostFirewall(); + ((HostMO) hyperHost).enableVncOnHostFirewall(); - AboutInfo aboutInfo = ((HostMO)hyperHost).getHostAboutInfo(); + AboutInfo aboutInfo = ((HostMO) hyperHost).getHostAboutInfo(); hostApiVersion = aboutInfo.getApiVersion(); } catch (Exception e) { @@ -5723,7 +5732,7 @@ private List initializeLocalStorage() { try { VmwareHypervisorHost hyperHost = getHyperHost(context); if (hyperHost instanceof HostMO) { - HostMO hostMo = (HostMO)hyperHost; + HostMO hostMo = (HostMO) hyperHost; List> dsList = hostMo.getLocalDatastoreOnHost(); for (Pair dsPair : dsList) { @@ -5804,15 +5813,15 @@ private String getIqn() { VmwareHypervisorHost hyperHost = getHyperHost(getServiceContext()); if (hyperHost instanceof HostMO) { - HostMO host = (HostMO)hyperHost; + HostMO host = (HostMO) hyperHost; HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO(); for (HostHostBusAdapter hba : hostStorageSystem.getStorageDeviceInfo().getHostBusAdapter()) { if (hba instanceof HostInternetScsiHba) { - HostInternetScsiHba hostInternetScsiHba = (HostInternetScsiHba)hba; + HostInternetScsiHba hostInternetScsiHba = (HostInternetScsiHba) hba; if (hostInternetScsiHba.isIsSoftwareBased()) { - return ((HostInternetScsiHba)hba).getIScsiName(); + return ((HostInternetScsiHba) hba).getIScsiName(); } } } @@ -5837,7 +5846,7 @@ private void fillHostHardwareInfo(VmwareContext serviceContext, StartupRoutingCo cmd.setDom0MinMemory(0); cmd.setSpeed(summary.getCpuSpeed()); cmd.setCpuSockets(summary.getCpuSockets()); - cmd.setCpus((int)summary.getCpuCount()); + cmd.setCpus((int) summary.getCpuCount()); cmd.setMemory(summary.getMemoryBytes()); } @@ -5849,7 +5858,7 @@ private void fillHostNetworkInfo(VmwareContext serviceContext, StartupRoutingCom assert (hyperHost instanceof HostMO); VmwareManager mgr = hyperHost.getContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME); - VmwareHypervisorHostNetworkSummary summary = hyperHost.getHyperHostNetworkSummary(mgr.getManagementPortGroupByHost((HostMO)hyperHost)); + VmwareHypervisorHostNetworkSummary summary = hyperHost.getHyperHostNetworkSummary(mgr.getManagementPortGroupByHost((HostMO) hyperHost)); if (summary == null) { throw new Exception("No ESX(i) host found"); } @@ -5994,7 +6003,7 @@ private VirtualMachineGuestOsIdentifier translateGuestOsIdentifier(String cpuArc private HashMap getHostVmStateReport() throws Exception { VmwareHypervisorHost hyperHost = getHyperHost(getServiceContext()); - int key = ((HostMO)hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_VM_INTERNAL_NAME); + int key = ((HostMO) hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_VM_INTERNAL_NAME); if (key == 0) { s_logger.warn("Custom field " + CustomFieldConstants.CLOUD_VM_INTERNAL_NAME + " is not registered ?!"); } @@ -6002,7 +6011,7 @@ private HashMap getHostVmStateReport() throws Ex // CLOUD_VM_INTERNAL_NAME stores the internal CS generated vm name. This was earlier stored in name. Now, name can be either the hostname or // the internal CS name, but the custom field CLOUD_VM_INTERNAL_NAME always stores the internal CS name. - ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(new String[] {"name", "runtime.powerState", "config.template", instanceNameCustomField}); + ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(new String[]{"name", "runtime.powerState", "config.template", instanceNameCustomField}); HashMap newStates = new HashMap(); if (ocs != null && ocs.length > 0) { @@ -6020,12 +6029,12 @@ private HashMap getHostVmStateReport() throws Ex isTemplate = true; } } else if (objProp.getName().equals("runtime.powerState")) { - powerState = (VirtualMachinePowerState)objProp.getVal(); + powerState = (VirtualMachinePowerState) objProp.getVal(); } else if (objProp.getName().equals("name")) { - name = (String)objProp.getVal(); + name = (String) objProp.getVal(); } else if (objProp.getName().contains(instanceNameCustomField)) { if (objProp.getVal() != null) - VMInternalCSName = ((CustomFieldStringValue)objProp.getVal()).getValue(); + VMInternalCSName = ((CustomFieldStringValue) objProp.getVal()).getValue(); } else { assert (false); } @@ -6046,7 +6055,7 @@ private HashMap getHostVmStateReport() throws Ex private HashMap getVmStates() throws Exception { VmwareHypervisorHost hyperHost = getHyperHost(getServiceContext()); - int key = ((HostMO)hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_VM_INTERNAL_NAME); + int key = ((HostMO) hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_VM_INTERNAL_NAME); if (key == 0) { s_logger.warn("Custom field " + CustomFieldConstants.CLOUD_VM_INTERNAL_NAME + " is not registered ?!"); } @@ -6054,7 +6063,7 @@ private HashMap getVmStates() throws Exception { // CLOUD_VM_INTERNAL_NAME stores the internal CS generated vm name. This was earlier stored in name. Now, name can be either the hostname or // the internal CS name, but the custom field CLOUD_VM_INTERNAL_NAME always stores the internal CS name. - ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(new String[] {"name", "runtime.powerState", "config.template", instanceNameCustomField}); + ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(new String[]{"name", "runtime.powerState", "config.template", instanceNameCustomField}); HashMap newStates = new HashMap(); if (ocs != null && ocs.length > 0) { @@ -6072,12 +6081,12 @@ private HashMap getVmStates() throws Exception { isTemplate = true; } } else if (objProp.getName().equals("runtime.powerState")) { - powerState = (VirtualMachinePowerState)objProp.getVal(); + powerState = (VirtualMachinePowerState) objProp.getVal(); } else if (objProp.getName().equals("name")) { - name = (String)objProp.getVal(); + name = (String) objProp.getVal(); } else if (objProp.getName().contains(instanceNameCustomField)) { if (objProp.getVal() != null) - VMInternalCSName = ((CustomFieldStringValue)objProp.getVal()).getValue(); + VMInternalCSName = ((CustomFieldStringValue) objProp.getVal()).getValue(); } else { assert (false); } @@ -6138,7 +6147,7 @@ private HashMap getVmStats(List vmNames) throws Ex } } - int key = ((HostMO)hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_VM_INTERNAL_NAME); + int key = ((HostMO) hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_VM_INTERNAL_NAME); if (key == 0) { s_logger.warn("Custom field " + CustomFieldConstants.CLOUD_VM_INTERNAL_NAME + " is not registered ?!"); } @@ -6151,8 +6160,8 @@ private HashMap getVmStats(List vmNames) throws Ex final String memMbStr = "config.hardware.memoryMB"; final String allocatedCpuStr = "summary.runtime.maxCpuUsage"; - ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(new String[] { - "name", numCpuStr, cpuUseStr, guestMemUseStr, memLimitStr, memMbStr,allocatedCpuStr, instanceNameCustomField + ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(new String[]{ + "name", numCpuStr, cpuUseStr, guestMemUseStr, memLimitStr, memMbStr, allocatedCpuStr, instanceNameCustomField }); if (ocs != null && ocs.length > 0) { @@ -6173,7 +6182,7 @@ private HashMap getVmStats(List vmNames) throws Ex vmNameOnVcenter = objProp.getVal().toString(); } else if (objProp.getName().contains(instanceNameCustomField)) { if (objProp.getVal() != null) - vmInternalCSName = ((CustomFieldStringValue)objProp.getVal()).getValue(); + vmInternalCSName = ((CustomFieldStringValue) objProp.getVal()).getValue(); } else if (objProp.getName().equals(guestMemUseStr)) { guestMemusage = objProp.getVal().toString(); } else if (objProp.getName().equals(numCpuStr)) { @@ -6184,12 +6193,12 @@ private HashMap getVmStats(List vmNames) throws Ex memlimit = objProp.getVal().toString(); } else if (objProp.getName().equals(memMbStr)) { memkb = objProp.getVal().toString(); - } else if (objProp.getName().equals(allocatedCpuStr)){ - allocatedCpu = NumberUtils.toDouble(objProp.getVal().toString()); + } else if (objProp.getName().equals(allocatedCpuStr)) { + allocatedCpu = NumberUtils.toDouble(objProp.getVal().toString()); } } - maxCpuUsage = (maxCpuUsage/allocatedCpu)*100; + maxCpuUsage = (maxCpuUsage / allocatedCpu) * 100; if (vmInternalCSName != null) { name = vmInternalCSName; } else { @@ -6276,7 +6285,7 @@ private HashMap getVmStats(List vmNames) throws Ex } } - final VmStatsEntry vmStats = new VmStatsEntry( NumberUtils.toDouble(memkb)*1024,NumberUtils.toDouble(guestMemusage)*1024,NumberUtils.toDouble(memlimit)*1024, + final VmStatsEntry vmStats = new VmStatsEntry(NumberUtils.toDouble(memkb) * 1024, NumberUtils.toDouble(guestMemusage) * 1024, NumberUtils.toDouble(memlimit) * 1024, maxCpuUsage, networkReadKBs, networkWriteKBs, NumberUtils.toInt(numberCPUs), "vm"); vmStats.setDiskReadIOs(diskReadIops); vmStats.setDiskWriteIOs(diskWriteIops); @@ -6401,7 +6410,7 @@ private static HostStatsEntry getHyperHostStats(VmwareHypervisorHost hyperHost) HostStatsEntry entry = new HostStatsEntry(); entry.setEntityType("host"); - double cpuUtilization = ((double)(hardwareSummary.getTotalCpu() - hardwareSummary.getEffectiveCpu()) / (double)hardwareSummary.getTotalCpu() * 100); + double cpuUtilization = ((double) (hardwareSummary.getTotalCpu() - hardwareSummary.getEffectiveCpu()) / (double) hardwareSummary.getTotalCpu() * 100); entry.setCpuUtilization(cpuUtilization); entry.setTotalMemoryKBs(hardwareSummary.getTotalMemory() / 1024); entry.setFreeMemoryKBs(hardwareSummary.getEffectiveMemory() * 1024); @@ -6435,14 +6444,14 @@ public boolean configure(String name, Map params) throws Configu try { _name = name; - _url = (String)params.get("url"); - _username = (String)params.get("username"); - _password = (String)params.get("password"); - _dcId = (String)params.get("zone"); - _pod = (String)params.get("pod"); - _cluster = (String)params.get("cluster"); + _url = (String) params.get("url"); + _username = (String) params.get("username"); + _password = (String) params.get("password"); + _dcId = (String) params.get("zone"); + _pod = (String) params.get("pod"); + _cluster = (String) params.get("cluster"); - _guid = (String)params.get("guid"); + _guid = (String) params.get("guid"); String[] tokens = _guid.split("@"); _vCenterAddress = tokens[1]; _morHyperHost = new ManagedObjectReference(); @@ -6450,8 +6459,8 @@ public boolean configure(String name, Map params) throws Configu _morHyperHost.setType(hostTokens[0]); _morHyperHost.setValue(hostTokens[1]); - _guestTrafficInfo = (VmwareTrafficLabel)params.get("guestTrafficInfo"); - _publicTrafficInfo = (VmwareTrafficLabel)params.get("publicTrafficInfo"); + _guestTrafficInfo = (VmwareTrafficLabel) params.get("guestTrafficInfo"); + _publicTrafficInfo = (VmwareTrafficLabel) params.get("publicTrafficInfo"); VmwareContext context = getServiceContext(); VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME); if (mgr == null) { @@ -6482,14 +6491,14 @@ public boolean configure(String name, Map params) throws Configu } if (_privateNetworkVSwitchName == null) { - _privateNetworkVSwitchName = (String)params.get("private.network.vswitch.name"); + _privateNetworkVSwitchName = (String) params.get("private.network.vswitch.name"); } - String value = (String)params.get("vmware.recycle.hung.wokervm"); + String value = (String) params.get("vmware.recycle.hung.wokervm"); if (value != null && value.equalsIgnoreCase("true")) _recycleHungWorker = true; - value = (String)params.get("vmware.root.disk.controller"); + value = (String) params.get("vmware.root.disk.controller"); if (value != null && value.equalsIgnoreCase("scsi")) _rootDiskController = DiskControllerType.scsi; else if (value != null && value.equalsIgnoreCase("ide")) @@ -6497,7 +6506,7 @@ else if (value != null && value.equalsIgnoreCase("ide")) else _rootDiskController = DiskControllerType.osdefault; - Integer intObj = (Integer)params.get("ports.per.dvportgroup"); + Integer intObj = (Integer) params.get("ports.per.dvportgroup"); if (intObj != null) _portsPerDvPortGroup = intObj.intValue(); @@ -6505,25 +6514,25 @@ else if (value != null && value.equalsIgnoreCase("ide")) + _publicTrafficInfo.getVirtualSwitchType() + " : " + _publicTrafficInfo.getVirtualSwitchName() + ", guest traffic over " + _guestTrafficInfo.getVirtualSwitchType() + " : " + _guestTrafficInfo.getVirtualSwitchName()); - Boolean boolObj = (Boolean)params.get("vmware.create.full.clone"); + Boolean boolObj = (Boolean) params.get("vmware.create.full.clone"); if (boolObj != null && boolObj.booleanValue()) { _fullCloneFlag = true; } else { _fullCloneFlag = false; } - boolObj = (Boolean)params.get("vm.instancename.flag"); + boolObj = (Boolean) params.get("vm.instancename.flag"); if (boolObj != null && boolObj.booleanValue()) { _instanceNameFlag = true; } else { _instanceNameFlag = false; } - value = (String)params.get("scripts.timeout"); + value = (String) params.get("scripts.timeout"); int timeout = NumbersUtil.parseInt(value, 1440) * 1000; storageNfsVersion = NfsSecondaryStorageResource.retrieveNfsVersionFromParams(params); - _storageProcessor = new VmwareStorageProcessor((VmwareHostService)this, _fullCloneFlag, (VmwareStorageMount)mgr, timeout, this, _shutdownWaitMs, null, + _storageProcessor = new VmwareStorageProcessor((VmwareHostService) this, _fullCloneFlag, (VmwareStorageMount) mgr, timeout, this, _shutdownWaitMs, null, storageNfsVersion); storageHandler = new VmwareStorageSubsystemCommandHandler(_storageProcessor, storageNfsVersion); @@ -6717,11 +6726,12 @@ public Answer execute(DestroyCommand cmd) { /** * Use data center to look for vm, instead of randomly picking up a cluster
* (in multiple cluster environments vm could not be found if wrong cluster was chosen) - * @param context vmware context + * + * @param context vmware context * @param hyperHost vmware hv host - * @param vol volume + * @param vol volume * @return a virtualmachinemo if could be found on datacenter. - * @throws Exception if there is an error while finding vm + * @throws Exception if there is an error while finding vm * @throws CloudRuntimeException if datacenter cannot be found */ protected VirtualMachineMO findVmOnDatacenter(VmwareContext context, VmwareHypervisorHost hyperHost, VolumeTO vol) throws Exception { @@ -6738,7 +6748,7 @@ public String getAbsoluteVmdkFile(VirtualDisk disk) { String vmdkAbsFile = null; VirtualDeviceBackingInfo backingInfo = disk.getBacking(); if (backingInfo instanceof VirtualDiskFlatVer2BackingInfo) { - VirtualDiskFlatVer2BackingInfo diskBackingInfo = (VirtualDiskFlatVer2BackingInfo)backingInfo; + VirtualDiskFlatVer2BackingInfo diskBackingInfo = (VirtualDiskFlatVer2BackingInfo) backingInfo; vmdkAbsFile = diskBackingInfo.getFileName(); } return vmdkAbsFile; @@ -6777,4 +6787,229 @@ private static File fetchSystemVmKeyFile() { } return keyFile; } + + private List getUnmanageInstanceDisks(VirtualMachineMO vmMo) { + List instanceDisks = new ArrayList<>(); + VirtualDisk[] disks = null; + try { + disks = vmMo.getAllDiskDevice(); + } catch (Exception e) { + s_logger.info("Unable to retrieve unmanaged instance disks! " + e.getMessage()); + } + if (disks != null) { + for (VirtualDevice diskDevice : disks) { + try { + if (diskDevice instanceof VirtualDisk) { + UnmanagedInstance.Disk instanceDisk = new UnmanagedInstance.Disk(); + VirtualDisk disk = (VirtualDisk) diskDevice; + instanceDisk.setDiskId(disk.getDiskObjectId()); + instanceDisk.setLabel(disk.getDeviceInfo() != null ? disk.getDeviceInfo().getLabel() : ""); + instanceDisk.setImagePath(getAbsoluteVmdkFile(disk)); + instanceDisk.setCapacity(disk.getCapacityInKB()); + 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("scsi"); + instanceDisk.setControllerUnit(((VirtualSCSIController) device).getBusNumber()); + } else { + instanceDisk.setController(DiskControllerType.none.toString()); + } + instanceDisk.setPosition(diskDevice.getUnitNumber()); + break; + } + } + s_logger.info(vmMo.getName() + " " + disk.getDeviceInfo().getLabel() + " " + disk.getDeviceInfo().getSummary() + " " + disk.getDiskObjectId() + " " + disk.getCapacityInKB() + " " + instanceDisk.getController()); + instanceDisks.add(instanceDisk); + } + } catch (Exception e) { + s_logger.info("Unable to retrieve unmanaged instance disk info! " + e.getMessage()); + } + } + Collections.sort(instanceDisks, new Comparator() { + @Override + public int compare(final UnmanagedInstance.Disk disk1, final UnmanagedInstance.Disk disk2) { + return extractInt(disk1) - extractInt(disk2); + } + + int extractInt(UnmanagedInstance.Disk disk) { + String num = disk.getLabel().replaceAll("\\D", ""); + // return 0 if no digits found + return num.isEmpty() ? 0 : Integer.parseInt(num); + } + }); + } + return instanceDisks; + } + + private List getUnmanageInstanceNics(VmwareHypervisorHost hyperHost, VirtualMachineMO vmMo) { + List instanceNics = new ArrayList<>(); + + HashMap guestNicMacIPAddressMap = new HashMap<>(); + try { + GuestInfo guestInfo = vmMo.getGuestInfo(); + if (guestInfo.getToolsStatus() == VirtualMachineToolsStatus.TOOLS_OK) { + for (GuestNicInfo nicInfo: guestInfo.getNet()) { + if (!nicInfo.getIpAddress().isEmpty()) { + guestNicMacIPAddressMap.put(nicInfo.getMacAddress(), nicInfo.getIpAddress().get(0)); + } + } + } else { + s_logger.info(String.format("Unable to retrieve guest nics for instance: %s from VMware tools as tools status: %s! ", vmMo.getName(), guestInfo.getToolsStatus().toString())); + } + } catch (Exception e) { + s_logger.info("Unable to retrieve guest nics for instance from VMware tools! " + e.getMessage()); + } + VirtualDevice[] nics = null; + try { + nics = vmMo.getNicDevices(); + } catch (Exception e) { + s_logger.info("Unable to retrieve unmanaged instance nics! " + e.getMessage()); + } + if (nics != null) { + for (VirtualDevice nic : nics) { + try { + VirtualEthernetCard ethCardDevice = (VirtualEthernetCard) nic; + s_logger.error(nic.getClass().getCanonicalName() + " " + nic.getBacking().getClass().getCanonicalName() + " " + ethCardDevice.getMacAddress()); + UnmanagedInstance.Nic instanceNic = new UnmanagedInstance.Nic(); + instanceNic.setNicId(ethCardDevice.getDeviceInfo().getLabel()); + instanceNic.setAdapterType(nic.getClass().getSimpleName()); + instanceNic.setMacAddress(ethCardDevice.getMacAddress()); + instanceNic.setIpAddress(guestNicMacIPAddressMap.get(instanceNic.getMacAddress())); + if (ethCardDevice.getSlotInfo() != null) { + instanceNic.setPciSlot(ethCardDevice.getSlotInfo().toString()); + } + VirtualDeviceBackingInfo backing = ethCardDevice.getBacking(); + if (backing instanceof VirtualEthernetCardDistributedVirtualPortBackingInfo) { + VirtualEthernetCardDistributedVirtualPortBackingInfo backingInfo = (VirtualEthernetCardDistributedVirtualPortBackingInfo) backing; + DistributedVirtualSwitchPortConnection port = backingInfo.getPort(); + String portKey = port.getPortKey(); + String portGroupKey = port.getPortgroupKey(); + String dvSwitchUuid = port.getSwitchUuid(); + + s_logger.debug("NIC " + nic.toString() + " is connected to dvSwitch " + dvSwitchUuid + " pg " + portGroupKey + " port " + portKey); + + ManagedObjectReference dvSwitchManager = vmMo.getContext().getVimClient().getServiceContent().getDvSwitchManager(); + ManagedObjectReference dvSwitch = vmMo.getContext().getVimClient().getService().queryDvsByUuid(dvSwitchManager, dvSwitchUuid); + + // Get all ports + DistributedVirtualSwitchPortCriteria criteria = new DistributedVirtualSwitchPortCriteria(); + criteria.setInside(true); + criteria.getPortgroupKey().add(portGroupKey); + List dvPorts = vmMo.getContext().getVimClient().getService().fetchDVPorts(dvSwitch, criteria); + + for (DistributedVirtualPort dvPort : dvPorts) { + // Find the port for this NIC by portkey + if (portKey.equals(dvPort.getKey())) { + VMwareDVSPortSetting settings = (VMwareDVSPortSetting) dvPort.getConfig().getSetting(); + VmwareDistributedVirtualSwitchVlanIdSpec vlanId = (VmwareDistributedVirtualSwitchVlanIdSpec) settings.getVlan(); + s_logger.trace("Found port " + dvPort.getKey() + " with vlan " + vlanId.getVlanId()); + if (vlanId.getVlanId() > 0 && vlanId.getVlanId() < 4095) { + instanceNic.setVlan(vlanId.getVlanId()); + } + break; + } + } + } else if (backing instanceof VirtualEthernetCardNetworkBackingInfo) { + VirtualEthernetCardNetworkBackingInfo backingInfo = (VirtualEthernetCardNetworkBackingInfo) backing; + instanceNic.setNetwork(backingInfo.getDeviceName()); + ManagedObjectReference mor = backingInfo.getNetwork(); + if (hyperHost instanceof HostMO) { + HostMO hostMo = (HostMO) hyperHost; + HostPortGroupSpec portGroupSpec = hostMo.getHostPortGroupSpec(backingInfo.getDeviceName()); + instanceNic.setVlan(portGroupSpec.getVlanId()); + } + } + instanceNics.add(instanceNic); + } catch (Exception e) { + s_logger.info("Unable to retrieve unmanaged instance nic info! " + e.getMessage()); + } + } + Collections.sort(instanceNics, new Comparator() { + @Override + public int compare(final UnmanagedInstance.Nic nic1, final UnmanagedInstance.Nic nic2) { + return extractInt(nic1) - extractInt(nic2); + } + + int extractInt(UnmanagedInstance.Nic nic) { + String num = nic.getNicId().replaceAll("\\D", ""); + // return 0 if no digits found + return num.isEmpty() ? 0 : Integer.parseInt(num); + } + }); + } + return instanceNics; + } + + private UnmanagedInstance getUnmanagedInstance(VmwareHypervisorHost hyperHost, VirtualMachineMO vmMo) { + UnmanagedInstance instance = null; + try { + instance = new UnmanagedInstance(); + instance.setName(vmMo.getVmName()); + instance.setCpuCores(vmMo.getConfigSummary().getNumCpu()); + instance.setCpuCoresPerSocket(vmMo.getCoresPerSocket()); + instance.setCpuSpeed(vmMo.getConfigSummary().getCpuReservation()); + instance.setMemory(vmMo.getConfigSummary().getMemorySizeMB()); + instance.setOperatingSystem(vmMo.getVmGuestInfo().getGuestFullName()); + if (Strings.isNullOrEmpty(instance.getOperatingSystem())) { + instance.setOperatingSystem(vmMo.getConfigSummary().getGuestFullName()); + } + UnmanagedInstance.PowerState powerState = UnmanagedInstance.PowerState.PowerUnknown; + if (vmMo.getPowerState().toString().equalsIgnoreCase("POWERED_ON")) { + powerState = UnmanagedInstance.PowerState.PowerOn; + } + if (vmMo.getPowerState().toString().equalsIgnoreCase("POWERED_OFF")) { + powerState = UnmanagedInstance.PowerState.PowerOff; + } + instance.setPowerState(powerState); + instance.setDisks(getUnmanageInstanceDisks(vmMo)); + instance.setNics(getUnmanageInstanceNics(hyperHost, vmMo)); + } catch (Exception e) { + s_logger.info("Unable to retrieve unmanaged instance info! " + e.getMessage()); + } + + return instance; + } + + private Answer execute(GetUnmanagedInstancesCommand cmd) { + if (s_logger.isInfoEnabled()) { + s_logger.info("Executing resource GetUnmanagedInstancesCommand " + _gson.toJson(cmd)); + } + + VmwareContext context = getServiceContext(); + HashMap unmanagedInstances = new HashMap<>(); + try { + VmwareHypervisorHost hyperHost = getHyperHost(context); + + String vmName = cmd.getInstanceName(); + List vmMos = hyperHost.listVmsOnHyperHost(vmName); + + for (VirtualMachineMO vmMo : vmMos) { + if (vmMo == null) { + continue; + } + if (vmMo.isTemplate()) { + continue; + } + // Filter managed instances + if (cmd.hasManagedInstance(vmMo.getName())) { + continue; + } + // Filter instance if answer is requested for a particular instance name + if (!Strings.isNullOrEmpty(cmd.getInstanceName()) && + !cmd.getInstanceName().equals(vmMo.getVmName())) { + continue; + } + UnmanagedInstance instance = getUnmanagedInstance(hyperHost, vmMo); + if (instance != null) { + unmanagedInstances.put(instance.getName(), instance); + } + } + } catch (Exception e) { + s_logger.info("GetUnmanagedInstancesCommand failed due to " + VmwareHelper.getExceptionMessage(e)); + } + return new GetUnmanagedInstancesAnswer(cmd, "", unmanagedInstances); + } } diff --git a/scripts/vm/hypervisor/vmware/discover_networks.py b/scripts/vm/hypervisor/vmware/discover_networks.py new file mode 100755 index 000000000000..6a7eeb2e5166 --- /dev/null +++ b/scripts/vm/hypervisor/vmware/discover_networks.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python3 +# 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. + +from __future__ import print_function +from pyVim.connect import SmartConnect, SmartConnectNoSSL, Disconnect +from pyVmomi import vim +import atexit +import sys +import argparse +import json + +isDebugLogs = False +hostClusterNameDict = {} +pgHostNameDict = {} +networksDict = {} + +def log_message(msg): + if isDebugLogs == True: + print(msg) + +def get_clusters(content, cluster=None): + if cluster is not None: + log_message("Getting clusters (name=" + cluster + ") ...") + else: + log_message("Getting clusters ...") + cluster_view = content.viewManager.CreateContainerView(content.rootFolder, + [vim.ClusterComputeResource], + True) + clusters = [] + if cluster is not None: + for c in cluster_view.view: + if c.name == cluster: + clusters.append(c) + hosts = c.host + for host in hosts: + hostClusterNameDict[host.name] = c.name + break + else: + for c in cluster_view.view: + clusters.append(c) + hosts = c.host + for host in hosts: + hostClusterNameDict[host.name] = c.name + cluster_view.Destroy() + log_message('\t{} cluster(s) found'.format(len(clusters))) + for c in clusters: + log_message('\t' + c.name) + return clusters + + +def get_vm_hosts(clusters): + log_message("Getting ESX hosts ...") + hosts = [] + for cluster in clusters: + hosts.extend(cluster.host) + log_message('\t{} host(s) found'.format(len(hosts))) + for host in hosts: + log_message('\t' + host.name) + return hosts + + +def get_vms(content): + log_message("Getting VMs ...") + vm_view = content.viewManager.CreateContainerView(content.rootFolder, + [vim.VirtualMachine], + True) + obj = [vm for vm in vm_view.view] + vm_view.Destroy() + return obj + + +def get_hosts_port_groups(hosts): + log_message("Collecting portGroups on hosts. This may take a while ...") + hostPgDict = {} + for host in hosts: + pgs = host.config.network.portgroup + hostPgDict[host] = pgs + for pg in pgs: + pgHostNameDict[pg.spec.name] = host.name + log_message("\tHost {} done.".format(host.name)) + log_message("\tPortgroup collection complete.") + return hostPgDict + + +def get_vm_info(vm, hostPgDict): + vmPowerState = vm.runtime.powerState + log_message('\tVM: ' + vm.name + '(' + vmPowerState + ')') + get_vm_nics(vm, hostPgDict) + + +def get_vm_nics(vm, hostPgDict): + try: + for dev in vm.config.hardware.device: + if isinstance(dev, vim.vm.device.VirtualEthernetCard): + dev_backing = dev.backing + portGroup = None + vlanId = None + vSwitch = None + if hasattr(dev_backing, 'port'): + portGroupKey = dev.backing.port.portgroupKey + dvsUuid = dev.backing.port.switchUuid + try: + dvs = content.dvSwitchManager.QueryDvsByUuid(dvsUuid) + except: + portGroup = "** Error: DVS not found **" + vlanId = "NA" + vSwitch = "NA" + else: + pgObj = dvs.LookupDvPortGroup(portGroupKey) + portGroup = pgObj.config.name + vlanId = str(pgObj.config.defaultPortConfig.vlan.vlanId) + vSwitch = str(dvs.name) + else: + portGroup = dev.backing.network.name + vmHost = vm.runtime.host + # global variable hostPgDict stores portGroups per host + pgs = hostPgDict[vmHost] + for p in pgs: + if portGroup in p.key: + vlanId = str(p.spec.vlanId) + vSwitch = str(p.spec.vswitchName) + if portGroup is None: + portGroup = 'NA' + if vlanId is None: + vlanId = 'NA' + if vSwitch is None: + vSwitch = 'NA' + add_network(portGroup, vlanId, vSwitch, vm.name, dev.deviceInfo.label, dev.macAddress) + log_message('\t\t' + dev.deviceInfo.label + '->' + dev.macAddress + + ' @ ' + vSwitch + '->' + portGroup + + ' (VLAN ' + vlanId + ')') + except AttributeError: + log_message('\tError: Unable retrieve details for ' + vm.name) + +def add_network(portGroup, vlanId, vSwitch, vmName, vmDeviceLabel, vmMacAddress): + key = vSwitch + '->' + portGroup + ' (VLAN ' + vlanId + ')' + device = {"label": vmDeviceLabel, "macaddress": vmMacAddress} + vm = {"name":vmName, "device": device} + if key in networksDict: + network = networksDict[key] + network["virtualmachines"].append(vm) + networksDict[key] = network + else: + vms = [vm] + host = pgHostNameDict[portGroup] + cluster = hostClusterNameDict[host] + network = {"portgroup": portGroup, "cluster": cluster, "host": host, "vlanid": vlanId, "switch": vSwitch, "virtualmachines": vms} + networksDict[key] = network + + +def get_args(): + parser = argparse.ArgumentParser( + description='Arguments for talking to vCenter') + + parser.add_argument('-s', '--host', + required=True, + action='store', + help='vSpehre service to connect to') + + parser.add_argument('-o', '--port', + type=int, + default=443, + action='store', + help='Port to connect on') + + parser.add_argument('-u', '--user', + required=True, + action='store', + help='User name to use') + + parser.add_argument('-p', '--password', + required=False, + action='store', + help='Password to use') + + parser.add_argument('-c', '--cluster', + required=False, + action='store', + help='Cluster for which discover networks') + + parser.add_argument('-S', '--disable_ssl_verification', + required=False, + action='store_true', + help='Disable ssl host certificate verification') + + parser.add_argument('-d', '--debug', + required=False, + action='store_true', + help='Debug log messages') + + args = parser.parse_args() + return args + + +def main(): + global content, isDebugLogs, hostClusterNameDict, pgHostNameDict, networksDict + args = get_args() + if args.password: + password = args.password + else: + password = getpass.getpass(prompt='Enter password for host %s and ' + 'user %s: ' % (args.host, args.user)) + if args.debug: + isDebugLogs = True + if args.disable_ssl_verification: + serviceInstance = SmartConnectNoSSL(host=args.host, + user=args.user, + pwd=password, + port=int(args.port)) + else: + serviceInstance = SmartConnect(host=args.host, + user=args.user, + pwd=password, + port=int(args.port)) + + atexit.register(Disconnect, serviceInstance) + content = serviceInstance.RetrieveContent() + if args.cluster: + clusters = get_clusters(content, args.cluster) + else: + clusters = get_clusters(content) + hosts = [] + if len(clusters) > 0: + hosts = get_vm_hosts(clusters) + if len(hosts) > 0: + hostPgDict = get_hosts_port_groups(hosts) + vms = get_vms(content) + log_message('\t{} VM(s) found'.format(len(vms))) + for vm in vms: + get_vm_info(vm, hostPgDict) + networks = list(networksDict.values()) + response = {"count": len(networks), "networks": networks} + print(json.dumps(response, indent=2, sort_keys=True)) + +# Main section +if __name__ == "__main__": + sys.exit(main()) diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index 6cb457471064..560e18781bdd 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -4075,7 +4075,7 @@ private VirtualMachine upgradeStoppedSystemVm(final Long systemVmId, final Long if (newServiceOffering.isDynamic()) { newServiceOffering.setDynamicFlag(true); _userVmMgr.validateCustomParameters(newServiceOffering, customparameters); - newServiceOffering = _offeringDao.getcomputeOffering(newServiceOffering, customparameters); + newServiceOffering = _offeringDao.getComputeOffering(newServiceOffering, customparameters); } _itMgr.checkIfCanUpgrade(systemVm, newServiceOffering); diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index 2503b33e3331..1dd1ea07fd4e 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -313,6 +313,7 @@ import com.cloud.vm.snapshot.VMSnapshotVO; import com.cloud.vm.snapshot.dao.VMSnapshotDao; import com.google.common.base.Strings; +import com.google.gson.Gson; public class UserVmManagerImpl extends ManagerBase implements UserVmManager, VirtualMachineGuru, UserVmService, Configurable { private static final Logger s_logger = Logger.getLogger(UserVmManagerImpl.class); @@ -489,6 +490,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir @Inject private TemplateOVFPropertiesDao templateOVFPropertiesDao; + protected Gson gson; + private ScheduledExecutorService _executor = null; private ScheduledExecutorService _vmIpFetchExecutor = null; private int _expungeInterval; @@ -986,7 +989,7 @@ public UserVm upgradeVirtualMachine(UpgradeVMCmd cmd) throws ResourceAllocationE if (newServiceOffering.isDynamic()) { newServiceOffering.setDynamicFlag(true); validateCustomParameters(newServiceOffering, cmd.getDetails()); - newServiceOffering = _offeringDao.getcomputeOffering(newServiceOffering, customParameters); + newServiceOffering = _offeringDao.getComputeOffering(newServiceOffering, customParameters); } ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId()); @@ -1092,7 +1095,7 @@ private UserVm upgradeStoppedVirtualMachine(Long vmId, Long svcOffId, Map networkNicMap, - final long id, final String instanceName, final String uuidName, final HypervisorType hypervisorType, final Map customParameters, final Map> extraDhcpOptionMap, final Map dataDiskTemplateToDiskOfferingMap, - Map userVmOVFPropertiesMap) throws InsufficientCapacityException { + private UserVmVO commitUserVm(final boolean isImport, final DataCenter zone, final Host host, final Host lastHost, final VirtualMachineTemplate template, final String hostName, final String displayName, final Account owner, + final Long diskOfferingId, final Long diskSize, final String userData, final Account caller, final Boolean isDisplayVm, final String keyboard, + final long accountId, final long userId, final ServiceOffering offering, final boolean isIso, final String sshPublicKey, final LinkedHashMap networkNicMap, + final long id, final String instanceName, final String uuidName, final HypervisorType hypervisorType, final Map customParameters, + final Map> extraDhcpOptionMap, final Map dataDiskTemplateToDiskOfferingMap, + final Map userVmOVFPropertiesMap, final VirtualMachine.PowerState powerState) throws InsufficientCapacityException { return Transaction.execute(new TransactionCallbackWithException() { @Override public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCapacityException { @@ -3901,9 +3904,21 @@ public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCap } } + if (isImport) { + vm.setDataCenterId(zone.getId()); + vm.setHostId(host.getId()); + if (lastHost != null) { + vm.setLastHostId(lastHost.getId()); + } + vm.setPowerState(powerState); + if (powerState == VirtualMachine.PowerState.PowerOn) { + vm.setState(State.Running); + } + } + _vmDao.persist(vm); for (String key : customParameters.keySet()) { - if( key.equalsIgnoreCase(VmDetailConstants.CPU_NUMBER) || + if (key.equalsIgnoreCase(VmDetailConstants.CPU_NUMBER) || key.equalsIgnoreCase(VmDetailConstants.CPU_SPEED) || key.equalsIgnoreCase(VmDetailConstants.MEMORY)) { // handle double byte strings. @@ -3937,27 +3952,28 @@ public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCap } _vmDao.saveDetails(vm); + if (!isImport) { + s_logger.debug("Allocating in the DB for vm"); + DataCenterDeployment plan = new DataCenterDeployment(zone.getId()); - s_logger.debug("Allocating in the DB for vm"); - DataCenterDeployment plan = new DataCenterDeployment(zone.getId()); - - List computeTags = new ArrayList(); - computeTags.add(offering.getHostTag()); + List computeTags = new ArrayList(); + computeTags.add(offering.getHostTag()); - List rootDiskTags = new ArrayList(); - rootDiskTags.add(offering.getTags()); + List rootDiskTags = new ArrayList(); + rootDiskTags.add(offering.getTags()); - if (isIso) { - _orchSrvc.createVirtualMachineFromScratch(vm.getUuid(), Long.toString(owner.getAccountId()), vm.getIsoId().toString(), hostName, displayName, - hypervisorType.name(), guestOSCategory.getName(), offering.getCpu(), offering.getSpeed(), offering.getRamSize(), diskSize, computeTags, rootDiskTags, - networkNicMap, plan, extraDhcpOptionMap); - } else { - _orchSrvc.createVirtualMachine(vm.getUuid(), Long.toString(owner.getAccountId()), Long.toString(template.getId()), hostName, displayName, hypervisorType.name(), - offering.getCpu(), offering.getSpeed(), offering.getRamSize(), diskSize, computeTags, rootDiskTags, networkNicMap, plan, rootDiskSize, extraDhcpOptionMap, dataDiskTemplateToDiskOfferingMap); - } + if (isIso) { + _orchSrvc.createVirtualMachineFromScratch(vm.getUuid(), Long.toString(owner.getAccountId()), vm.getIsoId().toString(), hostName, displayName, + hypervisorType.name(), guestOSCategory.getName(), offering.getCpu(), offering.getSpeed(), offering.getRamSize(), diskSize, computeTags, rootDiskTags, + networkNicMap, plan, extraDhcpOptionMap); + } else { + _orchSrvc.createVirtualMachine(vm.getUuid(), Long.toString(owner.getAccountId()), Long.toString(template.getId()), hostName, displayName, hypervisorType.name(), + offering.getCpu(), offering.getSpeed(), offering.getRamSize(), diskSize, computeTags, rootDiskTags, networkNicMap, plan, rootDiskSize, extraDhcpOptionMap, dataDiskTemplateToDiskOfferingMap); + } - if (s_logger.isDebugEnabled()) { - s_logger.debug("Successfully allocated DB entry for " + vm); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully allocated DB entry for " + vm); + } } CallContext.current().setEventDetails("Vm Id: " + vm.getUuid()); @@ -3976,6 +3992,20 @@ public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCap }); } + private UserVmVO commitUserVm(final DataCenter zone, final VirtualMachineTemplate template, final String hostName, final String displayName, final Account owner, + final Long diskOfferingId, final Long diskSize, final String userData, final Account caller, final Boolean isDisplayVm, final String keyboard, + final long accountId, final long userId, final ServiceOfferingVO offering, final boolean isIso, final String sshPublicKey, final LinkedHashMap networkNicMap, + final long id, final String instanceName, final String uuidName, final HypervisorType hypervisorType, final Map customParameters, final Map> extraDhcpOptionMap, final Map dataDiskTemplateToDiskOfferingMap, + Map userVmOVFPropertiesMap) throws InsufficientCapacityException { + return commitUserVm(false, zone, null, null, template, hostName, displayName, owner, + diskOfferingId, diskSize, userData, caller, isDisplayVm, keyboard, + accountId, userId, offering, isIso, sshPublicKey, networkNicMap, + id, instanceName, uuidName, hypervisorType, customParameters, + extraDhcpOptionMap, dataDiskTemplateToDiskOfferingMap, + userVmOVFPropertiesMap, null); + } + public void validateRootDiskResize(final HypervisorType hypervisorType, Long rootDiskSize, VMTemplateVO templateVO, UserVmVO vm, final Map customParameters) throws InvalidParameterValueException { // rootdisksize must be larger than template. @@ -6842,4 +6872,33 @@ private void deleteVolumesFromVm(List volumes) { } } } -} + + @Override + public UserVm importVM(final DataCenter zone, final Host host, final VirtualMachineTemplate template, final String instanceName, final String displayName, + final Account owner, final String userData, final Account caller, final Boolean isDisplayVm, final String keyboard, + final long accountId, final long userId, final ServiceOffering serviceOffering, final DiskOffering rootDiskOffering, final String sshPublicKey, + final String hostName, final HypervisorType hypervisorType, final Map customParameters, final VirtualMachine.PowerState powerState) throws InsufficientCapacityException { + if (zone == null) { + throw new InvalidParameterValueException("Unable to import virtual machine with invalid zone"); + } + if (host == null) { + throw new InvalidParameterValueException("Unable to import virtual machine with invalid host"); + } + + final long id = _vmDao.getNextInSequence(Long.class, "id"); + + if (hostName != null) { + // Check is hostName is RFC compliant + checkNameForRFCCompliance(hostName); + } + + final String uuidName = _uuidMgr.generateUuid(UserVm.class, null); + final Host lastHost = powerState != VirtualMachine.PowerState.PowerOn ? host : null; + UserVmVO userVmVO = commitUserVm(true, zone, host, lastHost, template, hostName, displayName, owner, + rootDiskOffering.getId(), null, userData, caller, isDisplayVm, keyboard, + accountId, userId, serviceOffering, false, sshPublicKey, null, + id, instanceName, uuidName, hypervisorType, customParameters, + null, null, null, powerState); + return userVmVO; + } +} \ No newline at end of file diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java new file mode 100644 index 000000000000..466b226bf0eb --- /dev/null +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -0,0 +1,811 @@ +// 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.vm; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.inject.Inject; + +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.ResponseGenerator; +import org.apache.cloudstack.api.ResponseObject; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.command.admin.vm.ImportUnmanagedInstanceCmd; +import org.apache.cloudstack.api.command.admin.vm.ListUnmanagedInstancesCmd; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.NicResponse; +import org.apache.cloudstack.api.response.UnmanagedInstanceDiskResponse; +import org.apache.cloudstack.api.response.UnmanagedInstanceResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; +import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.log4j.Logger; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.GetUnmanagedInstancesAnswer; +import com.cloud.agent.api.GetUnmanagedInstancesCommand; +import com.cloud.capacity.CapacityManager; +import com.cloud.configuration.Resource; +import com.cloud.dc.DataCenter; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.deploy.DataCenterDeployment; +import com.cloud.deploy.DeployDestination; +import com.cloud.deploy.DeploymentPlanner; +import com.cloud.deploy.DeploymentPlanningManager; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.host.Host; +import com.cloud.host.HostVO; +import com.cloud.host.Status; +import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor; +import com.cloud.network.Network; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkVO; +import com.cloud.offering.DiskOffering; +import com.cloud.offering.ServiceOffering; +import com.cloud.org.Cluster; +import com.cloud.resource.ResourceManager; +import com.cloud.serializer.GsonHelper; +import com.cloud.server.ManagementService; +import com.cloud.service.ServiceOfferingVO; +import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.storage.StoragePool; +import com.cloud.storage.VMTemplateStoragePoolVO; +import com.cloud.storage.Volume; +import com.cloud.storage.VolumeApiService; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.DiskOfferingDao; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VMTemplatePoolDao; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.template.VirtualMachineTemplate; +import com.cloud.user.Account; +import com.cloud.user.AccountService; +import com.cloud.user.ResourceLimitService; +import com.cloud.user.UserVO; +import com.cloud.user.dao.UserDao; +import com.cloud.uservm.UserVm; +import com.cloud.utils.Pair; +import com.cloud.utils.net.NetUtils; +import com.cloud.vm.DiskProfile; +import com.cloud.vm.NicProfile; +import com.cloud.vm.UserVmManager; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineManager; +import com.cloud.vm.VirtualMachineProfile; +import com.cloud.vm.VirtualMachineProfileImpl; +import com.cloud.vm.VmDetailConstants; +import com.cloud.vm.dao.NicDao; +import com.cloud.vm.dao.VMInstanceDao; +import com.google.common.base.Strings; +import com.google.gson.Gson; + +public class VmImportManagerImpl implements VmImportService { + private static final Logger LOGGER = Logger.getLogger(VmImportManagerImpl.class); + + @Inject + private AgentManager agentManager; + @Inject + private DataCenterDao dataCenterDao; + @Inject + private ClusterDao clusterDao; + @Inject + private HostDao hostDao; + @Inject + private AccountService accountService; + @Inject + private UserDao userDao; + @Inject + private VMTemplateDao templateDao; + @Inject + private VMTemplatePoolDao templatePoolDao; + @Inject + private ServiceOfferingDao serviceOfferingDao; + @Inject + private DiskOfferingDao diskOfferingDao; + @Inject + private ResourceManager resourceManager; + @Inject + private ResourceLimitService resourceLimitService; + @Inject + private UserVmManager userVmManager; + @Inject + private ResponseGenerator responseGenerator; + @Inject + private VolumeOrchestrationService volumeManager; + @Inject + private VolumeDao volumeDao; + @Inject + private PrimaryDataStoreDao primaryDataStoreDao; + @Inject + private NetworkDao networkDao; + @Inject + private NetworkOrchestrationService networkOrchestrationService; + @Inject + private VMInstanceDao vmDao; + @Inject + private CapacityManager capacityManager; + @Inject + private VolumeApiService volumeApiService; + @Inject + private DeploymentPlanningManager deploymentPlanningManager; + @Inject + private VirtualMachineManager virtualMachineManager; + @Inject + private ManagementService managementService; + @Inject + private NicDao nicDao; + + protected Gson gson; + + public VmImportManagerImpl() { + gson = GsonHelper.getGsonLogger(); + } + + private UnmanagedInstanceResponse createUnmanagedInstanceResponse(UnmanagedInstance instance, Cluster cluster, Host host) { + UnmanagedInstanceResponse response = new UnmanagedInstanceResponse(); + response.setName(instance.getName()); + if (cluster != null) { + response.setClusterId(cluster.getUuid()); + } + if (host != null) { + response.setHostId(host.getUuid()); + } + response.setPowerState(instance.getPowerState().toString()); + response.setCpuCores(instance.getCpuCores()); + response.setCpuSpeed(instance.getCpuSpeed()); + response.setCpuCoresPerSocket(instance.getCpuCoresPerSocket()); + response.setMemory(instance.getMemory()); + response.setOperatingSystem(instance.getOperatingSystem()); + response.setObjectName(UnmanagedInstance.class.getSimpleName().toLowerCase()); + + if (instance.getDisks() != null) { + for (UnmanagedInstance.Disk disk : instance.getDisks()) { + UnmanagedInstanceDiskResponse diskResponse = new UnmanagedInstanceDiskResponse(); + diskResponse.setDiskId(disk.getDiskId()); + if (!Strings.isNullOrEmpty(disk.getLabel())) { + diskResponse.setLabel(disk.getLabel()); + } + diskResponse.setCapacity(disk.getCapacity()); + diskResponse.setController(disk.getController()); + diskResponse.setControllerUnit(disk.getControllerUnit()); + diskResponse.setPosition(disk.getPosition()); + diskResponse.setImagePath(disk.getImagePath()); + response.addDisk(diskResponse); + } + } + + if (instance.getNics() != null) { + for (UnmanagedInstance.Nic nic : instance.getNics()) { + NicResponse nicResponse = new NicResponse(); + nicResponse.setId(nic.getNicId()); + nicResponse.setNetworkName(nic.getNetwork()); + nicResponse.setMacAddress(nic.getMacAddress()); + if (!Strings.isNullOrEmpty(nic.getIpAddress())) { + nicResponse.setIpaddress(nic.getIpAddress()); + } + nicResponse.setVlanId(nic.getVlan()); + response.addNic(nicResponse); + } + } + return response; + } + + private List getAdditionalNameFilters(Cluster cluster) { + List additionalNameFilter = new ArrayList<>(); + if (cluster == null) { + return additionalNameFilter; + } + // VMWare considers some templates and expunging volumes as VMs + if (cluster.getHypervisorType() == Hypervisor.HypervisorType.VMware) { + List templates = templatePoolDao.listAll(); + for (VMTemplateStoragePoolVO template : templates) { + additionalNameFilter.add(template.getInstallPath()); + } + } + return additionalNameFilter; + } + + private List getHostManagedVms(Host host) { + List managedVms = new ArrayList<>(); + List instances = vmDao.listByHostId(host.getId()); + for (VMInstanceVO instance : instances) { + managedVms.add(instance.getInstanceName()); + } + instances = vmDao.listByLastHostId(host.getId()); + for (VMInstanceVO instance : instances) { + managedVms.add(instance.getInstanceName()); + } + return managedVms; + } + + private boolean hostSupportsServiceOffering(HostVO host, ServiceOffering serviceOffering) { + if (host == null) { + return false; + } + if (serviceOffering == null) { + return false; + } + if (Strings.isNullOrEmpty(serviceOffering.getHostTag())) { + return true; + } + hostDao.loadHostTags(host); + return host.getHostTags() != null && host.getHostTags().contains(serviceOffering.getHostTag()); + } + + private boolean storagePoolSupportsDiskOffering(StoragePool pool, DiskOffering diskOffering) { + if (pool == null) { + return false; + } + if (diskOffering == null) { + return false; + } + return volumeApiService.doesTargetStorageSupportDiskOffering(pool, diskOffering.getTags()); + } + + private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedInstance instance, ServiceOfferingVO serviceOffering, final Account owner, final DataCenter zone, final Map details) + throws ServerApiException, PermissionDeniedException, ResourceAllocationException { + if (instance == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM is not valid!")); + } + if (serviceOffering == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering is not valid!", instance.getName())); + } + accountService.checkAccess(owner, serviceOffering, zone); + final Integer cpu = instance.getCpuCores(); + final Integer memory = instance.getMemory(); + Integer cpuSpeed = instance.getCpuSpeed(); + if (cpu == null || cpu == 0) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("CPU cores for VM not valid!", instance.getName())); + } + if (memory == null || memory == 0) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Memory for VM not valid!", instance.getName())); + } + if (serviceOffering.isDynamic()) { + if (cpuSpeed == null || cpuSpeed == 0) { + try { + cpuSpeed = Integer.parseInt(details.get(VmDetailConstants.CPU_SPEED)); + } catch (Exception e) { + cpuSpeed = 0; + } + } + Map parameters = new HashMap<>(); + parameters.put(VmDetailConstants.CPU_NUMBER, String.valueOf(cpu)); + parameters.put(VmDetailConstants.MEMORY, String.valueOf(memory)); + if (serviceOffering.getSpeed()==null && cpuSpeed > 0) { + parameters.put(VmDetailConstants.CPU_SPEED, String.valueOf(cpuSpeed)); + } + serviceOffering.setDynamicFlag(true); + userVmManager.validateCustomParameters(serviceOffering, parameters); + serviceOffering = serviceOfferingDao.getComputeOffering(serviceOffering, parameters); + } else { + if (!cpu.equals(serviceOffering.getCpu()) && !instance.getPowerState().equals(UnmanagedInstance.PowerState.PowerOff)) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %d CPU cores does not matches VM CPU cores %d and VM is not in powered off state (Power state: %s)!", serviceOffering.getUuid(), serviceOffering.getCpu(), cpu, instance.getPowerState())); + } + if (!memory.equals(serviceOffering.getRamSize()) && !instance.getPowerState().equals(UnmanagedInstance.PowerState.PowerOff)) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %dMB memory does not matches VM memory %dMB and VM is not in powered off state (Power state: %s)!", serviceOffering.getUuid(), serviceOffering.getRamSize(), memory, instance.getPowerState())); + } + if (cpuSpeed != null && cpuSpeed > 0 && !cpuSpeed.equals(serviceOffering.getSpeed()) && !instance.getPowerState().equals(UnmanagedInstance.PowerState.PowerOff)) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %dMHz CPU speed does not matches VM CPU speed %dMHz and VM is not in powered off state (Power state: %s)!", serviceOffering.getUuid(), serviceOffering.getSpeed(), cpuSpeed, instance.getPowerState())); + } + } + resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.cpu, new Long(serviceOffering.getCpu())); + resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.memory, new Long(serviceOffering.getRamSize())); + return serviceOffering; + } + + private void checkUnmanagedDiskAndOfferingForImport(UnmanagedInstance.Disk disk, DiskOffering diskOffering, final Account owner, final DataCenter zone) + throws ServerApiException, PermissionDeniedException, ResourceAllocationException { + if (diskOffering == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID: %s not found during VM import!", disk.getDiskId())); + } + accountService.checkAccess(owner, diskOffering, zone); + resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.volume); + long diskSize = disk.getCapacity() / (1024 * 1024); + if (!diskOffering.isCustomized() && diskOffering.getDiskSize() < diskSize) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk offering(ID: %s) %dGB is found less than the size of disk(ID: %s) %dGB during VM import!", diskOffering.getUuid(), diskOffering.getDiskSize(), disk.getDiskId(), diskSize)); + } + } + + private void checkUnmanagedDiskAndOfferingForImport(List disks, final Map diskOfferingMap, final Account owner, final DataCenter zone) + throws ServerApiException, PermissionDeniedException, ResourceAllocationException { + for (UnmanagedInstance.Disk disk : disks) { + if (!diskOfferingMap.containsKey(disk.getDiskId())) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID: %s not found during VM import!", disk.getDiskId())); + } + checkUnmanagedDiskAndOfferingForImport(disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), owner, zone); + } + } + + private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Network network, final DataCenter zone, final String hostName) throws ServerApiException { + if (network == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import!", nic.getNicId())); + } + if (network.getDataCenterId() != zone.getId()) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network(ID: %s) for nic(ID: %s) belongs to a different zone than VM to be imported!", network.getUuid(), nic.getNicId())); + } + if (nic.getVlan() != null && (Strings.isNullOrEmpty(network.getBroadcastUri().toString()) || !network.getBroadcastUri().toString().equals(String.format("vlan://%d", nic.getVlan())))) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VLAN of network(ID: %s) %s is found different from the VLAN of nic(ID: %s) vlan://%d during VM import!", network.getUuid(), network.getBroadcastUri().toString(), nic.getNicId(), nic.getVlan())); + } + // * get all vms hostNames in the network + List hostNames = vmDao.listDistinctHostNames(network.getId()); + // * verify that there are no duplicates + if (hostNames.contains(hostName)) { + throw new InvalidParameterValueException("The vm with hostName " + hostName + " already exists in the network domain: " + network.getNetworkDomain() + "; network=" + + network); + } + } + + private Map getUnmanagedNicNetworkMap(List nics, final Map callerNicNetworkMap, final DataCenter zone, final String hostName) throws ServerApiException { + Map nicNetworkMap = new HashMap<>(); + for (UnmanagedInstance.Nic nic : nics) { + Network network = null; + if (!callerNicNetworkMap.containsKey(nic.getNicId())) { + if (nic.getVlan() != null) { + // Find a suitable network + List networks = networkDao.listByZone(zone.getId()); + for (NetworkVO networkVO : networks) { + try { + checkUnmanagedNicAndNetworkForImport(nic, networkVO, zone, hostName); + network = networkVO; + break; + } catch (Exception e) { + } + } + } + } else { + network = networkDao.findById(callerNicNetworkMap.get(nic.getNicId())); + checkUnmanagedNicAndNetworkForImport(nic, network, zone, hostName); + } + if (network == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Suitable network for nic(ID: %s) not found during VM import!", nic.getNicId())); + } + nicNetworkMap.put(nic.getNicId(), network.getId()); + } + return nicNetworkMap; + } + + private Pair importDisk(UnmanagedInstance.Disk disk, VirtualMachine vm, DiskOffering diskOffering, + Volume.Type type, String name, Long diskSize, VirtualMachineTemplate template, + Account owner, Long deviceId, boolean migrateAllowed) { + VirtualMachineDiskInfo diskInfo = new VirtualMachineDiskInfo(); + diskInfo.setDiskDeviceBusName(String.format("%s%d:%d", disk.getController(), disk.getControllerUnit(), disk.getPosition())); + diskInfo.setDiskChain(new String[]{disk.getImagePath()}); + String path = disk.getImagePath(); + long poolId = 0; + StoragePool storagePool = null; + if (vm.getHypervisorType() == Hypervisor.HypervisorType.VMware) { + String[] splits = path.split(" "); + String poolUuid = splits[0]; + poolUuid = poolUuid.replace("[", "").replace("]", ""); + if (poolUuid.length() == 32) { + poolUuid = String.format("%s-%s-%s-%s-%s", poolUuid.substring(0, 8), + poolUuid.substring(8, 12), poolUuid.substring(12, 16), + poolUuid.substring(16, 20), poolUuid.substring(20, 32)); + storagePool = primaryDataStoreDao.findPoolByUUID(poolUuid); + } + if (storagePool == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Unable to import disk ID: %s as storage pool not found!"); + } + if (!migrateAllowed && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) { + throw new InvalidParameterValueException(String.format("Disk offering: %s is not compatible with storage pool: %s of unmanaged disk: %s", diskOffering.getUuid(), storagePool.getUuid(), disk.getDiskId())); + } + poolId = storagePool.getId(); + path = String.join(" ", Arrays.copyOfRange(splits, 1, splits.length)); + splits = path.split("/"); + path = splits[splits.length - 1]; + splits = path.split("\\."); + path = splits[0]; + } + DiskProfile profile = volumeManager.importVolume(type, name, diskOffering, diskSize, + diskOffering.getMinIops(), diskOffering.getMaxIops(), vm, template, owner, deviceId, poolId, path, gson.toJson(diskInfo)); + + return new Pair(profile, storagePool); + } + + private NicProfile importNic(UnmanagedInstance.Nic nic, VirtualMachine vm, Network network, String ipAddress, boolean isDefaultNic) { + Pair result = networkOrchestrationService.importNic(nic.getMacAddress(), 0, network, isDefaultNic, vm, ipAddress); + if (result == null) { + return null; + } + return result.first(); + } + + private void cleanupFailedImportVM(UserVm userVm, ServiceOfferingVO serviceOfferingVO) { + // Remove all volumes + List volumes = volumeDao.findByInstance(userVm.getId()); + volumeDao.deleteVolumesByInstance(userVm.getId()); + if (!CollectionUtils.isEmpty(volumes)) { + for (VolumeVO volumeVO : volumes) { + resourceLimitService.decrementResourceCount(userVm.getAccountId(), Resource.ResourceType.volume, volumeVO.isDisplayVolume()); + resourceLimitService.decrementResourceCount(userVm.getAccountId(), Resource.ResourceType.primary_storage, volumeVO.isDisplayVolume(), new Long(volumeVO.getSize())); + } + } + // Remove all nics + nicDao.removeNicsForInstance(userVm.getId()); + // Remove vm + vmDao.remove(userVm.getId()); + resourceLimitService.decrementResourceCount(userVm.getAccountId(), Resource.ResourceType.user_vm, userVm.isDisplayVm()); + resourceLimitService.decrementResourceCount(userVm.getAccountId(), Resource.ResourceType.cpu, userVm.isDisplayVm(), new Long(serviceOfferingVO.getCpu())); + resourceLimitService.decrementResourceCount(userVm.getAccountId(), Resource.ResourceType.memory, userVm.isDisplayVm(), new Long(serviceOfferingVO.getRamSize())); + } + + private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate template, ServiceOfferingVO serviceOffering, UserVm userVm, final Account owner, List> diskProfileStoragePoolList) { + UserVm vm = userVm; + if (sourceHost == null || serviceOffering == null || userVm == null || diskProfileStoragePoolList == null) { + LOGGER.warn("Failed to check VM migrations need during import!"); + return null; + } + if (!hostSupportsServiceOffering(sourceHost, serviceOffering)) { + final VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm, template, serviceOffering, owner, null); + DeploymentPlanner.ExcludeList excludeList = new DeploymentPlanner.ExcludeList(); + excludeList.addHost(sourceHost.getId()); + final DataCenterDeployment plan = new DataCenterDeployment(sourceHost.getDataCenterId(), sourceHost.getPodId(), sourceHost.getClusterId(), null, null, null); + DeployDestination dest = null; + try { + dest = deploymentPlanningManager.planDeployment(profile, plan, excludeList, null); + } catch (Exception e) { + LOGGER.warn(String.format("VM import failed for unmanaged vm: %s during vm migration, finding deployment destination!", vm.getInstanceName()), e); + cleanupFailedImportVM(vm, serviceOffering); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during vm migration, finding deployment destination!", vm.getInstanceName())); + } + if (dest != null) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(" Found " + dest + " for migrating the vm to."); + } + } + if (dest == null) { + cleanupFailedImportVM(vm, serviceOffering); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during vm migration, no deployment destination found!", vm.getInstanceName())); + } + try { + virtualMachineManager.migrate(vm.getUuid(), sourceHost.getId(), dest); + vm = userVmManager.getUserVm(vm.getId()); + } catch (Exception e) { + LOGGER.error(String.format("VM import failed for unmanaged vm: %s during vm migration!", vm.getInstanceName()), e); + cleanupFailedImportVM(vm, serviceOffering); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during vm migration! %s", userVm.getInstanceName(), e.getMessage())); + } + } + for (Pair diskProfileStoragePool : diskProfileStoragePoolList) { + if (diskProfileStoragePool == null || + diskProfileStoragePool.first() == null || + diskProfileStoragePool.second() == null) { + continue; + } + DiskProfile profile = diskProfileStoragePool.first(); + DiskOffering dOffering = diskOfferingDao.findById(profile.getDiskOfferingId()); + if (dOffering == null) { + continue; + } + VolumeVO volumeVO = volumeDao.findById(profile.getVolumeId()); + if (volumeVO == null) { + continue; + } + if (storagePoolSupportsDiskOffering(diskProfileStoragePool.second(), dOffering)) { + continue; + } + Pair, List> poolsPair = managementService.listStoragePoolsForMigrationOfVolume(profile.getVolumeId()); + List storagePools = poolsPair.second(); + if (CollectionUtils.isEmpty(storagePools)) { + cleanupFailedImportVM(vm, serviceOffering); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume migration!", userVm.getInstanceName())); + } + StoragePool storagePool = storagePools.get(0); + try { + volumeManager.migrateVolume(volumeVO, storagePool); + } catch (Exception e) { + LOGGER.error(String.format("VM import failed for unmanaged vm: %s during volume migration!", vm.getInstanceName()), e); + cleanupFailedImportVM(vm, serviceOffering); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume migration! %s", userVm.getInstanceName(), e.getMessage())); + } + } + return userVm; + } + + private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedInstance, final String instanceName, final DataCenter zone, final Cluster cluster, final HostVO host, + final VirtualMachineTemplate template, final String displayName, final String hostName, final Account caller, final Account owner, final Long userId, + final ServiceOfferingVO serviceOffering, final DiskOffering diskOffering, final Map dataDiskOfferingMap, + final Map nicNetworkMap, final Map nicIpAddressMap, + final Map details, final boolean migrateAllowed) { + UserVm userVm = null; + + ServiceOfferingVO validatedServiceOffering = null; + try { + validatedServiceOffering = getUnmanagedInstanceServiceOffering(unmanagedInstance, serviceOffering, owner, zone, details); + } catch (Exception e) { + LOGGER.error("Service offering for VM import not compatible!", e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import VM: %s! %s", unmanagedInstance.getName(), e.getMessage())); + } + + Map allDetails = new HashMap<>(details); + if (validatedServiceOffering.isDynamic()) { + allDetails.put(VmDetailConstants.CPU_NUMBER, String.valueOf(validatedServiceOffering.getCpu())); + allDetails.put(VmDetailConstants.MEMORY, String.valueOf(validatedServiceOffering.getRamSize())); + if (serviceOffering.getSpeed()==null) { + allDetails.put(VmDetailConstants.CPU_SPEED, String.valueOf(validatedServiceOffering.getSpeed())); + } + } + + if (!migrateAllowed && !hostSupportsServiceOffering(host, validatedServiceOffering)) { + throw new InvalidParameterValueException(String.format("Service offering: %s is not compatible with host: %s of unmanaged VM: %s", serviceOffering.getUuid(), host.getUuid(), instanceName)); + } + // Check disks and supplied disk offerings + List unmanagedInstanceDisks = unmanagedInstance.getDisks(); + if (CollectionUtils.isEmpty(unmanagedInstanceDisks)) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("No attached disks found for the unmanaged VM: %s", instanceName)); + } + final UnmanagedInstance.Disk rootDisk = unmanagedInstance.getDisks().get(0); + List dataDisks = new ArrayList<>(); + try { + checkUnmanagedDiskAndOfferingForImport(rootDisk, diskOffering, owner, zone); + if (unmanagedInstanceDisks.size() > 1) { // Data disk(s) present + dataDisks.addAll(unmanagedInstanceDisks); + dataDisks.remove(0); + checkUnmanagedDiskAndOfferingForImport(dataDisks, dataDiskOfferingMap, owner, zone); + } + resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.volume, unmanagedInstanceDisks.size()); + } catch (ResourceAllocationException e) { + LOGGER.error(String.format("Volume resource allocation error for owner: %s!", owner.getUuid()), e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resource allocation error for owner: %s! %s", owner.getUuid(), e.getMessage())); + } + // Check NICs and supplied networks + Map allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getNics(), nicNetworkMap, zone, hostName); + VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff; + if (unmanagedInstance.getPowerState().equals(UnmanagedInstance.PowerState.PowerOn)) { + powerState = VirtualMachine.PowerState.PowerOn; + } + try { + userVm = userVmManager.importVM(zone, host, template, instanceName, displayName, owner, + null, caller, true, null, owner.getAccountId(), userId, + validatedServiceOffering, diskOffering, null, hostName, + cluster.getHypervisorType(), allDetails, powerState); + } catch (InsufficientCapacityException ice) { + LOGGER.error(String.format("Failed to import vm name: %s", instanceName), ice); + throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ice.getMessage()); + } + if (userVm == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import vm name: %s", instanceName)); + } + List> diskProfileStoragePoolList = new ArrayList<>(); + try { + diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()), diskOffering.isCustomized() ? (rootDisk.getCapacity() / (1024 * 1024)) : null, template, owner, null, migrateAllowed)); + for (UnmanagedInstance.Disk disk : dataDisks) { + DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId())); + diskProfileStoragePoolList.add(importDisk(disk, userVm, offering, Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()), offering.isCustomized() ? (disk.getCapacity() / (1024 * 1024)) : null, template, owner, null, migrateAllowed)); + } + } catch (Exception e) { + LOGGER.error(String.format("Failed to import volumes while importing vm: %s", instanceName), e); + cleanupFailedImportVM(userVm, validatedServiceOffering); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", instanceName, e.getMessage())); + } + + try { + boolean firstNic = true; + for (UnmanagedInstance.Nic nic : unmanagedInstance.getNics()) { + Network network = networkDao.findById(allNicNetworkMap.get(nic.getNicId())); + String ipAddress = nicIpAddressMap.get(nic.getNicId()); + if (Strings.isNullOrEmpty(ipAddress)) { + ipAddress = nic.getIpAddress(); + } + importNic(nic, userVm, network, ipAddress, firstNic); + firstNic = false; + } + } catch (Exception e) { + LOGGER.error(String.format("Failed to import NICs while importing vm: %s", instanceName), e); + cleanupFailedImportVM(userVm, validatedServiceOffering); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import NICs while importing vm: %s. %s", instanceName, e.getMessage())); + } + if (migrateAllowed) { + userVm = migrateImportedVM(host, template, validatedServiceOffering, userVm, owner, diskProfileStoragePoolList); + } + return userVm; + } + + @Override + public ListResponse listUnmanagedInstances(ListUnmanagedInstancesCmd cmd) { + final Account caller = CallContext.current().getCallingAccount(); + if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + throw new PermissionDeniedException(String.format("Cannot perform this operation, Calling account is not root admin: %s", caller.getUuid())); + } + final Long clusterId = cmd.getClusterId(); + if (clusterId == null) { + throw new InvalidParameterValueException(String.format("Cluster ID cannot be null!")); + } + final Cluster cluster = clusterDao.findById(clusterId); + if (cluster == null) { + throw new InvalidParameterValueException(String.format("Cluster ID: %d cannot be found!", clusterId)); + } + if (cluster.getHypervisorType() != Hypervisor.HypervisorType.VMware) { + throw new InvalidParameterValueException(String.format("VM ingestion is currently not supported for hypervisor: %s", cluster.getHypervisorType().toString())); + } + List hosts = resourceManager.listHostsInClusterByStatus(clusterId, Status.Up); + List templatesFilterList = getAdditionalNameFilters(cluster); + List responses = new ArrayList<>(); + for (HostVO host : hosts) { + List managedVms = new ArrayList<>(); + managedVms.addAll(templatesFilterList); + managedVms.addAll(getHostManagedVms(host)); + + GetUnmanagedInstancesCommand command = new GetUnmanagedInstancesCommand(); + command.setInstanceName(cmd.getName()); + command.setManagedInstancesNames(managedVms); + Answer answer = agentManager.easySend(host.getId(), command); + if (!(answer instanceof GetUnmanagedInstancesAnswer)) { + continue; + } + GetUnmanagedInstancesAnswer unmanagedInstancesAnswer = (GetUnmanagedInstancesAnswer) answer; + HashMap unmanagedInstances = new HashMap<>(); + unmanagedInstances.putAll(unmanagedInstancesAnswer.getUnmanagedInstances()); + Set keys = unmanagedInstances.keySet(); + for (String key : keys) { + responses.add(createUnmanagedInstanceResponse(unmanagedInstances.get(key), cluster, host)); + } + } + ListResponse listResponses = new ListResponse<>(); + listResponses.setResponses(responses, responses.size()); + return listResponses; + } + + @Override + public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { + final Account caller = CallContext.current().getCallingAccount(); + if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + throw new PermissionDeniedException(String.format("Cannot perform this operation, Calling account is not root admin: %s", caller.getUuid())); + } + final Long clusterId = cmd.getClusterId(); + if (clusterId == null) { + throw new InvalidParameterValueException(String.format("Cluster ID cannot be null!")); + } + final Cluster cluster = clusterDao.findById(clusterId); + if (cluster == null) { + throw new InvalidParameterValueException(String.format("Cluster ID: %d cannot be found!", clusterId)); + } + if (cluster.getHypervisorType() != Hypervisor.HypervisorType.VMware) { + throw new InvalidParameterValueException(String.format("VM import is currently not supported for hypervisor: %s", cluster.getHypervisorType().toString())); + } + final DataCenter zone = dataCenterDao.findById(cluster.getDataCenterId()); + final String instanceName = cmd.getName(); + if (Strings.isNullOrEmpty(instanceName)) { + throw new InvalidParameterValueException(String.format("Instance name cannot be empty!")); + } + final Account owner = accountService.getActiveAccountById(cmd.getEntityOwnerId()); + + Long userId = null; + List userVOs = userDao.listByAccount(owner.getAccountId()); + if (CollectionUtils.isNotEmpty(userVOs)) { + userId = userVOs.get(0).getId(); + } + final Long templateId = cmd.getTemplateId(); + if (templateId == null) { + throw new InvalidParameterValueException(String.format("Template ID cannot be null!")); + } + final VirtualMachineTemplate template = templateDao.findById(templateId); + if (template == null) { + throw new InvalidParameterValueException(String.format("Template ID: %d cannot be found!", templateId)); + } + final Long serviceOfferingId = cmd.getServiceOfferingId(); + if (serviceOfferingId == null) { + throw new InvalidParameterValueException(String.format("Service offering ID cannot be null!")); + } + final ServiceOfferingVO serviceOffering = serviceOfferingDao.findById(serviceOfferingId); + if (serviceOffering == null) { + throw new InvalidParameterValueException(String.format("Service offering ID: %d cannot be found!", serviceOfferingId)); + } + accountService.checkAccess(owner, serviceOffering, zone); + try { + resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.user_vm, 1); + } catch (ResourceAllocationException e) { + LOGGER.error(String.format("VM resource allocation error for account: %s", owner.getUuid()), e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM resource allocation error for account: %s! %s", owner.getUuid(), e.getMessage())); + } + final Long diskOfferingId = cmd.getDiskOfferingId(); + if (diskOfferingId == null) { + throw new InvalidParameterValueException(String.format("Service offering ID cannot be null!")); + } + final DiskOffering diskOffering = diskOfferingDao.findById(diskOfferingId); + if (diskOffering == null) { + throw new InvalidParameterValueException(String.format("Disk offering ID: %d cannot be found!", diskOfferingId)); + } + String displayName = cmd.getDisplayName(); + if (Strings.isNullOrEmpty(displayName)) { + displayName = instanceName; + } + String hostName = cmd.getHostName(); + if (Strings.isNullOrEmpty(hostName)) { + if (!NetUtils.verifyDomainNameLabel(instanceName, true)) { + throw new InvalidParameterValueException(String.format("Please provide hostname for the VM. VM name contains unsupported characters for it to be used as hostname")); + } + hostName = instanceName; + } + if (!NetUtils.verifyDomainNameLabel(hostName, true)) { + throw new InvalidParameterValueException("Invalid VM hostname. VM hostname can contain ASCII letters 'a' through 'z', the digits '0' through '9', " + + "and the hyphen ('-'), must be between 1 and 63 characters long, and can't start or end with \"-\" and can't start with digit"); + } + final Map nicNetworkMap = cmd.getNicNetworkList(); + final Map nicIpAddressMap = cmd.getNicIpAddressList(); + final Map dataDiskOfferingMap = cmd.getDataDiskToDiskOfferingList(); + final Map details = cmd.getDetails(); + List hosts = resourceManager.listHostsInClusterByStatus(clusterId, Status.Up); + UserVm userVm = null; + List templatesFilterList = getAdditionalNameFilters(cluster); + for (HostVO host : hosts) { + List managedVms = new ArrayList<>(); + managedVms.addAll(templatesFilterList); + managedVms.addAll(getHostManagedVms(host)); + GetUnmanagedInstancesCommand command = new GetUnmanagedInstancesCommand(instanceName); + command.setManagedInstancesNames(managedVms); + Answer answer = agentManager.easySend(host.getId(), command); + if (!(answer instanceof GetUnmanagedInstancesAnswer)) { + continue; + } + GetUnmanagedInstancesAnswer unmanagedInstancesAnswer = (GetUnmanagedInstancesAnswer) answer; + HashMap unmanagedInstances = unmanagedInstancesAnswer.getUnmanagedInstances(); + if (MapUtils.isEmpty(unmanagedInstances)) { + continue; + } + Set names = unmanagedInstances.keySet(); + for (String name : names) { + if (instanceName.equals(name)) { + UnmanagedInstance unmanagedInstance = unmanagedInstances.get(name); + if (unmanagedInstance == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve details for unmanaged VM: %s", name)); + } + userVm = importVirtualMachineInternal(unmanagedInstance, instanceName, zone, cluster, host, + template, displayName, hostName, caller, owner, userId, + serviceOffering, diskOffering, dataDiskOfferingMap, + nicNetworkMap, nicIpAddressMap, + details, cmd.getMigrateAllowed()); + break; + } + } + if (userVm != null) { + break; + } + } + if (userVm == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to find unmanaged vm with name: %s", instanceName)); + } + UserVmResponse response = responseGenerator.createUserVmResponse(ResponseObject.ResponseView.Full, "virtualmachine", userVm).get(0); + return response; + } + + @Override + public List> getCommands() { + final List> cmdList = new ArrayList>(); + cmdList.add(ListUnmanagedInstancesCmd.class); + cmdList.add(ImportUnmanagedInstanceCmd.class); + return cmdList; + } +} diff --git a/server/src/main/resources/META-INF/cloudstack/server-compute/spring-server-compute-context.xml b/server/src/main/resources/META-INF/cloudstack/server-compute/spring-server-compute-context.xml index 38fb61971224..ca707a03ba6d 100644 --- a/server/src/main/resources/META-INF/cloudstack/server-compute/spring-server-compute-context.xml +++ b/server/src/main/resources/META-INF/cloudstack/server-compute/spring-server-compute-context.xml @@ -35,4 +35,6 @@ + + diff --git a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java index e99c2a864cb6..75152ffc217c 100644 --- a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java @@ -973,4 +973,9 @@ public boolean releasePodIp(ReleasePodIpCmdByAdmin ip) throws CloudRuntimeExcept public AcquirePodIpCmdResponse allocatePodIp(Account account, String zoneId, String podId) throws ResourceAllocationException, ConcurrentOperationException { return null; } + + @Override + public Pair importNic(String macAddress, int deviceId, Network network, Boolean isDefaultNic, VirtualMachine vm, String ipAddress) { + return null; + } } diff --git a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java new file mode 100644 index 000000000000..08054940f522 --- /dev/null +++ b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java @@ -0,0 +1,279 @@ +package org.apache.cloudstack.vm; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.when; + +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.UUID; + +import org.apache.cloudstack.api.ResponseGenerator; +import org.apache.cloudstack.api.ResponseObject; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.command.admin.vm.ImportUnmanagedInstanceCmd; +import org.apache.cloudstack.api.command.admin.vm.ListUnmanagedInstancesCmd; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; +import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.GetUnmanagedInstancesAnswer; +import com.cloud.agent.api.GetUnmanagedInstancesCommand; +import com.cloud.capacity.CapacityManager; +import com.cloud.configuration.Resource; +import com.cloud.dc.ClusterVO; +import com.cloud.dc.DataCenter; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.host.Host; +import com.cloud.host.HostVO; +import com.cloud.host.Status; +import com.cloud.hypervisor.Hypervisor; +import com.cloud.network.Network; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkVO; +import com.cloud.offering.DiskOffering; +import com.cloud.offering.ServiceOffering; +import com.cloud.resource.ResourceManager; +import com.cloud.service.ServiceOfferingVO; +import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.storage.DiskOfferingVO; +import com.cloud.storage.VMTemplateStoragePoolVO; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.Volume; +import com.cloud.storage.VolumeApiService; +import com.cloud.storage.dao.DiskOfferingDao; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VMTemplatePoolDao; +import com.cloud.template.VirtualMachineTemplate; +import com.cloud.user.Account; +import com.cloud.user.AccountService; +import com.cloud.user.AccountVO; +import com.cloud.user.ResourceLimitService; +import com.cloud.user.User; +import com.cloud.user.UserVO; +import com.cloud.user.dao.UserDao; +import com.cloud.uservm.UserVm; +import com.cloud.utils.Pair; +import com.cloud.vm.DiskProfile; +import com.cloud.vm.NicProfile; +import com.cloud.vm.UserVmManager; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.dao.VMInstanceDao; + +public class VmImportManagerImplTest { + + @InjectMocks + private VmImportService vmIngestionService = new VmImportManagerImpl(); + + @Mock + private UserVmManager userVmManager; + @Mock + private ClusterDao clusterDao; + @Mock + private ResourceManager resourceManager; + @Mock + private VMTemplatePoolDao templatePoolDao; + @Mock + private AgentManager agentManager; + @Mock + private AccountService accountService; + @Mock + private UserDao userDao; + @Mock + private DataCenterDao dataCenterDao; + @Mock + private VMTemplateDao templateDao; + @Mock + private VMInstanceDao vmDao; + @Mock + private ServiceOfferingDao serviceOfferingDao; + @Mock + private DiskOfferingDao diskOfferingDao; + @Mock + private NetworkDao networkDao; + @Mock + private NetworkOrchestrationService networkOrchestrationService; + @Mock + private VolumeOrchestrationService volumeManager; + @Mock + public ResponseGenerator responseGenerator; + @Mock + private CapacityManager capacityManager; + @Mock + private VolumeApiService volumeApiService; + @Mock + private ResourceLimitService resourceLimitService; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + AccountVO account = new AccountVO("admin", 1L, "", Account.ACCOUNT_TYPE_ADMIN, "uuid"); + UserVO user = new UserVO(1, "adminuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN); + CallContext.register(user, account); + + UnmanagedInstance instance = new UnmanagedInstance(); + instance.setName("TestInstance"); + instance.setCpuCores(2); + instance.setCpuCoresPerSocket(1); + instance.setCpuSpeed(1000); + instance.setMemory(1024); + instance.setOperatingSystem("CentOS 7"); + List instanceDisks = new ArrayList<>(); + UnmanagedInstance.Disk instanceDisk = new UnmanagedInstance.Disk(); + instanceDisk.setDiskId("1000-1"); + instanceDisk.setLabel("DiskLabel"); + instanceDisk.setImagePath("[SomeID] path/path.vmdk"); + instanceDisk.setCapacity(5242880L); + instanceDisks.add(instanceDisk); + instance.setDisks(instanceDisks); + List instanceNics = new ArrayList<>(); + UnmanagedInstance.Nic instanceNic = new UnmanagedInstance.Nic(); + instanceNic.setNicId("NIC 1"); + instanceNic.setAdapterType("VirtualE1000E"); + instanceNic.setMacAddress("02:00:2e:0f:00:02"); + instanceNic.setVlan(1024); + instanceNics.add(instanceNic); + instance.setNics(instanceNics); + instance.setPowerState(UnmanagedInstance.PowerState.PowerOn); + + ClusterVO cluster = new ClusterVO(1, 1, "Cluster"); + cluster.setHypervisorType(Hypervisor.HypervisorType.VMware.toString()); + when(clusterDao.findById(Mockito.anyLong())).thenReturn(cluster); + + List hosts = new ArrayList<>(); + HostVO hostVO = Mockito.mock(HostVO.class); + hosts.add(hostVO); + + doNothing().when(resourceLimitService).checkResourceLimit(any(Account.class), any(Resource.ResourceType.class), anyLong()); + when(resourceManager.listHostsInClusterByStatus(Mockito.anyLong(), Mockito.any(Status.class))).thenReturn(hosts); + List templates = new ArrayList<>(); + when(templatePoolDao.listAll()).thenReturn(templates); + List vms = new ArrayList<>(); + when(vmDao.listByHostId(Mockito.anyLong())).thenReturn(vms); + when(vmDao.listByLastHostId(Mockito.anyLong())).thenReturn(vms); + GetUnmanagedInstancesCommand cmd = Mockito.mock(GetUnmanagedInstancesCommand.class); + HashMap map = new HashMap<>(); + map.put(instance.getName(), instance); + Answer answer = new GetUnmanagedInstancesAnswer(cmd, "", map); + when(agentManager.easySend(Mockito.anyLong(), Mockito.any(GetUnmanagedInstancesCommand.class))).thenReturn(answer); + + DataCenterVO zone = Mockito.mock(DataCenterVO.class); + when(zone.getId()).thenReturn(1L); + when(dataCenterDao.findById(Mockito.anyLong())).thenReturn(zone); + when(accountService.getActiveAccountById(Mockito.anyLong())).thenReturn(Mockito.mock(Account.class)); + List users = new ArrayList<>(); + users.add(Mockito.mock(UserVO.class)); + when(userDao.listByAccount(Mockito.anyLong())).thenReturn(users); + when(templateDao.findById(Mockito.anyLong())).thenReturn(Mockito.mock(VMTemplateVO.class)); + ServiceOfferingVO serviceOffering = Mockito.mock(ServiceOfferingVO.class); + when(serviceOffering.getTags()).thenReturn(""); + when(serviceOffering.isDynamic()).thenReturn(false); + when(serviceOffering.getCpu()).thenReturn(instance.getCpuCores()); + when(serviceOffering.getRamSize()).thenReturn(instance.getMemory()); + when(serviceOffering.getSpeed()).thenReturn(instance.getCpuSpeed()); + when(serviceOfferingDao.findById(Mockito.anyLong())).thenReturn(serviceOffering); + DiskOfferingVO diskOfferingVO = Mockito.mock(DiskOfferingVO.class); + when(diskOfferingVO.isCustomized()).thenReturn(false); + when(diskOfferingVO.getDiskSize()).thenReturn(Long.MAX_VALUE); + when(diskOfferingDao.findById(Mockito.anyLong())).thenReturn(diskOfferingVO); + UserVmVO userVm = Mockito.mock(UserVmVO.class); + userVm.setInstanceName(instance.getName()); + userVm.setHostName(instance.getName()); + when(userVmManager.importVM(Mockito.any(DataCenter.class), Mockito.any(Host.class), Mockito.any(VirtualMachineTemplate.class), Mockito.anyString(), Mockito.anyString(), + Mockito.any(Account.class), Mockito.anyString(), Mockito.any(Account.class), Mockito.anyBoolean(), Mockito.anyString(), + Mockito.anyLong(), Mockito.anyLong(), Mockito.any(ServiceOffering.class), Mockito.any(DiskOffering.class), Mockito.anyString(), + Mockito.anyString(), Mockito.any(Hypervisor.HypervisorType.class), Mockito.anyMap(), Mockito.any(VirtualMachine.PowerState.class))).thenReturn(userVm); + NetworkVO networkVO = Mockito.mock(NetworkVO.class); + when(networkVO.getBroadcastUri()).thenReturn(URI.create(String.format("vlan://%d", instanceNic.getVlan()))); + when(networkVO.getDataCenterId()).thenReturn(1L); + when(networkDao.findById(Mockito.anyLong())).thenReturn(networkVO); + List networks = new ArrayList<>(); + networks.add(networkVO); + when(networkDao.listByZone(Mockito.anyLong())).thenReturn(networks); + NicProfile profile = Mockito.mock(NicProfile.class); + Integer deviceId = 100; + Pair pair = new Pair(profile, deviceId); + when(networkOrchestrationService.importNic(Mockito.anyString(), Mockito.anyInt(), Mockito.any(Network.class), Mockito.anyBoolean(), Mockito.any(VirtualMachine.class), Mockito.anyString())).thenReturn(pair); + when(volumeManager.importVolume(Mockito.any(Volume.Type.class), Mockito.anyString(), Mockito.any(DiskOffering.class), Mockito.anyLong(), + Mockito.anyLong(), Mockito.anyLong(), Mockito.any(VirtualMachine.class), Mockito.any(VirtualMachineTemplate.class), + Mockito.any(Account.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString(), Mockito.anyString())).thenReturn(Mockito.mock(DiskProfile.class)); + List userVmResponses = new ArrayList<>(); + UserVmResponse userVmResponse = new UserVmResponse(); + userVmResponse.setInstanceName(instance.getName()); + userVmResponses.add(userVmResponse); + when(responseGenerator.createUserVmResponse(Mockito.any(ResponseObject.ResponseView.class), Mockito.anyString(), Mockito.any(UserVm.class))).thenReturn(userVmResponses); + } + + @After + public void tearDown() { + CallContext.unregister(); + } + + @Test + public void listUnmanagedInstancesTest() { + ListUnmanagedInstancesCmd cmd = Mockito.mock(ListUnmanagedInstancesCmd.class); + vmIngestionService.listUnmanagedInstances(cmd); + } + + @Test(expected = InvalidParameterValueException.class) + public void listUnmanagedInstancesInvalidHypervisorTest() { + ListUnmanagedInstancesCmd cmd = Mockito.mock(ListUnmanagedInstancesCmd.class); + ClusterVO cluster = new ClusterVO(1, 1, "Cluster"); + cluster.setHypervisorType(Hypervisor.HypervisorType.KVM.toString()); + when(clusterDao.findById(Mockito.anyLong())).thenReturn(cluster); + vmIngestionService.listUnmanagedInstances(cmd); + } + + @Test(expected = PermissionDeniedException.class) + public void listUnmanagedInstancesInvalidCallerTest() { + CallContext.unregister(); + AccountVO account = new AccountVO("user", 1L, "", Account.ACCOUNT_TYPE_NORMAL, "uuid"); + UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN); + CallContext.register(user, account); + ListUnmanagedInstancesCmd cmd = Mockito.mock(ListUnmanagedInstancesCmd.class); + vmIngestionService.listUnmanagedInstances(cmd); + } + + @Test + public void importUnmanagedInstanceTest() { + ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class); + when(importUnmanageInstanceCmd.getName()).thenReturn("TestInstance"); + vmIngestionService.importUnmanagedInstance(importUnmanageInstanceCmd); + } + + @Test(expected = InvalidParameterValueException.class) + public void importUnmanagedInstanceInvalidHostnameTest() { + ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class); + when(importUnmanageInstanceCmd.getName()).thenReturn("TestInstance"); + when(importUnmanageInstanceCmd.getName()).thenReturn("some name"); + when(importUnmanageInstanceCmd.getMigrateAllowed()).thenReturn(false); + vmIngestionService.importUnmanagedInstance(importUnmanageInstanceCmd); + } + + @Test(expected = ServerApiException.class) + public void importUnmanagedInstanceMissingInstanceTest() { + ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class); + when(importUnmanageInstanceCmd.getName()).thenReturn("SomeInstance"); + vmIngestionService.importUnmanagedInstance(importUnmanageInstanceCmd); + } +} \ No newline at end of file diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py index 1b2a979d443b..51bf9161f1f0 100644 --- a/tools/apidoc/gen_toc.py +++ b/tools/apidoc/gen_toc.py @@ -192,6 +192,7 @@ 'Sioc' : 'Sioc', 'Diagnostics': 'Diagnostics', 'Management': 'Management', + 'UnmanagedInstance': 'Virtual Machine' } diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/ClusterMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/ClusterMO.java index ce9e9816280f..4b3786646220 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/ClusterMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/ClusterMO.java @@ -216,6 +216,19 @@ public ManagedObjectReference getHyperHostCluster() throws Exception { return _mor; } + @Override + public synchronized List listVmsOnHyperHost(String vmName) throws Exception { + List vms = new ArrayList<>(); + List hosts = _context.getVimClient().getDynamicProperty(_mor, "host"); + if (hosts != null && hosts.size() > 0) { + for (ManagedObjectReference morHost : hosts) { + HostMO hostMo = new HostMO(_context, morHost); + vms.addAll(hostMo.listVmsOnHyperHost(vmName)); + } + } + return vms; + } + @Override public VirtualMachineMO findVmOnHyperHost(String name) throws Exception { diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java index cc50b3d5bc13..5aab3a25ce28 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java @@ -496,6 +496,18 @@ public String getHostName() throws Exception { return (String)_context.getVimClient().getDynamicProperty(_mor, "name"); } + @Override + public synchronized List listVmsOnHyperHost(String vmName) throws Exception { + List vms = new ArrayList<>(); + if (vmName != null && !vmName.isEmpty()) { + vms.add(findVmOnHyperHost(vmName)); + } else { + loadVmCache(); + vms.addAll(_vmCache.values()); + } + return vms; + } + @Override public synchronized VirtualMachineMO findVmOnHyperHost(String vmName) throws Exception { if (s_logger.isDebugEnabled()) diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java index 6f0cd2291b47..a9ceb5d806ec 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java @@ -16,6 +16,8 @@ // under the License. package com.cloud.hypervisor.vmware.mo; +import java.util.List; + import com.vmware.vim25.ClusterDasConfigInfo; import com.vmware.vim25.ComputeResourceSummary; import com.vmware.vim25.ManagedObjectReference; @@ -51,6 +53,8 @@ public interface VmwareHypervisorHost { String getHyperHostDefaultGateway() throws Exception; + List listVmsOnHyperHost(String name) throws Exception; + VirtualMachineMO findVmOnHyperHost(String name) throws Exception; VirtualMachineMO findVmOnPeerHyperHost(String name) throws Exception; From f9e39369638ceca7be053dff8c56f9aeeb34cc54 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 2 Oct 2019 04:25:01 +0530 Subject: [PATCH 02/61] fixes Check for NPE during nic network validation Filter orphan, removed volumes while list unmanaged VMs from VMware Publish usage and update resource count only after import complete Use disk size when disk offering for disk is of higher size durng import Signed-off-by: Abhishek Kumar --- .../orchestration/VolumeOrchestrator.java | 9 - .../java/com/cloud/storage/dao/VolumeDao.java | 2 + .../com/cloud/storage/dao/VolumeDaoImpl.java | 7 + .../java/com/cloud/vm/UserVmManagerImpl.java | 20 ++- .../cloudstack/vm/VmImportManagerImpl.java | 164 +++++++++++++----- .../vm/VmImportManagerImplTest.java | 41 ++++- 6 files changed, 177 insertions(+), 66 deletions(-) diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java index afba2baecd00..9aebae41097f 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java @@ -1674,15 +1674,6 @@ public DiskProfile importVolume(Type type, String name, DiskOffering offering, L vol.setChainInfo(chainInfo); vol.setState(Volume.State.Ready); vol = _volsDao.persist(vol); - - // Save usage event and update resource count for user vm volumes - if (vm.getType() == VirtualMachine.Type.User) { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, vol.getAccountId(), vol.getDataCenterId(), vol.getId(), vol.getName(), offering.getId(), null, size, - Volume.class.getName(), vol.getUuid(), vol.isDisplayVolume()); - - _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.volume, vol.isDisplayVolume()); - _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.primary_storage, vol.isDisplayVolume(), new Long(vol.getSize())); - } return toDiskProfile(vol, offering); } } diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDao.java b/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDao.java index 14f48ea06a86..2741307c0546 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDao.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDao.java @@ -96,6 +96,8 @@ public interface VolumeDao extends GenericDao, StateDao listZoneWidePoolIdsByVolumeCount(long dcId, long accountId); + List findIncludingRemovedByZone(long zoneId); + /** * Gets the Total Primary Storage space allocated for an account * diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java b/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java index 7c63b9c75268..481313b78813 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java @@ -595,6 +595,13 @@ public List listZoneWidePoolIdsByVolumeCount(long dcId, long accountId) { } } + @Override + public List findIncludingRemovedByZone(long zoneId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("dcId", zoneId); + return searchIncludingRemoved(sc, null, null, false); + } + @Override @DB() public Pair getNonDestroyedCountAndTotalByPool(long poolId) { diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index 1dd1ea07fd4e..a6499ee2ec36 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -3977,16 +3977,18 @@ public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCap } CallContext.current().setEventDetails("Vm Id: " + vm.getUuid()); - if (!offering.isDynamic()) { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(), - hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplayVm()); - } else { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(), - hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid(), customParameters, vm.isDisplayVm()); - } + if (!isImport) { + if (!offering.isDynamic()) { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(), + hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplayVm()); + } else { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(), + hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid(), customParameters, vm.isDisplayVm()); + } - //Update Resource Count for the given account - resourceCountIncrement(accountId, isDisplayVm, new Long(offering.getCpu()), new Long(offering.getRamSize())); + //Update Resource Count for the given account + resourceCountIncrement(accountId, isDisplayVm, new Long(offering.getCpu()), new Long(offering.getRamSize())); + } return vm; } }); diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 466b226bf0eb..75d04096373b 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -59,6 +59,8 @@ import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlanner; import com.cloud.deploy.DeploymentPlanningManager; +import com.cloud.event.EventTypes; +import com.cloud.event.UsageEventUtils; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; @@ -69,6 +71,7 @@ import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor; import com.cloud.network.Network; +import com.cloud.network.Networks; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; import com.cloud.offering.DiskOffering; @@ -227,12 +230,62 @@ private List getAdditionalNameFilters(Cluster cluster) { if (cluster == null) { return additionalNameFilter; } - // VMWare considers some templates and expunging volumes as VMs if (cluster.getHypervisorType() == Hypervisor.HypervisorType.VMware) { + // VMWare considers some templates as VM and they are not filtered by VirtualMachineMO.isTemplate() List templates = templatePoolDao.listAll(); for (VMTemplateStoragePoolVO template : templates) { additionalNameFilter.add(template.getInstallPath()); } + + // VMWare considers some removed volumes as VM + List volumes = volumeDao.findIncludingRemovedByZone(cluster.getDataCenterId()); + for (VolumeVO volumeVO : volumes) { + if (volumeVO.getRemoved() == null) { + continue; + } + if (Strings.isNullOrEmpty(volumeVO.getChainInfo())) { + continue; + } + List volumeFileNames = new ArrayList<>(); + try { + VirtualMachineDiskInfo diskInfo = gson.fromJson(volumeVO.getChainInfo(), VirtualMachineDiskInfo.class); + String[] files = diskInfo.getDiskChain(); + if (files.length == 1) { + continue; + } + boolean firstFile = true; + for (final String file : files) { + if (firstFile) { + firstFile = false; + continue; + } + String path = file; + String[] split = path.split(" "); + path = split[split.length - 1]; + split = path.split("/"); + ; + path = split[split.length - 1]; + split = path.split("\\."); + path = split[0]; + if (!Strings.isNullOrEmpty(path)) { + if (!additionalNameFilter.contains(path)) { + volumeFileNames.add(path); + } + if (path.contains("-")) { + split = path.split("-"); + path = split[0]; + if (!Strings.isNullOrEmpty(path) && !path.equals("ROOT") && !additionalNameFilter.contains(path)) { + volumeFileNames.add(path); + } + } + } + } + } catch (Exception e) { + } + if (!volumeFileNames.isEmpty()) { + additionalNameFilter.addAll(volumeFileNames); + } + } } return additionalNameFilter; } @@ -303,7 +356,7 @@ private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedIns Map parameters = new HashMap<>(); parameters.put(VmDetailConstants.CPU_NUMBER, String.valueOf(cpu)); parameters.put(VmDetailConstants.MEMORY, String.valueOf(memory)); - if (serviceOffering.getSpeed()==null && cpuSpeed > 0) { + if (serviceOffering.getSpeed() == null && cpuSpeed > 0) { parameters.put(VmDetailConstants.CPU_SPEED, String.valueOf(cpuSpeed)); } serviceOffering.setDynamicFlag(true); @@ -332,9 +385,8 @@ private void checkUnmanagedDiskAndOfferingForImport(UnmanagedInstance.Disk disk, } accountService.checkAccess(owner, diskOffering, zone); resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.volume); - long diskSize = disk.getCapacity() / (1024 * 1024); - if (!diskOffering.isCustomized() && diskOffering.getDiskSize() < diskSize) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk offering(ID: %s) %dGB is found less than the size of disk(ID: %s) %dGB during VM import!", diskOffering.getUuid(), diskOffering.getDiskSize(), disk.getDiskId(), diskSize)); + if (!diskOffering.isCustomized() && diskOffering.getDiskSize() < disk.getCapacity()) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk offering(ID: %s) %dGB is found less than the size of disk(ID: %s) %dGB during VM import!", diskOffering.getUuid(), (diskOffering.getDiskSize() / (1024 * 1024 * 1024)), disk.getDiskId(), (disk.getCapacity() / (1024 * 1024)))); } } @@ -361,7 +413,7 @@ private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Net // * get all vms hostNames in the network List hostNames = vmDao.listDistinctHostNames(network.getId()); // * verify that there are no duplicates - if (hostNames.contains(hostName)) { + if (CollectionUtils.isNotEmpty(hostNames) && hostNames.contains(hostName)) { throw new InvalidParameterValueException("The vm with hostName " + hostName + " already exists in the network domain: " + network.getNetworkDomain() + "; network=" + network); } @@ -376,6 +428,9 @@ private Map getUnmanagedNicNetworkMap(List // Find a suitable network List networks = networkDao.listByZone(zone.getId()); for (NetworkVO networkVO : networks) { + if (networkVO.getTrafficType() == Networks.TrafficType.None || Networks.TrafficType.isSystemNetwork(networkVO.getTrafficType())) { + continue; + } try { checkUnmanagedNicAndNetworkForImport(nic, networkVO, zone, hostName); network = networkVO; @@ -442,30 +497,28 @@ private NicProfile importNic(UnmanagedInstance.Nic nic, VirtualMachine vm, Netwo return result.first(); } - private void cleanupFailedImportVM(UserVm userVm, ServiceOfferingVO serviceOfferingVO) { + private void cleanupFailedImportVM(final UserVm userVm) { + if (userVm == null) { + return; + } // Remove all volumes - List volumes = volumeDao.findByInstance(userVm.getId()); volumeDao.deleteVolumesByInstance(userVm.getId()); - if (!CollectionUtils.isEmpty(volumes)) { - for (VolumeVO volumeVO : volumes) { - resourceLimitService.decrementResourceCount(userVm.getAccountId(), Resource.ResourceType.volume, volumeVO.isDisplayVolume()); - resourceLimitService.decrementResourceCount(userVm.getAccountId(), Resource.ResourceType.primary_storage, volumeVO.isDisplayVolume(), new Long(volumeVO.getSize())); - } - } // Remove all nics nicDao.removeNicsForInstance(userVm.getId()); // Remove vm vmDao.remove(userVm.getId()); - resourceLimitService.decrementResourceCount(userVm.getAccountId(), Resource.ResourceType.user_vm, userVm.isDisplayVm()); - resourceLimitService.decrementResourceCount(userVm.getAccountId(), Resource.ResourceType.cpu, userVm.isDisplayVm(), new Long(serviceOfferingVO.getCpu())); - resourceLimitService.decrementResourceCount(userVm.getAccountId(), Resource.ResourceType.memory, userVm.isDisplayVm(), new Long(serviceOfferingVO.getRamSize())); } private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate template, ServiceOfferingVO serviceOffering, UserVm userVm, final Account owner, List> diskProfileStoragePoolList) { UserVm vm = userVm; - if (sourceHost == null || serviceOffering == null || userVm == null || diskProfileStoragePoolList == null) { - LOGGER.warn("Failed to check VM migrations need during import!"); - return null; + if (vm == null) { + LOGGER.error(String.format("Failed to check migrations need during VM import!")); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to check migrations need during VM import!")); + } + if (sourceHost == null || serviceOffering == null || diskProfileStoragePoolList == null) { + LOGGER.error(String.format("Failed to check migrations need during import, VM: %s!", userVm.getInstanceName())); + cleanupFailedImportVM(vm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to check migrations need during import, VM: %s!", userVm.getInstanceName())); } if (!hostSupportsServiceOffering(sourceHost, serviceOffering)) { final VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm, template, serviceOffering, owner, null); @@ -477,7 +530,7 @@ private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate templ dest = deploymentPlanningManager.planDeployment(profile, plan, excludeList, null); } catch (Exception e) { LOGGER.warn(String.format("VM import failed for unmanaged vm: %s during vm migration, finding deployment destination!", vm.getInstanceName()), e); - cleanupFailedImportVM(vm, serviceOffering); + cleanupFailedImportVM(vm); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during vm migration, finding deployment destination!", vm.getInstanceName())); } if (dest != null) { @@ -486,7 +539,7 @@ private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate templ } } if (dest == null) { - cleanupFailedImportVM(vm, serviceOffering); + cleanupFailedImportVM(vm); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during vm migration, no deployment destination found!", vm.getInstanceName())); } try { @@ -494,7 +547,7 @@ private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate templ vm = userVmManager.getUserVm(vm.getId()); } catch (Exception e) { LOGGER.error(String.format("VM import failed for unmanaged vm: %s during vm migration!", vm.getInstanceName()), e); - cleanupFailedImportVM(vm, serviceOffering); + cleanupFailedImportVM(vm); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during vm migration! %s", userVm.getInstanceName(), e.getMessage())); } } @@ -519,7 +572,7 @@ private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate templ Pair, List> poolsPair = managementService.listStoragePoolsForMigrationOfVolume(profile.getVolumeId()); List storagePools = poolsPair.second(); if (CollectionUtils.isEmpty(storagePools)) { - cleanupFailedImportVM(vm, serviceOffering); + cleanupFailedImportVM(vm); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume migration!", userVm.getInstanceName())); } StoragePool storagePool = storagePools.get(0); @@ -527,13 +580,39 @@ private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate templ volumeManager.migrateVolume(volumeVO, storagePool); } catch (Exception e) { LOGGER.error(String.format("VM import failed for unmanaged vm: %s during volume migration!", vm.getInstanceName()), e); - cleanupFailedImportVM(vm, serviceOffering); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume migration! %s", userVm.getInstanceName(), e.getMessage())); + cleanupFailedImportVM(vm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume migration! %s", userVm.getInstanceName(), Strings.nullToEmpty(e.getMessage()))); } } return userVm; } + private void publishVMUsageUpdateResourceCount(final UserVm userVm, ServiceOfferingVO serviceOfferingVO) { + if (userVm == null || serviceOfferingVO == null) { + LOGGER.error("Failed to publish usage records during VM import!"); + return; + } + if (!serviceOfferingVO.isDynamic()) { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_IMPORT, userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), userVm.getHostName(), serviceOfferingVO.getId(), userVm.getTemplateId(), + userVm.getHypervisorType().toString(), VirtualMachine.class.getName(), userVm.getUuid(), userVm.isDisplayVm()); + } else { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_IMPORT, userVm.getAccountId(), userVm.getAccountId(), userVm.getDataCenterId(), userVm.getHostName(), serviceOfferingVO.getId(), userVm.getTemplateId(), + userVm.getHypervisorType().toString(), VirtualMachine.class.getName(), userVm.getUuid(), userVm.getDetails(), userVm.isDisplayVm()); + } + resourceLimitService.incrementResourceCount(userVm.getAccountId(), Resource.ResourceType.user_vm, userVm.isDisplayVm()); + resourceLimitService.incrementResourceCount(userVm.getAccountId(), Resource.ResourceType.cpu, userVm.isDisplayVm(), new Long(serviceOfferingVO.getCpu())); + resourceLimitService.incrementResourceCount(userVm.getAccountId(), Resource.ResourceType.memory, userVm.isDisplayVm(), new Long(serviceOfferingVO.getRamSize())); + // Save usage event and update resource count for user vm volumes + List volumes = volumeDao.findByInstance(userVm.getId()); + for (VolumeVO volume : volumes) { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), volume.getDiskOfferingId(), null, volume.getSize(), + Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); + + resourceLimitService.incrementResourceCount(userVm.getAccountId(), Resource.ResourceType.volume, volume.isDisplayVolume()); + resourceLimitService.incrementResourceCount(userVm.getAccountId(), Resource.ResourceType.primary_storage, volume.isDisplayVolume(), volume.getSize()); + } + } + private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedInstance, final String instanceName, final DataCenter zone, final Cluster cluster, final HostVO host, final VirtualMachineTemplate template, final String displayName, final String hostName, final Account caller, final Account owner, final Long userId, final ServiceOfferingVO serviceOffering, final DiskOffering diskOffering, final Map dataDiskOfferingMap, @@ -546,14 +625,14 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns validatedServiceOffering = getUnmanagedInstanceServiceOffering(unmanagedInstance, serviceOffering, owner, zone, details); } catch (Exception e) { LOGGER.error("Service offering for VM import not compatible!", e); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import VM: %s! %s", unmanagedInstance.getName(), e.getMessage())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import VM: %s! %s", unmanagedInstance.getName(), Strings.nullToEmpty(e.getMessage()))); } Map allDetails = new HashMap<>(details); if (validatedServiceOffering.isDynamic()) { allDetails.put(VmDetailConstants.CPU_NUMBER, String.valueOf(validatedServiceOffering.getCpu())); allDetails.put(VmDetailConstants.MEMORY, String.valueOf(validatedServiceOffering.getRamSize())); - if (serviceOffering.getSpeed()==null) { + if (serviceOffering.getSpeed() == null) { allDetails.put(VmDetailConstants.CPU_SPEED, String.valueOf(validatedServiceOffering.getSpeed())); } } @@ -578,7 +657,7 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.volume, unmanagedInstanceDisks.size()); } catch (ResourceAllocationException e) { LOGGER.error(String.format("Volume resource allocation error for owner: %s!", owner.getUuid()), e); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resource allocation error for owner: %s! %s", owner.getUuid(), e.getMessage())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resource allocation error for owner: %s! %s", owner.getUuid(), Strings.nullToEmpty(e.getMessage()))); } // Check NICs and supplied networks Map allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getNics(), nicNetworkMap, zone, hostName); @@ -600,17 +679,16 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns } List> diskProfileStoragePoolList = new ArrayList<>(); try { - diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()), diskOffering.isCustomized() ? (rootDisk.getCapacity() / (1024 * 1024)) : null, template, owner, null, migrateAllowed)); + diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()), (rootDisk.getCapacity() / (1024 * 1024)), template, owner, null, migrateAllowed)); for (UnmanagedInstance.Disk disk : dataDisks) { DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId())); - diskProfileStoragePoolList.add(importDisk(disk, userVm, offering, Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()), offering.isCustomized() ? (disk.getCapacity() / (1024 * 1024)) : null, template, owner, null, migrateAllowed)); + diskProfileStoragePoolList.add(importDisk(disk, userVm, offering, Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()), (disk.getCapacity() / (1024 * 1024)), template, owner, null, migrateAllowed)); } } catch (Exception e) { LOGGER.error(String.format("Failed to import volumes while importing vm: %s", instanceName), e); - cleanupFailedImportVM(userVm, validatedServiceOffering); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", instanceName, e.getMessage())); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", instanceName, Strings.nullToEmpty(e.getMessage()))); } - try { boolean firstNic = true; for (UnmanagedInstance.Nic nic : unmanagedInstance.getNics()) { @@ -624,12 +702,13 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns } } catch (Exception e) { LOGGER.error(String.format("Failed to import NICs while importing vm: %s", instanceName), e); - cleanupFailedImportVM(userVm, validatedServiceOffering); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import NICs while importing vm: %s. %s", instanceName, e.getMessage())); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import NICs while importing vm: %s. %s", instanceName, Strings.nullToEmpty(e.getMessage()))); } if (migrateAllowed) { userVm = migrateImportedVM(host, template, validatedServiceOffering, userVm, owner, diskProfileStoragePoolList); } + publishVMUsageUpdateResourceCount(userVm, validatedServiceOffering); return userVm; } @@ -651,11 +730,11 @@ public ListResponse listUnmanagedInstances(ListUnmana throw new InvalidParameterValueException(String.format("VM ingestion is currently not supported for hypervisor: %s", cluster.getHypervisorType().toString())); } List hosts = resourceManager.listHostsInClusterByStatus(clusterId, Status.Up); - List templatesFilterList = getAdditionalNameFilters(cluster); + List additionalNameFilters = getAdditionalNameFilters(cluster); List responses = new ArrayList<>(); for (HostVO host : hosts) { List managedVms = new ArrayList<>(); - managedVms.addAll(templatesFilterList); + managedVms.addAll(additionalNameFilters); managedVms.addAll(getHostManagedVms(host)); GetUnmanagedInstancesCommand command = new GetUnmanagedInstancesCommand(); @@ -728,7 +807,7 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.user_vm, 1); } catch (ResourceAllocationException e) { LOGGER.error(String.format("VM resource allocation error for account: %s", owner.getUuid()), e); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM resource allocation error for account: %s! %s", owner.getUuid(), e.getMessage())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM resource allocation error for account: %s! %s", owner.getUuid(), Strings.nullToEmpty(e.getMessage()))); } final Long diskOfferingId = cmd.getDiskOfferingId(); if (diskOfferingId == null) { @@ -759,10 +838,10 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { final Map details = cmd.getDetails(); List hosts = resourceManager.listHostsInClusterByStatus(clusterId, Status.Up); UserVm userVm = null; - List templatesFilterList = getAdditionalNameFilters(cluster); + List additionalNameFilters = getAdditionalNameFilters(cluster); for (HostVO host : hosts) { List managedVms = new ArrayList<>(); - managedVms.addAll(templatesFilterList); + managedVms.addAll(additionalNameFilters); managedVms.addAll(getHostManagedVms(host)); GetUnmanagedInstancesCommand command = new GetUnmanagedInstancesCommand(instanceName); command.setManagedInstancesNames(managedVms); @@ -797,8 +876,7 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { if (userVm == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to find unmanaged vm with name: %s", instanceName)); } - UserVmResponse response = responseGenerator.createUserVmResponse(ResponseObject.ResponseView.Full, "virtualmachine", userVm).get(0); - return response; + return responseGenerator.createUserVmResponse(ResponseObject.ResponseView.Full, "virtualmachine", userVm).get(0); } @Override diff --git a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java index 08054940f522..f03160c425de 100644 --- a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java @@ -20,25 +20,31 @@ import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.GetUnmanagedInstancesAnswer; import com.cloud.agent.api.GetUnmanagedInstancesCommand; -import com.cloud.capacity.CapacityManager; import com.cloud.configuration.Resource; import com.cloud.dc.ClusterVO; import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.DataCenterDao; +import com.cloud.event.UsageEventUtils; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.host.Host; @@ -54,13 +60,16 @@ import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.DiskOfferingVO; +import com.cloud.storage.StoragePool; import com.cloud.storage.VMTemplateStoragePoolVO; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.Volume; import com.cloud.storage.VolumeApiService; +import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplatePoolDao; +import com.cloud.storage.dao.VolumeDao; import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; import com.cloud.user.AccountService; @@ -79,6 +88,8 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.dao.VMInstanceDao; +@RunWith(PowerMockRunner.class) +@PrepareForTest(UsageEventUtils.class) public class VmImportManagerImplTest { @InjectMocks @@ -117,11 +128,13 @@ public class VmImportManagerImplTest { @Mock public ResponseGenerator responseGenerator; @Mock - private CapacityManager capacityManager; - @Mock - private VolumeApiService volumeApiService; + private VolumeDao volumeDao; @Mock private ResourceLimitService resourceLimitService; + @Mock + private PrimaryDataStoreDao primaryDataStoreDao; + @Mock + private VolumeApiService volumeApiService; @Before public void setUp() throws Exception { @@ -142,7 +155,8 @@ public void setUp() throws Exception { UnmanagedInstance.Disk instanceDisk = new UnmanagedInstance.Disk(); instanceDisk.setDiskId("1000-1"); instanceDisk.setLabel("DiskLabel"); - instanceDisk.setImagePath("[SomeID] path/path.vmdk"); + instanceDisk.setController("scsi"); + instanceDisk.setImagePath("[b6ccf44a1fa13e29b3667b4954fa10ee] TestInstance/ROOT-1.vmdk"); instanceDisk.setCapacity(5242880L); instanceDisks.add(instanceDisk); instance.setDisks(instanceDisks); @@ -168,6 +182,8 @@ public void setUp() throws Exception { when(resourceManager.listHostsInClusterByStatus(Mockito.anyLong(), Mockito.any(Status.class))).thenReturn(hosts); List templates = new ArrayList<>(); when(templatePoolDao.listAll()).thenReturn(templates); + List volumes = new ArrayList<>(); + when(volumeDao.findIncludingRemovedByZone(Mockito.anyLong())).thenReturn(volumes); List vms = new ArrayList<>(); when(vmDao.listByHostId(Mockito.anyLong())).thenReturn(vms); when(vmDao.listByLastHostId(Mockito.anyLong())).thenReturn(vms); @@ -186,6 +202,7 @@ public void setUp() throws Exception { when(userDao.listByAccount(Mockito.anyLong())).thenReturn(users); when(templateDao.findById(Mockito.anyLong())).thenReturn(Mockito.mock(VMTemplateVO.class)); ServiceOfferingVO serviceOffering = Mockito.mock(ServiceOfferingVO.class); + when(serviceOffering.getId()).thenReturn(1L); when(serviceOffering.getTags()).thenReturn(""); when(serviceOffering.isDynamic()).thenReturn(false); when(serviceOffering.getCpu()).thenReturn(instance.getCpuCores()); @@ -197,12 +214,24 @@ public void setUp() throws Exception { when(diskOfferingVO.getDiskSize()).thenReturn(Long.MAX_VALUE); when(diskOfferingDao.findById(Mockito.anyLong())).thenReturn(diskOfferingVO); UserVmVO userVm = Mockito.mock(UserVmVO.class); + when(userVm.getAccountId()).thenReturn(1L); + when(userVm.getDataCenterId()).thenReturn(1L); + when(userVm.getHostName()).thenReturn(instance.getName()); + when(userVm.getTemplateId()).thenReturn(1L); + when(userVm.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.VMware); + when(userVm.getUuid()).thenReturn("abcd"); + when(userVm.isDisplayVm()).thenReturn(true); + // Skip usage publishing and resource increment for test + when(userVm.getType()).thenReturn(VirtualMachine.Type.Instance); userVm.setInstanceName(instance.getName()); userVm.setHostName(instance.getName()); when(userVmManager.importVM(Mockito.any(DataCenter.class), Mockito.any(Host.class), Mockito.any(VirtualMachineTemplate.class), Mockito.anyString(), Mockito.anyString(), Mockito.any(Account.class), Mockito.anyString(), Mockito.any(Account.class), Mockito.anyBoolean(), Mockito.anyString(), Mockito.anyLong(), Mockito.anyLong(), Mockito.any(ServiceOffering.class), Mockito.any(DiskOffering.class), Mockito.anyString(), Mockito.anyString(), Mockito.any(Hypervisor.HypervisorType.class), Mockito.anyMap(), Mockito.any(VirtualMachine.PowerState.class))).thenReturn(userVm); + StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); + when(primaryDataStoreDao.findPoolByUUID(Mockito.anyString())).thenReturn(poolVO); + when(volumeApiService.doesTargetStorageSupportDiskOffering(Mockito.any(StoragePool.class), Mockito.anyString())).thenReturn(true); NetworkVO networkVO = Mockito.mock(NetworkVO.class); when(networkVO.getBroadcastUri()).thenReturn(URI.create(String.format("vlan://%d", instanceNic.getVlan()))); when(networkVO.getDataCenterId()).thenReturn(1L); @@ -217,6 +246,7 @@ public void setUp() throws Exception { when(volumeManager.importVolume(Mockito.any(Volume.Type.class), Mockito.anyString(), Mockito.any(DiskOffering.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.any(VirtualMachine.class), Mockito.any(VirtualMachineTemplate.class), Mockito.any(Account.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString(), Mockito.anyString())).thenReturn(Mockito.mock(DiskProfile.class)); + when(volumeDao.findByInstance(Mockito.anyLong())).thenReturn(volumes); List userVmResponses = new ArrayList<>(); UserVmResponse userVmResponse = new UserVmResponse(); userVmResponse.setInstanceName(instance.getName()); @@ -258,6 +288,7 @@ public void listUnmanagedInstancesInvalidCallerTest() { public void importUnmanagedInstanceTest() { ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class); when(importUnmanageInstanceCmd.getName()).thenReturn("TestInstance"); + PowerMockito.mockStatic(UsageEventUtils.class); vmIngestionService.importUnmanagedInstance(importUnmanageInstanceCmd); } From db2c8cae523332e37dfa371adabd68c0116f3ec3 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 3 Oct 2019 16:52:04 +0530 Subject: [PATCH 03/61] fixes Fixed disk offering size check during import to not allow fixed disk offerings with lower size than disk Fixed listing nics of unmanaged VM with dvSwitch with pvlan Added adaptertype param in listUnmanagedInstances API when available CHanged capacity parameter of VM of listUnmanagedInstance API to return size in bytes for consistency Fixed disk/volume size after import Fixed IP address assignment, check for duplicate IP on network Fixed debian packaging of VMware network discovery tool discover_networks.py Miscellaneous fixes for null check, error message string Signed-off-by: Abhishek Kumar --- .../java/com/cloud/vm/VmDetailConstants.java | 1 + .../apache/cloudstack/api/ApiConstants.java | 1 + .../admin/vm/ImportUnmanagedInstanceCmd.java | 28 +++- .../cloudstack/api/response/NicResponse.java | 12 ++ .../UnmanagedInstanceDiskResponse.java | 2 +- debian/cloudstack-common.install | 1 + .../service/NetworkOrchestrationService.java | 3 +- .../orchestration/NetworkOrchestrator.java | 41 ++++-- .../vmware/resource/VmwareResource.java | 22 +++- .../cloudstack/vm/VmImportManagerImpl.java | 120 +++++++++++++++--- .../com/cloud/vpc/MockNetworkManagerImpl.java | 2 +- .../vm/VmImportManagerImplTest.java | 19 ++- 12 files changed, 195 insertions(+), 57 deletions(-) diff --git a/api/src/main/java/com/cloud/vm/VmDetailConstants.java b/api/src/main/java/com/cloud/vm/VmDetailConstants.java index 35c7485d2ebb..8ef71b750c33 100644 --- a/api/src/main/java/com/cloud/vm/VmDetailConstants.java +++ b/api/src/main/java/com/cloud/vm/VmDetailConstants.java @@ -59,6 +59,7 @@ public interface VmDetailConstants { String NIC = "nic"; String NETWORK = "network"; String IP_ADDRESS = "ipAddress"; + String IP6_ADDRESS = "ip6Address"; String DISK = "disk"; String DISK_OFFERING = "diskOffering"; } diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index f51050c43f5f..d52bd1eb0604 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -22,6 +22,7 @@ public class ApiConstants { public static final String ACCOUNT_TYPE = "accounttype"; public static final String ACCOUNT_ID = "accountid"; public static final String ACTIVITY = "activity"; + public static final String ADAPTER_TYPE = "adaptertype"; public static final String ADDRESS = "address"; public static final String ALGORITHM = "algorithm"; public static final String ALLOCATED_ONLY = "allocatedonly"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java index 1a012ee50b3e..bb2eacd41933 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java @@ -220,16 +220,32 @@ public Map getNicNetworkList() { return nicNetworkMap; } - public Map getNicIpAddressList() { - Map nicIpAddressMap = new HashMap<>(); + public Map getNicIpAddressList() { + Map nicIpAddressMap = new HashMap<>(); if (MapUtils.isNotEmpty(nicIpAddressList)) { for (Map entry : (Collection>)nicIpAddressList.values()) { String nic = entry.get(VmDetailConstants.NIC); - String ipAddress = entry.get(VmDetailConstants.IP_ADDRESS); - if (Strings.isNullOrEmpty(nic) || Strings.isNullOrEmpty(ipAddress) || !NetUtils.isValidIp4(ipAddress)) { - throw new InvalidParameterValueException(String.format("IP Address: %s for NIC ID: %s is invalid", ipAddress, nic)); + String ipAddress = Strings.emptyToNull(entry.get(VmDetailConstants.IP_ADDRESS)); + String ip6Address = Strings.emptyToNull(entry.get(VmDetailConstants.IP6_ADDRESS)); + if (Strings.isNullOrEmpty(nic)) { + throw new InvalidParameterValueException(String.format("NIC ID: '%s' is invalid for IP address mapping", nic)); } - nicIpAddressMap.put(nic, ipAddress); + if (Strings.isNullOrEmpty(ipAddress) && Strings.isNullOrEmpty(ip6Address)) { + throw new InvalidParameterValueException(String.format("IP addresses for NIC ID: %s is invalid", ipAddress, nic)); + } + if (!Strings.isNullOrEmpty(ipAddress)) { + if (!ipAddress.equals("auto") && !NetUtils.isValidIp4(ipAddress)) { + throw new InvalidParameterValueException(String.format("IP v4 address '%s' for NIC ID: %s is invalid", ipAddress, nic)); + } + if (ipAddress.equals("auto")) { + ipAddress = null; + } + } + if (!Strings.isNullOrEmpty(ip6Address) && !NetUtils.isValidIp6(ip6Address)) { + throw new InvalidParameterValueException(String.format("IP v6 address '%s' for NIC ID: %s is invalid", ip6Address, nic)); + } + Network.IpAddresses ipAddresses = new Network.IpAddresses(ipAddress, ip6Address); + nicIpAddressMap.put(nic, ipAddresses); } } return nicIpAddressMap; diff --git a/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java index e9cf952d942c..34f88e0d6865 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java @@ -118,6 +118,10 @@ public class NicResponse extends BaseResponse { @Param(description = "ID of the VLAN/VNI if available", since="4.14.0") private Integer vlanId; + @SerializedName(ApiConstants.ADAPTER_TYPE) + @Param(description = "Type of adapter if available", since="4.14.0") + private String adapterType; + public void setVmId(String vmId) { this.vmId = vmId; } @@ -316,4 +320,12 @@ public Integer getVlanId() { public void setVlanId(Integer vlanId) { this.vlanId = vlanId; } + + public String getAdapterType() { + return adapterType; + } + + public void setAdapterType(String adapterType) { + this.adapterType = adapterType; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceDiskResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceDiskResponse.java index f9b506a6fcb4..81563b76a31c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceDiskResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceDiskResponse.java @@ -34,7 +34,7 @@ public class UnmanagedInstanceDiskResponse extends BaseResponse { private String label; @SerializedName(ApiConstants.CAPACITY) - @Param(description = "the capacity in KB of the disk") + @Param(description = "the capacity of the disk in bytes") private Long capacity; @SerializedName(ApiConstants.IMAGE_PATH) diff --git a/debian/cloudstack-common.install b/debian/cloudstack-common.install index accc6fadfa22..53302111b369 100644 --- a/debian/cloudstack-common.install +++ b/debian/cloudstack-common.install @@ -27,6 +27,7 @@ /usr/share/cloudstack-common/scripts/vm/hypervisor/update_host_passwd.sh /usr/share/cloudstack-common/scripts/vm/hypervisor/versions.sh /usr/share/cloudstack-common/scripts/vm/hypervisor/xenserver/* +/usr/share/cloudstack-common/scripts/vm/hypervisor/vmware/* /usr/share/cloudstack-common/lib/* /usr/bin/cloudstack-set-guest-password /usr/bin/cloudstack-set-guest-sshkey diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java index c0c82ea70f64..800f37080954 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java @@ -23,6 +23,7 @@ import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.ConfigKey.Scope; + import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; @@ -314,5 +315,5 @@ void implementNetworkElementsAndResources(DeployDestination dest, ReservationCon */ void cleanupNicDhcpDnsEntry(Network network, VirtualMachineProfile vmProfile, NicProfile nicProfile); - Pair importNic(final String macAddress, int deviceId, final Network network, final Boolean isDefaultNic, final VirtualMachine vm, final String ipAddress); + Pair importNic(final String macAddress, int deviceId, final Network network, final Boolean isDefaultNic, final VirtualMachine vm, final Network.IpAddresses ipAddresses) throws InsufficientVirtualNetworkCapacityException; } diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index 6ed770046fed..dfa5b844e400 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -3943,32 +3943,45 @@ public NicVO savePlaceholderNic(final Network network, final String ip4Address, @DB @Override - public Pair importNic(final String macAddress, int deviceId, final Network network, final Boolean isDefaultNic, final VirtualMachine vm, final String ipAddress) - throws ConcurrentOperationException { - s_logger.debug("Allocating nic for vm " + vm.getUuid() + " in network " + network + " during ingestion"); - + public Pair importNic(final String macAddress, int deviceId, final Network network, final Boolean isDefaultNic, final VirtualMachine vm, final Network.IpAddresses ipAddresses) + throws ConcurrentOperationException, InsufficientVirtualNetworkCapacityException { + s_logger.debug("Allocating nic for vm " + vm.getUuid() + " in network " + network + " during import"); + if (ipAddresses != null) { + // Auto assign ip4 + String guestIp = _ipAddrMgr.acquireGuestIpAddress(network, ipAddresses.getIp4Address()); + if (guestIp == null && network.getGuestType() != GuestType.L2 && !_networkModel.listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) { + throw new InsufficientVirtualNetworkCapacityException("Unable to acquire Guest IP" + " address for network " + network, DataCenter.class, + network.getDataCenterId()); + } + } NicVO vo = Transaction.execute(new TransactionCallback() { @Override public NicVO doInTransaction(TransactionStatus status) { NicVO vo = new NicVO(network.getGuruName(), vm.getId(), network.getId(), vm.getType()); vo.setMacAddress(macAddress); vo.setAddressFormat(Networks.AddressFormat.Ip4); - vo.setIPv4Address(ipAddress); - if (!Strings.isNullOrEmpty(ipAddress)) { - vo.setIPv4Address(ipAddress); - } - if (!Strings.isNullOrEmpty(network.getGateway())) { - vo.setIPv4Gateway(network.getGateway()); - } - if (!Strings.isNullOrEmpty(network.getCidr())) { - vo.setIPv4Netmask(NetUtils.cidr2Netmask(network.getCidr())); + if (ipAddresses != null) { + if (!Strings.isNullOrEmpty(ipAddresses.getIp4Address()) && !Strings.isNullOrEmpty(network.getGateway())) { + vo.setIPv4Address(ipAddresses.getIp4Address()); + vo.setIPv4Gateway(network.getGateway()); + if (!Strings.isNullOrEmpty(network.getCidr())) { + vo.setIPv4Netmask(NetUtils.cidr2Netmask(network.getCidr())); + } + } + if (!Strings.isNullOrEmpty(ipAddresses.getIp6Address()) && !Strings.isNullOrEmpty(network.getIp6Gateway())) { + vo.setAddressFormat(Networks.AddressFormat.Ip6); + vo.setIPv6Address(ipAddresses.getIp6Address()); + vo.setIPv6Gateway(network.getIp6Gateway()); + if (!Strings.isNullOrEmpty(network.getIp6Cidr())) { + vo.setIPv6Cidr(NetUtils.cidr2Netmask(network.getCidr())); + } + } } vo.setBroadcastUri(network.getBroadcastUri()); vo.setMode(network.getMode()); vo.setState(Nic.State.Reserved); vo.setReservationStrategy(ReservationStrategy.Start); vo.setReservationId(UUID.randomUUID().toString()); - vo.setDeviceId(deviceId); vo.setIsolationUri(network.getBroadcastUri()); vo.setDeviceId(deviceId); vo.setDefaultNic(isDefaultNic); diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 4d14f0727119..8266ff9fcd71 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -45,7 +45,6 @@ import javax.xml.datatype.XMLGregorianCalendar; import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.vm.UnmanagedInstance; import org.apache.cloudstack.storage.command.CopyCommand; import org.apache.cloudstack.storage.command.StorageSubSystemCommand; import org.apache.cloudstack.storage.configdrive.ConfigDrive; @@ -54,6 +53,7 @@ import org.apache.cloudstack.storage.to.TemplateObjectTO; import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo; +import org.apache.cloudstack.vm.UnmanagedInstance; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; @@ -328,6 +328,7 @@ import com.vmware.vim25.VirtualUSBController; import com.vmware.vim25.VmConfigInfo; import com.vmware.vim25.VmConfigSpec; +import com.vmware.vim25.VmwareDistributedVirtualSwitchPvlanSpec; import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec; public class VmwareResource implements StoragePoolResource, ServerResource, VmwareHostService, VirtualRouterDeployer { @@ -6805,7 +6806,7 @@ private List getUnmanageInstanceDisks(VirtualMachineMO v instanceDisk.setDiskId(disk.getDiskObjectId()); instanceDisk.setLabel(disk.getDeviceInfo() != null ? disk.getDeviceInfo().getLabel() : ""); instanceDisk.setImagePath(getAbsoluteVmdkFile(disk)); - instanceDisk.setCapacity(disk.getCapacityInKB()); + instanceDisk.setCapacity(disk.getCapacityInBytes()); for (VirtualDevice device : vmMo.getAllDeviceList()) { if (diskDevice.getControllerKey() == device.getKey()) { if (device instanceof VirtualIDEController) { @@ -6904,10 +6905,18 @@ private List getUnmanageInstanceNics(VmwareHypervisorHost // Find the port for this NIC by portkey if (portKey.equals(dvPort.getKey())) { VMwareDVSPortSetting settings = (VMwareDVSPortSetting) dvPort.getConfig().getSetting(); - VmwareDistributedVirtualSwitchVlanIdSpec vlanId = (VmwareDistributedVirtualSwitchVlanIdSpec) settings.getVlan(); - s_logger.trace("Found port " + dvPort.getKey() + " with vlan " + vlanId.getVlanId()); - if (vlanId.getVlanId() > 0 && vlanId.getVlanId() < 4095) { - instanceNic.setVlan(vlanId.getVlanId()); + if (settings.getVlan() instanceof VmwareDistributedVirtualSwitchVlanIdSpec) { + VmwareDistributedVirtualSwitchVlanIdSpec vlanId = (VmwareDistributedVirtualSwitchVlanIdSpec) settings.getVlan(); + s_logger.trace("Found port " + dvPort.getKey() + " with vlan " + vlanId.getVlanId()); + if (vlanId.getVlanId() > 0 && vlanId.getVlanId() < 4095) { + instanceNic.setVlan(vlanId.getVlanId()); + } + } else if (settings.getVlan() instanceof VmwareDistributedVirtualSwitchPvlanSpec) { + VmwareDistributedVirtualSwitchPvlanSpec pvlanSpec = (VmwareDistributedVirtualSwitchPvlanSpec) settings.getVlan(); + s_logger.trace("Found port " + dvPort.getKey() + " with pvlan " + pvlanSpec.getPvlanId()); + if (pvlanSpec.getPvlanId() > 0 && pvlanSpec.getPvlanId() < 4095) { + instanceNic.setVlan(pvlanSpec.getPvlanId()); + } } break; } @@ -6915,7 +6924,6 @@ private List getUnmanageInstanceNics(VmwareHypervisorHost } else if (backing instanceof VirtualEthernetCardNetworkBackingInfo) { VirtualEthernetCardNetworkBackingInfo backingInfo = (VirtualEthernetCardNetworkBackingInfo) backing; instanceNic.setNetwork(backingInfo.getDeviceName()); - ManagedObjectReference mor = backingInfo.getNetwork(); if (hyperHost instanceof HostMO) { HostMO hostMo = (HostMO) hyperHost; HostPortGroupSpec portGroupSpec = hostMo.getHostPortGroupSpec(backingInfo.getDeviceName()); diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 75d04096373b..2ac7fbb635c7 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -26,6 +26,7 @@ import javax.inject.Inject; +import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.ResponseGenerator; import org.apache.cloudstack.api.ResponseObject; @@ -40,6 +41,7 @@ import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo; import org.apache.commons.collections.CollectionUtils; @@ -51,6 +53,7 @@ import com.cloud.agent.api.GetUnmanagedInstancesAnswer; import com.cloud.agent.api.GetUnmanagedInstancesCommand; import com.cloud.capacity.CapacityManager; +import com.cloud.configuration.Config; import com.cloud.configuration.Resource; import com.cloud.dc.DataCenter; import com.cloud.dc.dao.ClusterDao; @@ -62,6 +65,7 @@ import com.cloud.event.EventTypes; import com.cloud.event.UsageEventUtils; import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InsufficientVirtualNetworkCapacityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; @@ -71,6 +75,7 @@ import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor; import com.cloud.network.Network; +import com.cloud.network.NetworkModel; import com.cloud.network.Networks; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; @@ -169,6 +174,10 @@ public class VmImportManagerImpl implements VmImportService { private ManagementService managementService; @Inject private NicDao nicDao; + @Inject + private NetworkModel networkModel; + @Inject + private ConfigurationDao configurationDao; protected Gson gson; @@ -215,6 +224,9 @@ private UnmanagedInstanceResponse createUnmanagedInstanceResponse(UnmanagedInsta nicResponse.setId(nic.getNicId()); nicResponse.setNetworkName(nic.getNetwork()); nicResponse.setMacAddress(nic.getMacAddress()); + if (!Strings.isNullOrEmpty(nic.getAdapterType())) { + nicResponse.setAdapterType(nic.getAdapterType()); + } if (!Strings.isNullOrEmpty(nic.getIpAddress())) { nicResponse.setIpaddress(nic.getIpAddress()); } @@ -378,6 +390,27 @@ private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedIns return serviceOffering; } + private Map getNicIpAddresses(final List nics, final Map callerNicIpAddressMap) { + Map nicIpAddresses = new HashMap<>(); + for (UnmanagedInstance.Nic nic : nics) { + Network.IpAddresses ipAddresses = null; + if (MapUtils.isNotEmpty(callerNicIpAddressMap) && callerNicIpAddressMap.containsKey(nic.getNicId())) { + ipAddresses = callerNicIpAddressMap.get(nic.getNicId()); + } + if (!Strings.isNullOrEmpty(nic.getIpAddress()) && + (ipAddresses == null || Strings.isNullOrEmpty(ipAddresses.getIp4Address()))) { + if (ipAddresses == null) { + ipAddresses = new Network.IpAddresses(null, null); + } + ipAddresses.setIp4Address(nic.getIpAddress()); + } + if (ipAddresses != null) { + nicIpAddresses.put(nic.getNicId(), ipAddresses); + } + } + return nicIpAddresses; + } + private void checkUnmanagedDiskAndOfferingForImport(UnmanagedInstance.Disk disk, DiskOffering diskOffering, final Account owner, final DataCenter zone) throws ServerApiException, PermissionDeniedException, ResourceAllocationException { if (diskOffering == null) { @@ -385,8 +418,14 @@ private void checkUnmanagedDiskAndOfferingForImport(UnmanagedInstance.Disk disk, } accountService.checkAccess(owner, diskOffering, zone); resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.volume); + if (disk.getCapacity() == null || disk.getCapacity() == 0) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk(ID: %s) is found invalid during VM import!", disk.getDiskId())); + } + if (!diskOffering.isCustomized() && diskOffering.getDiskSize() == 0) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of fixed disk offering(ID: %s) is found invalid during VM import!", diskOffering.getUuid())); + } if (!diskOffering.isCustomized() && diskOffering.getDiskSize() < disk.getCapacity()) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk offering(ID: %s) %dGB is found less than the size of disk(ID: %s) %dGB during VM import!", diskOffering.getUuid(), (diskOffering.getDiskSize() / (1024 * 1024 * 1024)), disk.getDiskId(), (disk.getCapacity() / (1024 * 1024)))); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk offering(ID: %s) %dGB is found less than the size of disk(ID: %s) %dGB during VM import!", diskOffering.getUuid(), (diskOffering.getDiskSize() / Resource.ResourceType.bytesToGiB), disk.getDiskId(), (disk.getCapacity() / (Resource.ResourceType.bytesToGiB)))); } } @@ -400,31 +439,49 @@ private void checkUnmanagedDiskAndOfferingForImport(List } } - private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Network network, final DataCenter zone, final String hostName) throws ServerApiException { + private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Network network, final Network.IpAddresses ipAddresses, final DataCenter zone, final String hostName, final Account owner) throws ServerApiException { if (network == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import!", nic.getNicId())); } if (network.getDataCenterId() != zone.getId()) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network(ID: %s) for nic(ID: %s) belongs to a different zone than VM to be imported!", network.getUuid(), nic.getNicId())); } + networkModel.checkNetworkPermissions(owner, network); if (nic.getVlan() != null && (Strings.isNullOrEmpty(network.getBroadcastUri().toString()) || !network.getBroadcastUri().toString().equals(String.format("vlan://%d", nic.getVlan())))) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VLAN of network(ID: %s) %s is found different from the VLAN of nic(ID: %s) vlan://%d during VM import!", network.getUuid(), network.getBroadcastUri().toString(), nic.getNicId(), nic.getVlan())); } - // * get all vms hostNames in the network + if (!network.getGuestType().equals(Network.GuestType.L2)) { + if (ipAddresses == null) { // No IP address was provided by API and NIC details don't have one + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC(ID: %s) needs a valid IP address for it to be associated with network(ID: %s)! %s parameter of API can be used for this.", nic.getNicId(), network.getUuid(), ApiConstants.NIC_IP_ADDRESS_LIST)); + } + if (Strings.isNullOrEmpty(ipAddresses.getIp4Address()) || Strings.isNullOrEmpty(ipAddresses.getIp6Address())) { + networkModel.checkRequestedIpAddresses(network.getId(), ipAddresses); // This only checks ipv6 + } + if (Strings.isNullOrEmpty(ipAddresses.getIp4Address())) { + Set ips = networkModel.getAvailableIps(network, ipAddresses.getIp4Address()); + if (CollectionUtils.isEmpty(ips)) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("IP address %s for NIC(ID: %s) is not available in network(ID: %s)!", nic.getNicId(), network.getUuid(), ApiConstants.NIC_IP_ADDRESS_LIST)); + } + } + } + // Check for duplicate hostname in network, get all vms hostNames in the network List hostNames = vmDao.listDistinctHostNames(network.getId()); - // * verify that there are no duplicates if (CollectionUtils.isNotEmpty(hostNames) && hostNames.contains(hostName)) { throw new InvalidParameterValueException("The vm with hostName " + hostName + " already exists in the network domain: " + network.getNetworkDomain() + "; network=" + network); } } - private Map getUnmanagedNicNetworkMap(List nics, final Map callerNicNetworkMap, final DataCenter zone, final String hostName) throws ServerApiException { + private Map getUnmanagedNicNetworkMap(List nics, final Map callerNicNetworkMap, final Map callerNicIpAddressMap, final DataCenter zone, final String hostName, final Account owner) throws ServerApiException { Map nicNetworkMap = new HashMap<>(); for (UnmanagedInstance.Nic nic : nics) { Network network = null; + Network.IpAddresses ipAddresses = null; + if (MapUtils.isNotEmpty(callerNicIpAddressMap) && callerNicIpAddressMap.containsKey(nic.getNicId())) { + ipAddresses = callerNicIpAddressMap.get(nic.getNicId()); + } if (!callerNicNetworkMap.containsKey(nic.getNicId())) { - if (nic.getVlan() != null) { + if (nic.getVlan() != null && nic.getVlan() != 0) { // Find a suitable network List networks = networkDao.listByZone(zone.getId()); for (NetworkVO networkVO : networks) { @@ -432,7 +489,7 @@ private Map getUnmanagedNicNetworkMap(List continue; } try { - checkUnmanagedNicAndNetworkForImport(nic, networkVO, zone, hostName); + checkUnmanagedNicAndNetworkForImport(nic, networkVO, ipAddresses, zone, hostName, owner); network = networkVO; break; } catch (Exception e) { @@ -441,7 +498,7 @@ private Map getUnmanagedNicNetworkMap(List } } else { network = networkDao.findById(callerNicNetworkMap.get(nic.getNicId())); - checkUnmanagedNicAndNetworkForImport(nic, network, zone, hostName); + checkUnmanagedNicAndNetworkForImport(nic, network, ipAddresses, zone, hostName, owner); } if (network == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Suitable network for nic(ID: %s) not found during VM import!", nic.getNicId())); @@ -471,7 +528,7 @@ private Pair importDisk(UnmanagedInstance.Disk disk, V storagePool = primaryDataStoreDao.findPoolByUUID(poolUuid); } if (storagePool == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Unable to import disk ID: %s as storage pool not found!"); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to import disk ID: %s as storage pool not found!", disk.getDiskId())); } if (!migrateAllowed && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) { throw new InvalidParameterValueException(String.format("Disk offering: %s is not compatible with storage pool: %s of unmanaged disk: %s", diskOffering.getUuid(), storagePool.getUuid(), disk.getDiskId())); @@ -489,10 +546,10 @@ private Pair importDisk(UnmanagedInstance.Disk disk, V return new Pair(profile, storagePool); } - private NicProfile importNic(UnmanagedInstance.Nic nic, VirtualMachine vm, Network network, String ipAddress, boolean isDefaultNic) { - Pair result = networkOrchestrationService.importNic(nic.getMacAddress(), 0, network, isDefaultNic, vm, ipAddress); + private NicProfile importNic(UnmanagedInstance.Nic nic, VirtualMachine vm, Network network, Network.IpAddresses ipAddresses, boolean isDefaultNic) throws InsufficientVirtualNetworkCapacityException { + Pair result = networkOrchestrationService.importNic(nic.getMacAddress(), 0, network, isDefaultNic, vm, ipAddresses); if (result == null) { - return null; + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC ID: %s import failed!", nic.getNicId())); } return result.first(); } @@ -616,7 +673,7 @@ private void publishVMUsageUpdateResourceCount(final UserVm userVm, ServiceOffer private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedInstance, final String instanceName, final DataCenter zone, final Cluster cluster, final HostVO host, final VirtualMachineTemplate template, final String displayName, final String hostName, final Account caller, final Account owner, final Long userId, final ServiceOfferingVO serviceOffering, final DiskOffering diskOffering, final Map dataDiskOfferingMap, - final Map nicNetworkMap, final Map nicIpAddressMap, + final Map nicNetworkMap, final Map callerNicIpAddressMap, final Map details, final boolean migrateAllowed) { UserVm userVm = null; @@ -660,7 +717,8 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resource allocation error for owner: %s! %s", owner.getUuid(), Strings.nullToEmpty(e.getMessage()))); } // Check NICs and supplied networks - Map allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getNics(), nicNetworkMap, zone, hostName); + Map nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap); + Map allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner); VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff; if (unmanagedInstance.getPowerState().equals(UnmanagedInstance.PowerState.PowerOn)) { powerState = VirtualMachine.PowerState.PowerOn; @@ -679,10 +737,16 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns } List> diskProfileStoragePoolList = new ArrayList<>(); try { - diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()), (rootDisk.getCapacity() / (1024 * 1024)), template, owner, null, migrateAllowed)); + if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) { + throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId())); + } + diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()), (rootDisk.getCapacity() / Resource.ResourceType.bytesToGiB), template, owner, null, migrateAllowed)); for (UnmanagedInstance.Disk disk : dataDisks) { + if (disk.getCapacity() == null || disk.getCapacity() == 0) { + throw new InvalidParameterValueException(String.format("Disk ID: %s size is invalid", rootDisk.getDiskId())); + } DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId())); - diskProfileStoragePoolList.add(importDisk(disk, userVm, offering, Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()), (disk.getCapacity() / (1024 * 1024)), template, owner, null, migrateAllowed)); + diskProfileStoragePoolList.add(importDisk(disk, userVm, offering, Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()), (disk.getCapacity() / Resource.ResourceType.bytesToGiB), template, owner, null, migrateAllowed)); } } catch (Exception e) { LOGGER.error(String.format("Failed to import volumes while importing vm: %s", instanceName), e); @@ -693,11 +757,16 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns boolean firstNic = true; for (UnmanagedInstance.Nic nic : unmanagedInstance.getNics()) { Network network = networkDao.findById(allNicNetworkMap.get(nic.getNicId())); - String ipAddress = nicIpAddressMap.get(nic.getNicId()); - if (Strings.isNullOrEmpty(ipAddress)) { - ipAddress = nic.getIpAddress(); + Network.IpAddresses ipAddresses = nicIpAddressMap.get(nic.getNicId()); + if (ipAddresses == null || (Strings.isNullOrEmpty(ipAddresses.getIp4Address()) && Strings.isNullOrEmpty(ipAddresses.getIp6Address()))) { + if (ipAddresses == null) { + ipAddresses = new Network.IpAddresses(null, null); + } + if (!Strings.isNullOrEmpty(nic.getIpAddress())) { + ipAddresses.setIp4Address(nic.getIpAddress()); + } } - importNic(nic, userVm, network, ipAddress, firstNic); + importNic(nic, userVm, network, ipAddresses, firstNic); firstNic = false; } } catch (Exception e) { @@ -832,8 +901,17 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { throw new InvalidParameterValueException("Invalid VM hostname. VM hostname can contain ASCII letters 'a' through 'z', the digits '0' through '9', " + "and the hyphen ('-'), must be between 1 and 63 characters long, and can't start or end with \"-\" and can't start with digit"); } + if (cluster.getHypervisorType().equals(Hypervisor.HypervisorType.VMware) && + Boolean.parseBoolean(configurationDao.getValue(Config.SetVmInternalNameUsingDisplayName.key()))) { + // If global config vm.instancename.flag is set to true, then CS will set guest VM's name as it appears on the hypervisor, to its hostname. + // In case of VMware since VM name must be unique within a DC, check if VM with the same hostname already exists in the zone. + VMInstanceVO vmByHostName = vmDao.findVMByHostNameInZone(hostName, zone.getId()); + if (vmByHostName != null && vmByHostName.getState() != VirtualMachine.State.Expunging) { + throw new InvalidParameterValueException(String.format("Failed to import VM: %s! There already exists a VM by the hostname: %s in zone: %s", instanceName, hostName, zone.getUuid())); + } + } final Map nicNetworkMap = cmd.getNicNetworkList(); - final Map nicIpAddressMap = cmd.getNicIpAddressList(); + final Map nicIpAddressMap = cmd.getNicIpAddressList(); final Map dataDiskOfferingMap = cmd.getDataDiskToDiskOfferingList(); final Map details = cmd.getDetails(); List hosts = resourceManager.listHostsInClusterByStatus(clusterId, Status.Up); diff --git a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java index 75152ffc217c..75508b54378e 100644 --- a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java @@ -975,7 +975,7 @@ public AcquirePodIpCmdResponse allocatePodIp(Account account, String zoneId, Str } @Override - public Pair importNic(String macAddress, int deviceId, Network network, Boolean isDefaultNic, VirtualMachine vm, String ipAddress) { + public Pair importNic(String macAddress, int deviceId, Network network, Boolean isDefaultNic, VirtualMachine vm, IpAddresses ipAddresses) { return null; } } diff --git a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java index f03160c425de..44884493913c 100644 --- a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java @@ -20,6 +20,7 @@ import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.junit.After; @@ -52,6 +53,7 @@ import com.cloud.host.Status; import com.cloud.hypervisor.Hypervisor; import com.cloud.network.Network; +import com.cloud.network.NetworkModel; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; import com.cloud.offering.DiskOffering; @@ -135,6 +137,10 @@ public class VmImportManagerImplTest { private PrimaryDataStoreDao primaryDataStoreDao; @Mock private VolumeApiService volumeApiService; + @Mock + private NetworkModel networkModel; + @Mock + private ConfigurationDao configurationDao; @Before public void setUp() throws Exception { @@ -173,12 +179,11 @@ public void setUp() throws Exception { ClusterVO cluster = new ClusterVO(1, 1, "Cluster"); cluster.setHypervisorType(Hypervisor.HypervisorType.VMware.toString()); when(clusterDao.findById(Mockito.anyLong())).thenReturn(cluster); - + when(configurationDao.getValue(Mockito.anyString())).thenReturn(null); + doNothing().when(resourceLimitService).checkResourceLimit(any(Account.class), any(Resource.ResourceType.class), anyLong()); List hosts = new ArrayList<>(); HostVO hostVO = Mockito.mock(HostVO.class); - hosts.add(hostVO); - - doNothing().when(resourceLimitService).checkResourceLimit(any(Account.class), any(Resource.ResourceType.class), anyLong()); + hosts.add(hostVO);; when(resourceManager.listHostsInClusterByStatus(Mockito.anyLong(), Mockito.any(Status.class))).thenReturn(hosts); List templates = new ArrayList<>(); when(templatePoolDao.listAll()).thenReturn(templates); @@ -192,7 +197,6 @@ public void setUp() throws Exception { map.put(instance.getName(), instance); Answer answer = new GetUnmanagedInstancesAnswer(cmd, "", map); when(agentManager.easySend(Mockito.anyLong(), Mockito.any(GetUnmanagedInstancesCommand.class))).thenReturn(answer); - DataCenterVO zone = Mockito.mock(DataCenterVO.class); when(zone.getId()).thenReturn(1L); when(dataCenterDao.findById(Mockito.anyLong())).thenReturn(zone); @@ -233,16 +237,19 @@ public void setUp() throws Exception { when(primaryDataStoreDao.findPoolByUUID(Mockito.anyString())).thenReturn(poolVO); when(volumeApiService.doesTargetStorageSupportDiskOffering(Mockito.any(StoragePool.class), Mockito.anyString())).thenReturn(true); NetworkVO networkVO = Mockito.mock(NetworkVO.class); + when(networkVO.getGuestType()).thenReturn(Network.GuestType.L2); when(networkVO.getBroadcastUri()).thenReturn(URI.create(String.format("vlan://%d", instanceNic.getVlan()))); when(networkVO.getDataCenterId()).thenReturn(1L); when(networkDao.findById(Mockito.anyLong())).thenReturn(networkVO); List networks = new ArrayList<>(); networks.add(networkVO); when(networkDao.listByZone(Mockito.anyLong())).thenReturn(networks); + doNothing().when(networkModel).checkNetworkPermissions(Mockito.any(Account.class), Mockito.any(Network.class)); + doNothing().when(networkModel).checkRequestedIpAddresses(Mockito.anyLong(), Mockito.any(Network.IpAddresses.class)); NicProfile profile = Mockito.mock(NicProfile.class); Integer deviceId = 100; Pair pair = new Pair(profile, deviceId); - when(networkOrchestrationService.importNic(Mockito.anyString(), Mockito.anyInt(), Mockito.any(Network.class), Mockito.anyBoolean(), Mockito.any(VirtualMachine.class), Mockito.anyString())).thenReturn(pair); + when(networkOrchestrationService.importNic(Mockito.anyString(), Mockito.anyInt(), Mockito.any(Network.class), Mockito.anyBoolean(), Mockito.any(VirtualMachine.class), Mockito.any(Network.IpAddresses.class))).thenReturn(pair); when(volumeManager.importVolume(Mockito.any(Volume.Type.class), Mockito.anyString(), Mockito.any(DiskOffering.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.any(VirtualMachine.class), Mockito.any(VirtualMachineTemplate.class), Mockito.any(Account.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString(), Mockito.anyString())).thenReturn(Mockito.mock(DiskProfile.class)); From 89f0e283f66cd1dfc1e0610d11d8b5737f51c73c Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 3 Oct 2019 20:29:48 +0530 Subject: [PATCH 04/61] Update cloudstack-common.install --- debian/cloudstack-common.install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/cloudstack-common.install b/debian/cloudstack-common.install index 53302111b369..9a9cf3bbc09f 100644 --- a/debian/cloudstack-common.install +++ b/debian/cloudstack-common.install @@ -26,8 +26,8 @@ /usr/share/cloudstack-common/scripts/vm/hypervisor/kvm/* /usr/share/cloudstack-common/scripts/vm/hypervisor/update_host_passwd.sh /usr/share/cloudstack-common/scripts/vm/hypervisor/versions.sh -/usr/share/cloudstack-common/scripts/vm/hypervisor/xenserver/* /usr/share/cloudstack-common/scripts/vm/hypervisor/vmware/* +/usr/share/cloudstack-common/scripts/vm/hypervisor/xenserver/* /usr/share/cloudstack-common/lib/* /usr/bin/cloudstack-set-guest-password /usr/bin/cloudstack-set-guest-sshkey From f0800086f54bc5eb6f2116795ae6ea75941392ed Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 4 Oct 2019 14:32:51 +0530 Subject: [PATCH 05/61] fixes Fixed storage pool not found error. Unmanaged VM will return disk with details of its datastore. Fixed migration check for VM root disk with service offering tags. Signed-off-by: Abhishek Kumar --- .../apache/cloudstack/api/ApiConstants.java | 4 + .../UnmanagedInstanceDiskResponse.java | 48 ++++++++++ .../cloudstack/vm/UnmanagedInstance.java | 40 ++++++++ .../vmware/resource/VmwareResource.java | 17 ++++ .../cloudstack/vm/VmImportManagerImpl.java | 96 ++++++++++++------- 5 files changed, 170 insertions(+), 35 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index d52bd1eb0604..fba43f55cf08 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -57,6 +57,10 @@ public class ApiConstants { public static final String COPY_IMAGE_TAGS = "copyimagetags"; public static final String CSR = "csr"; public static final String PRIVATE_KEY = "privatekey"; + public static final String DATASTORE_HOST = "datastorehost"; + public static final String DATASTORE_NAME = "datastorename"; + public static final String DATASTORE_PATH = "datastorepath"; + public static final String DATASTORE_TYPE = "datastoretype"; public static final String DOMAIN_SUFFIX = "domainsuffix"; public static final String DNS_SEARCH_ORDER = "dnssearchorder"; public static final String CHAIN_INFO = "chaininfo"; diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceDiskResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceDiskResponse.java index 81563b76a31c..083c83fbf85a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceDiskResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceDiskResponse.java @@ -53,6 +53,22 @@ public class UnmanagedInstanceDiskResponse extends BaseResponse { @Param(description = "the position of the disk") private Integer position; + @SerializedName(ApiConstants.DATASTORE_NAME) + @Param(description = "the controller of the disk") + private String datastoreName; + + @SerializedName(ApiConstants.DATASTORE_HOST) + @Param(description = "the controller of the disk") + private String datastoreHost; + + @SerializedName(ApiConstants.DATASTORE_PATH) + @Param(description = "the controller of the disk") + private String datastorePath; + + @SerializedName(ApiConstants.DATASTORE_TYPE) + @Param(description = "the controller of the disk") + private String datastoreType; + public String getDiskId() { return diskId; } @@ -108,4 +124,36 @@ public Integer getPosition() { public void setPosition(Integer position) { this.position = position; } + + public String getDatastoreName() { + return datastoreName; + } + + public void setDatastoreName(String datastoreName) { + this.datastoreName = datastoreName; + } + + public String getDatastoreHost() { + return datastoreHost; + } + + public void setDatastoreHost(String datastoreHost) { + this.datastoreHost = datastoreHost; + } + + public String getDatastorePath() { + return datastorePath; + } + + public void setDatastorePath(String datastorePath) { + this.datastorePath = datastorePath; + } + + public String getDatastoreType() { + return datastoreType; + } + + public void setDatastoreType(String datastoreType) { + this.datastoreType = datastoreType; + } } diff --git a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java index 43e2fa6e8887..121a7041cac1 100644 --- a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java +++ b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java @@ -132,6 +132,14 @@ public static class Disk { private Integer position; + private String datastoreName; + + private String datastoreHost; + + private String datastorePath; + + private String datastoreType; + public String getDiskId() { return diskId; } @@ -187,6 +195,38 @@ public Integer getPosition() { public void setPosition(Integer position) { this.position = position; } + + public String getDatastoreName() { + return datastoreName; + } + + public void setDatastoreName(String datastoreName) { + this.datastoreName = datastoreName; + } + + public String getDatastoreHost() { + return datastoreHost; + } + + public void setDatastoreHost(String datastoreHost) { + this.datastoreHost = datastoreHost; + } + + public String getDatastorePath() { + return datastorePath; + } + + public void setDatastorePath(String datastorePath) { + this.datastorePath = datastorePath; + } + + public String getDatastoreType() { + return datastoreType; + } + + public void setDatastoreType(String datastoreType) { + this.datastoreType = datastoreType; + } } public static class Nic { diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 8266ff9fcd71..2201cb410554 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -271,6 +271,7 @@ import com.vmware.vim25.DVPortConfigInfo; import com.vmware.vim25.DVPortConfigSpec; import com.vmware.vim25.DasVmPriority; +import com.vmware.vim25.DatastoreInfo; import com.vmware.vim25.DatastoreSummary; import com.vmware.vim25.DistributedVirtualPort; import com.vmware.vim25.DistributedVirtualSwitchPortConnection; @@ -283,6 +284,7 @@ import com.vmware.vim25.HostInternetScsiHba; import com.vmware.vim25.HostPortGroupSpec; import com.vmware.vim25.ManagedObjectReference; +import com.vmware.vim25.NasDatastoreInfo; import com.vmware.vim25.ObjectContent; import com.vmware.vim25.OptionValue; import com.vmware.vim25.PerfCounterInfo; @@ -306,6 +308,7 @@ import com.vmware.vim25.VirtualDeviceBackingInfo; import com.vmware.vim25.VirtualDeviceConfigSpec; import com.vmware.vim25.VirtualDeviceConfigSpecOperation; +import com.vmware.vim25.VirtualDeviceFileBackingInfo; import com.vmware.vim25.VirtualDisk; import com.vmware.vim25.VirtualDiskFlatVer2BackingInfo; import com.vmware.vim25.VirtualEthernetCard; @@ -6822,6 +6825,20 @@ private List getUnmanageInstanceDisks(VirtualMachineMO v break; } } + if (disk.getBacking() instanceof VirtualDeviceFileBackingInfo) { + VirtualDeviceFileBackingInfo diskBacking = (VirtualDeviceFileBackingInfo) disk.getBacking(); + ManagedObjectReference morDs = diskBacking.getDatastore(); + DatastoreInfo info = (DatastoreInfo)vmMo.getContext().getVimClient().getDynamicProperty(diskBacking.getDatastore(), "info"); + if (info instanceof NasDatastoreInfo) { + NasDatastoreInfo nasInfo = (NasDatastoreInfo) info; + instanceDisk.setDatastoreName(nasInfo.getName()); + if (nasInfo.getNas() != null) { + instanceDisk.setDatastoreHost(nasInfo.getNas().getRemoteHost()); + instanceDisk.setDatastorePath(nasInfo.getNas().getRemotePath()); + instanceDisk.setDatastoreType(nasInfo.getNas().getType()); + } + } + } s_logger.info(vmMo.getName() + " " + disk.getDeviceInfo().getLabel() + " " + disk.getDeviceInfo().getSummary() + " " + disk.getDiskObjectId() + " " + disk.getCapacityInKB() + " " + instanceDisk.getController()); instanceDisks.add(instanceDisk); } diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 2ac7fbb635c7..76c35ead006a 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.vm; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -43,6 +42,7 @@ import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; @@ -214,6 +214,10 @@ private UnmanagedInstanceResponse createUnmanagedInstanceResponse(UnmanagedInsta diskResponse.setControllerUnit(disk.getControllerUnit()); diskResponse.setPosition(disk.getPosition()); diskResponse.setImagePath(disk.getImagePath()); + diskResponse.setDatastoreName(disk.getDatastoreName()); + diskResponse.setDatastoreHost(disk.getDatastoreHost()); + diskResponse.setDatastorePath(disk.getDatastorePath()); + diskResponse.setDatastoreType(disk.getDatastoreType()); response.addDisk(diskResponse); } } @@ -339,6 +343,16 @@ private boolean storagePoolSupportsDiskOffering(StoragePool pool, DiskOffering d return volumeApiService.doesTargetStorageSupportDiskOffering(pool, diskOffering.getTags()); } + private boolean storagePoolSupportsServiceOffering(StoragePool pool, ServiceOffering serviceOffering) { + if (pool == null) { + return false; + } + if (serviceOffering == null) { + return false; + } + return volumeApiService.doesTargetStorageSupportDiskOffering(pool, serviceOffering.getTags()); + } + private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedInstance instance, ServiceOfferingVO serviceOffering, final Account owner, final DataCenter zone, final Map details) throws ServerApiException, PermissionDeniedException, ResourceAllocationException { if (instance == null) { @@ -411,7 +425,7 @@ private Map getNicIpAddresses(final List pools = primaryDataStoreDao.listPoolByHostPath(dsHost, dsPath); + for (StoragePool pool : pools) { + if (pool.getDataCenterId() == zone.getId() && + pool.getClusterId() == cluster.getId()) { + storagePool = pool; + break; + } + } + if (storagePool == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk ID: %s with host: %s, path: %s, type: %s not found!", disk.getDiskId(), dsHost, dsPath, dsType)); + } + if (!migrateAllowed && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) { + throw new InvalidParameterValueException(String.format("Disk offering: %s is not compatible with storage pool: %s of unmanaged disk: %s", diskOffering.getUuid(), storagePool.getUuid(), disk.getDiskId())); + } } - private void checkUnmanagedDiskAndOfferingForImport(List disks, final Map diskOfferingMap, final Account owner, final DataCenter zone) + private void checkUnmanagedDiskAndOfferingForImport(List disks, final Map diskOfferingMap, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed) throws ServerApiException, PermissionDeniedException, ResourceAllocationException { for (UnmanagedInstance.Disk disk : disks) { if (!diskOfferingMap.containsKey(disk.getDiskId())) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID: %s not found during VM import!", disk.getDiskId())); } - checkUnmanagedDiskAndOfferingForImport(disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), owner, zone); + checkUnmanagedDiskAndOfferingForImport(disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), owner, zone, cluster, migrateAllowed); } } @@ -508,40 +540,30 @@ private Map getUnmanagedNicNetworkMap(List return nicNetworkMap; } - private Pair importDisk(UnmanagedInstance.Disk disk, VirtualMachine vm, DiskOffering diskOffering, + private Pair importDisk(UnmanagedInstance.Disk disk, VirtualMachine vm, Cluster cluster, DiskOffering diskOffering, Volume.Type type, String name, Long diskSize, VirtualMachineTemplate template, Account owner, Long deviceId, boolean migrateAllowed) { VirtualMachineDiskInfo diskInfo = new VirtualMachineDiskInfo(); diskInfo.setDiskDeviceBusName(String.format("%s%d:%d", disk.getController(), disk.getControllerUnit(), disk.getPosition())); diskInfo.setDiskChain(new String[]{disk.getImagePath()}); - String path = disk.getImagePath(); - long poolId = 0; + final String imagePath = disk.getImagePath(); + final String dsHost = disk.getDatastoreHost(); + final String dsPath = disk.getDatastorePath(); + final String dsType = disk.getDatastoreType(); StoragePool storagePool = null; - if (vm.getHypervisorType() == Hypervisor.HypervisorType.VMware) { - String[] splits = path.split(" "); - String poolUuid = splits[0]; - poolUuid = poolUuid.replace("[", "").replace("]", ""); - if (poolUuid.length() == 32) { - poolUuid = String.format("%s-%s-%s-%s-%s", poolUuid.substring(0, 8), - poolUuid.substring(8, 12), poolUuid.substring(12, 16), - poolUuid.substring(16, 20), poolUuid.substring(20, 32)); - storagePool = primaryDataStoreDao.findPoolByUUID(poolUuid); - } - if (storagePool == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to import disk ID: %s as storage pool not found!", disk.getDiskId())); - } - if (!migrateAllowed && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) { - throw new InvalidParameterValueException(String.format("Disk offering: %s is not compatible with storage pool: %s of unmanaged disk: %s", diskOffering.getUuid(), storagePool.getUuid(), disk.getDiskId())); - } - poolId = storagePool.getId(); - path = String.join(" ", Arrays.copyOfRange(splits, 1, splits.length)); - splits = path.split("/"); - path = splits[splits.length - 1]; - splits = path.split("\\."); - path = splits[0]; + List pools = primaryDataStoreDao.listPoolByHostPath(dsHost, dsPath); + for (StoragePool pool : pools) { + if (pool.getDataCenterId() == vm.getDataCenterId() && + pool.getClusterId() == cluster.getId()) { + storagePool = pool; + break; + } + } + if (storagePool == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk ID: %s with host: %s, path: %s, type: %s not found!", disk.getDiskId(), dsHost, dsPath, dsType)); } DiskProfile profile = volumeManager.importVolume(type, name, diskOffering, diskSize, - diskOffering.getMinIops(), diskOffering.getMaxIops(), vm, template, owner, deviceId, poolId, path, gson.toJson(diskInfo)); + diskOffering.getMinIops(), diskOffering.getMaxIops(), vm, template, owner, deviceId, storagePool.getId(), imagePath, gson.toJson(diskInfo)); return new Pair(profile, storagePool); } @@ -623,7 +645,11 @@ private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate templ if (volumeVO == null) { continue; } - if (storagePoolSupportsDiskOffering(diskProfileStoragePool.second(), dOffering)) { + boolean poolSupportsOfferings = storagePoolSupportsDiskOffering(diskProfileStoragePool.second(), dOffering); + if (poolSupportsOfferings && profile.getType() == Volume.Type.ROOT) { + poolSupportsOfferings = storagePoolSupportsServiceOffering(diskProfileStoragePool.second(), serviceOffering); + } + if (poolSupportsOfferings) { continue; } Pair, List> poolsPair = managementService.listStoragePoolsForMigrationOfVolume(profile.getVolumeId()); @@ -705,11 +731,11 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns final UnmanagedInstance.Disk rootDisk = unmanagedInstance.getDisks().get(0); List dataDisks = new ArrayList<>(); try { - checkUnmanagedDiskAndOfferingForImport(rootDisk, diskOffering, owner, zone); + checkUnmanagedDiskAndOfferingForImport(rootDisk, diskOffering, owner, zone, cluster, migrateAllowed); if (unmanagedInstanceDisks.size() > 1) { // Data disk(s) present dataDisks.addAll(unmanagedInstanceDisks); dataDisks.remove(0); - checkUnmanagedDiskAndOfferingForImport(dataDisks, dataDiskOfferingMap, owner, zone); + checkUnmanagedDiskAndOfferingForImport(dataDisks, dataDiskOfferingMap, owner, zone, cluster, migrateAllowed); } resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.volume, unmanagedInstanceDisks.size()); } catch (ResourceAllocationException e) { @@ -740,13 +766,13 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) { throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId())); } - diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()), (rootDisk.getCapacity() / Resource.ResourceType.bytesToGiB), template, owner, null, migrateAllowed)); + diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, cluster, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()), (rootDisk.getCapacity() / Resource.ResourceType.bytesToGiB), template, owner, null, migrateAllowed)); for (UnmanagedInstance.Disk disk : dataDisks) { if (disk.getCapacity() == null || disk.getCapacity() == 0) { throw new InvalidParameterValueException(String.format("Disk ID: %s size is invalid", rootDisk.getDiskId())); } DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId())); - diskProfileStoragePoolList.add(importDisk(disk, userVm, offering, Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()), (disk.getCapacity() / Resource.ResourceType.bytesToGiB), template, owner, null, migrateAllowed)); + diskProfileStoragePoolList.add(importDisk(disk, userVm, cluster, offering, Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()), (disk.getCapacity() / Resource.ResourceType.bytesToGiB), template, owner, null, migrateAllowed)); } } catch (Exception e) { LOGGER.error(String.format("Failed to import volumes while importing vm: %s", instanceName), e); From 2cb3f4f00dea24cca8156ec76eea03300145c084 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 4 Oct 2019 16:25:13 +0530 Subject: [PATCH 06/61] fixed failing unit test Signed-off-by: Abhishek Kumar --- .../cloudstack/vm/VmImportManagerImpl.java | 4 ++-- .../vm/VmImportManagerImplTest.java | 21 ++++++++++++++----- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 76c35ead006a..a6fa1f0feab6 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -454,7 +454,7 @@ private void checkUnmanagedDiskAndOfferingForImport(UnmanagedInstance.Disk disk, } } if (storagePool == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk ID: %s with host: %s, path: %s, type: %s not found!", disk.getDiskId(), dsHost, dsPath, dsType)); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk ID: %s with host: %s, path: %s, type: %s not found in zone ID: %s, cluster ID: %s!", disk.getDiskId(), dsHost, dsPath, dsType, zone.getUuid(), cluster.getUuid())); } if (!migrateAllowed && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) { throw new InvalidParameterValueException(String.format("Disk offering: %s is not compatible with storage pool: %s of unmanaged disk: %s", diskOffering.getUuid(), storagePool.getUuid(), disk.getDiskId())); @@ -560,7 +560,7 @@ private Pair importDisk(UnmanagedInstance.Disk disk, V } } if (storagePool == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk ID: %s with host: %s, path: %s, type: %s not found!", disk.getDiskId(), dsHost, dsPath, dsType)); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk ID: %s with host: %s, path: %s, type: %s not found in cluster ID: %s!", disk.getDiskId(), dsHost, dsPath, dsType, cluster.getUuid())); } DiskProfile profile = volumeManager.importVolume(type, name, diskOffering, diskSize, diskOffering.getMinIops(), diskOffering.getMaxIops(), vm, template, owner, deviceId, storagePool.getId(), imagePath, gson.toJson(diskInfo)); diff --git a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java index 44884493913c..2238309a76cf 100644 --- a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java @@ -164,6 +164,10 @@ public void setUp() throws Exception { instanceDisk.setController("scsi"); instanceDisk.setImagePath("[b6ccf44a1fa13e29b3667b4954fa10ee] TestInstance/ROOT-1.vmdk"); instanceDisk.setCapacity(5242880L); + instanceDisk.setDatastoreName("Test"); + instanceDisk.setDatastoreHost("Test"); + instanceDisk.setDatastorePath("Test"); + instanceDisk.setDatastoreType("Test"); instanceDisks.add(instanceDisk); instance.setDisks(instanceDisks); List instanceNics = new ArrayList<>(); @@ -176,9 +180,9 @@ public void setUp() throws Exception { instance.setNics(instanceNics); instance.setPowerState(UnmanagedInstance.PowerState.PowerOn); - ClusterVO cluster = new ClusterVO(1, 1, "Cluster"); - cluster.setHypervisorType(Hypervisor.HypervisorType.VMware.toString()); - when(clusterDao.findById(Mockito.anyLong())).thenReturn(cluster); + ClusterVO clusterVO = new ClusterVO(1L, 1L, "Cluster"); + clusterVO.setHypervisorType(Hypervisor.HypervisorType.VMware.toString()); + when(clusterDao.findById(Mockito.anyLong())).thenReturn(clusterVO); when(configurationDao.getValue(Mockito.anyString())).thenReturn(null); doNothing().when(resourceLimitService).checkResourceLimit(any(Account.class), any(Resource.ResourceType.class), anyLong()); List hosts = new ArrayList<>(); @@ -229,12 +233,19 @@ public void setUp() throws Exception { when(userVm.getType()).thenReturn(VirtualMachine.Type.Instance); userVm.setInstanceName(instance.getName()); userVm.setHostName(instance.getName()); + StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); + when(poolVO.getDataCenterId()).thenReturn(1L); + when(poolVO.getClusterId()).thenReturn(1L); + List pools = new ArrayList<>(); + pools.add(poolVO); + StoragePoolVO poolVO1 = Mockito.mock(StoragePoolVO.class); + when(poolVO.getDataCenterId()).thenReturn(1L); + when(poolVO.getClusterId()).thenReturn(0L); + when(primaryDataStoreDao.listPoolByHostPath(Mockito.anyString(), Mockito.anyString())).thenReturn(pools); when(userVmManager.importVM(Mockito.any(DataCenter.class), Mockito.any(Host.class), Mockito.any(VirtualMachineTemplate.class), Mockito.anyString(), Mockito.anyString(), Mockito.any(Account.class), Mockito.anyString(), Mockito.any(Account.class), Mockito.anyBoolean(), Mockito.anyString(), Mockito.anyLong(), Mockito.anyLong(), Mockito.any(ServiceOffering.class), Mockito.any(DiskOffering.class), Mockito.anyString(), Mockito.anyString(), Mockito.any(Hypervisor.HypervisorType.class), Mockito.anyMap(), Mockito.any(VirtualMachine.PowerState.class))).thenReturn(userVm); - StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); - when(primaryDataStoreDao.findPoolByUUID(Mockito.anyString())).thenReturn(poolVO); when(volumeApiService.doesTargetStorageSupportDiskOffering(Mockito.any(StoragePool.class), Mockito.anyString())).thenReturn(true); NetworkVO networkVO = Mockito.mock(NetworkVO.class); when(networkVO.getGuestType()).thenReturn(Network.GuestType.L2); From 3432b17ab920127ba53ef0e95e8fc5a244104449 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 4 Oct 2019 16:35:19 +0530 Subject: [PATCH 07/61] fix - cleaned test Signed-off-by: Abhishek Kumar --- .../org/apache/cloudstack/vm/VmImportManagerImplTest.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java index 2238309a76cf..89aac06a4459 100644 --- a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java @@ -235,12 +235,9 @@ public void setUp() throws Exception { userVm.setHostName(instance.getName()); StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); when(poolVO.getDataCenterId()).thenReturn(1L); - when(poolVO.getClusterId()).thenReturn(1L); + when(poolVO.getClusterId()).thenReturn(clusterVO.getId()); List pools = new ArrayList<>(); pools.add(poolVO); - StoragePoolVO poolVO1 = Mockito.mock(StoragePoolVO.class); - when(poolVO.getDataCenterId()).thenReturn(1L); - when(poolVO.getClusterId()).thenReturn(0L); when(primaryDataStoreDao.listPoolByHostPath(Mockito.anyString(), Mockito.anyString())).thenReturn(pools); when(userVmManager.importVM(Mockito.any(DataCenter.class), Mockito.any(Host.class), Mockito.any(VirtualMachineTemplate.class), Mockito.anyString(), Mockito.anyString(), Mockito.any(Account.class), Mockito.anyString(), Mockito.any(Account.class), Mockito.anyBoolean(), Mockito.anyString(), From 3739e4d195c7de5b96cda7b41dde4875bf7019de Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 7 Oct 2019 13:44:23 +0530 Subject: [PATCH 08/61] fix for vmfs storage pool Signed-off-by: Abhishek Kumar --- .../vmware/resource/VmwareResource.java | 21 ++++++++++++----- .../cloudstack/vm/VmImportManagerImpl.java | 23 ++++++++++++++----- .../vm/VmImportManagerImplTest.java | 2 +- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 2201cb410554..621eb843f5a7 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -331,6 +331,7 @@ import com.vmware.vim25.VirtualUSBController; import com.vmware.vim25.VmConfigInfo; import com.vmware.vim25.VmConfigSpec; +import com.vmware.vim25.VmfsDatastoreInfo; import com.vmware.vim25.VmwareDistributedVirtualSwitchPvlanSpec; import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec; @@ -6830,13 +6831,21 @@ private List getUnmanageInstanceDisks(VirtualMachineMO v ManagedObjectReference morDs = diskBacking.getDatastore(); DatastoreInfo info = (DatastoreInfo)vmMo.getContext().getVimClient().getDynamicProperty(diskBacking.getDatastore(), "info"); if (info instanceof NasDatastoreInfo) { - NasDatastoreInfo nasInfo = (NasDatastoreInfo) info; - instanceDisk.setDatastoreName(nasInfo.getName()); - if (nasInfo.getNas() != null) { - instanceDisk.setDatastoreHost(nasInfo.getNas().getRemoteHost()); - instanceDisk.setDatastorePath(nasInfo.getNas().getRemotePath()); - instanceDisk.setDatastoreType(nasInfo.getNas().getType()); + NasDatastoreInfo dsInfo = (NasDatastoreInfo) info; + instanceDisk.setDatastoreName(dsInfo.getName()); + if (dsInfo.getNas() != null) { + instanceDisk.setDatastoreHost(dsInfo.getNas().getRemoteHost()); + instanceDisk.setDatastorePath(dsInfo.getNas().getRemotePath()); + instanceDisk.setDatastoreType(dsInfo.getNas().getType()); } + } else if (info instanceof VmfsDatastoreInfo) { + VmfsDatastoreInfo dsInfo = (VmfsDatastoreInfo) info; + instanceDisk.setDatastoreName(dsInfo.getVmfs().getName()); + instanceDisk.setDatastoreType(dsInfo.getVmfs().getType()); + } else { + String msg = String.format(String.format("Unmanaged instance disk: %s is on unsupported datastore %s", instanceDisk.getDiskId(), info.getClass().getSimpleName())); + s_logger.error(msg); + throw new Exception(msg); } } s_logger.info(vmMo.getName() + " " + disk.getDeviceInfo().getLabel() + " " + disk.getDeviceInfo().getSummary() + " " + disk.getDiskObjectId() + " " + disk.getCapacityInKB() + " " + instanceDisk.getController()); diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index a6fa1f0feab6..3673eb830963 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -547,16 +547,27 @@ private Pair importDisk(UnmanagedInstance.Disk disk, V diskInfo.setDiskDeviceBusName(String.format("%s%d:%d", disk.getController(), disk.getControllerUnit(), disk.getPosition())); diskInfo.setDiskChain(new String[]{disk.getImagePath()}); final String imagePath = disk.getImagePath(); + final String dsName = disk.getDatastoreName(); final String dsHost = disk.getDatastoreHost(); final String dsPath = disk.getDatastorePath(); final String dsType = disk.getDatastoreType(); StoragePool storagePool = null; - List pools = primaryDataStoreDao.listPoolByHostPath(dsHost, dsPath); - for (StoragePool pool : pools) { - if (pool.getDataCenterId() == vm.getDataCenterId() && - pool.getClusterId() == cluster.getId()) { - storagePool = pool; - break; + if (dsType == "VMFS") { + List pools = primaryDataStoreDao.listPoolsByCluster(cluster.getId()); + for (StoragePool pool : pools) { + if (pool.getPath().endsWith(dsName)) { + storagePool = pool; + break; + } + } + } else { + List pools = primaryDataStoreDao.listPoolByHostPath(dsHost, dsPath); + for (StoragePool pool : pools) { + if (pool.getDataCenterId() == vm.getDataCenterId() && + pool.getClusterId() == cluster.getId()) { + storagePool = pool; + break; + } } } if (storagePool == null) { diff --git a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java index 89aac06a4459..e4111d481850 100644 --- a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java @@ -167,7 +167,7 @@ public void setUp() throws Exception { instanceDisk.setDatastoreName("Test"); instanceDisk.setDatastoreHost("Test"); instanceDisk.setDatastorePath("Test"); - instanceDisk.setDatastoreType("Test"); + instanceDisk.setDatastoreType("NFS"); instanceDisks.add(instanceDisk); instance.setDisks(instanceDisks); List instanceNics = new ArrayList<>(); From 8dedca7b98e0f698b2d4d6b1e3e52c8fc56ce118 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 7 Oct 2019 15:40:32 +0530 Subject: [PATCH 09/61] fix storage pool check Update NIC count for network during import Signed-off-by: Abhishek Kumar --- .../orchestration/NetworkOrchestrator.java | 1 + .../vmware/resource/VmwareResource.java | 2 +- .../cloudstack/vm/VmImportManagerImpl.java | 76 ++++++++++--------- 3 files changed, 41 insertions(+), 38 deletions(-) diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index dfa5b844e400..6dbeb4db9aac 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -3989,6 +3989,7 @@ public NicVO doInTransaction(TransactionStatus status) { return vo; } }); + updateNic(vo, network.getId(), 1); final Integer networkRate = _networkModel.getNetworkRate(network.getId(), vm.getId()); final NicProfile vmNic = new NicProfile(vo, network, vo.getBroadcastUri(), vo.getIsolationUri(), networkRate, _networkModel.isSecurityGroupSupportedInNetwork(network), diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 621eb843f5a7..efb97e6b28f5 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -6843,7 +6843,7 @@ private List getUnmanageInstanceDisks(VirtualMachineMO v instanceDisk.setDatastoreName(dsInfo.getVmfs().getName()); instanceDisk.setDatastoreType(dsInfo.getVmfs().getType()); } else { - String msg = String.format(String.format("Unmanaged instance disk: %s is on unsupported datastore %s", instanceDisk.getDiskId(), info.getClass().getSimpleName())); + String msg = String.format("Unmanaged instance disk: %s is on unsupported datastore %s", instanceDisk.getDiskId(), info.getClass().getSimpleName()); s_logger.error(msg); throw new Exception(msg); } diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 3673eb830963..e1ce4b665659 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -87,6 +87,7 @@ import com.cloud.server.ManagementService; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.storage.Storage; import com.cloud.storage.StoragePool; import com.cloud.storage.VMTemplateStoragePoolVO; import com.cloud.storage.Volume; @@ -425,6 +426,39 @@ private Map getNicIpAddresses(final List pools = primaryDataStoreDao.listPoolsByCluster(cluster.getId()); + for (StoragePool pool : pools) { + if (pool.getPoolType() != Storage.StoragePoolType.VMFS) { + continue; + } + if (pool.getPath().endsWith(dsName)) { + storagePool = pool; + break; + } + } + } else { + List pools = primaryDataStoreDao.listPoolByHostPath(dsHost, dsPath); + for (StoragePool pool : pools) { + if (pool.getDataCenterId() == zone.getId() && + pool.getClusterId() == cluster.getId()) { + storagePool = pool; + break; + } + } + } + return storagePool; + } + private void checkUnmanagedDiskAndOfferingForImport(UnmanagedInstance.Disk disk, DiskOffering diskOffering, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed) throws ServerApiException, PermissionDeniedException, ResourceAllocationException { if (diskOffering == null) { @@ -441,20 +475,9 @@ private void checkUnmanagedDiskAndOfferingForImport(UnmanagedInstance.Disk disk, if (!diskOffering.isCustomized() && diskOffering.getDiskSize() < disk.getCapacity()) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk offering(ID: %s) %dGB is found less than the size of disk(ID: %s) %dGB during VM import!", diskOffering.getUuid(), (diskOffering.getDiskSize() / Resource.ResourceType.bytesToGiB), disk.getDiskId(), (disk.getCapacity() / (Resource.ResourceType.bytesToGiB)))); } - final String dsHost = disk.getDatastoreHost(); - final String dsPath = disk.getDatastorePath(); - final String dsType = disk.getDatastoreType(); - StoragePool storagePool = null; - List pools = primaryDataStoreDao.listPoolByHostPath(dsHost, dsPath); - for (StoragePool pool : pools) { - if (pool.getDataCenterId() == zone.getId() && - pool.getClusterId() == cluster.getId()) { - storagePool = pool; - break; - } - } + StoragePool storagePool = getStoragePool(disk, zone, cluster); if (storagePool == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk ID: %s with host: %s, path: %s, type: %s not found in zone ID: %s, cluster ID: %s!", disk.getDiskId(), dsHost, dsPath, dsType, zone.getUuid(), cluster.getUuid())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk ID: %s with datastore: %s not found in zone ID: %s, cluster ID: %s!", disk.getDiskId(), disk.getDatastoreName(), zone.getUuid(), cluster.getUuid())); } if (!migrateAllowed && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) { throw new InvalidParameterValueException(String.format("Disk offering: %s is not compatible with storage pool: %s of unmanaged disk: %s", diskOffering.getUuid(), storagePool.getUuid(), disk.getDiskId())); @@ -547,31 +570,10 @@ private Pair importDisk(UnmanagedInstance.Disk disk, V diskInfo.setDiskDeviceBusName(String.format("%s%d:%d", disk.getController(), disk.getControllerUnit(), disk.getPosition())); diskInfo.setDiskChain(new String[]{disk.getImagePath()}); final String imagePath = disk.getImagePath(); - final String dsName = disk.getDatastoreName(); - final String dsHost = disk.getDatastoreHost(); - final String dsPath = disk.getDatastorePath(); - final String dsType = disk.getDatastoreType(); - StoragePool storagePool = null; - if (dsType == "VMFS") { - List pools = primaryDataStoreDao.listPoolsByCluster(cluster.getId()); - for (StoragePool pool : pools) { - if (pool.getPath().endsWith(dsName)) { - storagePool = pool; - break; - } - } - } else { - List pools = primaryDataStoreDao.listPoolByHostPath(dsHost, dsPath); - for (StoragePool pool : pools) { - if (pool.getDataCenterId() == vm.getDataCenterId() && - pool.getClusterId() == cluster.getId()) { - storagePool = pool; - break; - } - } - } + final DataCenter zone = dataCenterDao.findById(vm.getDataCenterId()); + StoragePool storagePool = getStoragePool(disk, zone, cluster); if (storagePool == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk ID: %s with host: %s, path: %s, type: %s not found in cluster ID: %s!", disk.getDiskId(), dsHost, dsPath, dsType, cluster.getUuid())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk ID: %s with datastore: %s not found in zone ID: %s, cluster ID: %s!", disk.getDiskId(), disk.getDatastoreName(), zone.getUuid(), cluster.getUuid())); } DiskProfile profile = volumeManager.importVolume(type, name, diskOffering, diskSize, diskOffering.getMinIops(), diskOffering.getMaxIops(), vm, template, owner, deviceId, storagePool.getId(), imagePath, gson.toJson(diskInfo)); From 7e1f2812cd71294737ab4fd006cefc1f2fe3a470 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 7 Oct 2019 18:13:24 +0530 Subject: [PATCH 10/61] fix zone wide storage pool check, controllers details While importing VM volume, zone wide storage pools must also be searched. Disk controllers and NIC adapter type must be copied in VM details from unmanaged vm data. Signed-off-by: Abhishek Kumar --- .../vmware/resource/VmwareResource.java | 13 ++++++- .../cloudstack/vm/VmImportManagerImpl.java | 36 ++++++++++++++++--- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index efb97e6b28f5..42b7a0c77ab3 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -327,8 +327,11 @@ import com.vmware.vim25.VirtualMachineRuntimeInfo; import com.vmware.vim25.VirtualMachineToolsStatus; import com.vmware.vim25.VirtualMachineVideoCard; +import com.vmware.vim25.VirtualPCNet32; import com.vmware.vim25.VirtualSCSIController; import com.vmware.vim25.VirtualUSBController; +import com.vmware.vim25.VirtualVmxnet2; +import com.vmware.vim25.VirtualVmxnet3; import com.vmware.vim25.VmConfigInfo; import com.vmware.vim25.VmConfigSpec; import com.vmware.vim25.VmfsDatastoreInfo; @@ -6902,7 +6905,15 @@ private List getUnmanageInstanceNics(VmwareHypervisorHost s_logger.error(nic.getClass().getCanonicalName() + " " + nic.getBacking().getClass().getCanonicalName() + " " + ethCardDevice.getMacAddress()); UnmanagedInstance.Nic instanceNic = new UnmanagedInstance.Nic(); instanceNic.setNicId(ethCardDevice.getDeviceInfo().getLabel()); - instanceNic.setAdapterType(nic.getClass().getSimpleName()); + if (ethCardDevice instanceof VirtualPCNet32) { + instanceNic.setAdapterType(VirtualEthernetCardType.PCNet32.toString()); + } else if (ethCardDevice instanceof VirtualVmxnet2) { + instanceNic.setAdapterType(VirtualEthernetCardType.Vmxnet2.toString()); + } else if (ethCardDevice instanceof VirtualVmxnet3) { + instanceNic.setAdapterType(VirtualEthernetCardType.Vmxnet3.toString()); + } else { + instanceNic.setAdapterType(VirtualEthernetCardType.E1000.toString()); + } instanceNic.setMacAddress(ethCardDevice.getMacAddress()); instanceNic.setIpAddress(guestNicMacIPAddressMap.get(instanceNic.getMacAddress())); if (ethCardDevice.getSlotInfo() != null) { diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index e1ce4b665659..a973dae8d976 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -428,15 +428,13 @@ private Map getNicIpAddresses(final List pools = primaryDataStoreDao.listPoolsByCluster(cluster.getId()); + pools.addAll(primaryDataStoreDao.listByDataCenterId(zone.getId())); for (StoragePool pool : pools) { if (pool.getPoolType() != Storage.StoragePoolType.VMFS) { continue; @@ -450,12 +448,15 @@ private StoragePool getStoragePool(final UnmanagedInstance.Disk disk, final Data List pools = primaryDataStoreDao.listPoolByHostPath(dsHost, dsPath); for (StoragePool pool : pools) { if (pool.getDataCenterId() == zone.getId() && - pool.getClusterId() == cluster.getId()) { + (pool.getClusterId()==null || pool.getClusterId().equals(cluster.getId()))) { storagePool = pool; break; } } } + if (storagePool == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk %s(%s) with datastore: %s not found in zone ID: %s!", disk.getLabel(), disk.getDiskId(), disk.getDatastoreName(), zone.getUuid())); + } return storagePool; } @@ -486,10 +487,18 @@ private void checkUnmanagedDiskAndOfferingForImport(UnmanagedInstance.Disk disk, private void checkUnmanagedDiskAndOfferingForImport(List disks, final Map diskOfferingMap, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed) throws ServerApiException, PermissionDeniedException, ResourceAllocationException { + String diskController = null; for (UnmanagedInstance.Disk disk : disks) { if (!diskOfferingMap.containsKey(disk.getDiskId())) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID: %s not found during VM import!", disk.getDiskId())); } + if (Strings.isNullOrEmpty(diskController)) { + diskController = disk.getController(); + } else { + if (!diskController.equals(disk.getController())) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple disk controllers (%s, %s) found during VM import!", diskController, disk.getController())); + } + } checkUnmanagedDiskAndOfferingForImport(disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), owner, zone, cluster, migrateAllowed); } } @@ -529,7 +538,15 @@ private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Net private Map getUnmanagedNicNetworkMap(List nics, final Map callerNicNetworkMap, final Map callerNicIpAddressMap, final DataCenter zone, final String hostName, final Account owner) throws ServerApiException { Map nicNetworkMap = new HashMap<>(); + String nicAdapter = null; for (UnmanagedInstance.Nic nic : nics) { + if (Strings.isNullOrEmpty(nicAdapter)) { + nicAdapter = nic.getAdapterType(); + } else { + if (!nicAdapter.equals(nic.getAdapterType())) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple network adapter types (%s, %s) are not supported for import!", nicAdapter, nic.getAdapterType())); + } + } Network network = null; Network.IpAddresses ipAddresses = null; if (MapUtils.isNotEmpty(callerNicIpAddressMap) && callerNicIpAddressMap.containsKey(nic.getNicId())) { @@ -742,12 +759,20 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("No attached disks found for the unmanaged VM: %s", instanceName)); } final UnmanagedInstance.Disk rootDisk = unmanagedInstance.getDisks().get(0); + if (rootDisk == null || Strings.isNullOrEmpty(rootDisk.getController())) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed! Unable to retrieve root disk details for VM: %s ", instanceName)); + } + allDetails.put(VmDetailConstants.ROOT_DISK_CONTROLLER, rootDisk.getController()); List dataDisks = new ArrayList<>(); try { checkUnmanagedDiskAndOfferingForImport(rootDisk, diskOffering, owner, zone, cluster, migrateAllowed); if (unmanagedInstanceDisks.size() > 1) { // Data disk(s) present dataDisks.addAll(unmanagedInstanceDisks); dataDisks.remove(0); + if (dataDisks.get(0) == null || Strings.isNullOrEmpty(dataDisks.get(0).getController())) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed! Unable to retrieve data disk details for VM: %s ", instanceName)); + } + allDetails.put(VmDetailConstants.DATA_DISK_CONTROLLER, dataDisks.get(0).getController()); checkUnmanagedDiskAndOfferingForImport(dataDisks, dataDiskOfferingMap, owner, zone, cluster, migrateAllowed); } resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.volume, unmanagedInstanceDisks.size()); @@ -758,6 +783,9 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns // Check NICs and supplied networks Map nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap); Map allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner); + if (CollectionUtils.isEmpty(unmanagedInstance.getNics())) { + allDetails.put(VmDetailConstants.NIC_ADAPTER, unmanagedInstance.getNics().get(0).getAdapterType()); + } VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff; if (unmanagedInstance.getPowerState().equals(UnmanagedInstance.PowerState.PowerOn)) { powerState = VirtualMachine.PowerState.PowerOn; From 254d31816b4e8ed365cc7d9303bd3027ab92434e Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 9 Oct 2019 00:50:49 +0530 Subject: [PATCH 11/61] fix cpuSpeed for unconstrained offering cpuSpeed param will be honored if cpu reservation is set in VMware. nicAdapter details fix Signed-off-by: Abhishek Kumar --- .../apache/cloudstack/vm/VmImportManagerImpl.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index a973dae8d976..e47396747a63 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -360,25 +360,23 @@ private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedIns throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM is not valid!")); } if (serviceOffering == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering is not valid!", instance.getName())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering is not valid!")); } accountService.checkAccess(owner, serviceOffering, zone); final Integer cpu = instance.getCpuCores(); final Integer memory = instance.getMemory(); - Integer cpuSpeed = instance.getCpuSpeed(); + Integer cpuSpeed = instance.getCpuSpeed() == null ? 0 : instance.getCpuSpeed(); if (cpu == null || cpu == 0) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("CPU cores for VM not valid!", instance.getName())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("CPU cores for VM not valid!")); } if (memory == null || memory == 0) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Memory for VM not valid!", instance.getName())); } if (serviceOffering.isDynamic()) { - if (cpuSpeed == null || cpuSpeed == 0) { + if (details.containsKey(VmDetailConstants.CPU_SPEED)) { try { cpuSpeed = Integer.parseInt(details.get(VmDetailConstants.CPU_SPEED)); - } catch (Exception e) { - cpuSpeed = 0; - } + } catch (Exception e) {} } Map parameters = new HashMap<>(); parameters.put(VmDetailConstants.CPU_NUMBER, String.valueOf(cpu)); @@ -783,7 +781,7 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns // Check NICs and supplied networks Map nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap); Map allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner); - if (CollectionUtils.isEmpty(unmanagedInstance.getNics())) { + if (!CollectionUtils.isEmpty(unmanagedInstance.getNics())) { allDetails.put(VmDetailConstants.NIC_ADAPTER, unmanagedInstance.getNics().get(0).getAdapterType()); } VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff; From bfb850525d0214a584da8208b9a0cf074c86104c Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 9 Oct 2019 01:35:02 +0530 Subject: [PATCH 12/61] fix warnings and refactoring Signed-off-by: Abhishek Kumar --- .../org/apache/cloudstack/vm/VmImportManagerImpl.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index e47396747a63..7b37b230a4f7 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -376,7 +376,8 @@ private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedIns if (details.containsKey(VmDetailConstants.CPU_SPEED)) { try { cpuSpeed = Integer.parseInt(details.get(VmDetailConstants.CPU_SPEED)); - } catch (Exception e) {} + } catch (Exception e) { + } } Map parameters = new HashMap<>(); parameters.put(VmDetailConstants.CPU_NUMBER, String.valueOf(cpu)); @@ -446,7 +447,7 @@ private StoragePool getStoragePool(final UnmanagedInstance.Disk disk, final Data List pools = primaryDataStoreDao.listPoolByHostPath(dsHost, dsPath); for (StoragePool pool : pools) { if (pool.getDataCenterId() == zone.getId() && - (pool.getClusterId()==null || pool.getClusterId().equals(cluster.getId()))) { + (pool.getClusterId() == null || pool.getClusterId().equals(cluster.getId()))) { storagePool = pool; break; } @@ -494,7 +495,7 @@ private void checkUnmanagedDiskAndOfferingForImport(List diskController = disk.getController(); } else { if (!diskController.equals(disk.getController())) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple disk controllers (%s, %s) found during VM import!", diskController, disk.getController())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple disk controllers of different type (%s, %s) are not supported for import. Please make sure that all disk controllers are of the same type!", diskController, disk.getController())); } } checkUnmanagedDiskAndOfferingForImport(disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), owner, zone, cluster, migrateAllowed); @@ -542,7 +543,7 @@ private Map getUnmanagedNicNetworkMap(List nicAdapter = nic.getAdapterType(); } else { if (!nicAdapter.equals(nic.getAdapterType())) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple network adapter types (%s, %s) are not supported for import!", nicAdapter, nic.getAdapterType())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple network adapter of different type (%s, %s) are not supported for import. Please make sure that all network adapters are of the same type!", nicAdapter, nic.getAdapterType())); } } Network network = null; From 52d414898f6b162116544c075c2bb04151c71347 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 9 Oct 2019 03:48:58 +0530 Subject: [PATCH 13/61] fixes Check for disk controller across disks Filter destroyed VMs Fix list unmanaged VM details Signed-off-by: Abhishek Kumar --- .../java/com/cloud/vm/dao/VMInstanceDao.java | 2 ++ .../com/cloud/vm/dao/VMInstanceDaoImpl.java | 8 +++++++ .../vmware/resource/VmwareResource.java | 2 +- .../cloudstack/vm/VmImportManagerImpl.java | 21 +++++++------------ .../vm/VmImportManagerImplTest.java | 2 +- 5 files changed, 20 insertions(+), 15 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java index ce4d46abc250..04b1771be6eb 100755 --- a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDao.java @@ -100,6 +100,8 @@ public interface VMInstanceDao extends GenericDao, StateDao< List listByLastHostId(Long hostId); + List listByLastHostIdAndStates(Long hostId, State... states); + List listByTypeAndState(VirtualMachine.Type type, State state); List listByAccountId(long accountId); diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java index 405e023f10a0..24099bfd5035 100755 --- a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -560,6 +560,14 @@ public List listByLastHostId(Long hostId) { return listBy(sc); } + @Override + public List listByLastHostIdAndStates(Long hostId, State... states) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("lastHost", hostId); + sc.setParameters("state", (Object[])states); + return listBy(sc); + } + @Override public List findIdsOfAllocatedVirtualRoutersForAccount(long accountId) { SearchCriteria sc = FindIdsOfVirtualRoutersByAccount.create(); diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 42b7a0c77ab3..aec320157c3c 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -6820,7 +6820,7 @@ private List getUnmanageInstanceDisks(VirtualMachineMO v instanceDisk.setController(DiskControllerType.getType(device.getClass().getSimpleName()).toString()); instanceDisk.setControllerUnit(((VirtualIDEController) device).getBusNumber()); } else if (device instanceof VirtualSCSIController) { - instanceDisk.setController("scsi"); + instanceDisk.setController(DiskControllerType.getType(device.getClass().getSimpleName()).toString()); instanceDisk.setControllerUnit(((VirtualSCSIController) device).getBusNumber()); } else { instanceDisk.setController(DiskControllerType.none.toString()); diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 7b37b230a4f7..61d5ca4d7fb0 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -313,7 +313,10 @@ private List getHostManagedVms(Host host) { for (VMInstanceVO instance : instances) { managedVms.add(instance.getInstanceName()); } - instances = vmDao.listByLastHostId(host.getId()); + instances = vmDao.listByLastHostIdAndStates(host.getId(), + VirtualMachine.State.Stopped, VirtualMachine.State.Destroyed, + VirtualMachine.State.Expunging, VirtualMachine.State.Error, + VirtualMachine.State.Unknown, VirtualMachine.State.Shutdowned); for (VMInstanceVO instance : instances) { managedVms.add(instance.getInstanceName()); } @@ -484,19 +487,14 @@ private void checkUnmanagedDiskAndOfferingForImport(UnmanagedInstance.Disk disk, } } - private void checkUnmanagedDiskAndOfferingForImport(List disks, final Map diskOfferingMap, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed) + private void checkUnmanagedDiskAndOfferingForImport(List disks, final Map diskOfferingMap, final String diskController, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed) throws ServerApiException, PermissionDeniedException, ResourceAllocationException { - String diskController = null; for (UnmanagedInstance.Disk disk : disks) { if (!diskOfferingMap.containsKey(disk.getDiskId())) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID: %s not found during VM import!", disk.getDiskId())); } - if (Strings.isNullOrEmpty(diskController)) { - diskController = disk.getController(); - } else { - if (!diskController.equals(disk.getController())) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple disk controllers of different type (%s, %s) are not supported for import. Please make sure that all disk controllers are of the same type!", diskController, disk.getController())); - } + if (!Strings.isNullOrEmpty(diskController) && !diskController.equals(disk.getController())) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple disk controllers of different type (%s, %s) are not supported for import. Please make sure that all disk controllers are of the same type!", diskController, disk.getController())); } checkUnmanagedDiskAndOfferingForImport(disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), owner, zone, cluster, migrateAllowed); } @@ -768,11 +766,8 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns if (unmanagedInstanceDisks.size() > 1) { // Data disk(s) present dataDisks.addAll(unmanagedInstanceDisks); dataDisks.remove(0); - if (dataDisks.get(0) == null || Strings.isNullOrEmpty(dataDisks.get(0).getController())) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed! Unable to retrieve data disk details for VM: %s ", instanceName)); - } + checkUnmanagedDiskAndOfferingForImport(dataDisks, dataDiskOfferingMap, rootDisk.getController(), owner, zone, cluster, migrateAllowed); allDetails.put(VmDetailConstants.DATA_DISK_CONTROLLER, dataDisks.get(0).getController()); - checkUnmanagedDiskAndOfferingForImport(dataDisks, dataDiskOfferingMap, owner, zone, cluster, migrateAllowed); } resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.volume, unmanagedInstanceDisks.size()); } catch (ResourceAllocationException e) { diff --git a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java index e4111d481850..3941577f545c 100644 --- a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java @@ -195,7 +195,7 @@ public void setUp() throws Exception { when(volumeDao.findIncludingRemovedByZone(Mockito.anyLong())).thenReturn(volumes); List vms = new ArrayList<>(); when(vmDao.listByHostId(Mockito.anyLong())).thenReturn(vms); - when(vmDao.listByLastHostId(Mockito.anyLong())).thenReturn(vms); + when(vmDao.listByLastHostIdAndStates(Mockito.anyLong())).thenReturn(vms); GetUnmanagedInstancesCommand cmd = Mockito.mock(GetUnmanagedInstancesCommand.class); HashMap map = new HashMap<>(); map.put(instance.getName(), instance); From b2780a3d8effebdfaced10b56f9ef92980d91e24 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 9 Oct 2019 12:54:06 +0530 Subject: [PATCH 14/61] fix VM states search, host maintenance Signed-off-by: Abhishek Kumar --- .../main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java | 10 ++++++++-- .../org/apache/cloudstack/vm/VmImportManagerImpl.java | 3 +++ .../apache/cloudstack/vm/VmImportManagerImplTest.java | 3 ++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java index 24099bfd5035..e2d174cf7afd 100755 --- a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -94,6 +94,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem protected SearchBuilder HostAndStateSearch; protected SearchBuilder StartingWithNoHostSearch; protected SearchBuilder NotMigratingSearch; + protected SearchBuilder LastHostAndStatesSearch; @Inject ResourceTagDao _tagsDao; @@ -286,6 +287,11 @@ protected void init() { NotMigratingSearch.and("lastHost", NotMigratingSearch.entity().getLastHostId(), Op.EQ); NotMigratingSearch.and("state", NotMigratingSearch.entity().getState(), Op.NEQ); NotMigratingSearch.done(); + + LastHostAndStatesSearch = createSearchBuilder(); + LastHostAndStatesSearch.and("lastHost", LastHostAndStatesSearch.entity().getLastHostId(), Op.EQ); + LastHostAndStatesSearch.and("states", LastHostAndStatesSearch.entity().getState(), Op.IN); + LastHostAndStatesSearch.done(); } @Override @@ -562,9 +568,9 @@ public List listByLastHostId(Long hostId) { @Override public List listByLastHostIdAndStates(Long hostId, State... states) { - SearchCriteria sc = AllFieldsSearch.create(); + SearchCriteria sc = LastHostAndStatesSearch.create(); sc.setParameters("lastHost", hostId); - sc.setParameters("state", (Object[])states); + sc.setParameters("states", (Object[])states); return listBy(sc); } diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 61d5ca4d7fb0..81472182c9a6 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -863,6 +863,9 @@ public ListResponse listUnmanagedInstances(ListUnmana List additionalNameFilters = getAdditionalNameFilters(cluster); List responses = new ArrayList<>(); for (HostVO host : hosts) { + if (host.isInMaintenanceStates()) { + continue; + } List managedVms = new ArrayList<>(); managedVms.addAll(additionalNameFilters); managedVms.addAll(getHostManagedVms(host)); diff --git a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java index 3941577f545c..510b8cc7c755 100644 --- a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java @@ -187,7 +187,8 @@ public void setUp() throws Exception { doNothing().when(resourceLimitService).checkResourceLimit(any(Account.class), any(Resource.ResourceType.class), anyLong()); List hosts = new ArrayList<>(); HostVO hostVO = Mockito.mock(HostVO.class); - hosts.add(hostVO);; + when(hostVO.isInMaintenanceStates()).thenReturn(false); + hosts.add(hostVO); when(resourceManager.listHostsInClusterByStatus(Mockito.anyLong(), Mockito.any(Status.class))).thenReturn(hosts); List templates = new ArrayList<>(); when(templatePoolDao.listAll()).thenReturn(templates); From 96db5737d200da6d288e0cca6c8bc23a23dc4863 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 9 Oct 2019 12:54:33 +0530 Subject: [PATCH 15/61] fix nic, ipaddress assignment Signed-off-by: Abhishek Kumar --- .../admin/vm/ImportUnmanagedInstanceCmd.java | 14 ++-- .../cloudstack/vm/UnmanagedInstance.java | 6 +- .../service/NetworkOrchestrationService.java | 2 +- .../orchestration/NetworkOrchestrator.java | 54 ++++++++----- .../vmware/resource/VmwareResource.java | 8 +- .../cloudstack/vm/VmImportManagerImpl.java | 75 ++++++++++++------- 6 files changed, 100 insertions(+), 59 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java index bb2eacd41933..54fd5fe9d8ed 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java @@ -231,18 +231,20 @@ public Map getNicIpAddressList() { throw new InvalidParameterValueException(String.format("NIC ID: '%s' is invalid for IP address mapping", nic)); } if (Strings.isNullOrEmpty(ipAddress) && Strings.isNullOrEmpty(ip6Address)) { - throw new InvalidParameterValueException(String.format("IP addresses for NIC ID: %s is invalid", ipAddress, nic)); + throw new InvalidParameterValueException(String.format("IP addresses for NIC ID: %s is invalid", nic)); + } + if (!Strings.isNullOrEmpty(ipAddress) && !Strings.isNullOrEmpty(ip6Address)) { + throw new InvalidParameterValueException(String.format("Multiple IP addresses(%s, %s) for NIC ID: %s cannot be assigned automatically", ipAddress, ip6Address, nic)); } if (!Strings.isNullOrEmpty(ipAddress)) { if (!ipAddress.equals("auto") && !NetUtils.isValidIp4(ipAddress)) { throw new InvalidParameterValueException(String.format("IP v4 address '%s' for NIC ID: %s is invalid", ipAddress, nic)); } - if (ipAddress.equals("auto")) { - ipAddress = null; - } } - if (!Strings.isNullOrEmpty(ip6Address) && !NetUtils.isValidIp6(ip6Address)) { - throw new InvalidParameterValueException(String.format("IP v6 address '%s' for NIC ID: %s is invalid", ip6Address, nic)); + if (!Strings.isNullOrEmpty(ip6Address)) { + if (!ip6Address.equals("auto") && !NetUtils.isValidIp6(ip6Address)) { + throw new InvalidParameterValueException(String.format("IP v6 address '%s' for NIC ID: %s is invalid", ip6Address, nic)); + } } Network.IpAddresses ipAddresses = new Network.IpAddresses(ipAddress, ip6Address); nicIpAddressMap.put(nic, ipAddresses); diff --git a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java index 121a7041cac1..45a7a7b1eefa 100644 --- a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java +++ b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java @@ -240,7 +240,7 @@ public static class Nic { private Integer vlan; - private String ipAddress; + private List ipAddress; private String pciSlot; @@ -284,11 +284,11 @@ public void setVlan(Integer vlan) { this.vlan = vlan; } - public String getIpAddress() { + public List getIpAddress() { return ipAddress; } - public void setIpAddress(String ipAddress) { + public void setIpAddress(List ipAddress) { this.ipAddress = ipAddress; } diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java index 800f37080954..b111a86c930b 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java @@ -315,5 +315,5 @@ void implementNetworkElementsAndResources(DeployDestination dest, ReservationCon */ void cleanupNicDhcpDnsEntry(Network network, VirtualMachineProfile vmProfile, NicProfile nicProfile); - Pair importNic(final String macAddress, int deviceId, final Network network, final Boolean isDefaultNic, final VirtualMachine vm, final Network.IpAddresses ipAddresses) throws InsufficientVirtualNetworkCapacityException; + Pair importNic(final String macAddress, int deviceId, final Network network, final Boolean isDefaultNic, final VirtualMachine vm, final Network.IpAddresses ipAddresses) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException; } diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index 6dbeb4db9aac..212270af6c2d 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -97,6 +97,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.IpAddress; import com.cloud.network.IpAddressManager; +import com.cloud.network.Ipv6AddressManager; import com.cloud.network.Network; import com.cloud.network.Network.Capability; import com.cloud.network.Network.Event; @@ -286,6 +287,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra RemoteAccessVpnDao _remoteAccessVpnDao; @Inject VpcVirtualNetworkApplianceService _routerService; + @Inject + protected Ipv6AddressManager ipv6AddressManager; List networkGurus; @@ -3944,37 +3947,48 @@ public NicVO savePlaceholderNic(final Network network, final String ip4Address, @DB @Override public Pair importNic(final String macAddress, int deviceId, final Network network, final Boolean isDefaultNic, final VirtualMachine vm, final Network.IpAddresses ipAddresses) - throws ConcurrentOperationException, InsufficientVirtualNetworkCapacityException { + throws ConcurrentOperationException, InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException { s_logger.debug("Allocating nic for vm " + vm.getUuid() + " in network " + network + " during import"); + String guestIp = null; if (ipAddresses != null) { - // Auto assign ip4 - String guestIp = _ipAddrMgr.acquireGuestIpAddress(network, ipAddresses.getIp4Address()); - if (guestIp == null && network.getGuestType() != GuestType.L2 && !_networkModel.listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) { - throw new InsufficientVirtualNetworkCapacityException("Unable to acquire Guest IP" + " address for network " + network, DataCenter.class, - network.getDataCenterId()); + // Assign ip + if (!Strings.isNullOrEmpty(ipAddresses.getIp4Address())) { + if (ipAddresses.getIp4Address().equals("auto")) { + ipAddresses.setIp4Address(null); + } + guestIp = _ipAddrMgr.acquireGuestIpAddress(network, ipAddresses.getIp4Address()); + if (guestIp == null && network.getGuestType() != GuestType.L2 && !_networkModel.listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) { + throw new InsufficientVirtualNetworkCapacityException("Unable to acquire Guest IP address for network " + network, DataCenter.class, + network.getDataCenterId()); + } + } else if (!Strings.isNullOrEmpty(ipAddresses.getIp6Address())) { + guestIp = ipv6AddressManager.acquireGuestIpv6Address(network, ipAddresses.getIp6Address()); + if (guestIp == null && network.getGuestType() != GuestType.Shared && !_networkModel.listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) { + throw new InsufficientVirtualNetworkCapacityException("Unable to acquire Guest IP v6 address for network " + network, DataCenter.class, + network.getDataCenterId()); + } } } + final String finalGuestIp = guestIp; NicVO vo = Transaction.execute(new TransactionCallback() { @Override public NicVO doInTransaction(TransactionStatus status) { NicVO vo = new NicVO(network.getGuruName(), vm.getId(), network.getId(), vm.getType()); vo.setMacAddress(macAddress); vo.setAddressFormat(Networks.AddressFormat.Ip4); - if (ipAddresses != null) { - if (!Strings.isNullOrEmpty(ipAddresses.getIp4Address()) && !Strings.isNullOrEmpty(network.getGateway())) { - vo.setIPv4Address(ipAddresses.getIp4Address()); - vo.setIPv4Gateway(network.getGateway()); - if (!Strings.isNullOrEmpty(network.getCidr())) { - vo.setIPv4Netmask(NetUtils.cidr2Netmask(network.getCidr())); - } + if (NetUtils.isValidIp4(finalGuestIp) && !Strings.isNullOrEmpty(network.getGateway())) { + vo.setIPv4Address(finalGuestIp); + vo.setIPv4Gateway(network.getGateway()); + if (!Strings.isNullOrEmpty(network.getCidr())) { + vo.setIPv4Netmask(NetUtils.cidr2Netmask(network.getCidr())); } - if (!Strings.isNullOrEmpty(ipAddresses.getIp6Address()) && !Strings.isNullOrEmpty(network.getIp6Gateway())) { - vo.setAddressFormat(Networks.AddressFormat.Ip6); - vo.setIPv6Address(ipAddresses.getIp6Address()); - vo.setIPv6Gateway(network.getIp6Gateway()); - if (!Strings.isNullOrEmpty(network.getIp6Cidr())) { - vo.setIPv6Cidr(NetUtils.cidr2Netmask(network.getCidr())); - } + } + if (NetUtils.isValidIp6(finalGuestIp) && !Strings.isNullOrEmpty(network.getIp6Gateway())) { + vo.setAddressFormat(Networks.AddressFormat.Ip6); + vo.setIPv6Address(finalGuestIp); + vo.setIPv6Gateway(network.getIp6Gateway()); + if (!Strings.isNullOrEmpty(network.getIp6Cidr())) { + vo.setIPv6Cidr(NetUtils.cidr2Netmask(network.getCidr())); } } vo.setBroadcastUri(network.getBroadcastUri()); diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index aec320157c3c..c006bc237044 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -6877,13 +6877,13 @@ int extractInt(UnmanagedInstance.Disk disk) { private List getUnmanageInstanceNics(VmwareHypervisorHost hyperHost, VirtualMachineMO vmMo) { List instanceNics = new ArrayList<>(); - HashMap guestNicMacIPAddressMap = new HashMap<>(); + HashMap> guestNicMacIPAddressMap = new HashMap<>(); try { GuestInfo guestInfo = vmMo.getGuestInfo(); if (guestInfo.getToolsStatus() == VirtualMachineToolsStatus.TOOLS_OK) { for (GuestNicInfo nicInfo: guestInfo.getNet()) { if (!nicInfo.getIpAddress().isEmpty()) { - guestNicMacIPAddressMap.put(nicInfo.getMacAddress(), nicInfo.getIpAddress().get(0)); + guestNicMacIPAddressMap.put(nicInfo.getMacAddress(), nicInfo.getIpAddress()); } } } else { @@ -6915,7 +6915,9 @@ private List getUnmanageInstanceNics(VmwareHypervisorHost instanceNic.setAdapterType(VirtualEthernetCardType.E1000.toString()); } instanceNic.setMacAddress(ethCardDevice.getMacAddress()); - instanceNic.setIpAddress(guestNicMacIPAddressMap.get(instanceNic.getMacAddress())); + if (guestNicMacIPAddressMap.containsKey(instanceNic.getMacAddress())) { + instanceNic.setIpAddress(guestNicMacIPAddressMap.get(instanceNic.getMacAddress())); + } if (ethCardDevice.getSlotInfo() != null) { instanceNic.setPciSlot(ethCardDevice.getSlotInfo().toString()); } diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 81472182c9a6..21e20d33e544 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -64,6 +64,7 @@ import com.cloud.deploy.DeploymentPlanningManager; import com.cloud.event.EventTypes; import com.cloud.event.UsageEventUtils; +import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InsufficientVirtualNetworkCapacityException; import com.cloud.exception.InvalidParameterValueException; @@ -232,8 +233,15 @@ private UnmanagedInstanceResponse createUnmanagedInstanceResponse(UnmanagedInsta if (!Strings.isNullOrEmpty(nic.getAdapterType())) { nicResponse.setAdapterType(nic.getAdapterType()); } - if (!Strings.isNullOrEmpty(nic.getIpAddress())) { - nicResponse.setIpaddress(nic.getIpAddress()); + if (!CollectionUtils.isEmpty(nic.getIpAddress())) { + for (String address : nic.getIpAddress()) { + if (Strings.isNullOrEmpty(nicResponse.getIpaddress()) && NetUtils.isValidIp4(address)) { + nicResponse.setIpaddress(address); + } + if (Strings.isNullOrEmpty(nicResponse.getIp6Address()) && NetUtils.isValidIp6(address)) { + nicResponse.setIp6Address(address); + } + } } nicResponse.setVlanId(nic.getVlan()); response.addNic(nicResponse); @@ -414,12 +422,22 @@ private Map getNicIpAddresses(final List 1) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple IP addresses (%s, %s) present for nic ID: %s cannot be imported automatically!", nic.getIpAddress().get(0), nic.getIpAddress().get(1), nic.getNicId())); + } + if (ipAddresses == null || (Strings.isNullOrEmpty(ipAddresses.getIp4Address()) && Strings.isNullOrEmpty(ipAddresses.getIp4Address()))) { + if (ipAddresses == null) { + ipAddresses = new Network.IpAddresses(null, null); + } + String address = nic.getIpAddress().get(0); + if (NetUtils.isValidIp4(address)) { + ipAddresses.setIp4Address(address); + } + if (NetUtils.isValidIp6(address)) { + ipAddresses.setIp6Address(address); + } } - ipAddresses.setIp4Address(nic.getIpAddress()); } if (ipAddresses != null) { nicIpAddresses.put(nic.getNicId(), ipAddresses); @@ -511,18 +529,31 @@ private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Net if (nic.getVlan() != null && (Strings.isNullOrEmpty(network.getBroadcastUri().toString()) || !network.getBroadcastUri().toString().equals(String.format("vlan://%d", nic.getVlan())))) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VLAN of network(ID: %s) %s is found different from the VLAN of nic(ID: %s) vlan://%d during VM import!", network.getUuid(), network.getBroadcastUri().toString(), nic.getNicId(), nic.getVlan())); } - if (!network.getGuestType().equals(Network.GuestType.L2)) { - if (ipAddresses == null) { // No IP address was provided by API and NIC details don't have one - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC(ID: %s) needs a valid IP address for it to be associated with network(ID: %s)! %s parameter of API can be used for this.", nic.getNicId(), network.getUuid(), ApiConstants.NIC_IP_ADDRESS_LIST)); + // Check IP is assigned for non L2 networks + if (!network.getGuestType().equals(Network.GuestType.L2) && (ipAddresses == null || (Strings.isNullOrEmpty(ipAddresses.getIp4Address()) && Strings.isNullOrEmpty(ipAddresses.getIp6Address())))) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC(ID: %s) needs a valid IP address for it to be associated with network(ID: %s)! %s parameter of API can be used for this.", nic.getNicId(), network.getUuid(), ApiConstants.NIC_IP_ADDRESS_LIST)); + } + // Check both IP v4 and v6 are not assigned at the same time + if (ipAddresses != null && !Strings.isNullOrEmpty(ipAddresses.getIp4Address()) && !Strings.isNullOrEmpty(ipAddresses.getIp6Address())) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple IP addresses(%s, %s) for NIC ID: %s cannot be assigned automatically", ipAddresses.getIp4Address(), ipAddresses.getIp6Address(), nic.getNicId())); + } + // If IP v4 is assigned and not set to auto check it is available for network + if (ipAddresses != null && !Strings.isNullOrEmpty(ipAddresses.getIp4Address()) && !ipAddresses.getIp4Address().equals("auto")) { + Set ips = networkModel.getAvailableIps(network, ipAddresses.getIp4Address()); + if (CollectionUtils.isEmpty(ips) || !ips.contains(NetUtils.ip2Long(ipAddresses.getIp4Address()))) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("IP address %s for NIC(ID: %s) is not available in network(ID: %s)!", nic.getNicId(), network.getUuid(), ApiConstants.NIC_IP_ADDRESS_LIST)); } - if (Strings.isNullOrEmpty(ipAddresses.getIp4Address()) || Strings.isNullOrEmpty(ipAddresses.getIp6Address())) { - networkModel.checkRequestedIpAddresses(network.getId(), ipAddresses); // This only checks ipv6 + } + // If IP v6 is assigned check network is Shared, supports IPv6 and if IP not set to auto check if available + if (ipAddresses != null && !Strings.isNullOrEmpty(ipAddresses.getIp6Address())) { + if (!network.getGuestType().equals(Network.GuestType.Shared)) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("IP v6 addressing %s for NIC(ID: %s) is not supported for in network(ID: %s), type: %s!", ipAddresses.getIp6Address(), nic.getNicId(), network.getUuid(), network.getGuestType())); } - if (Strings.isNullOrEmpty(ipAddresses.getIp4Address())) { - Set ips = networkModel.getAvailableIps(network, ipAddresses.getIp4Address()); - if (CollectionUtils.isEmpty(ips)) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("IP address %s for NIC(ID: %s) is not available in network(ID: %s)!", nic.getNicId(), network.getUuid(), ApiConstants.NIC_IP_ADDRESS_LIST)); - } + if (Strings.isNullOrEmpty(network.getIp6Gateway())) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network(ID: %s) assigned to NIC(ID: %s) is not configured for IP v6 addressing!", network.getUuid(), nic.getNicId())); + } + if (!ipAddresses.getIp6Address().equals("auto")) { + networkModel.checkRequestedIpAddresses(network.getId(), ipAddresses); } } // Check for duplicate hostname in network, get all vms hostNames in the network @@ -595,7 +626,7 @@ private Pair importDisk(UnmanagedInstance.Disk disk, V return new Pair(profile, storagePool); } - private NicProfile importNic(UnmanagedInstance.Nic nic, VirtualMachine vm, Network network, Network.IpAddresses ipAddresses, boolean isDefaultNic) throws InsufficientVirtualNetworkCapacityException { + private NicProfile importNic(UnmanagedInstance.Nic nic, VirtualMachine vm, Network network, Network.IpAddresses ipAddresses, boolean isDefaultNic) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException { Pair result = networkOrchestrationService.importNic(nic.getMacAddress(), 0, network, isDefaultNic, vm, ipAddresses); if (result == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC ID: %s import failed!", nic.getNicId())); @@ -819,14 +850,6 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns for (UnmanagedInstance.Nic nic : unmanagedInstance.getNics()) { Network network = networkDao.findById(allNicNetworkMap.get(nic.getNicId())); Network.IpAddresses ipAddresses = nicIpAddressMap.get(nic.getNicId()); - if (ipAddresses == null || (Strings.isNullOrEmpty(ipAddresses.getIp4Address()) && Strings.isNullOrEmpty(ipAddresses.getIp6Address()))) { - if (ipAddresses == null) { - ipAddresses = new Network.IpAddresses(null, null); - } - if (!Strings.isNullOrEmpty(nic.getIpAddress())) { - ipAddresses.setIp4Address(nic.getIpAddress()); - } - } importNic(nic, userVm, network, ipAddresses, firstNic); firstNic = false; } From 1c483ecf33d8d1559206972400ed6c9f05638a60 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 9 Oct 2019 13:01:21 +0530 Subject: [PATCH 16/61] fix host maintenance while import Signed-off-by: Abhishek Kumar --- .../java/org/apache/cloudstack/vm/VmImportManagerImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 21e20d33e544..d18bab5ff580 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -1005,6 +1005,9 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { UserVm userVm = null; List additionalNameFilters = getAdditionalNameFilters(cluster); for (HostVO host : hosts) { + if (host.isInMaintenanceStates()) { + continue; + } List managedVms = new ArrayList<>(); managedVms.addAll(additionalNameFilters); managedVms.addAll(getHostManagedVms(host)); From dda4a171a9a8c1cc01065d4436939351ed3790d7 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 9 Oct 2019 13:48:11 +0530 Subject: [PATCH 17/61] fix Ip assignment, error message Signed-off-by: Abhishek Kumar --- .../admin/vm/ImportUnmanagedInstanceCmd.java | 2 +- .../engine/orchestration/NetworkOrchestrator.java | 15 +++++++++++++-- .../apache/cloudstack/vm/VmImportManagerImpl.java | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java index 54fd5fe9d8ed..cdb7162ee7e7 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java @@ -143,7 +143,7 @@ public class ImportUnmanagedInstanceCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.NIC_IP_ADDRESS_LIST, type = CommandType.MAP, - description = "VM nic to ip address mapping using keys nic and ipAddress") + description = "VM nic to ip address mapping using keys nic, ipAddress, ip6Address") private Map nicIpAddressList; @Parameter(name = ApiConstants.DATADISK_OFFERING_LIST, diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index 212270af6c2d..256ff38b46a9 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -3956,13 +3956,24 @@ public Pair importNic(final String macAddress, int deviceId if (ipAddresses.getIp4Address().equals("auto")) { ipAddresses.setIp4Address(null); } - guestIp = _ipAddrMgr.acquireGuestIpAddress(network, ipAddresses.getIp4Address()); + if (network.getGuestType() != GuestType.L2) { + guestIp = _ipAddrMgr.acquireGuestIpAddress(network, ipAddresses.getIp4Address()); + } else { + guestIp = ipAddresses.getIp4Address(); + } if (guestIp == null && network.getGuestType() != GuestType.L2 && !_networkModel.listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) { throw new InsufficientVirtualNetworkCapacityException("Unable to acquire Guest IP address for network " + network, DataCenter.class, network.getDataCenterId()); } } else if (!Strings.isNullOrEmpty(ipAddresses.getIp6Address())) { - guestIp = ipv6AddressManager.acquireGuestIpv6Address(network, ipAddresses.getIp6Address()); + if (ipAddresses.getIp6Address().equals("auto")) { + ipAddresses.setIp6Address(null); + } + if (network.getGuestType() != GuestType.L2) { + guestIp = ipv6AddressManager.acquireGuestIpv6Address(network, ipAddresses.getIp6Address()); + } else { + guestIp = ipAddresses.getIp6Address(); + } if (guestIp == null && network.getGuestType() != GuestType.Shared && !_networkModel.listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) { throw new InsufficientVirtualNetworkCapacityException("Unable to acquire Guest IP v6 address for network " + network, DataCenter.class, network.getDataCenterId()); diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index d18bab5ff580..fa7a90c6e69a 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -541,7 +541,7 @@ private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Net if (ipAddresses != null && !Strings.isNullOrEmpty(ipAddresses.getIp4Address()) && !ipAddresses.getIp4Address().equals("auto")) { Set ips = networkModel.getAvailableIps(network, ipAddresses.getIp4Address()); if (CollectionUtils.isEmpty(ips) || !ips.contains(NetUtils.ip2Long(ipAddresses.getIp4Address()))) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("IP address %s for NIC(ID: %s) is not available in network(ID: %s)!", nic.getNicId(), network.getUuid(), ApiConstants.NIC_IP_ADDRESS_LIST)); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("IP address %s for NIC(ID: %s) is not available in network(ID: %s)!", ipAddresses.getIp4Address(), nic.getNicId(), network.getUuid())); } } // If IP v6 is assigned check network is Shared, supports IPv6 and if IP not set to auto check if available From 51b1ef997330b999661f386dbe9e53c5d3f830de Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 9 Oct 2019 14:41:06 +0530 Subject: [PATCH 18/61] fix disk controller check Signed-off-by: Abhishek Kumar --- .../cloudstack/vm/VmImportManagerImpl.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index fa7a90c6e69a..d9fc1f548fd6 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -505,14 +505,22 @@ private void checkUnmanagedDiskAndOfferingForImport(UnmanagedInstance.Disk disk, } } - private void checkUnmanagedDiskAndOfferingForImport(List disks, final Map diskOfferingMap, final String diskController, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed) + private void checkUnmanagedDiskAndOfferingForImport(List disks, final Map diskOfferingMap, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed) throws ServerApiException, PermissionDeniedException, ResourceAllocationException { + String diskController = null; for (UnmanagedInstance.Disk disk : disks) { + if (disk == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve disk details for VM!")); + } if (!diskOfferingMap.containsKey(disk.getDiskId())) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID: %s not found during VM import!", disk.getDiskId())); } - if (!Strings.isNullOrEmpty(diskController) && !diskController.equals(disk.getController())) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple disk controllers of different type (%s, %s) are not supported for import. Please make sure that all disk controllers are of the same type!", diskController, disk.getController())); + if (Strings.isNullOrEmpty(diskController)) { + diskController = disk.getController(); + } else { + if(!diskController.equals(disk.getController())) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple disk controllers of different type (%s, %s) are not supported for import. Please make sure that all disk controllers are of the same type!", diskController, disk.getController())); + } } checkUnmanagedDiskAndOfferingForImport(disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), owner, zone, cluster, migrateAllowed); } @@ -797,7 +805,7 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns if (unmanagedInstanceDisks.size() > 1) { // Data disk(s) present dataDisks.addAll(unmanagedInstanceDisks); dataDisks.remove(0); - checkUnmanagedDiskAndOfferingForImport(dataDisks, dataDiskOfferingMap, rootDisk.getController(), owner, zone, cluster, migrateAllowed); + checkUnmanagedDiskAndOfferingForImport(dataDisks, dataDiskOfferingMap, owner, zone, cluster, migrateAllowed); allDetails.put(VmDetailConstants.DATA_DISK_CONTROLLER, dataDisks.get(0).getController()); } resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.volume, unmanagedInstanceDisks.size()); From bbd6589aebb6cf3deb3cdc26ffc33ad7183bfd88 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 10 Oct 2019 09:14:49 +0530 Subject: [PATCH 19/61] fix script error Signed-off-by: Abhishek Kumar --- scripts/vm/hypervisor/vmware/discover_networks.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/scripts/vm/hypervisor/vmware/discover_networks.py b/scripts/vm/hypervisor/vmware/discover_networks.py index 6a7eeb2e5166..be95afe90f84 100755 --- a/scripts/vm/hypervisor/vmware/discover_networks.py +++ b/scripts/vm/hypervisor/vmware/discover_networks.py @@ -157,8 +157,15 @@ def add_network(portGroup, vlanId, vSwitch, vmName, vmDeviceLabel, vmMacAddress) networksDict[key] = network else: vms = [vm] - host = pgHostNameDict[portGroup] - cluster = hostClusterNameDict[host] + try: + host = pgHostNameDict[portGroup] + except KeyError: + host = '' + try: + cluster = hostClusterNameDict[host] + except KeyError: + cluster = '' + network = {"portgroup": portGroup, "cluster": cluster, "host": host, "vlanid": vlanId, "switch": vSwitch, "virtualmachines": vms} networksDict[key] = network From 3454a7bf41599057bad82485265fa3dbdb7171cf Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 10 Oct 2019 10:50:09 +0530 Subject: [PATCH 20/61] fix network vlan error Signed-off-by: Abhishek Kumar --- scripts/vm/hypervisor/vmware/discover_networks.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/vm/hypervisor/vmware/discover_networks.py b/scripts/vm/hypervisor/vmware/discover_networks.py index be95afe90f84..09761f3b251b 100755 --- a/scripts/vm/hypervisor/vmware/discover_networks.py +++ b/scripts/vm/hypervisor/vmware/discover_networks.py @@ -123,7 +123,10 @@ def get_vm_nics(vm, hostPgDict): else: pgObj = dvs.LookupDvPortGroup(portGroupKey) portGroup = pgObj.config.name - vlanId = str(pgObj.config.defaultPortConfig.vlan.vlanId) + try: + vlanId = str(pgObj.config.defaultPortConfig.vlan.vlanId) + except AttributeError: + vlanId = '0' vSwitch = str(dvs.name) else: portGroup = dev.backing.network.name From fbbf975d2470110203ba7f26a261209887220e20 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 10 Oct 2019 10:52:05 +0530 Subject: [PATCH 21/61] fix auto assign network message Signed-off-by: Abhishek Kumar --- .../cloudstack/vm/VmImportManagerImpl.java | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index d9fc1f548fd6..e1297cbe3921 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -526,7 +526,10 @@ private void checkUnmanagedDiskAndOfferingForImport(List } } - private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Network network, final Network.IpAddresses ipAddresses, final DataCenter zone, final String hostName, final Account owner) throws ServerApiException { + private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Network network, final DataCenter zone, final String hostName, final Account owner) throws ServerApiException { + if (nic == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import!", nic.getNicId())); + } if (network == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import!", nic.getNicId())); } @@ -537,6 +540,21 @@ private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Net if (nic.getVlan() != null && (Strings.isNullOrEmpty(network.getBroadcastUri().toString()) || !network.getBroadcastUri().toString().equals(String.format("vlan://%d", nic.getVlan())))) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VLAN of network(ID: %s) %s is found different from the VLAN of nic(ID: %s) vlan://%d during VM import!", network.getUuid(), network.getBroadcastUri().toString(), nic.getNicId(), nic.getVlan())); } + // Check for duplicate hostname in network, get all vms hostNames in the network + List hostNames = vmDao.listDistinctHostNames(network.getId()); + if (CollectionUtils.isNotEmpty(hostNames) && hostNames.contains(hostName)) { + throw new InvalidParameterValueException("The vm with hostName " + hostName + " already exists in the network domain: " + network.getNetworkDomain() + "; network=" + + network); + } + } + + private void checkUnmanagedNicIpAndNetworkForImport(UnmanagedInstance.Nic nic, Network network, final Network.IpAddresses ipAddresses) throws ServerApiException { + if (nic == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import!", nic.getNicId())); + } + if (network == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import!", nic.getNicId())); + } // Check IP is assigned for non L2 networks if (!network.getGuestType().equals(Network.GuestType.L2) && (ipAddresses == null || (Strings.isNullOrEmpty(ipAddresses.getIp4Address()) && Strings.isNullOrEmpty(ipAddresses.getIp6Address())))) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC(ID: %s) needs a valid IP address for it to be associated with network(ID: %s)! %s parameter of API can be used for this.", nic.getNicId(), network.getUuid(), ApiConstants.NIC_IP_ADDRESS_LIST)); @@ -564,12 +582,6 @@ private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Net networkModel.checkRequestedIpAddresses(network.getId(), ipAddresses); } } - // Check for duplicate hostname in network, get all vms hostNames in the network - List hostNames = vmDao.listDistinctHostNames(network.getId()); - if (CollectionUtils.isNotEmpty(hostNames) && hostNames.contains(hostName)) { - throw new InvalidParameterValueException("The vm with hostName " + hostName + " already exists in the network domain: " + network.getNetworkDomain() + "; network=" - + network); - } } private Map getUnmanagedNicNetworkMap(List nics, final Map callerNicNetworkMap, final Map callerNicIpAddressMap, final DataCenter zone, final String hostName, final Account owner) throws ServerApiException { @@ -597,16 +609,20 @@ private Map getUnmanagedNicNetworkMap(List continue; } try { - checkUnmanagedNicAndNetworkForImport(nic, networkVO, ipAddresses, zone, hostName, owner); + checkUnmanagedNicAndNetworkForImport(nic, networkVO, zone, hostName, owner); network = networkVO; - break; } catch (Exception e) { } + if (network != null) { + checkUnmanagedNicIpAndNetworkForImport(nic, network, ipAddresses); + break; + } } } } else { network = networkDao.findById(callerNicNetworkMap.get(nic.getNicId())); - checkUnmanagedNicAndNetworkForImport(nic, network, ipAddresses, zone, hostName, owner); + checkUnmanagedNicAndNetworkForImport(nic, network, zone, hostName, owner); + checkUnmanagedNicIpAndNetworkForImport(nic, network, ipAddresses); } if (network == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Suitable network for nic(ID: %s) not found during VM import!", nic.getNicId())); From 3c0140c1c5c9dc129c9ce5439955a71573ad814b Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 10 Oct 2019 13:28:25 +0530 Subject: [PATCH 22/61] fix network cluster, host Signed-off-by: Abhishek Kumar --- .../vm/hypervisor/vmware/discover_networks.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/scripts/vm/hypervisor/vmware/discover_networks.py b/scripts/vm/hypervisor/vmware/discover_networks.py index 09761f3b251b..cb5dbf131e4c 100755 --- a/scripts/vm/hypervisor/vmware/discover_networks.py +++ b/scripts/vm/hypervisor/vmware/discover_networks.py @@ -143,14 +143,24 @@ def get_vm_nics(vm, hostPgDict): vlanId = 'NA' if vSwitch is None: vSwitch = 'NA' - add_network(portGroup, vlanId, vSwitch, vm.name, dev.deviceInfo.label, dev.macAddress) + vmHostName = None + vmClusterName = None + try: + vmHostName = vm.runtime.host.name + except AttributeError: + vmHostName = '' + try: + vmClusterName = vm.runtime.host.parent.name + except AttributeError: + vmClusterName = '' + add_network(portGroup, vlanId, vSwitch, vm.name, dev.deviceInfo.label, dev.macAddress, vmClusterName, vmHostName) log_message('\t\t' + dev.deviceInfo.label + '->' + dev.macAddress + ' @ ' + vSwitch + '->' + portGroup + ' (VLAN ' + vlanId + ')') except AttributeError: log_message('\tError: Unable retrieve details for ' + vm.name) -def add_network(portGroup, vlanId, vSwitch, vmName, vmDeviceLabel, vmMacAddress): +def add_network(portGroup, vlanId, vSwitch, vmName, vmDeviceLabel, vmMacAddress, vmClusterName, vmHostName): key = vSwitch + '->' + portGroup + ' (VLAN ' + vlanId + ')' device = {"label": vmDeviceLabel, "macaddress": vmMacAddress} vm = {"name":vmName, "device": device} @@ -163,11 +173,11 @@ def add_network(portGroup, vlanId, vSwitch, vmName, vmDeviceLabel, vmMacAddress) try: host = pgHostNameDict[portGroup] except KeyError: - host = '' + host = vmHostName try: cluster = hostClusterNameDict[host] except KeyError: - cluster = '' + cluster = vmClusterName network = {"portgroup": portGroup, "cluster": cluster, "host": host, "vlanid": vlanId, "switch": vSwitch, "virtualmachines": vms} networksDict[key] = network From 44756d552375ceda9cd441c6035638a92df5e1ee Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 10 Oct 2019 18:07:36 +0530 Subject: [PATCH 23/61] fix network IP address checks Added check for usage event publish failure after VM import Signed-off-by: Abhishek Kumar --- .../apache/cloudstack/api/ApiConstants.java | 1 + .../admin/vm/ImportUnmanagedInstanceCmd.java | 23 ++--- .../cloudstack/api/response/NicResponse.java | 12 +++ .../orchestration/NetworkOrchestrator.java | 49 +++-------- .../vmware/resource/VmwareResource.java | 10 ++- .../cloudstack/vm/VmImportManagerImpl.java | 85 ++++++++----------- 6 files changed, 72 insertions(+), 108 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index fba43f55cf08..f36ea40d1af0 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -191,6 +191,7 @@ public class ApiConstants { public static final String IOPS_WRITE_RATE_MAX = "iopswriteratemax"; public static final String IOPS_WRITE_RATE_MAX_LENGTH = "iopswriteratemaxlength"; public static final String IP_ADDRESS = "ipaddress"; + public static final String IP_ADDRESSES = "ipaddresses"; public static final String IP6_ADDRESS = "ip6address"; public static final String IP_ADDRESS_ID = "ipaddressid"; public static final String IS_ASYNC = "isasync"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java index cdb7162ee7e7..59af2c7aa223 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java @@ -143,7 +143,7 @@ public class ImportUnmanagedInstanceCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.NIC_IP_ADDRESS_LIST, type = CommandType.MAP, - description = "VM nic to ip address mapping using keys nic, ipAddress, ip6Address") + description = "VM nic to ip address mapping using keys nic, ipAddress") private Map nicIpAddressList; @Parameter(name = ApiConstants.DATADISK_OFFERING_LIST, @@ -226,27 +226,16 @@ public Map getNicIpAddressList() { for (Map entry : (Collection>)nicIpAddressList.values()) { String nic = entry.get(VmDetailConstants.NIC); String ipAddress = Strings.emptyToNull(entry.get(VmDetailConstants.IP_ADDRESS)); - String ip6Address = Strings.emptyToNull(entry.get(VmDetailConstants.IP6_ADDRESS)); if (Strings.isNullOrEmpty(nic)) { throw new InvalidParameterValueException(String.format("NIC ID: '%s' is invalid for IP address mapping", nic)); } - if (Strings.isNullOrEmpty(ipAddress) && Strings.isNullOrEmpty(ip6Address)) { - throw new InvalidParameterValueException(String.format("IP addresses for NIC ID: %s is invalid", nic)); + if (Strings.isNullOrEmpty(ipAddress)) { + throw new InvalidParameterValueException(String.format("IP address '%s' for NIC ID: %s is invalid", ipAddress, nic)); } - if (!Strings.isNullOrEmpty(ipAddress) && !Strings.isNullOrEmpty(ip6Address)) { - throw new InvalidParameterValueException(String.format("Multiple IP addresses(%s, %s) for NIC ID: %s cannot be assigned automatically", ipAddress, ip6Address, nic)); + if (!Strings.isNullOrEmpty(ipAddress) && !ipAddress.equals("auto") && !NetUtils.isValidIp4(ipAddress)) { + throw new InvalidParameterValueException(String.format("IP address '%s' for NIC ID: %s is invalid", ipAddress, nic)); } - if (!Strings.isNullOrEmpty(ipAddress)) { - if (!ipAddress.equals("auto") && !NetUtils.isValidIp4(ipAddress)) { - throw new InvalidParameterValueException(String.format("IP v4 address '%s' for NIC ID: %s is invalid", ipAddress, nic)); - } - } - if (!Strings.isNullOrEmpty(ip6Address)) { - if (!ip6Address.equals("auto") && !NetUtils.isValidIp6(ip6Address)) { - throw new InvalidParameterValueException(String.format("IP v6 address '%s' for NIC ID: %s is invalid", ip6Address, nic)); - } - } - Network.IpAddresses ipAddresses = new Network.IpAddresses(ipAddress, ip6Address); + Network.IpAddresses ipAddresses = new Network.IpAddresses(ipAddress, null); nicIpAddressMap.put(nic, ipAddresses); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java index 34f88e0d6865..09ac41604269 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java @@ -122,6 +122,10 @@ public class NicResponse extends BaseResponse { @Param(description = "Type of adapter if available", since="4.14.0") private String adapterType; + @SerializedName(ApiConstants.IP_ADDRESSES) + @Param(description = "IP addresses associated with NIC found for unmanaged VM", since="4.14.0") + private List ipAddresses; + public void setVmId(String vmId) { this.vmId = vmId; } @@ -328,4 +332,12 @@ public String getAdapterType() { public void setAdapterType(String adapterType) { this.adapterType = adapterType; } + + public List getIpAddresses() { + return ipAddresses; + } + + public void setIpAddresses(List ipAddresses) { + this.ipAddresses = ipAddresses; + } } diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index 256ff38b46a9..bfa69ddcc50e 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -97,7 +97,6 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.IpAddress; import com.cloud.network.IpAddressManager; -import com.cloud.network.Ipv6AddressManager; import com.cloud.network.Network; import com.cloud.network.Network.Capability; import com.cloud.network.Network.Event; @@ -287,8 +286,6 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra RemoteAccessVpnDao _remoteAccessVpnDao; @Inject VpcVirtualNetworkApplianceService _routerService; - @Inject - protected Ipv6AddressManager ipv6AddressManager; List networkGurus; @@ -3950,34 +3947,16 @@ public Pair importNic(final String macAddress, int deviceId throws ConcurrentOperationException, InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException { s_logger.debug("Allocating nic for vm " + vm.getUuid() + " in network " + network + " during import"); String guestIp = null; - if (ipAddresses != null) { - // Assign ip - if (!Strings.isNullOrEmpty(ipAddresses.getIp4Address())) { - if (ipAddresses.getIp4Address().equals("auto")) { - ipAddresses.setIp4Address(null); - } - if (network.getGuestType() != GuestType.L2) { - guestIp = _ipAddrMgr.acquireGuestIpAddress(network, ipAddresses.getIp4Address()); - } else { - guestIp = ipAddresses.getIp4Address(); - } - if (guestIp == null && network.getGuestType() != GuestType.L2 && !_networkModel.listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) { - throw new InsufficientVirtualNetworkCapacityException("Unable to acquire Guest IP address for network " + network, DataCenter.class, - network.getDataCenterId()); - } - } else if (!Strings.isNullOrEmpty(ipAddresses.getIp6Address())) { - if (ipAddresses.getIp6Address().equals("auto")) { - ipAddresses.setIp6Address(null); - } - if (network.getGuestType() != GuestType.L2) { - guestIp = ipv6AddressManager.acquireGuestIpv6Address(network, ipAddresses.getIp6Address()); - } else { - guestIp = ipAddresses.getIp6Address(); - } - if (guestIp == null && network.getGuestType() != GuestType.Shared && !_networkModel.listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) { - throw new InsufficientVirtualNetworkCapacityException("Unable to acquire Guest IP v6 address for network " + network, DataCenter.class, - network.getDataCenterId()); - } + if (ipAddresses != null && !Strings.isNullOrEmpty(ipAddresses.getIp4Address())) { + if (ipAddresses.getIp4Address().equals("auto")) { + ipAddresses.setIp4Address(null); + } + if (network.getGuestType() != GuestType.L2) { + guestIp = _ipAddrMgr.acquireGuestIpAddress(network, ipAddresses.getIp4Address()); + } + if (guestIp == null && network.getGuestType() != GuestType.L2 && !_networkModel.listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) { + throw new InsufficientVirtualNetworkCapacityException("Unable to acquire Guest IP address for network " + network, DataCenter.class, + network.getDataCenterId()); } } final String finalGuestIp = guestIp; @@ -3994,14 +3973,6 @@ public NicVO doInTransaction(TransactionStatus status) { vo.setIPv4Netmask(NetUtils.cidr2Netmask(network.getCidr())); } } - if (NetUtils.isValidIp6(finalGuestIp) && !Strings.isNullOrEmpty(network.getIp6Gateway())) { - vo.setAddressFormat(Networks.AddressFormat.Ip6); - vo.setIPv6Address(finalGuestIp); - vo.setIPv6Gateway(network.getIp6Gateway()); - if (!Strings.isNullOrEmpty(network.getIp6Cidr())) { - vo.setIPv6Cidr(NetUtils.cidr2Netmask(network.getCidr())); - } - } vo.setBroadcastUri(network.getBroadcastUri()); vo.setMode(network.getMode()); vo.setState(Nic.State.Reserved); diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index c006bc237044..bc59b8bc3ea2 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -6882,8 +6882,14 @@ private List getUnmanageInstanceNics(VmwareHypervisorHost GuestInfo guestInfo = vmMo.getGuestInfo(); if (guestInfo.getToolsStatus() == VirtualMachineToolsStatus.TOOLS_OK) { for (GuestNicInfo nicInfo: guestInfo.getNet()) { - if (!nicInfo.getIpAddress().isEmpty()) { - guestNicMacIPAddressMap.put(nicInfo.getMacAddress(), nicInfo.getIpAddress()); + if (CollectionUtils.isNotEmpty(nicInfo.getIpAddress())) { + List ipAddresses = new ArrayList<>(); + for (String ipAddress : nicInfo.getIpAddress()) { + if (NetUtils.isValidIp4(ipAddress)) { + ipAddresses.add(ipAddress); + } + } + guestNicMacIPAddressMap.put(nicInfo.getMacAddress(), ipAddresses); } } } else { diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index e1297cbe3921..f24100220eb2 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -234,14 +234,7 @@ private UnmanagedInstanceResponse createUnmanagedInstanceResponse(UnmanagedInsta nicResponse.setAdapterType(nic.getAdapterType()); } if (!CollectionUtils.isEmpty(nic.getIpAddress())) { - for (String address : nic.getIpAddress()) { - if (Strings.isNullOrEmpty(nicResponse.getIpaddress()) && NetUtils.isValidIp4(address)) { - nicResponse.setIpaddress(address); - } - if (Strings.isNullOrEmpty(nicResponse.getIp6Address()) && NetUtils.isValidIp6(address)) { - nicResponse.setIp6Address(address); - } - } + nicResponse.setIpAddresses(nic.getIpAddress()); } nicResponse.setVlanId(nic.getVlan()); response.addNic(nicResponse); @@ -422,21 +415,14 @@ private Map getNicIpAddresses(final List 1) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple IP addresses (%s, %s) present for nic ID: %s cannot be imported automatically!", nic.getIpAddress().get(0), nic.getIpAddress().get(1), nic.getNicId())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple IP addresses (%s, %s) present for nic ID: %s. IP address cannot be assigned automatically, only single IP address auto-assigning supported!", nic.getIpAddress().get(0), nic.getIpAddress().get(1), nic.getNicId())); } - if (ipAddresses == null || (Strings.isNullOrEmpty(ipAddresses.getIp4Address()) && Strings.isNullOrEmpty(ipAddresses.getIp4Address()))) { - if (ipAddresses == null) { - ipAddresses = new Network.IpAddresses(null, null); - } - String address = nic.getIpAddress().get(0); - if (NetUtils.isValidIp4(address)) { - ipAddresses.setIp4Address(address); - } - if (NetUtils.isValidIp6(address)) { - ipAddresses.setIp6Address(address); - } + String address = nic.getIpAddress().get(0); + if (NetUtils.isValidIp4(address)) { + ipAddresses.setIp4Address(address); } } if (ipAddresses != null) { @@ -556,32 +542,16 @@ private void checkUnmanagedNicIpAndNetworkForImport(UnmanagedInstance.Nic nic, N throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import!", nic.getNicId())); } // Check IP is assigned for non L2 networks - if (!network.getGuestType().equals(Network.GuestType.L2) && (ipAddresses == null || (Strings.isNullOrEmpty(ipAddresses.getIp4Address()) && Strings.isNullOrEmpty(ipAddresses.getIp6Address())))) { + if (!network.getGuestType().equals(Network.GuestType.L2) && (ipAddresses == null || Strings.isNullOrEmpty(ipAddresses.getIp4Address()))) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC(ID: %s) needs a valid IP address for it to be associated with network(ID: %s)! %s parameter of API can be used for this.", nic.getNicId(), network.getUuid(), ApiConstants.NIC_IP_ADDRESS_LIST)); } - // Check both IP v4 and v6 are not assigned at the same time - if (ipAddresses != null && !Strings.isNullOrEmpty(ipAddresses.getIp4Address()) && !Strings.isNullOrEmpty(ipAddresses.getIp6Address())) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple IP addresses(%s, %s) for NIC ID: %s cannot be assigned automatically", ipAddresses.getIp4Address(), ipAddresses.getIp6Address(), nic.getNicId())); - } - // If IP v4 is assigned and not set to auto check it is available for network + // If IP v4 is assigned and not set to auto-assign check it is available for network if (ipAddresses != null && !Strings.isNullOrEmpty(ipAddresses.getIp4Address()) && !ipAddresses.getIp4Address().equals("auto")) { Set ips = networkModel.getAvailableIps(network, ipAddresses.getIp4Address()); if (CollectionUtils.isEmpty(ips) || !ips.contains(NetUtils.ip2Long(ipAddresses.getIp4Address()))) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("IP address %s for NIC(ID: %s) is not available in network(ID: %s)!", ipAddresses.getIp4Address(), nic.getNicId(), network.getUuid())); } } - // If IP v6 is assigned check network is Shared, supports IPv6 and if IP not set to auto check if available - if (ipAddresses != null && !Strings.isNullOrEmpty(ipAddresses.getIp6Address())) { - if (!network.getGuestType().equals(Network.GuestType.Shared)) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("IP v6 addressing %s for NIC(ID: %s) is not supported for in network(ID: %s), type: %s!", ipAddresses.getIp6Address(), nic.getNicId(), network.getUuid(), network.getGuestType())); - } - if (Strings.isNullOrEmpty(network.getIp6Gateway())) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network(ID: %s) assigned to NIC(ID: %s) is not configured for IP v6 addressing!", network.getUuid(), nic.getNicId())); - } - if (!ipAddresses.getIp6Address().equals("auto")) { - networkModel.checkRequestedIpAddresses(network.getId(), ipAddresses); - } - } } private Map getUnmanagedNicNetworkMap(List nics, final Map callerNicNetworkMap, final Map callerNicIpAddressMap, final DataCenter zone, final String hostName, final Account owner) throws ServerApiException { @@ -662,10 +632,15 @@ private void cleanupFailedImportVM(final UserVm userVm) { if (userVm == null) { return; } + VirtualMachineProfile profile = new VirtualMachineProfileImpl(userVm); // Remove all volumes volumeDao.deleteVolumesByInstance(userVm.getId()); // Remove all nics - nicDao.removeNicsForInstance(userVm.getId()); + try { + networkOrchestrationService.release(profile, true); + } catch (Exception e) { + nicDao.removeNicsForInstance(userVm.getId()); + } // Remove vm vmDao.remove(userVm.getId()); } @@ -755,14 +730,21 @@ private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate templ private void publishVMUsageUpdateResourceCount(final UserVm userVm, ServiceOfferingVO serviceOfferingVO) { if (userVm == null || serviceOfferingVO == null) { LOGGER.error("Failed to publish usage records during VM import!"); - return; + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm during publishing usage records")); } - if (!serviceOfferingVO.isDynamic()) { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_IMPORT, userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), userVm.getHostName(), serviceOfferingVO.getId(), userVm.getTemplateId(), - userVm.getHypervisorType().toString(), VirtualMachine.class.getName(), userVm.getUuid(), userVm.isDisplayVm()); - } else { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_IMPORT, userVm.getAccountId(), userVm.getAccountId(), userVm.getDataCenterId(), userVm.getHostName(), serviceOfferingVO.getId(), userVm.getTemplateId(), - userVm.getHypervisorType().toString(), VirtualMachine.class.getName(), userVm.getUuid(), userVm.getDetails(), userVm.isDisplayVm()); + try { + if (!serviceOfferingVO.isDynamic()) { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_IMPORT, userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), userVm.getHostName(), serviceOfferingVO.getId(), userVm.getTemplateId(), + userVm.getHypervisorType().toString(), VirtualMachine.class.getName(), userVm.getUuid(), userVm.isDisplayVm()); + } else { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_IMPORT, userVm.getAccountId(), userVm.getAccountId(), userVm.getDataCenterId(), userVm.getHostName(), serviceOfferingVO.getId(), userVm.getTemplateId(), + userVm.getHypervisorType().toString(), VirtualMachine.class.getName(), userVm.getUuid(), userVm.getDetails(), userVm.isDisplayVm()); + } + } catch (Exception e) { + LOGGER.error("Failed to publish usage records during VM import!"); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm %s during publishing usage records", userVm.getInstanceName())); } resourceLimitService.incrementResourceCount(userVm.getAccountId(), Resource.ResourceType.user_vm, userVm.isDisplayVm()); resourceLimitService.incrementResourceCount(userVm.getAccountId(), Resource.ResourceType.cpu, userVm.isDisplayVm(), new Long(serviceOfferingVO.getCpu())); @@ -770,9 +752,12 @@ private void publishVMUsageUpdateResourceCount(final UserVm userVm, ServiceOffer // Save usage event and update resource count for user vm volumes List volumes = volumeDao.findByInstance(userVm.getId()); for (VolumeVO volume : volumes) { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), volume.getDiskOfferingId(), null, volume.getSize(), - Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); - + try { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), volume.getDiskOfferingId(), null, volume.getSize(), + Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); + } catch (Exception e) { + LOGGER.error(String.format("Failed to publish volume usage records during VM import! %s", Strings.nullToEmpty(e.getMessage()))); + } resourceLimitService.incrementResourceCount(userVm.getAccountId(), Resource.ResourceType.volume, volume.isDisplayVolume()); resourceLimitService.incrementResourceCount(userVm.getAccountId(), Resource.ResourceType.primary_storage, volume.isDisplayVolume(), volume.getSize()); } From 3991d75e7937a0047f645f6b21475f6f50f18a36 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 10 Oct 2019 18:27:43 +0530 Subject: [PATCH 24/61] templateid param for importUnmanagedInstance API made optional Logic has been changed to search for default vm import template when templateid paramter is not passed. When templateid is not passed operating system details for the imported VM will be set using details retrieved from VM's guest OS details. osid response parameter has been added to listUnmnagedInstance API. Signed-off-by: Abhishek Kumar --- .../apache/cloudstack/api/ApiConstants.java | 1 + .../admin/vm/ImportUnmanagedInstanceCmd.java | 1 - .../response/UnmanagedInstanceResponse.java | 12 +++++++ .../cloudstack/vm/UnmanagedInstance.java | 10 ++++++ .../vmware/resource/VmwareResource.java | 18 ++++++++-- .../java/com/cloud/vm/UserVmManagerImpl.java | 2 +- .../cloudstack/vm/VmImportManagerImpl.java | 35 +++++++++++++++++-- .../vm/VmImportManagerImplTest.java | 6 +++- .../vmware/util/VmwareGuestOsMapper.java | 24 +++++++++++-- 9 files changed, 100 insertions(+), 9 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index f36ea40d1af0..ac5ed614cc38 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -244,6 +244,7 @@ public class ApiConstants { public static final String OLD_FORMAT = "oldformat"; public static final String OP = "op"; public static final String OS_CATEGORY_ID = "oscategoryid"; + public static final String OS_ID = "osid"; public static final String OS_TYPE_ID = "ostypeid"; public static final String OS_DISPLAY_NAME = "osdisplayname"; public static final String OS_NAME_FOR_HYPERVISOR = "osnameforhypervisor"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java index 59af2c7aa223..ab42adea32f6 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java @@ -118,7 +118,6 @@ public class ImportUnmanagedInstanceCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.TEMPLATE_ID, type = CommandType.UUID, entityType = TemplateResponse.class, - required = true, description = "the ID of the template for the virtual machine") private Long templateId; diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java index cd3f7a8f8259..36bf01a7e40f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java @@ -63,6 +63,10 @@ public class UnmanagedInstanceResponse extends BaseResponse { @Param(description = "the memory of the virtual machine in MB") private Integer memory; + @SerializedName(ApiConstants.OS_ID) + @Param(description = "the operating system ID of the virtual machine") + private String operatingSystemId; + @SerializedName(ApiConstants.OS_DISPLAY_NAME) @Param(description = "the operating system of the virtual machine") private String operatingSystem; @@ -144,6 +148,14 @@ public void setMemory(Integer memory) { this.memory = memory; } + public String getOperatingSystemId() { + return operatingSystemId; + } + + public void setOperatingSystemId(String operatingSystemId) { + this.operatingSystemId = operatingSystemId; + } + public String getOperatingSystem() { return operatingSystem; } diff --git a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java index 45a7a7b1eefa..58ac513790d3 100644 --- a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java +++ b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java @@ -39,6 +39,8 @@ public enum PowerState { private Integer cpuSpeed; + private String operatingSystemId; + private String operatingSystem; private List disks; @@ -93,6 +95,14 @@ public void setCpuSpeed(Integer cpuSpeed) { this.cpuSpeed = cpuSpeed; } + public String getOperatingSystemId() { + return operatingSystemId; + } + + public void setOperatingSystemId(String operatingSystemId) { + this.operatingSystemId = operatingSystemId; + } + public String getOperatingSystem() { return operatingSystem; } diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index bc59b8bc3ea2..8af8553cd56e 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -225,6 +225,7 @@ import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHostResourceSummary; import com.cloud.hypervisor.vmware.util.VmwareContext; import com.cloud.hypervisor.vmware.util.VmwareContextPool; +import com.cloud.hypervisor.vmware.util.VmwareGuestOsMapper; import com.cloud.hypervisor.vmware.util.VmwareHelper; import com.cloud.network.Networks; import com.cloud.network.Networks.BroadcastDomainType; @@ -7005,10 +7006,23 @@ private UnmanagedInstance getUnmanagedInstance(VmwareHypervisorHost hyperHost, V instance.setCpuCoresPerSocket(vmMo.getCoresPerSocket()); instance.setCpuSpeed(vmMo.getConfigSummary().getCpuReservation()); instance.setMemory(vmMo.getConfigSummary().getMemorySizeMB()); - instance.setOperatingSystem(vmMo.getVmGuestInfo().getGuestFullName()); + instance.setOperatingSystemId(vmMo.getVmGuestInfo().getGuestId()); + if (Strings.isNullOrEmpty(instance.getOperatingSystemId())) { + instance.setOperatingSystemId(vmMo.getConfigSummary().getGuestId()); + } + VirtualMachineGuestOsIdentifier osIdentifier = VirtualMachineGuestOsIdentifier.OTHER_GUEST; + try { + osIdentifier = VirtualMachineGuestOsIdentifier.fromValue(instance.getOperatingSystemId()); + } catch (IllegalArgumentException iae) { + if (!Strings.isNullOrEmpty(instance.getOperatingSystemId()) && instance.getOperatingSystemId().contains("64")) { + osIdentifier = VirtualMachineGuestOsIdentifier.OTHER_GUEST_64; + } + } + instance.setOperatingSystem(VmwareGuestOsMapper.getGuestOsName(osIdentifier)); + /*instance.setOperatingSystem(vmMo.getGuestInfo().getGuestFullName()); if (Strings.isNullOrEmpty(instance.getOperatingSystem())) { instance.setOperatingSystem(vmMo.getConfigSummary().getGuestFullName()); - } + }*/ UnmanagedInstance.PowerState powerState = UnmanagedInstance.PowerState.PowerUnknown; if (vmMo.getPowerState().toString().equalsIgnoreCase("POWERED_ON")) { powerState = UnmanagedInstance.PowerState.PowerOn; diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index a6499ee2ec36..56c46dcbcc46 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -6898,7 +6898,7 @@ public UserVm importVM(final DataCenter zone, final Host host, final VirtualMach final Host lastHost = powerState != VirtualMachine.PowerState.PowerOn ? host : null; UserVmVO userVmVO = commitUserVm(true, zone, host, lastHost, template, hostName, displayName, owner, rootDiskOffering.getId(), null, userData, caller, isDisplayVm, keyboard, - accountId, userId, serviceOffering, false, sshPublicKey, null, + accountId, userId, serviceOffering, template.getFormat().equals(ImageFormat.ISO), sshPublicKey, null, id, instanceName, uuidName, hypervisorType, customParameters, null, null, null, powerState); return userVmVO; diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index f24100220eb2..8f27a8d85af8 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -88,13 +88,18 @@ import com.cloud.server.ManagementService; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.storage.GuestOS; +import com.cloud.storage.GuestOSHypervisor; import com.cloud.storage.Storage; import com.cloud.storage.StoragePool; import com.cloud.storage.VMTemplateStoragePoolVO; +import com.cloud.storage.VMTemplateVO; import com.cloud.storage.Volume; import com.cloud.storage.VolumeApiService; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.DiskOfferingDao; +import com.cloud.storage.dao.GuestOSDao; +import com.cloud.storage.dao.GuestOSHypervisorDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplatePoolDao; import com.cloud.storage.dao.VolumeDao; @@ -122,6 +127,7 @@ import com.google.gson.Gson; public class VmImportManagerImpl implements VmImportService { + public static final String VMWARE_IMPORT_DEFAULT_TEMPLATE_NAME = "vmware-import-default.ova"; private static final Logger LOGGER = Logger.getLogger(VmImportManagerImpl.class); @Inject @@ -180,6 +186,10 @@ public class VmImportManagerImpl implements VmImportService { private NetworkModel networkModel; @Inject private ConfigurationDao configurationDao; + @Inject + private GuestOSDao guestOSDao; + @Inject + private GuestOSHypervisorDao guestOSHypervisorDao; protected Gson gson; @@ -201,6 +211,7 @@ private UnmanagedInstanceResponse createUnmanagedInstanceResponse(UnmanagedInsta response.setCpuSpeed(instance.getCpuSpeed()); response.setCpuCoresPerSocket(instance.getCpuCoresPerSocket()); response.setMemory(instance.getMemory()); + response.setOperatingSystemId(instance.getOperatingSystemId()); response.setOperatingSystem(instance.getOperatingSystem()); response.setObjectName(UnmanagedInstance.class.getSimpleName().toLowerCase()); @@ -951,11 +962,16 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { if (CollectionUtils.isNotEmpty(userVOs)) { userId = userVOs.get(0).getId(); } + VMTemplateVO template = null; final Long templateId = cmd.getTemplateId(); if (templateId == null) { - throw new InvalidParameterValueException(String.format("Template ID cannot be null!")); + template = templateDao.findByName(VMWARE_IMPORT_DEFAULT_TEMPLATE_NAME); + if (template == null) { + throw new InvalidParameterValueException(String.format("Default VM import template with unique name: %s for hypervisor: %s cannot be found! Please use templateid paramter for import.", VMWARE_IMPORT_DEFAULT_TEMPLATE_NAME, cluster.getHypervisorType().toString())); + } + } else { + template = templateDao.findById(templateId); } - final VirtualMachineTemplate template = templateDao.findById(templateId); if (template == null) { throw new InvalidParameterValueException(String.format("Template ID: %d cannot be found!", templateId)); } @@ -1038,6 +1054,21 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { if (unmanagedInstance == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve details for unmanaged VM: %s", name)); } + if (template.getName().equals(VMWARE_IMPORT_DEFAULT_TEMPLATE_NAME)) { + String osName = unmanagedInstance.getOperatingSystem(); + if (Strings.isNullOrEmpty(osName)) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve guest OS details for unmanaged VM: %s. templateid parameter can be used to assign template for VM", name)); + } + GuestOS guestOS = guestOSDao.listByDisplayName(osName); + if (guestOS == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve guest OS details for unmanaged VM: %s. templateid parameter can be used to assign template for VM", name)); + } + GuestOSHypervisor guestOSHypervisor = guestOSHypervisorDao.findByOsIdAndHypervisor(guestOS.getId(), host.getHypervisorType().toString(), host.getHypervisorVersion()); + if (guestOSHypervisor == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve guest OS details for unmanaged VM: %s for hypervisor: %s version: %s. templateid parameter can be used to assign template for VM", name, host.getHypervisorType().toString(), host.getHypervisorVersion())); + } + template.setGuestOSId(guestOS.getId()); + } userVm = importVirtualMachineInternal(unmanagedInstance, instanceName, zone, cluster, host, template, displayName, hostName, caller, owner, userId, serviceOffering, diskOffering, dataDiskOfferingMap, diff --git a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java index 510b8cc7c755..64338e2f7996 100644 --- a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java @@ -209,7 +209,11 @@ public void setUp() throws Exception { List users = new ArrayList<>(); users.add(Mockito.mock(UserVO.class)); when(userDao.listByAccount(Mockito.anyLong())).thenReturn(users); - when(templateDao.findById(Mockito.anyLong())).thenReturn(Mockito.mock(VMTemplateVO.class)); + VMTemplateVO template = Mockito.mock(VMTemplateVO.class); + when(template.getId()).thenReturn(1L); + when(template.getName()).thenReturn("Template"); + when(templateDao.findById(Mockito.anyLong())).thenReturn(template); + when(templateDao.findByName(Mockito.anyString())).thenReturn(template); ServiceOfferingVO serviceOffering = Mockito.mock(ServiceOfferingVO.class); when(serviceOffering.getId()).thenReturn(1L); when(serviceOffering.getTags()).thenReturn(""); diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java index b50620ea3478..2aea7426c6b9 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java @@ -16,9 +16,13 @@ // under the License. package com.cloud.hypervisor.vmware.util; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; +import org.apache.commons.collections.CollectionUtils; + import com.vmware.vim25.VirtualMachineGuestOsIdentifier; public class VmwareGuestOsMapper { @@ -120,8 +124,11 @@ public class VmwareGuestOsMapper { s_mapper.put("CentOS 5.5 (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_64_GUEST); s_mapper.put("CentOS 5.6 (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_GUEST); s_mapper.put("CentOS 5.6 (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_64_GUEST); - s_mapper.put("CentOS 6.0 (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_GUEST); - s_mapper.put("CentOS 6.0 (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_64_GUEST); + s_mapper.put("CentOS 6.0 (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_6_GUEST); + s_mapper.put("CentOS 6.0 (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_6_64_GUEST); + s_mapper.put("CentOS 7.0 (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_7_GUEST); + s_mapper.put("CentOS 7.0 (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_7_64_GUEST); + s_mapper.put("CentOS 8.0 (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_8_64_GUEST); s_mapper.put("Other CentOS (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_GUEST); s_mapper.put("Other CentOS (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_64_GUEST); @@ -200,4 +207,17 @@ public static VirtualMachineGuestOsIdentifier getGuestOsIdentifier(String guestO return s_mapper.get(guestOsName); } + public static String getGuestOsName(VirtualMachineGuestOsIdentifier identifier) { + String guestOsName = null; + List keys = new ArrayList<>(); + for (Map.Entry entry : s_mapper.entrySet()) { + if (entry.getValue().equals(identifier)) { + keys.add(entry.getKey()); + } + } + if (CollectionUtils.isNotEmpty(keys)) { + guestOsName = keys.get(keys.size()-1); + } + return guestOsName; + } } From 4824e5372a3ecede5b66ac21e598b89ad2d91445 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 11 Oct 2019 11:40:17 +0530 Subject: [PATCH 25/61] fix error message multiple data disk controllers Signed-off-by: Abhishek Kumar --- .../main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 8f27a8d85af8..fa32979f602f 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -516,7 +516,7 @@ private void checkUnmanagedDiskAndOfferingForImport(List diskController = disk.getController(); } else { if(!diskController.equals(disk.getController())) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple disk controllers of different type (%s, %s) are not supported for import. Please make sure that all disk controllers are of the same type!", diskController, disk.getController())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple data disk controllers of different type (%s, %s) are not supported for import. Please make sure that all disk controllers are of the same type!", diskController, disk.getController())); } } checkUnmanagedDiskAndOfferingForImport(disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), owner, zone, cluster, migrateAllowed); From 8f17219a1159cb4fd9b88b96cf014d30333a5a6d Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 11 Oct 2019 11:54:30 +0530 Subject: [PATCH 26/61] fix vm import with dummy ISO Signed-off-by: Abhishek Kumar --- server/src/main/java/com/cloud/vm/UserVmManagerImpl.java | 2 +- .../org/apache/cloudstack/vm/VmImportManagerImpl.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index 56c46dcbcc46..6a3fa088935e 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -3852,7 +3852,7 @@ public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCap vm.setDetail(VmDetailConstants.KEYBOARD, keyboard); } - if (isIso) { + if (!isImport && isIso) { vm.setIsoId(template.getId()); } Long rootDiskSize = null; diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index fa32979f602f..fe6e8ea8b05c 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -127,7 +127,7 @@ import com.google.gson.Gson; public class VmImportManagerImpl implements VmImportService { - public static final String VMWARE_IMPORT_DEFAULT_TEMPLATE_NAME = "vmware-import-default.ova"; + public static final String VM_IMPORT_DEFAULT_TEMPLATE_NAME = "system-default-vm-import-dummy-template.iso"; private static final Logger LOGGER = Logger.getLogger(VmImportManagerImpl.class); @Inject @@ -965,9 +965,9 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { VMTemplateVO template = null; final Long templateId = cmd.getTemplateId(); if (templateId == null) { - template = templateDao.findByName(VMWARE_IMPORT_DEFAULT_TEMPLATE_NAME); + template = templateDao.findByName(VM_IMPORT_DEFAULT_TEMPLATE_NAME); if (template == null) { - throw new InvalidParameterValueException(String.format("Default VM import template with unique name: %s for hypervisor: %s cannot be found! Please use templateid paramter for import.", VMWARE_IMPORT_DEFAULT_TEMPLATE_NAME, cluster.getHypervisorType().toString())); + throw new InvalidParameterValueException(String.format("Default VM import template with unique name: %s for hypervisor: %s cannot be found! Please use templateid paramter for import.", VM_IMPORT_DEFAULT_TEMPLATE_NAME, cluster.getHypervisorType().toString())); } } else { template = templateDao.findById(templateId); @@ -1054,7 +1054,7 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { if (unmanagedInstance == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve details for unmanaged VM: %s", name)); } - if (template.getName().equals(VMWARE_IMPORT_DEFAULT_TEMPLATE_NAME)) { + if (template.getName().equals(VM_IMPORT_DEFAULT_TEMPLATE_NAME)) { String osName = unmanagedInstance.getOperatingSystem(); if (Strings.isNullOrEmpty(osName)) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve guest OS details for unmanaged VM: %s. templateid parameter can be used to assign template for VM", name)); From b4359578bafc41ac1223e8c2ee6fa9f59776752f Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 11 Oct 2019 12:47:03 +0530 Subject: [PATCH 27/61] fix hostname error on auto assign NIC Signed-off-by: Abhishek Kumar --- .../cloudstack/vm/VmImportManagerImpl.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index fe6e8ea8b05c..0923ee1cedda 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -523,9 +523,9 @@ private void checkUnmanagedDiskAndOfferingForImport(List } } - private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Network network, final DataCenter zone, final String hostName, final Account owner) throws ServerApiException { + private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Network network, final DataCenter zone, final Account owner) throws ServerApiException { if (nic == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import!", nic.getNicId())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import!")); } if (network == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import!", nic.getNicId())); @@ -537,6 +537,15 @@ private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Net if (nic.getVlan() != null && (Strings.isNullOrEmpty(network.getBroadcastUri().toString()) || !network.getBroadcastUri().toString().equals(String.format("vlan://%d", nic.getVlan())))) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VLAN of network(ID: %s) %s is found different from the VLAN of nic(ID: %s) vlan://%d during VM import!", network.getUuid(), network.getBroadcastUri().toString(), nic.getNicId(), nic.getVlan())); } + } + + private void checkUnmanagedNicAndNetworkHostnameForImport(UnmanagedInstance.Nic nic, Network network, final String hostName) throws ServerApiException { + if (nic == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import!")); + } + if (network == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import!", nic.getNicId())); + } // Check for duplicate hostname in network, get all vms hostNames in the network List hostNames = vmDao.listDistinctHostNames(network.getId()); if (CollectionUtils.isNotEmpty(hostNames) && hostNames.contains(hostName)) { @@ -547,7 +556,7 @@ private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Net private void checkUnmanagedNicIpAndNetworkForImport(UnmanagedInstance.Nic nic, Network network, final Network.IpAddresses ipAddresses) throws ServerApiException { if (nic == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import!", nic.getNicId())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import!")); } if (network == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import!", nic.getNicId())); @@ -590,11 +599,12 @@ private Map getUnmanagedNicNetworkMap(List continue; } try { - checkUnmanagedNicAndNetworkForImport(nic, networkVO, zone, hostName, owner); + checkUnmanagedNicAndNetworkForImport(nic, networkVO, zone, owner); network = networkVO; } catch (Exception e) { } if (network != null) { + checkUnmanagedNicAndNetworkHostnameForImport(nic, network, hostName); checkUnmanagedNicIpAndNetworkForImport(nic, network, ipAddresses); break; } @@ -602,7 +612,8 @@ private Map getUnmanagedNicNetworkMap(List } } else { network = networkDao.findById(callerNicNetworkMap.get(nic.getNicId())); - checkUnmanagedNicAndNetworkForImport(nic, network, zone, hostName, owner); + checkUnmanagedNicAndNetworkForImport(nic, network, zone, owner); + checkUnmanagedNicAndNetworkHostnameForImport(nic, network, hostName); checkUnmanagedNicIpAndNetworkForImport(nic, network, ipAddresses); } if (network == null) { From 370d88f205306df1bad501ab2ee6bc56b79672e3 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 11 Oct 2019 15:13:02 +0530 Subject: [PATCH 28/61] fix missing guest OS mapping Signed-off-by: Abhishek Kumar --- .../cloudstack/vm/VmImportManagerImpl.java | 6 ++-- .../vmware/util/VmwareGuestOsMapper.java | 31 +++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 0923ee1cedda..cd9af2c5986d 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -1068,15 +1068,15 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { if (template.getName().equals(VM_IMPORT_DEFAULT_TEMPLATE_NAME)) { String osName = unmanagedInstance.getOperatingSystem(); if (Strings.isNullOrEmpty(osName)) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve guest OS details for unmanaged VM: %s. templateid parameter can be used to assign template for VM", name)); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve guest OS details for unmanaged VM: %s with OS name: %s. templateid parameter can be used to assign template for VM", name, unmanagedInstance.getOperatingSystem())); } GuestOS guestOS = guestOSDao.listByDisplayName(osName); if (guestOS == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve guest OS details for unmanaged VM: %s. templateid parameter can be used to assign template for VM", name)); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve guest OS details for unmanaged VM: %s with OS ID: %s, OS name: %s. templateid parameter can be used to assign template for VM", name, unmanagedInstance.getOperatingSystemId(), unmanagedInstance.getOperatingSystem())); } GuestOSHypervisor guestOSHypervisor = guestOSHypervisorDao.findByOsIdAndHypervisor(guestOS.getId(), host.getHypervisorType().toString(), host.getHypervisorVersion()); if (guestOSHypervisor == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve guest OS details for unmanaged VM: %s for hypervisor: %s version: %s. templateid parameter can be used to assign template for VM", name, host.getHypervisorType().toString(), host.getHypervisorVersion())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to find hypervisor guest OS ID: %s details for unmanaged VM:%s for hypervisor: %s version: %s. templateid parameter can be used to assign template for VM", guestOS.getUuid(), name, host.getHypervisorType().toString(), host.getHypervisorVersion())); } template.setGuestOSId(guestOS.getId()); } diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java index 2aea7426c6b9..83fa468c8ef4 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java @@ -66,11 +66,23 @@ public class VmwareGuestOsMapper { s_mapper.put("Windows 8 (64-bit)", VirtualMachineGuestOsIdentifier.WINDOWS_8_64_GUEST); s_mapper.put("Windows Server 2012 (64-bit)", VirtualMachineGuestOsIdentifier.WINDOWS_8_SERVER_64_GUEST); s_mapper.put("Windows Server 2012 R2 (64-bit)", VirtualMachineGuestOsIdentifier.WINDOWS_8_SERVER_64_GUEST); + s_mapper.put("Windows 10 (32-bit)", VirtualMachineGuestOsIdentifier.WINDOWS_9_GUEST); + s_mapper.put("Windows 10 (64-bit)", VirtualMachineGuestOsIdentifier.WINDOWS_9_64_GUEST); + s_mapper.put("Windows 10 Server (64-bit)", VirtualMachineGuestOsIdentifier.WINDOWS_9_SERVER_64_GUEST); + s_mapper.put("Windows Hyper-V", VirtualMachineGuestOsIdentifier.WINDOWS_HYPER_V_GUEST); + s_mapper.put("Apple Mac OS 10.5 (64 bit)", VirtualMachineGuestOsIdentifier.DARWIN_64_GUEST); s_mapper.put("Apple Mac OS X 10.6 (32-bit)", VirtualMachineGuestOsIdentifier.DARWIN_10_GUEST); s_mapper.put("Apple Mac OS X 10.6 (64-bit)", VirtualMachineGuestOsIdentifier.DARWIN_10_64_GUEST); s_mapper.put("Apple Mac OS X 10.7 (32-bit)", VirtualMachineGuestOsIdentifier.DARWIN_11_GUEST); s_mapper.put("Apple Mac OS X 10.7 (64-bit)", VirtualMachineGuestOsIdentifier.DARWIN_11_64_GUEST); + s_mapper.put("Apple Mac OS 10.8 (64 bit)", VirtualMachineGuestOsIdentifier.DARWIN_12_64_GUEST); + s_mapper.put("Apple Mac OS 10.9 (64 bit)", VirtualMachineGuestOsIdentifier.DARWIN_13_64_GUEST); + s_mapper.put("Apple Mac OS 10.10 (64 bit)", VirtualMachineGuestOsIdentifier.DARWIN_14_64_GUEST); + s_mapper.put("Apple Mac OS 10.11 (64 bit)", VirtualMachineGuestOsIdentifier.DARWIN_15_64_GUEST); + s_mapper.put("Apple Mac OS 10.12 (64 bit)", VirtualMachineGuestOsIdentifier.DARWIN_16_64_GUEST); + s_mapper.put("Apple Mac OS 10.13 (64 bit)", VirtualMachineGuestOsIdentifier.DARWIN_17_64_GUEST); + s_mapper.put("Apple Mac OS 10.14 (64 bit)", VirtualMachineGuestOsIdentifier.DARWIN_18_64_GUEST); s_mapper.put("Open Enterprise Server", VirtualMachineGuestOsIdentifier.OES_GUEST); @@ -106,6 +118,22 @@ public class VmwareGuestOsMapper { s_mapper.put("Other SUSE Linux(32-bit)", VirtualMachineGuestOsIdentifier.SUSE_GUEST); s_mapper.put("Other SUSE Linux(64-bit)", VirtualMachineGuestOsIdentifier.SUSE_64_GUEST); + s_mapper.put("Suse Linux Enterprise Server 9", VirtualMachineGuestOsIdentifier.SLES_GUEST); + s_mapper.put("Suse Linux Enterprise Server 9 (64 bit)", VirtualMachineGuestOsIdentifier.SLES_64_GUEST); + s_mapper.put("SUSE Linux Enterprise Server 10 SP1 (32-bit)", VirtualMachineGuestOsIdentifier.SLES_10_GUEST); + s_mapper.put("SUSE Linux Enterprise Server 10 SP1 (64-bit)", VirtualMachineGuestOsIdentifier.SLES_10_64_GUEST); + s_mapper.put("SUSE Linux Enterprise Server 10 SP2 (32-bit)", VirtualMachineGuestOsIdentifier.SLES_10_GUEST); + s_mapper.put("SUSE Linux Enterprise Server 10 SP2 (64-bit)", VirtualMachineGuestOsIdentifier.SLES_10_64_GUEST); + s_mapper.put("SUSE Linux Enterprise Server 10 SP3 (32-bit)", VirtualMachineGuestOsIdentifier.SLES_10_GUEST); + s_mapper.put("SUSE Linux Enterprise Server 10 SP3 (64-bit)", VirtualMachineGuestOsIdentifier.SLES_10_64_GUEST); + s_mapper.put("SUSE Linux Enterprise Server 10 SP4 (32-bit)", VirtualMachineGuestOsIdentifier.SLES_10_GUEST); + s_mapper.put("SUSE Linux Enterprise Server 10 SP4 (64-bit)", VirtualMachineGuestOsIdentifier.SLES_10_64_GUEST); + s_mapper.put("SUSE Linux Enterprise Server 11 (32-bit)", VirtualMachineGuestOsIdentifier.SLES_11_GUEST); + s_mapper.put("SUSE Linux Enterprise Server 11 (64-bit)", VirtualMachineGuestOsIdentifier.SLES_11_64_GUEST); + s_mapper.put("SUSE Linux Enterprise Server 12 (32-bit)", VirtualMachineGuestOsIdentifier.SLES_12_GUEST); + s_mapper.put("SUSE Linux Enterprise Server 12 (64-bit)", VirtualMachineGuestOsIdentifier.SLES_12_64_GUEST); + s_mapper.put("SUSE Linux Enterprise Server 15 (64-bit)", VirtualMachineGuestOsIdentifier.SLES_15_64_GUEST); + s_mapper.put("CentOS 4.5 (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_GUEST); s_mapper.put("CentOS 4.6 (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_GUEST); s_mapper.put("CentOS 4.7 (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_GUEST); @@ -176,6 +204,9 @@ public class VmwareGuestOsMapper { s_mapper.put("Red Hat Enterprise Linux 6.3 (64-bit)", VirtualMachineGuestOsIdentifier.RHEL_6_64_GUEST); s_mapper.put("Red Hat Enterprise Linux 6.4 (32-bit)", VirtualMachineGuestOsIdentifier.RHEL_6_GUEST); s_mapper.put("Red Hat Enterprise Linux 6.4 (64-bit)", VirtualMachineGuestOsIdentifier.RHEL_6_64_GUEST); + s_mapper.put("Red Hat Enterprise Linux 7 (32-bit)", VirtualMachineGuestOsIdentifier.RHEL_7_GUEST); + s_mapper.put("Red Hat Enterprise Linux 7 (64-bit)", VirtualMachineGuestOsIdentifier.RHEL_7_64_GUEST); + s_mapper.put("Red Hat Enterprise Linux 8 (64-bit)", VirtualMachineGuestOsIdentifier.RHEL_8_64_GUEST); s_mapper.put("Ubuntu 8.04 (32-bit)", VirtualMachineGuestOsIdentifier.UBUNTU_GUEST); s_mapper.put("Ubuntu 8.04 (64-bit)", VirtualMachineGuestOsIdentifier.UBUNTU_64_GUEST); From ffa90b96ac5bb854032be897213717949cbde3d9 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 11 Oct 2019 15:37:10 +0530 Subject: [PATCH 29/61] refatorings - error message Signed-off-by: Abhishek Kumar --- .../vmware/resource/VmwareResource.java | 14 +- .../cloudstack/vm/VmImportManagerImpl.java | 126 +++++++++--------- 2 files changed, 70 insertions(+), 70 deletions(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 8af8553cd56e..2b4916fe914b 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -6803,7 +6803,7 @@ private List getUnmanageInstanceDisks(VirtualMachineMO v try { disks = vmMo.getAllDiskDevice(); } catch (Exception e) { - s_logger.info("Unable to retrieve unmanaged instance disks! " + e.getMessage()); + s_logger.info("Unable to retrieve unmanaged instance disks. " + e.getMessage()); } if (disks != null) { for (VirtualDevice diskDevice : disks) { @@ -6856,7 +6856,7 @@ private List getUnmanageInstanceDisks(VirtualMachineMO v instanceDisks.add(instanceDisk); } } catch (Exception e) { - s_logger.info("Unable to retrieve unmanaged instance disk info! " + e.getMessage()); + s_logger.info("Unable to retrieve unmanaged instance disk info. " + e.getMessage()); } } Collections.sort(instanceDisks, new Comparator() { @@ -6894,16 +6894,16 @@ private List getUnmanageInstanceNics(VmwareHypervisorHost } } } else { - s_logger.info(String.format("Unable to retrieve guest nics for instance: %s from VMware tools as tools status: %s! ", vmMo.getName(), guestInfo.getToolsStatus().toString())); + s_logger.info(String.format("Unable to retrieve guest nics for instance: %s from VMware tools as tools status: %s", vmMo.getName(), guestInfo.getToolsStatus().toString())); } } catch (Exception e) { - s_logger.info("Unable to retrieve guest nics for instance from VMware tools! " + e.getMessage()); + s_logger.info("Unable to retrieve guest nics for instance from VMware tools. " + e.getMessage()); } VirtualDevice[] nics = null; try { nics = vmMo.getNicDevices(); } catch (Exception e) { - s_logger.info("Unable to retrieve unmanaged instance nics! " + e.getMessage()); + s_logger.info("Unable to retrieve unmanaged instance nics. " + e.getMessage()); } if (nics != null) { for (VirtualDevice nic : nics) { @@ -6978,7 +6978,7 @@ private List getUnmanageInstanceNics(VmwareHypervisorHost } instanceNics.add(instanceNic); } catch (Exception e) { - s_logger.info("Unable to retrieve unmanaged instance nic info! " + e.getMessage()); + s_logger.info("Unable to retrieve unmanaged instance nic info. " + e.getMessage()); } } Collections.sort(instanceNics, new Comparator() { @@ -7034,7 +7034,7 @@ private UnmanagedInstance getUnmanagedInstance(VmwareHypervisorHost hyperHost, V instance.setDisks(getUnmanageInstanceDisks(vmMo)); instance.setNics(getUnmanageInstanceNics(hyperHost, vmMo)); } catch (Exception e) { - s_logger.info("Unable to retrieve unmanaged instance info! " + e.getMessage()); + s_logger.info("Unable to retrieve unmanaged instance info. " + e.getMessage()); } return instance; diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index cd9af2c5986d..96e9603f7672 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -372,20 +372,20 @@ private boolean storagePoolSupportsServiceOffering(StoragePool pool, ServiceOffe private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedInstance instance, ServiceOfferingVO serviceOffering, final Account owner, final DataCenter zone, final Map details) throws ServerApiException, PermissionDeniedException, ResourceAllocationException { if (instance == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM is not valid!")); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM is not valid")); } if (serviceOffering == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering is not valid!")); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering is not valid")); } accountService.checkAccess(owner, serviceOffering, zone); final Integer cpu = instance.getCpuCores(); final Integer memory = instance.getMemory(); Integer cpuSpeed = instance.getCpuSpeed() == null ? 0 : instance.getCpuSpeed(); if (cpu == null || cpu == 0) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("CPU cores for VM not valid!")); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("CPU cores for VM not valid")); } if (memory == null || memory == 0) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Memory for VM not valid!", instance.getName())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Memory for VM not valid", instance.getName())); } if (serviceOffering.isDynamic()) { if (details.containsKey(VmDetailConstants.CPU_SPEED)) { @@ -405,13 +405,13 @@ private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedIns serviceOffering = serviceOfferingDao.getComputeOffering(serviceOffering, parameters); } else { if (!cpu.equals(serviceOffering.getCpu()) && !instance.getPowerState().equals(UnmanagedInstance.PowerState.PowerOff)) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %d CPU cores does not matches VM CPU cores %d and VM is not in powered off state (Power state: %s)!", serviceOffering.getUuid(), serviceOffering.getCpu(), cpu, instance.getPowerState())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %d CPU cores does not matches VM CPU cores %d and VM is not in powered off state (Power state: %s)", serviceOffering.getUuid(), serviceOffering.getCpu(), cpu, instance.getPowerState())); } if (!memory.equals(serviceOffering.getRamSize()) && !instance.getPowerState().equals(UnmanagedInstance.PowerState.PowerOff)) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %dMB memory does not matches VM memory %dMB and VM is not in powered off state (Power state: %s)!", serviceOffering.getUuid(), serviceOffering.getRamSize(), memory, instance.getPowerState())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %dMB memory does not matches VM memory %dMB and VM is not in powered off state (Power state: %s)", serviceOffering.getUuid(), serviceOffering.getRamSize(), memory, instance.getPowerState())); } if (cpuSpeed != null && cpuSpeed > 0 && !cpuSpeed.equals(serviceOffering.getSpeed()) && !instance.getPowerState().equals(UnmanagedInstance.PowerState.PowerOff)) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %dMHz CPU speed does not matches VM CPU speed %dMHz and VM is not in powered off state (Power state: %s)!", serviceOffering.getUuid(), serviceOffering.getSpeed(), cpuSpeed, instance.getPowerState())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %dMHz CPU speed does not matches VM CPU speed %dMHz and VM is not in powered off state (Power state: %s)", serviceOffering.getUuid(), serviceOffering.getSpeed(), cpuSpeed, instance.getPowerState())); } } resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.cpu, new Long(serviceOffering.getCpu())); @@ -429,7 +429,7 @@ private Map getNicIpAddresses(final List 1) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple IP addresses (%s, %s) present for nic ID: %s. IP address cannot be assigned automatically, only single IP address auto-assigning supported!", nic.getIpAddress().get(0), nic.getIpAddress().get(1), nic.getNicId())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple IP addresses (%s, %s) present for nic ID: %s. IP address cannot be assigned automatically, only single IP address auto-assigning supported", nic.getIpAddress().get(0), nic.getIpAddress().get(1), nic.getNicId())); } String address = nic.getIpAddress().get(0); if (NetUtils.isValidIp4(address)) { @@ -472,7 +472,7 @@ private StoragePool getStoragePool(final UnmanagedInstance.Disk disk, final Data } } if (storagePool == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk %s(%s) with datastore: %s not found in zone ID: %s!", disk.getLabel(), disk.getDiskId(), disk.getDatastoreName(), zone.getUuid())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk %s(%s) with datastore: %s not found in zone ID: %s", disk.getLabel(), disk.getDiskId(), disk.getDatastoreName(), zone.getUuid())); } return storagePool; } @@ -480,22 +480,22 @@ private StoragePool getStoragePool(final UnmanagedInstance.Disk disk, final Data private void checkUnmanagedDiskAndOfferingForImport(UnmanagedInstance.Disk disk, DiskOffering diskOffering, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed) throws ServerApiException, PermissionDeniedException, ResourceAllocationException { if (diskOffering == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID: %s not found during VM import!", disk.getDiskId())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID: %s not found during VM import", disk.getDiskId())); } accountService.checkAccess(owner, diskOffering, zone); resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.volume); if (disk.getCapacity() == null || disk.getCapacity() == 0) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk(ID: %s) is found invalid during VM import!", disk.getDiskId())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk(ID: %s) is found invalid during VM import", disk.getDiskId())); } if (!diskOffering.isCustomized() && diskOffering.getDiskSize() == 0) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of fixed disk offering(ID: %s) is found invalid during VM import!", diskOffering.getUuid())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of fixed disk offering(ID: %s) is found invalid during VM import", diskOffering.getUuid())); } if (!diskOffering.isCustomized() && diskOffering.getDiskSize() < disk.getCapacity()) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk offering(ID: %s) %dGB is found less than the size of disk(ID: %s) %dGB during VM import!", diskOffering.getUuid(), (diskOffering.getDiskSize() / Resource.ResourceType.bytesToGiB), disk.getDiskId(), (disk.getCapacity() / (Resource.ResourceType.bytesToGiB)))); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk offering(ID: %s) %dGB is found less than the size of disk(ID: %s) %dGB during VM import", diskOffering.getUuid(), (diskOffering.getDiskSize() / Resource.ResourceType.bytesToGiB), disk.getDiskId(), (disk.getCapacity() / (Resource.ResourceType.bytesToGiB)))); } StoragePool storagePool = getStoragePool(disk, zone, cluster); if (storagePool == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk ID: %s with datastore: %s not found in zone ID: %s, cluster ID: %s!", disk.getDiskId(), disk.getDatastoreName(), zone.getUuid(), cluster.getUuid())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk ID: %s with datastore: %s not found in zone ID: %s, cluster ID: %s", disk.getDiskId(), disk.getDatastoreName(), zone.getUuid(), cluster.getUuid())); } if (!migrateAllowed && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) { throw new InvalidParameterValueException(String.format("Disk offering: %s is not compatible with storage pool: %s of unmanaged disk: %s", diskOffering.getUuid(), storagePool.getUuid(), disk.getDiskId())); @@ -507,16 +507,16 @@ private void checkUnmanagedDiskAndOfferingForImport(List String diskController = null; for (UnmanagedInstance.Disk disk : disks) { if (disk == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve disk details for VM!")); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve disk details for VM")); } if (!diskOfferingMap.containsKey(disk.getDiskId())) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID: %s not found during VM import!", disk.getDiskId())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID: %s not found during VM import", disk.getDiskId())); } if (Strings.isNullOrEmpty(diskController)) { diskController = disk.getController(); } else { if(!diskController.equals(disk.getController())) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple data disk controllers of different type (%s, %s) are not supported for import. Please make sure that all disk controllers are of the same type!", diskController, disk.getController())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple data disk controllers of different type (%s, %s) are not supported for import. Please make sure that all data disk controllers are of the same type", diskController, disk.getController())); } } checkUnmanagedDiskAndOfferingForImport(disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), owner, zone, cluster, migrateAllowed); @@ -525,17 +525,17 @@ private void checkUnmanagedDiskAndOfferingForImport(List private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Network network, final DataCenter zone, final Account owner) throws ServerApiException { if (nic == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import!")); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import")); } if (network == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import!", nic.getNicId())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import", nic.getNicId())); } if (network.getDataCenterId() != zone.getId()) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network(ID: %s) for nic(ID: %s) belongs to a different zone than VM to be imported!", network.getUuid(), nic.getNicId())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network(ID: %s) for nic(ID: %s) belongs to a different zone than VM to be imported", network.getUuid(), nic.getNicId())); } networkModel.checkNetworkPermissions(owner, network); if (nic.getVlan() != null && (Strings.isNullOrEmpty(network.getBroadcastUri().toString()) || !network.getBroadcastUri().toString().equals(String.format("vlan://%d", nic.getVlan())))) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VLAN of network(ID: %s) %s is found different from the VLAN of nic(ID: %s) vlan://%d during VM import!", network.getUuid(), network.getBroadcastUri().toString(), nic.getNicId(), nic.getVlan())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VLAN of network(ID: %s) %s is found different from the VLAN of nic(ID: %s) vlan://%d during VM import", network.getUuid(), network.getBroadcastUri().toString(), nic.getNicId(), nic.getVlan())); } } @@ -556,20 +556,20 @@ private void checkUnmanagedNicAndNetworkHostnameForImport(UnmanagedInstance.Nic private void checkUnmanagedNicIpAndNetworkForImport(UnmanagedInstance.Nic nic, Network network, final Network.IpAddresses ipAddresses) throws ServerApiException { if (nic == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import!")); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import")); } if (network == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import!", nic.getNicId())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import", nic.getNicId())); } // Check IP is assigned for non L2 networks if (!network.getGuestType().equals(Network.GuestType.L2) && (ipAddresses == null || Strings.isNullOrEmpty(ipAddresses.getIp4Address()))) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC(ID: %s) needs a valid IP address for it to be associated with network(ID: %s)! %s parameter of API can be used for this.", nic.getNicId(), network.getUuid(), ApiConstants.NIC_IP_ADDRESS_LIST)); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC(ID: %s) needs a valid IP address for it to be associated with network(ID: %s). %s parameter of API can be used for this", nic.getNicId(), network.getUuid(), ApiConstants.NIC_IP_ADDRESS_LIST)); } // If IP v4 is assigned and not set to auto-assign check it is available for network if (ipAddresses != null && !Strings.isNullOrEmpty(ipAddresses.getIp4Address()) && !ipAddresses.getIp4Address().equals("auto")) { Set ips = networkModel.getAvailableIps(network, ipAddresses.getIp4Address()); if (CollectionUtils.isEmpty(ips) || !ips.contains(NetUtils.ip2Long(ipAddresses.getIp4Address()))) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("IP address %s for NIC(ID: %s) is not available in network(ID: %s)!", ipAddresses.getIp4Address(), nic.getNicId(), network.getUuid())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("IP address %s for NIC(ID: %s) is not available in network(ID: %s)", ipAddresses.getIp4Address(), nic.getNicId(), network.getUuid())); } } } @@ -582,7 +582,7 @@ private Map getUnmanagedNicNetworkMap(List nicAdapter = nic.getAdapterType(); } else { if (!nicAdapter.equals(nic.getAdapterType())) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple network adapter of different type (%s, %s) are not supported for import. Please make sure that all network adapters are of the same type!", nicAdapter, nic.getAdapterType())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple network adapter of different type (%s, %s) are not supported for import. Please make sure that all network adapters are of the same type", nicAdapter, nic.getAdapterType())); } } Network network = null; @@ -617,7 +617,7 @@ private Map getUnmanagedNicNetworkMap(List checkUnmanagedNicIpAndNetworkForImport(nic, network, ipAddresses); } if (network == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Suitable network for nic(ID: %s) not found during VM import!", nic.getNicId())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Suitable network for nic(ID: %s) not found during VM import", nic.getNicId())); } nicNetworkMap.put(nic.getNicId(), network.getId()); } @@ -634,7 +634,7 @@ private Pair importDisk(UnmanagedInstance.Disk disk, V final DataCenter zone = dataCenterDao.findById(vm.getDataCenterId()); StoragePool storagePool = getStoragePool(disk, zone, cluster); if (storagePool == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk ID: %s with datastore: %s not found in zone ID: %s, cluster ID: %s!", disk.getDiskId(), disk.getDatastoreName(), zone.getUuid(), cluster.getUuid())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk ID: %s with datastore: %s not found in zone ID: %s, cluster ID: %s", disk.getDiskId(), disk.getDatastoreName(), zone.getUuid(), cluster.getUuid())); } DiskProfile profile = volumeManager.importVolume(type, name, diskOffering, diskSize, diskOffering.getMinIops(), diskOffering.getMaxIops(), vm, template, owner, deviceId, storagePool.getId(), imagePath, gson.toJson(diskInfo)); @@ -645,7 +645,7 @@ private Pair importDisk(UnmanagedInstance.Disk disk, V private NicProfile importNic(UnmanagedInstance.Nic nic, VirtualMachine vm, Network network, Network.IpAddresses ipAddresses, boolean isDefaultNic) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException { Pair result = networkOrchestrationService.importNic(nic.getMacAddress(), 0, network, isDefaultNic, vm, ipAddresses); if (result == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC ID: %s import failed!", nic.getNicId())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC ID: %s import failed", nic.getNicId())); } return result.first(); } @@ -670,13 +670,13 @@ private void cleanupFailedImportVM(final UserVm userVm) { private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate template, ServiceOfferingVO serviceOffering, UserVm userVm, final Account owner, List> diskProfileStoragePoolList) { UserVm vm = userVm; if (vm == null) { - LOGGER.error(String.format("Failed to check migrations need during VM import!")); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to check migrations need during VM import!")); + LOGGER.error(String.format("Failed to check migrations need during VM import")); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to check migrations need during VM import")); } if (sourceHost == null || serviceOffering == null || diskProfileStoragePoolList == null) { - LOGGER.error(String.format("Failed to check migrations need during import, VM: %s!", userVm.getInstanceName())); + LOGGER.error(String.format("Failed to check migrations need during import, VM: %s", userVm.getInstanceName())); cleanupFailedImportVM(vm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to check migrations need during import, VM: %s!", userVm.getInstanceName())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to check migrations need during import, VM: %s", userVm.getInstanceName())); } if (!hostSupportsServiceOffering(sourceHost, serviceOffering)) { final VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm, template, serviceOffering, owner, null); @@ -687,26 +687,26 @@ private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate templ try { dest = deploymentPlanningManager.planDeployment(profile, plan, excludeList, null); } catch (Exception e) { - LOGGER.warn(String.format("VM import failed for unmanaged vm: %s during vm migration, finding deployment destination!", vm.getInstanceName()), e); + LOGGER.warn(String.format("VM import failed for unmanaged vm: %s during vm migration, finding deployment destination", vm.getInstanceName()), e); cleanupFailedImportVM(vm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during vm migration, finding deployment destination!", vm.getInstanceName())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during vm migration, finding deployment destination", vm.getInstanceName())); } if (dest != null) { if (LOGGER.isDebugEnabled()) { - LOGGER.debug(" Found " + dest + " for migrating the vm to."); + LOGGER.debug(" Found " + dest + " for migrating the vm to"); } } if (dest == null) { cleanupFailedImportVM(vm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during vm migration, no deployment destination found!", vm.getInstanceName())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during vm migration, no deployment destination found", vm.getInstanceName())); } try { virtualMachineManager.migrate(vm.getUuid(), sourceHost.getId(), dest); vm = userVmManager.getUserVm(vm.getId()); } catch (Exception e) { - LOGGER.error(String.format("VM import failed for unmanaged vm: %s during vm migration!", vm.getInstanceName()), e); + LOGGER.error(String.format("VM import failed for unmanaged vm: %s during vm migration", vm.getInstanceName()), e); cleanupFailedImportVM(vm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during vm migration! %s", userVm.getInstanceName(), e.getMessage())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during vm migration. %s", userVm.getInstanceName(), e.getMessage())); } } for (Pair diskProfileStoragePool : diskProfileStoragePoolList) { @@ -735,15 +735,15 @@ private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate templ List storagePools = poolsPair.second(); if (CollectionUtils.isEmpty(storagePools)) { cleanupFailedImportVM(vm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume migration!", userVm.getInstanceName())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume migration", userVm.getInstanceName())); } StoragePool storagePool = storagePools.get(0); try { volumeManager.migrateVolume(volumeVO, storagePool); } catch (Exception e) { - LOGGER.error(String.format("VM import failed for unmanaged vm: %s during volume migration!", vm.getInstanceName()), e); + LOGGER.error(String.format("VM import failed for unmanaged vm: %s during volume migration", vm.getInstanceName()), e); cleanupFailedImportVM(vm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume migration! %s", userVm.getInstanceName(), Strings.nullToEmpty(e.getMessage()))); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume migration. %s", userVm.getInstanceName(), Strings.nullToEmpty(e.getMessage()))); } } return userVm; @@ -751,7 +751,7 @@ private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate templ private void publishVMUsageUpdateResourceCount(final UserVm userVm, ServiceOfferingVO serviceOfferingVO) { if (userVm == null || serviceOfferingVO == null) { - LOGGER.error("Failed to publish usage records during VM import!"); + LOGGER.error("Failed to publish usage records during VM import"); cleanupFailedImportVM(userVm); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm during publishing usage records")); } @@ -764,7 +764,7 @@ private void publishVMUsageUpdateResourceCount(final UserVm userVm, ServiceOffer userVm.getHypervisorType().toString(), VirtualMachine.class.getName(), userVm.getUuid(), userVm.getDetails(), userVm.isDisplayVm()); } } catch (Exception e) { - LOGGER.error("Failed to publish usage records during VM import!"); + LOGGER.error("Failed to publish usage records during VM import"); cleanupFailedImportVM(userVm); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm %s during publishing usage records", userVm.getInstanceName())); } @@ -778,7 +778,7 @@ private void publishVMUsageUpdateResourceCount(final UserVm userVm, ServiceOffer UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), volume.getDiskOfferingId(), null, volume.getSize(), Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); } catch (Exception e) { - LOGGER.error(String.format("Failed to publish volume usage records during VM import! %s", Strings.nullToEmpty(e.getMessage()))); + LOGGER.error(String.format("Failed to publish volume usage records during VM import. %s", Strings.nullToEmpty(e.getMessage()))); } resourceLimitService.incrementResourceCount(userVm.getAccountId(), Resource.ResourceType.volume, volume.isDisplayVolume()); resourceLimitService.incrementResourceCount(userVm.getAccountId(), Resource.ResourceType.primary_storage, volume.isDisplayVolume(), volume.getSize()); @@ -796,8 +796,8 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns try { validatedServiceOffering = getUnmanagedInstanceServiceOffering(unmanagedInstance, serviceOffering, owner, zone, details); } catch (Exception e) { - LOGGER.error("Service offering for VM import not compatible!", e); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import VM: %s! %s", unmanagedInstance.getName(), Strings.nullToEmpty(e.getMessage()))); + LOGGER.error("Service offering for VM import not compatible", e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import VM: %s. %s", unmanagedInstance.getName(), Strings.nullToEmpty(e.getMessage()))); } Map allDetails = new HashMap<>(details); @@ -819,7 +819,7 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns } final UnmanagedInstance.Disk rootDisk = unmanagedInstance.getDisks().get(0); if (rootDisk == null || Strings.isNullOrEmpty(rootDisk.getController())) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed! Unable to retrieve root disk details for VM: %s ", instanceName)); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed. Unable to retrieve root disk details for VM: %s ", instanceName)); } allDetails.put(VmDetailConstants.ROOT_DISK_CONTROLLER, rootDisk.getController()); List dataDisks = new ArrayList<>(); @@ -833,8 +833,8 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns } resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.volume, unmanagedInstanceDisks.size()); } catch (ResourceAllocationException e) { - LOGGER.error(String.format("Volume resource allocation error for owner: %s!", owner.getUuid()), e); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resource allocation error for owner: %s! %s", owner.getUuid(), Strings.nullToEmpty(e.getMessage()))); + LOGGER.error(String.format("Volume resource allocation error for owner: %s", owner.getUuid()), e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resource allocation error for owner: %s. %s", owner.getUuid(), Strings.nullToEmpty(e.getMessage()))); } // Check NICs and supplied networks Map nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap); @@ -904,11 +904,11 @@ public ListResponse listUnmanagedInstances(ListUnmana } final Long clusterId = cmd.getClusterId(); if (clusterId == null) { - throw new InvalidParameterValueException(String.format("Cluster ID cannot be null!")); + throw new InvalidParameterValueException(String.format("Cluster ID cannot be null")); } final Cluster cluster = clusterDao.findById(clusterId); if (cluster == null) { - throw new InvalidParameterValueException(String.format("Cluster ID: %d cannot be found!", clusterId)); + throw new InvalidParameterValueException(String.format("Cluster ID: %d cannot be found", clusterId)); } if (cluster.getHypervisorType() != Hypervisor.HypervisorType.VMware) { throw new InvalidParameterValueException(String.format("VM ingestion is currently not supported for hypervisor: %s", cluster.getHypervisorType().toString())); @@ -952,11 +952,11 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { } final Long clusterId = cmd.getClusterId(); if (clusterId == null) { - throw new InvalidParameterValueException(String.format("Cluster ID cannot be null!")); + throw new InvalidParameterValueException(String.format("Cluster ID cannot be null")); } final Cluster cluster = clusterDao.findById(clusterId); if (cluster == null) { - throw new InvalidParameterValueException(String.format("Cluster ID: %d cannot be found!", clusterId)); + throw new InvalidParameterValueException(String.format("Cluster ID: %d cannot be found", clusterId)); } if (cluster.getHypervisorType() != Hypervisor.HypervisorType.VMware) { throw new InvalidParameterValueException(String.format("VM import is currently not supported for hypervisor: %s", cluster.getHypervisorType().toString())); @@ -964,7 +964,7 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { final DataCenter zone = dataCenterDao.findById(cluster.getDataCenterId()); final String instanceName = cmd.getName(); if (Strings.isNullOrEmpty(instanceName)) { - throw new InvalidParameterValueException(String.format("Instance name cannot be empty!")); + throw new InvalidParameterValueException(String.format("Instance name cannot be empty")); } final Account owner = accountService.getActiveAccountById(cmd.getEntityOwnerId()); @@ -978,36 +978,36 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { if (templateId == null) { template = templateDao.findByName(VM_IMPORT_DEFAULT_TEMPLATE_NAME); if (template == null) { - throw new InvalidParameterValueException(String.format("Default VM import template with unique name: %s for hypervisor: %s cannot be found! Please use templateid paramter for import.", VM_IMPORT_DEFAULT_TEMPLATE_NAME, cluster.getHypervisorType().toString())); + throw new InvalidParameterValueException(String.format("Default VM import template with unique name: %s for hypervisor: %s cannot be found. Please use templateid paramter for import", VM_IMPORT_DEFAULT_TEMPLATE_NAME, cluster.getHypervisorType().toString())); } } else { template = templateDao.findById(templateId); } if (template == null) { - throw new InvalidParameterValueException(String.format("Template ID: %d cannot be found!", templateId)); + throw new InvalidParameterValueException(String.format("Template ID: %d cannot be found", templateId)); } final Long serviceOfferingId = cmd.getServiceOfferingId(); if (serviceOfferingId == null) { - throw new InvalidParameterValueException(String.format("Service offering ID cannot be null!")); + throw new InvalidParameterValueException(String.format("Service offering ID cannot be null")); } final ServiceOfferingVO serviceOffering = serviceOfferingDao.findById(serviceOfferingId); if (serviceOffering == null) { - throw new InvalidParameterValueException(String.format("Service offering ID: %d cannot be found!", serviceOfferingId)); + throw new InvalidParameterValueException(String.format("Service offering ID: %d cannot be found", serviceOfferingId)); } accountService.checkAccess(owner, serviceOffering, zone); try { resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.user_vm, 1); } catch (ResourceAllocationException e) { LOGGER.error(String.format("VM resource allocation error for account: %s", owner.getUuid()), e); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM resource allocation error for account: %s! %s", owner.getUuid(), Strings.nullToEmpty(e.getMessage()))); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM resource allocation error for account: %s. %s", owner.getUuid(), Strings.nullToEmpty(e.getMessage()))); } final Long diskOfferingId = cmd.getDiskOfferingId(); if (diskOfferingId == null) { - throw new InvalidParameterValueException(String.format("Service offering ID cannot be null!")); + throw new InvalidParameterValueException(String.format("Service offering ID cannot be null")); } final DiskOffering diskOffering = diskOfferingDao.findById(diskOfferingId); if (diskOffering == null) { - throw new InvalidParameterValueException(String.format("Disk offering ID: %d cannot be found!", diskOfferingId)); + throw new InvalidParameterValueException(String.format("Disk offering ID: %d cannot be found", diskOfferingId)); } String displayName = cmd.getDisplayName(); if (Strings.isNullOrEmpty(displayName)) { @@ -1030,7 +1030,7 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { // In case of VMware since VM name must be unique within a DC, check if VM with the same hostname already exists in the zone. VMInstanceVO vmByHostName = vmDao.findVMByHostNameInZone(hostName, zone.getId()); if (vmByHostName != null && vmByHostName.getState() != VirtualMachine.State.Expunging) { - throw new InvalidParameterValueException(String.format("Failed to import VM: %s! There already exists a VM by the hostname: %s in zone: %s", instanceName, hostName, zone.getUuid())); + throw new InvalidParameterValueException(String.format("Failed to import VM: %s. There already exists a VM by the hostname: %s in zone: %s", instanceName, hostName, zone.getUuid())); } } final Map nicNetworkMap = cmd.getNicNetworkList(); From e6ab488c64178f1d93fd9148c602237126c2491b Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 11 Oct 2019 16:00:12 +0530 Subject: [PATCH 30/61] fix - ignore IP for L2 networks Signed-off-by: Abhishek Kumar --- .../cloudstack/engine/orchestration/NetworkOrchestrator.java | 2 ++ .../java/org/apache/cloudstack/vm/VmImportManagerImpl.java | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index bfa69ddcc50e..972aad6e0525 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -3953,6 +3953,8 @@ public Pair importNic(final String macAddress, int deviceId } if (network.getGuestType() != GuestType.L2) { guestIp = _ipAddrMgr.acquireGuestIpAddress(network, ipAddresses.getIp4Address()); + } else { + guestIp = null; } if (guestIp == null && network.getGuestType() != GuestType.L2 && !_networkModel.listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) { throw new InsufficientVirtualNetworkCapacityException("Unable to acquire Guest IP address for network " + network, DataCenter.class, diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 96e9603f7672..540d025ac26f 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -565,8 +565,8 @@ private void checkUnmanagedNicIpAndNetworkForImport(UnmanagedInstance.Nic nic, N if (!network.getGuestType().equals(Network.GuestType.L2) && (ipAddresses == null || Strings.isNullOrEmpty(ipAddresses.getIp4Address()))) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC(ID: %s) needs a valid IP address for it to be associated with network(ID: %s). %s parameter of API can be used for this", nic.getNicId(), network.getUuid(), ApiConstants.NIC_IP_ADDRESS_LIST)); } - // If IP v4 is assigned and not set to auto-assign check it is available for network - if (ipAddresses != null && !Strings.isNullOrEmpty(ipAddresses.getIp4Address()) && !ipAddresses.getIp4Address().equals("auto")) { + // If network is non L2, IP v4 is assigned and not set to auto-assign, check it is available for network + if (!network.getGuestType().equals(Network.GuestType.L2) && ipAddresses != null && !Strings.isNullOrEmpty(ipAddresses.getIp4Address()) && !ipAddresses.getIp4Address().equals("auto")) { Set ips = networkModel.getAvailableIps(network, ipAddresses.getIp4Address()); if (CollectionUtils.isEmpty(ips) || !ips.contains(NetUtils.ip2Long(ipAddresses.getIp4Address()))) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("IP address %s for NIC(ID: %s) is not available in network(ID: %s)", ipAddresses.getIp4Address(), nic.getNicId(), network.getUuid())); From 39fd3b5ded8d05a53881e83d5c25502b6174f421 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 14 Oct 2019 14:30:54 +0530 Subject: [PATCH 31/61] fix unmanaged nic vlan check Signed-off-by: Abhishek Kumar --- .../main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 540d025ac26f..003d689b0895 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -534,7 +534,7 @@ private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Net throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network(ID: %s) for nic(ID: %s) belongs to a different zone than VM to be imported", network.getUuid(), nic.getNicId())); } networkModel.checkNetworkPermissions(owner, network); - if (nic.getVlan() != null && (Strings.isNullOrEmpty(network.getBroadcastUri().toString()) || !network.getBroadcastUri().toString().equals(String.format("vlan://%d", nic.getVlan())))) { + if (nic.getVlan() != null && nic.getVlan() != 0 && (Strings.isNullOrEmpty(network.getBroadcastUri().toString()) || !network.getBroadcastUri().toString().equals(String.format("vlan://%d", nic.getVlan())))) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VLAN of network(ID: %s) %s is found different from the VLAN of nic(ID: %s) vlan://%d during VM import", network.getUuid(), network.getBroadcastUri().toString(), nic.getNicId(), nic.getVlan())); } } From 384122cb86605606e389d44cd18de8b608e9f6b6 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 14 Oct 2019 10:34:06 +0530 Subject: [PATCH 32/61] fix volume migration failure Signed-off-by: Abhishek Kumar --- .../cloudstack/vm/UnmanagedInstance.java | 20 ++++++++++++++ .../vmware/resource/VmwareResource.java | 8 +++++- .../cloudstack/vm/VmImportManagerImpl.java | 26 +++++++++---------- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java index 58ac513790d3..e008915457da 100644 --- a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java +++ b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java @@ -134,6 +134,8 @@ public static class Disk { private Long capacity; + private String fileBaseName; + private String imagePath; private String controller; @@ -142,6 +144,8 @@ public static class Disk { private Integer position; + private String chainInfo; + private String datastoreName; private String datastoreHost; @@ -174,6 +178,14 @@ public void setCapacity(Long capacity) { this.capacity = capacity; } + public String getFileBaseName() { + return fileBaseName; + } + + public void setFileBaseName(String fileBaseName) { + this.fileBaseName = fileBaseName; + } + public String getImagePath() { return imagePath; } @@ -206,6 +218,14 @@ public void setPosition(Integer position) { this.position = position; } + public String getChainInfo() { + return chainInfo; + } + + public void setChainInfo(String chainInfo) { + this.chainInfo = chainInfo; + } + public String getDatastoreName() { return datastoreName; } diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 2b4916fe914b..b790835adbeb 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -6813,8 +6813,15 @@ private List getUnmanageInstanceDisks(VirtualMachineMO v VirtualDisk disk = (VirtualDisk) diskDevice; instanceDisk.setDiskId(disk.getDiskObjectId()); instanceDisk.setLabel(disk.getDeviceInfo() != null ? disk.getDeviceInfo().getLabel() : ""); + instanceDisk.setFileBaseName(vmMo.getVmdkFileBaseName(disk)); instanceDisk.setImagePath(getAbsoluteVmdkFile(disk)); instanceDisk.setCapacity(disk.getCapacityInBytes()); + instanceDisk.setPosition(diskDevice.getUnitNumber()); + DatastoreFile file = new DatastoreFile(getAbsoluteVmdkFile(disk)); + if (!Strings.isNullOrEmpty(file.getFileBaseName()) && !Strings.isNullOrEmpty(file.getDatastoreName())) { + VirtualMachineDiskInfo diskInfo = vmMo.getDiskInfoBuilder().getDiskInfoByBackingFileBaseName(file.getFileBaseName(), file.getDatastoreName()); + instanceDisk.setChainInfo(getGson().toJson(diskInfo)); + } for (VirtualDevice device : vmMo.getAllDeviceList()) { if (diskDevice.getControllerKey() == device.getKey()) { if (device instanceof VirtualIDEController) { @@ -6826,7 +6833,6 @@ private List getUnmanageInstanceDisks(VirtualMachineMO v } else { instanceDisk.setController(DiskControllerType.none.toString()); } - instanceDisk.setPosition(diskDevice.getUnitNumber()); break; } } diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 003d689b0895..8b3547922cd2 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -494,9 +494,6 @@ private void checkUnmanagedDiskAndOfferingForImport(UnmanagedInstance.Disk disk, throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk offering(ID: %s) %dGB is found less than the size of disk(ID: %s) %dGB during VM import", diskOffering.getUuid(), (diskOffering.getDiskSize() / Resource.ResourceType.bytesToGiB), disk.getDiskId(), (disk.getCapacity() / (Resource.ResourceType.bytesToGiB)))); } StoragePool storagePool = getStoragePool(disk, zone, cluster); - if (storagePool == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk ID: %s with datastore: %s not found in zone ID: %s, cluster ID: %s", disk.getDiskId(), disk.getDatastoreName(), zone.getUuid(), cluster.getUuid())); - } if (!migrateAllowed && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) { throw new InvalidParameterValueException(String.format("Disk offering: %s is not compatible with storage pool: %s of unmanaged disk: %s", diskOffering.getUuid(), storagePool.getUuid(), disk.getDiskId())); } @@ -626,18 +623,19 @@ private Map getUnmanagedNicNetworkMap(List private Pair importDisk(UnmanagedInstance.Disk disk, VirtualMachine vm, Cluster cluster, DiskOffering diskOffering, Volume.Type type, String name, Long diskSize, VirtualMachineTemplate template, - Account owner, Long deviceId, boolean migrateAllowed) { - VirtualMachineDiskInfo diskInfo = new VirtualMachineDiskInfo(); - diskInfo.setDiskDeviceBusName(String.format("%s%d:%d", disk.getController(), disk.getControllerUnit(), disk.getPosition())); - diskInfo.setDiskChain(new String[]{disk.getImagePath()}); - final String imagePath = disk.getImagePath(); + Account owner, Long deviceId) { final DataCenter zone = dataCenterDao.findById(vm.getDataCenterId()); - StoragePool storagePool = getStoragePool(disk, zone, cluster); - if (storagePool == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Storage pool for disk ID: %s with datastore: %s not found in zone ID: %s, cluster ID: %s", disk.getDiskId(), disk.getDatastoreName(), zone.getUuid(), cluster.getUuid())); + final String path = Strings.isNullOrEmpty(disk.getFileBaseName()) ? disk.getImagePath() : disk.getFileBaseName(); + String chainInfo = disk.getChainInfo(); + if (Strings.isNullOrEmpty(chainInfo)) { + VirtualMachineDiskInfo diskInfo = new VirtualMachineDiskInfo(); + diskInfo.setDiskDeviceBusName(String.format("%s%d:%d", disk.getController(), disk.getControllerUnit(), disk.getPosition())); + diskInfo.setDiskChain(new String[]{disk.getImagePath()}); + chainInfo = gson.toJson(diskInfo); } + StoragePool storagePool = getStoragePool(disk, zone, cluster); DiskProfile profile = volumeManager.importVolume(type, name, diskOffering, diskSize, - diskOffering.getMinIops(), diskOffering.getMaxIops(), vm, template, owner, deviceId, storagePool.getId(), imagePath, gson.toJson(diskInfo)); + diskOffering.getMinIops(), diskOffering.getMaxIops(), vm, template, owner, deviceId, storagePool.getId(), path, disk.getChainInfo()); return new Pair(profile, storagePool); } @@ -863,13 +861,13 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) { throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId())); } - diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, cluster, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()), (rootDisk.getCapacity() / Resource.ResourceType.bytesToGiB), template, owner, null, migrateAllowed)); + diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, cluster, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()), (rootDisk.getCapacity() / Resource.ResourceType.bytesToGiB), template, owner, null)); for (UnmanagedInstance.Disk disk : dataDisks) { if (disk.getCapacity() == null || disk.getCapacity() == 0) { throw new InvalidParameterValueException(String.format("Disk ID: %s size is invalid", rootDisk.getDiskId())); } DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId())); - diskProfileStoragePoolList.add(importDisk(disk, userVm, cluster, offering, Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()), (disk.getCapacity() / Resource.ResourceType.bytesToGiB), template, owner, null, migrateAllowed)); + diskProfileStoragePoolList.add(importDisk(disk, userVm, cluster, offering, Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()), (disk.getCapacity() / Resource.ResourceType.bytesToGiB), template, owner, null)); } } catch (Exception e) { LOGGER.error(String.format("Failed to import volumes while importing vm: %s", instanceName), e); From 2a45661ce9ebb864e28b829124998220a84a30db Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 14 Oct 2019 15:52:52 +0530 Subject: [PATCH 33/61] changes for creating dummy template from import service Signed-off-by: Abhishek Kumar --- .../java/com/cloud/storage/VMTemplateVO.java | 7 ++++++ .../cloudstack/vm/VmImportManagerImpl.java | 24 ++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/engine/schema/src/main/java/com/cloud/storage/VMTemplateVO.java b/engine/schema/src/main/java/com/cloud/storage/VMTemplateVO.java index 30440d3dc745..af04099f9a2a 100644 --- a/engine/schema/src/main/java/com/cloud/storage/VMTemplateVO.java +++ b/engine/schema/src/main/java/com/cloud/storage/VMTemplateVO.java @@ -230,6 +230,13 @@ public static VMTemplateVO createPreHostIso(Long id, String uniqueName, String n return template; } + public static VMTemplateVO createSystemIso(Long id, String uniqueName, String name, boolean isPublic, + String url, boolean requiresHvm, int bits, long accountId, String cksum, + String displayText, boolean enablePassword, long guestOSId) { + return new VMTemplateVO(id, uniqueName, name, ImageFormat.ISO, isPublic, false, TemplateType.SYSTEM, url, null, requiresHvm, bits, accountId, cksum, displayText, enablePassword, + guestOSId, false, null); + } + public VMTemplateVO(Long id, String uniqueName, String name, ImageFormat format, boolean isPublic, boolean featured, TemplateType type, String url, Date created, boolean requiresHvm, int bits, long accountId, String cksum, String displayText, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType) { diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 8b3547922cd2..63c14d70098d 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -197,6 +197,25 @@ public VmImportManagerImpl() { gson = GsonHelper.getGsonLogger(); } + private VMTemplateVO createDefaultDummyVmImportTemplate() { + VMTemplateVO template = null; + try { + template = VMTemplateVO.createSystemIso(templateDao.getNextInSequence(Long.class, "id"), VM_IMPORT_DEFAULT_TEMPLATE_NAME, VM_IMPORT_DEFAULT_TEMPLATE_NAME, true, + "", true, 64, Account.ACCOUNT_ID_SYSTEM, "", + "VM Import Default Template", false, 1); + template.setState(VirtualMachineTemplate.State.Inactive); + template = templateDao.persist(template); + if (template == null) { + return null; + } + templateDao.remove(template.getId()); + template = templateDao.findByName(VM_IMPORT_DEFAULT_TEMPLATE_NAME); + } catch (Exception e) { + LOGGER.error("Unable to create default dummy template for VM import", e); + } + return template; + } + private UnmanagedInstanceResponse createUnmanagedInstanceResponse(UnmanagedInstance instance, Cluster cluster, Host host) { UnmanagedInstanceResponse response = new UnmanagedInstanceResponse(); response.setName(instance.getName()); @@ -976,7 +995,10 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { if (templateId == null) { template = templateDao.findByName(VM_IMPORT_DEFAULT_TEMPLATE_NAME); if (template == null) { - throw new InvalidParameterValueException(String.format("Default VM import template with unique name: %s for hypervisor: %s cannot be found. Please use templateid paramter for import", VM_IMPORT_DEFAULT_TEMPLATE_NAME, cluster.getHypervisorType().toString())); + template = createDefaultDummyVmImportTemplate(); + if (template == null) { + throw new InvalidParameterValueException(String.format("Default VM import template with unique name: %s for hypervisor: %s cannot be created. Please use templateid paramter for import", VM_IMPORT_DEFAULT_TEMPLATE_NAME, cluster.getHypervisorType().toString())); + } } } else { template = templateDao.findById(templateId); From 2d6af838e40a53950398c36bb5a37471fe1b4d4a Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 14 Oct 2019 18:02:29 +0530 Subject: [PATCH 34/61] fix service offering, storage pool migration Signed-off-by: Abhishek Kumar --- .../cloudstack/vm/VmImportManagerImpl.java | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 63c14d70098d..cb0cea71f07a 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -496,7 +496,7 @@ private StoragePool getStoragePool(final UnmanagedInstance.Disk disk, final Data return storagePool; } - private void checkUnmanagedDiskAndOfferingForImport(UnmanagedInstance.Disk disk, DiskOffering diskOffering, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed) + private void checkUnmanagedDiskAndOfferingForImport(UnmanagedInstance.Disk disk, DiskOffering diskOffering, ServiceOffering serviceOffering, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed) throws ServerApiException, PermissionDeniedException, ResourceAllocationException { if (diskOffering == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID: %s not found during VM import", disk.getDiskId())); @@ -516,6 +516,9 @@ private void checkUnmanagedDiskAndOfferingForImport(UnmanagedInstance.Disk disk, if (!migrateAllowed && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) { throw new InvalidParameterValueException(String.format("Disk offering: %s is not compatible with storage pool: %s of unmanaged disk: %s", diskOffering.getUuid(), storagePool.getUuid(), disk.getDiskId())); } + if (serviceOffering != null && !migrateAllowed && !storagePoolSupportsServiceOffering(storagePool, serviceOffering)) { + throw new InvalidParameterValueException(String.format("Service offering: %s is not compatible with storage pool: %s of unmanaged disk: %s", diskOffering.getUuid(), storagePool.getUuid(), disk.getDiskId())); + } } private void checkUnmanagedDiskAndOfferingForImport(List disks, final Map diskOfferingMap, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed) @@ -535,7 +538,7 @@ private void checkUnmanagedDiskAndOfferingForImport(List throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple data disk controllers of different type (%s, %s) are not supported for import. Please make sure that all data disk controllers are of the same type", diskController, disk.getController())); } } - checkUnmanagedDiskAndOfferingForImport(disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), owner, zone, cluster, migrateAllowed); + checkUnmanagedDiskAndOfferingForImport(disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), null, owner, zone, cluster, migrateAllowed); } } @@ -696,6 +699,7 @@ private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate templ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to check migrations need during import, VM: %s", userVm.getInstanceName())); } if (!hostSupportsServiceOffering(sourceHost, serviceOffering)) { + LOGGER.debug(String.format("VM %s needs to be migrated", vm.getUuid())); final VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm, template, serviceOffering, owner, null); DeploymentPlanner.ExcludeList excludeList = new DeploymentPlanner.ExcludeList(); excludeList.addHost(sourceHost.getId()); @@ -745,16 +749,26 @@ private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate templ if (poolSupportsOfferings && profile.getType() == Volume.Type.ROOT) { poolSupportsOfferings = storagePoolSupportsServiceOffering(diskProfileStoragePool.second(), serviceOffering); } + LOGGER.debug(String.format("Pool tags %s, service offering tags %s, disk offering tags %s", diskProfileStoragePool.second().getId(), serviceOffering.getTags(), dOffering.getTags())); if (poolSupportsOfferings) { continue; } + LOGGER.debug(String.format("Volume %s needs to be migrated", volumeVO.getUuid())); Pair, List> poolsPair = managementService.listStoragePoolsForMigrationOfVolume(profile.getVolumeId()); List storagePools = poolsPair.second(); if (CollectionUtils.isEmpty(storagePools)) { cleanupFailedImportVM(vm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume migration", userVm.getInstanceName())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume ID: %s migration as no suitable pool found", userVm.getInstanceName(), volumeVO.getUuid())); + } + StoragePool storagePool = null; + for (StoragePool pool : storagePools) { + if (diskProfileStoragePool.second().getId() != pool.getId() && + storagePoolSupportsDiskOffering(pool, dOffering) && + storagePoolSupportsServiceOffering(pool, serviceOffering)) { + storagePool = pool; + break; + } } - StoragePool storagePool = storagePools.get(0); try { volumeManager.migrateVolume(volumeVO, storagePool); } catch (Exception e) { @@ -841,7 +855,7 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns allDetails.put(VmDetailConstants.ROOT_DISK_CONTROLLER, rootDisk.getController()); List dataDisks = new ArrayList<>(); try { - checkUnmanagedDiskAndOfferingForImport(rootDisk, diskOffering, owner, zone, cluster, migrateAllowed); + checkUnmanagedDiskAndOfferingForImport(rootDisk, diskOffering, validatedServiceOffering, owner, zone, cluster, migrateAllowed); if (unmanagedInstanceDisks.size() > 1) { // Data disk(s) present dataDisks.addAll(unmanagedInstanceDisks); dataDisks.remove(0); From 8638d05df57cd0ad00a93972ae7910cc71315d08 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 14 Oct 2019 18:57:08 +0530 Subject: [PATCH 35/61] migration null check Signed-off-by: Abhishek Kumar --- .../java/org/apache/cloudstack/vm/VmImportManagerImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index cb0cea71f07a..4153403d7711 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -769,6 +769,9 @@ private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate templ break; } } + if (storagePool == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume ID: %s migration as no suitable pool found", userVm.getInstanceName(), volumeVO.getUuid())); + } try { volumeManager.migrateVolume(volumeVO, storagePool); } catch (Exception e) { From 76b581f21a551d04d3cd9a1ec02478eebfaf3711 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 15 Oct 2019 01:36:07 +0530 Subject: [PATCH 36/61] fix volume migration Signed-off-by: Abhishek Kumar --- .../cloudstack/vm/VmImportManagerImpl.java | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 4153403d7711..f574cb55a788 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -534,7 +534,7 @@ private void checkUnmanagedDiskAndOfferingForImport(List if (Strings.isNullOrEmpty(diskController)) { diskController = disk.getController(); } else { - if(!diskController.equals(disk.getController())) { + if (!diskController.equals(disk.getController())) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Multiple data disk controllers of different type (%s, %s) are not supported for import. Please make sure that all data disk controllers are of the same type", diskController, disk.getController())); } } @@ -749,28 +749,45 @@ private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate templ if (poolSupportsOfferings && profile.getType() == Volume.Type.ROOT) { poolSupportsOfferings = storagePoolSupportsServiceOffering(diskProfileStoragePool.second(), serviceOffering); } - LOGGER.debug(String.format("Pool tags %s, service offering tags %s, disk offering tags %s", diskProfileStoragePool.second().getId(), serviceOffering.getTags(), dOffering.getTags())); if (poolSupportsOfferings) { continue; } LOGGER.debug(String.format("Volume %s needs to be migrated", volumeVO.getUuid())); Pair, List> poolsPair = managementService.listStoragePoolsForMigrationOfVolume(profile.getVolumeId()); - List storagePools = poolsPair.second(); - if (CollectionUtils.isEmpty(storagePools)) { + if (CollectionUtils.isEmpty(poolsPair.first()) && CollectionUtils.isEmpty(poolsPair.second())) { cleanupFailedImportVM(vm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume ID: %s migration as no suitable pool found", userVm.getInstanceName(), volumeVO.getUuid())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume ID: %s migration as no suitable pool(s) found", userVm.getInstanceName(), volumeVO.getUuid())); } + List storagePools = poolsPair.second(); StoragePool storagePool = null; - for (StoragePool pool : storagePools) { - if (diskProfileStoragePool.second().getId() != pool.getId() && - storagePoolSupportsDiskOffering(pool, dOffering) && - storagePoolSupportsServiceOffering(pool, serviceOffering)) { - storagePool = pool; - break; + if (CollectionUtils.isNotEmpty(storagePools)) { + for (StoragePool pool : storagePools) { + if (diskProfileStoragePool.second().getId() != pool.getId() && + storagePoolSupportsDiskOffering(pool, dOffering) && + (!profile.getType().equals(Volume.Type.ROOT) || + profile.getType().equals(Volume.Type.ROOT) && storagePoolSupportsServiceOffering(pool, serviceOffering))) { + storagePool = pool; + break; + } + } + } + // For zone-wide pools, at times, suitable storage pools are not returned therefore consider all pools. + if (storagePool == null && CollectionUtils.isNotEmpty(poolsPair.first())) { + storagePools = poolsPair.first(); + for (StoragePool pool : storagePools) { + if (diskProfileStoragePool.second().getId() != pool.getId() && + storagePoolSupportsDiskOffering(pool, dOffering) && + (!profile.getType().equals(Volume.Type.ROOT) || + profile.getType().equals(Volume.Type.ROOT) && storagePoolSupportsServiceOffering(pool, serviceOffering))) { + storagePool = pool; + break; + } } } if (storagePool == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume ID: %s migration as no suitable pool found", userVm.getInstanceName(), volumeVO.getUuid())); + } else { + LOGGER.debug(String.format("Found storage pool %s(%s) for migrating the volume %s to", storagePool.getName(), storagePool.getUuid(), volumeVO.getUuid())); } try { volumeManager.migrateVolume(volumeVO, storagePool); From c18b818d5ba9c6c567535575695a9bf82904fc2f Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 15 Oct 2019 11:58:49 +0530 Subject: [PATCH 37/61] fix isolated networks Signed-off-by: Abhishek Kumar --- .../org/apache/cloudstack/vm/VmImportManagerImpl.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index f574cb55a788..12a65466a64b 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -542,7 +542,7 @@ private void checkUnmanagedDiskAndOfferingForImport(List } } - private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Network network, final DataCenter zone, final Account owner) throws ServerApiException { + private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Network network, final DataCenter zone, final Account owner, final boolean autoAssign) throws ServerApiException { if (nic == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import")); } @@ -553,6 +553,9 @@ private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Net throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network(ID: %s) for nic(ID: %s) belongs to a different zone than VM to be imported", network.getUuid(), nic.getNicId())); } networkModel.checkNetworkPermissions(owner, network); + if (!autoAssign && network.getGuestType().equals(Network.GuestType.Isolated)) { + return; + } if (nic.getVlan() != null && nic.getVlan() != 0 && (Strings.isNullOrEmpty(network.getBroadcastUri().toString()) || !network.getBroadcastUri().toString().equals(String.format("vlan://%d", nic.getVlan())))) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VLAN of network(ID: %s) %s is found different from the VLAN of nic(ID: %s) vlan://%d during VM import", network.getUuid(), network.getBroadcastUri().toString(), nic.getNicId(), nic.getVlan())); } @@ -618,7 +621,7 @@ private Map getUnmanagedNicNetworkMap(List continue; } try { - checkUnmanagedNicAndNetworkForImport(nic, networkVO, zone, owner); + checkUnmanagedNicAndNetworkForImport(nic, networkVO, zone, owner, true); network = networkVO; } catch (Exception e) { } @@ -631,7 +634,7 @@ private Map getUnmanagedNicNetworkMap(List } } else { network = networkDao.findById(callerNicNetworkMap.get(nic.getNicId())); - checkUnmanagedNicAndNetworkForImport(nic, network, zone, owner); + checkUnmanagedNicAndNetworkForImport(nic, network, zone, owner, false); checkUnmanagedNicAndNetworkHostnameForImport(nic, network, hostName); checkUnmanagedNicIpAndNetworkForImport(nic, network, ipAddresses); } From 3029da73b45f2a413365952d95a4466d2dbf2193 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 15 Oct 2019 15:30:00 +0530 Subject: [PATCH 38/61] fix volume migration based on vm running state Signed-off-by: Abhishek Kumar --- .../service/VolumeOrchestrationService.java | 2 ++ .../engine/orchestration/VolumeOrchestrator.java | 3 ++- .../org/apache/cloudstack/vm/VmImportManagerImpl.java | 10 +++++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java index f21b0f0c574e..a769a3428b5e 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java @@ -88,6 +88,8 @@ VolumeInfo moveVolume(VolumeInfo volume, long destPoolDcId, Long destPoolPodId, Volume migrateVolume(Volume volume, StoragePool destPool) throws StorageUnavailableException; + Volume liveMigrateVolume(Volume volume, StoragePool destPool); + void cleanupStorageJobs(); void destroyVolume(Volume volume); diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java index 9aebae41097f..641538e4a3d1 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java @@ -1005,8 +1005,9 @@ public Volume migrateVolume(Volume volume, StoragePool destPool) throws StorageU } } + @Override @DB - protected Volume liveMigrateVolume(Volume volume, StoragePool destPool) { + public Volume liveMigrateVolume(Volume volume, StoragePool destPool) { VolumeInfo vol = volFactory.getVolume(volume.getId()); AsyncCallFuture future = volService.migrateVolume(vol, (DataStore)destPool); try { diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 12a65466a64b..d3eb39c94cf6 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -793,7 +793,15 @@ private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate templ LOGGER.debug(String.format("Found storage pool %s(%s) for migrating the volume %s to", storagePool.getName(), storagePool.getUuid(), volumeVO.getUuid())); } try { - volumeManager.migrateVolume(volumeVO, storagePool); + Volume volume = null; + if (vm.getState().equals(VirtualMachine.State.Running)) { + volume = volumeManager.liveMigrateVolume(volumeVO, storagePool); + } else { + volume = volumeManager.migrateVolume(volumeVO, storagePool); + } + if (volume == null) { + throw new Exception(); + } } catch (Exception e) { LOGGER.error(String.format("VM import failed for unmanaged vm: %s during volume migration", vm.getInstanceName()), e); cleanupFailedImportVM(vm); From c74ca2ec02219bc674d1137e28f09e559d06dfe7 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 15 Oct 2019 16:53:50 +0530 Subject: [PATCH 39/61] fix NPE for projectid param in import Signed-off-by: Abhishek Kumar --- .../java/org/apache/cloudstack/vm/VmImportManagerImpl.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index d3eb39c94cf6..090143d8be8d 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -1029,8 +1029,7 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { throw new InvalidParameterValueException(String.format("Instance name cannot be empty")); } final Account owner = accountService.getActiveAccountById(cmd.getEntityOwnerId()); - - Long userId = null; + long userId = CallContext.current().getCallingUserId(); List userVOs = userDao.listByAccount(owner.getAccountId()); if (CollectionUtils.isNotEmpty(userVOs)) { userId = userVOs.get(0).getId(); From 38318e64d35cad6ef77cfc9a22ae26916434c678 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 15 Oct 2019 17:35:09 +0530 Subject: [PATCH 40/61] fix - raise error when domainid is without accout param for import Signed-off-by: Abhishek Kumar --- .../java/org/apache/cloudstack/vm/VmImportManagerImpl.java | 3 +++ .../org/apache/cloudstack/vm/VmImportManagerImplTest.java | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 090143d8be8d..82a9b78ac0d9 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -1028,6 +1028,9 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { if (Strings.isNullOrEmpty(instanceName)) { throw new InvalidParameterValueException(String.format("Instance name cannot be empty")); } + if (cmd.getDomainId() != null && Strings.isNullOrEmpty(cmd.getAccountName())) { + throw new InvalidParameterValueException("domainid parameter must be specified with account parameter"); + } final Account owner = accountService.getActiveAccountById(cmd.getEntityOwnerId()); long userId = CallContext.current().getCallingUserId(); List userVOs = userDao.listByAccount(owner.getAccountId()); diff --git a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java index 64338e2f7996..9dc9fa82e048 100644 --- a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java @@ -308,6 +308,8 @@ public void listUnmanagedInstancesInvalidCallerTest() { public void importUnmanagedInstanceTest() { ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class); when(importUnmanageInstanceCmd.getName()).thenReturn("TestInstance"); + when(importUnmanageInstanceCmd.getAccountName()).thenReturn(null); + when(importUnmanageInstanceCmd.getDomainId()).thenReturn(null); PowerMockito.mockStatic(UsageEventUtils.class); vmIngestionService.importUnmanagedInstance(importUnmanageInstanceCmd); } @@ -325,6 +327,8 @@ public void importUnmanagedInstanceInvalidHostnameTest() { public void importUnmanagedInstanceMissingInstanceTest() { ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class); when(importUnmanageInstanceCmd.getName()).thenReturn("SomeInstance"); + when(importUnmanageInstanceCmd.getAccountName()).thenReturn(null); + when(importUnmanageInstanceCmd.getDomainId()).thenReturn(null); vmIngestionService.importUnmanagedInstance(importUnmanageInstanceCmd); } } \ No newline at end of file From df1be1e198a6e282014ea20f921c4e589fc882a4 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 16 Oct 2019 01:23:26 +0530 Subject: [PATCH 41/61] fix storagepool datastore casting Signed-off-by: Abhishek Kumar --- .../cloudstack/engine/orchestration/VolumeOrchestrator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java index 641538e4a3d1..1ab310093a11 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java @@ -1009,7 +1009,8 @@ public Volume migrateVolume(Volume volume, StoragePool destPool) throws StorageU @DB public Volume liveMigrateVolume(Volume volume, StoragePool destPool) { VolumeInfo vol = volFactory.getVolume(volume.getId()); - AsyncCallFuture future = volService.migrateVolume(vol, (DataStore)destPool); + DataStore dataStoreTarget = dataStoreMgr.getDataStore(destPool.getId(), DataStoreRole.Primary); + AsyncCallFuture future = volService.migrateVolume(vol, dataStoreTarget); try { VolumeApiResult result = future.get(); if (result.isFailed()) { From e105ccf8bf3b0d658c51c4c074e2aba018bd32fe Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 16 Oct 2019 01:28:59 +0530 Subject: [PATCH 42/61] fix moveVMToUser for removed template Signed-off-by: Abhishek Kumar --- server/src/main/java/com/cloud/vm/UserVmManagerImpl.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index 6a3fa088935e..23349bd487a5 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -5991,7 +5991,10 @@ public UserVm moveVMToUser(final AssignVMCmd cmd) throws ResourceAllocationExcep _resourceLimitMgr.checkResourceLimit(newAccount, ResourceType.primary_storage, totalVolumesSize); // VV 4: Check if new owner can use the vm template - VirtualMachineTemplate template = _templateDao.findById(vm.getTemplateId()); + VirtualMachineTemplate template = _templateDao.findByIdIncludingRemoved(vm.getTemplateId()); + if (template == null) { + throw new InvalidParameterValueException(String.format("Template for VM: %s cannot be found", vm.getUuid())); + } if (!template.isPublicTemplate()) { Account templateOwner = _accountMgr.getAccount(template.getAccountId()); _accountMgr.checkAccess(newAccount, null, true, templateOwner); From 8381d2ae7403fff71d3c659d4f41578c3222e1d2 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 17 Oct 2019 17:10:57 +0530 Subject: [PATCH 43/61] fix - add cluster details in error Signed-off-by: Abhishek Kumar --- .../main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 82a9b78ac0d9..c3ea89911eb2 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -1160,7 +1160,7 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { } } if (userVm == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to find unmanaged vm with name: %s", instanceName)); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to find unmanaged vm with name: %s in cluster: %s", instanceName, cluster.getUuid())); } return responseGenerator.createUserVmResponse(ResponseObject.ResponseView.Full, "virtualmachine", userVm).get(0); } From 81d189cdf5d2529291dfd6d5b88d679be9cac6ee Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 18 Oct 2019 15:01:35 +0530 Subject: [PATCH 44/61] fix guest OS retrieval Signed-off-by: Abhishek Kumar --- .../storage/dao/GuestOSHypervisorDao.java | 2 ++ .../storage/dao/GuestOSHypervisorDaoImpl.java | 20 +++++++++++++++++++ .../cloudstack/vm/VmImportManagerImpl.java | 13 ++++++++---- .../vmware/util/VmwareGuestOsMapper.java | 6 +++--- 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDao.java b/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDao.java index a7775165265f..cd00703ce13e 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDao.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDao.java @@ -29,4 +29,6 @@ public interface GuestOSHypervisorDao extends GenericDao guestOsSearch; protected final SearchBuilder mappingSearch; protected final SearchBuilder userDefinedMappingSearch; + protected final SearchBuilder guestOsNameSearch; protected GuestOSHypervisorDaoImpl() { guestOsSearch = createSearchBuilder(); @@ -51,6 +52,12 @@ protected GuestOSHypervisorDaoImpl() { userDefinedMappingSearch.and("hypervisor_version", userDefinedMappingSearch.entity().getHypervisorVersion(), SearchCriteria.Op.EQ); userDefinedMappingSearch.and("is_user_defined", userDefinedMappingSearch.entity().getIsUserDefined(), SearchCriteria.Op.EQ); userDefinedMappingSearch.done(); + + guestOsNameSearch = createSearchBuilder(); + guestOsNameSearch.and("guest_os_name", guestOsNameSearch.entity().getGuestOsName(), SearchCriteria.Op.EQ); + guestOsNameSearch.and("hypervisor_type", guestOsNameSearch.entity().getHypervisorType(), SearchCriteria.Op.EQ); + guestOsNameSearch.and("hypervisor_version", guestOsNameSearch.entity().getHypervisorVersion(), SearchCriteria.Op.EQ); + guestOsNameSearch.done(); } @Override @@ -97,4 +104,17 @@ public boolean removeGuestOsMapping(Long id) { return super.remove(id); } + @Override + public GuestOSHypervisorVO findByOsNameAndHypervisor(String guestOsName, String hypervisorType, String hypervisorVersion) { + SearchCriteria sc = guestOsNameSearch.create(); + String version = "default"; + if (!(hypervisorVersion == null || hypervisorVersion.isEmpty())) { + version = hypervisorVersion; + } + sc.setParameters("guest_os_name", guestOsName); + sc.setParameters("hypervisor_type", hypervisorType); + sc.setParameters("hypervisor_version", version); + return findOneBy(sc); + } + } diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index c3ea89911eb2..69f45c50bcf3 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -1138,14 +1138,19 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve guest OS details for unmanaged VM: %s with OS name: %s. templateid parameter can be used to assign template for VM", name, unmanagedInstance.getOperatingSystem())); } GuestOS guestOS = guestOSDao.listByDisplayName(osName); + GuestOSHypervisor guestOSHypervisor = null; if (guestOS == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve guest OS details for unmanaged VM: %s with OS ID: %s, OS name: %s. templateid parameter can be used to assign template for VM", name, unmanagedInstance.getOperatingSystemId(), unmanagedInstance.getOperatingSystem())); + guestOSHypervisor = guestOSHypervisorDao.findByOsNameAndHypervisor(unmanagedInstance.getOperatingSystemId(), host.getHypervisorType().toString(), host.getHypervisorVersion()); + } else { + guestOSHypervisor = guestOSHypervisorDao.findByOsIdAndHypervisor(guestOS.getId(), host.getHypervisorType().toString(), host.getHypervisorVersion()); } - GuestOSHypervisor guestOSHypervisor = guestOSHypervisorDao.findByOsIdAndHypervisor(guestOS.getId(), host.getHypervisorType().toString(), host.getHypervisorVersion()); if (guestOSHypervisor == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to find hypervisor guest OS ID: %s details for unmanaged VM:%s for hypervisor: %s version: %s. templateid parameter can be used to assign template for VM", guestOS.getUuid(), name, host.getHypervisorType().toString(), host.getHypervisorVersion())); + if (guestOS != null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to find hypervisor guest OS ID: %s details for unmanaged VM: %s for hypervisor: %s version: %s. templateid parameter can be used to assign template for VM", guestOS.getUuid(), name, host.getHypervisorType().toString(), host.getHypervisorVersion())); + } + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve guest OS details for unmanaged VM: %s with OS name: %s, OS ID: %s for hypervisor: %s version: %s. templateid parameter can be used to assign template for VM", name, osName, unmanagedInstance.getOperatingSystemId(), host.getHypervisorType().toString(), host.getHypervisorVersion())); } - template.setGuestOSId(guestOS.getId()); + template.setGuestOSId(guestOSHypervisor.getGuestOsId()); } userVm = importVirtualMachineInternal(unmanagedInstance, instanceName, zone, cluster, host, template, displayName, hostName, caller, owner, userId, diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java index 83fa468c8ef4..6182e8235716 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java @@ -154,9 +154,9 @@ public class VmwareGuestOsMapper { s_mapper.put("CentOS 5.6 (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_64_GUEST); s_mapper.put("CentOS 6.0 (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_6_GUEST); s_mapper.put("CentOS 6.0 (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_6_64_GUEST); - s_mapper.put("CentOS 7.0 (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_7_GUEST); - s_mapper.put("CentOS 7.0 (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_7_64_GUEST); - s_mapper.put("CentOS 8.0 (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_8_64_GUEST); + s_mapper.put("CentOS 7 (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_7_GUEST); + s_mapper.put("CentOS 7 (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_7_64_GUEST); + s_mapper.put("CentOS 8 (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_8_64_GUEST); s_mapper.put("Other CentOS (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_GUEST); s_mapper.put("Other CentOS (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_64_GUEST); From 405675b181b916c194db8b2ed398a5e534df3b0d Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 18 Oct 2019 17:37:53 +0530 Subject: [PATCH 45/61] fix vm guest os retrieval based on os id Signed-off-by: Abhishek Kumar --- .../hypervisor/vmware/resource/VmwareResource.java | 6 ++++-- .../apache/cloudstack/vm/VmImportManagerImpl.java | 13 +++++++------ .../hypervisor/vmware/util/VmwareGuestOsMapper.java | 10 ++++++++++ 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index b790835adbeb..5030395f33fe 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -7025,10 +7025,12 @@ private UnmanagedInstance getUnmanagedInstance(VmwareHypervisorHost hyperHost, V } } instance.setOperatingSystem(VmwareGuestOsMapper.getGuestOsName(osIdentifier)); - /*instance.setOperatingSystem(vmMo.getGuestInfo().getGuestFullName()); + if (Strings.isNullOrEmpty(instance.getOperatingSystem())) { + instance.setOperatingSystem(vmMo.getGuestInfo().getGuestFullName()); + } if (Strings.isNullOrEmpty(instance.getOperatingSystem())) { instance.setOperatingSystem(vmMo.getConfigSummary().getGuestFullName()); - }*/ + } UnmanagedInstance.PowerState powerState = UnmanagedInstance.PowerState.PowerUnknown; if (vmMo.getPowerState().toString().equalsIgnoreCase("POWERED_ON")) { powerState = UnmanagedInstance.PowerState.PowerOn; diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 69f45c50bcf3..4656dedc9590 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -1134,16 +1134,17 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { } if (template.getName().equals(VM_IMPORT_DEFAULT_TEMPLATE_NAME)) { String osName = unmanagedInstance.getOperatingSystem(); - if (Strings.isNullOrEmpty(osName)) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve guest OS details for unmanaged VM: %s with OS name: %s. templateid parameter can be used to assign template for VM", name, unmanagedInstance.getOperatingSystem())); + GuestOS guestOS = null; + if (!Strings.isNullOrEmpty(osName)) { + guestOS = guestOSDao.listByDisplayName(osName); } - GuestOS guestOS = guestOSDao.listByDisplayName(osName); GuestOSHypervisor guestOSHypervisor = null; - if (guestOS == null) { - guestOSHypervisor = guestOSHypervisorDao.findByOsNameAndHypervisor(unmanagedInstance.getOperatingSystemId(), host.getHypervisorType().toString(), host.getHypervisorVersion()); - } else { + if (guestOS != null) { guestOSHypervisor = guestOSHypervisorDao.findByOsIdAndHypervisor(guestOS.getId(), host.getHypervisorType().toString(), host.getHypervisorVersion()); } + if (guestOSHypervisor == null && Strings.isNullOrEmpty(unmanagedInstance.getOperatingSystemId())) { + guestOSHypervisor = guestOSHypervisorDao.findByOsNameAndHypervisor(unmanagedInstance.getOperatingSystemId(), host.getHypervisorType().toString(), host.getHypervisorVersion()); + } if (guestOSHypervisor == null) { if (guestOS != null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to find hypervisor guest OS ID: %s details for unmanaged VM: %s for hypervisor: %s version: %s. templateid parameter can be used to assign template for VM", guestOS.getUuid(), name, host.getHypervisorType().toString(), host.getHypervisorVersion())); diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java index 6182e8235716..df9b0a1b3bef 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java @@ -89,6 +89,16 @@ public class VmwareGuestOsMapper { s_mapper.put("Asianux 3(32-bit)", VirtualMachineGuestOsIdentifier.ASIANUX_3_GUEST); s_mapper.put("Asianux 3(64-bit)", VirtualMachineGuestOsIdentifier.ASIANUX_3_64_GUEST); + s_mapper.put("Debian GNU/Linux 10 (32-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_10_64_GUEST); + s_mapper.put("Debian GNU/Linux 10 (64-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_10_64_GUEST); + s_mapper.put("Debian GNU/Linux 9 (32-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_9_GUEST); + s_mapper.put("Debian GNU/Linux 9 (64-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_9_64_GUEST); + s_mapper.put("Debian GNU/Linux 8 (32-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_8_GUEST); + s_mapper.put("Debian GNU/Linux 8 (64-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_8_64_GUEST); + s_mapper.put("Debian GNU/Linux 7(32-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_7_GUEST); + s_mapper.put("Debian GNU/Linux 7(64-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_7_64_GUEST); + s_mapper.put("Debian GNU/Linux 6(32-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_6_GUEST); + s_mapper.put("Debian GNU/Linux 6(64-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_6_64_GUEST); s_mapper.put("Debian GNU/Linux 5(64-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_5_64_GUEST); s_mapper.put("Debian GNU/Linux 5.0 (32-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_5_GUEST); s_mapper.put("Debian GNU/Linux 4(32-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_4_GUEST); From 0fddb5036edb5a6781c6069ef775eaa821308271 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 18 Oct 2019 18:41:28 +0530 Subject: [PATCH 46/61] revert all os mapper changes Signed-off-by: Abhishek Kumar --- .../vmware/resource/VmwareResource.java | 6 +- .../vmware/util/VmwareGuestOsMapper.java | 65 +------------------ 2 files changed, 3 insertions(+), 68 deletions(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 5030395f33fe..cfbec6715b3f 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -225,7 +225,6 @@ import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHostResourceSummary; import com.cloud.hypervisor.vmware.util.VmwareContext; import com.cloud.hypervisor.vmware.util.VmwareContextPool; -import com.cloud.hypervisor.vmware.util.VmwareGuestOsMapper; import com.cloud.hypervisor.vmware.util.VmwareHelper; import com.cloud.network.Networks; import com.cloud.network.Networks.BroadcastDomainType; @@ -7024,10 +7023,7 @@ private UnmanagedInstance getUnmanagedInstance(VmwareHypervisorHost hyperHost, V osIdentifier = VirtualMachineGuestOsIdentifier.OTHER_GUEST_64; } } - instance.setOperatingSystem(VmwareGuestOsMapper.getGuestOsName(osIdentifier)); - if (Strings.isNullOrEmpty(instance.getOperatingSystem())) { - instance.setOperatingSystem(vmMo.getGuestInfo().getGuestFullName()); - } + instance.setOperatingSystem(vmMo.getGuestInfo().getGuestFullName()); if (Strings.isNullOrEmpty(instance.getOperatingSystem())) { instance.setOperatingSystem(vmMo.getConfigSummary().getGuestFullName()); } diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java index df9b0a1b3bef..b50620ea3478 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java @@ -16,13 +16,9 @@ // under the License. package com.cloud.hypervisor.vmware.util; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; -import org.apache.commons.collections.CollectionUtils; - import com.vmware.vim25.VirtualMachineGuestOsIdentifier; public class VmwareGuestOsMapper { @@ -66,39 +62,17 @@ public class VmwareGuestOsMapper { s_mapper.put("Windows 8 (64-bit)", VirtualMachineGuestOsIdentifier.WINDOWS_8_64_GUEST); s_mapper.put("Windows Server 2012 (64-bit)", VirtualMachineGuestOsIdentifier.WINDOWS_8_SERVER_64_GUEST); s_mapper.put("Windows Server 2012 R2 (64-bit)", VirtualMachineGuestOsIdentifier.WINDOWS_8_SERVER_64_GUEST); - s_mapper.put("Windows 10 (32-bit)", VirtualMachineGuestOsIdentifier.WINDOWS_9_GUEST); - s_mapper.put("Windows 10 (64-bit)", VirtualMachineGuestOsIdentifier.WINDOWS_9_64_GUEST); - s_mapper.put("Windows 10 Server (64-bit)", VirtualMachineGuestOsIdentifier.WINDOWS_9_SERVER_64_GUEST); - s_mapper.put("Windows Hyper-V", VirtualMachineGuestOsIdentifier.WINDOWS_HYPER_V_GUEST); - s_mapper.put("Apple Mac OS 10.5 (64 bit)", VirtualMachineGuestOsIdentifier.DARWIN_64_GUEST); s_mapper.put("Apple Mac OS X 10.6 (32-bit)", VirtualMachineGuestOsIdentifier.DARWIN_10_GUEST); s_mapper.put("Apple Mac OS X 10.6 (64-bit)", VirtualMachineGuestOsIdentifier.DARWIN_10_64_GUEST); s_mapper.put("Apple Mac OS X 10.7 (32-bit)", VirtualMachineGuestOsIdentifier.DARWIN_11_GUEST); s_mapper.put("Apple Mac OS X 10.7 (64-bit)", VirtualMachineGuestOsIdentifier.DARWIN_11_64_GUEST); - s_mapper.put("Apple Mac OS 10.8 (64 bit)", VirtualMachineGuestOsIdentifier.DARWIN_12_64_GUEST); - s_mapper.put("Apple Mac OS 10.9 (64 bit)", VirtualMachineGuestOsIdentifier.DARWIN_13_64_GUEST); - s_mapper.put("Apple Mac OS 10.10 (64 bit)", VirtualMachineGuestOsIdentifier.DARWIN_14_64_GUEST); - s_mapper.put("Apple Mac OS 10.11 (64 bit)", VirtualMachineGuestOsIdentifier.DARWIN_15_64_GUEST); - s_mapper.put("Apple Mac OS 10.12 (64 bit)", VirtualMachineGuestOsIdentifier.DARWIN_16_64_GUEST); - s_mapper.put("Apple Mac OS 10.13 (64 bit)", VirtualMachineGuestOsIdentifier.DARWIN_17_64_GUEST); - s_mapper.put("Apple Mac OS 10.14 (64 bit)", VirtualMachineGuestOsIdentifier.DARWIN_18_64_GUEST); s_mapper.put("Open Enterprise Server", VirtualMachineGuestOsIdentifier.OES_GUEST); s_mapper.put("Asianux 3(32-bit)", VirtualMachineGuestOsIdentifier.ASIANUX_3_GUEST); s_mapper.put("Asianux 3(64-bit)", VirtualMachineGuestOsIdentifier.ASIANUX_3_64_GUEST); - s_mapper.put("Debian GNU/Linux 10 (32-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_10_64_GUEST); - s_mapper.put("Debian GNU/Linux 10 (64-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_10_64_GUEST); - s_mapper.put("Debian GNU/Linux 9 (32-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_9_GUEST); - s_mapper.put("Debian GNU/Linux 9 (64-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_9_64_GUEST); - s_mapper.put("Debian GNU/Linux 8 (32-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_8_GUEST); - s_mapper.put("Debian GNU/Linux 8 (64-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_8_64_GUEST); - s_mapper.put("Debian GNU/Linux 7(32-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_7_GUEST); - s_mapper.put("Debian GNU/Linux 7(64-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_7_64_GUEST); - s_mapper.put("Debian GNU/Linux 6(32-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_6_GUEST); - s_mapper.put("Debian GNU/Linux 6(64-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_6_64_GUEST); s_mapper.put("Debian GNU/Linux 5(64-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_5_64_GUEST); s_mapper.put("Debian GNU/Linux 5.0 (32-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_5_GUEST); s_mapper.put("Debian GNU/Linux 4(32-bit)", VirtualMachineGuestOsIdentifier.DEBIAN_4_GUEST); @@ -128,22 +102,6 @@ public class VmwareGuestOsMapper { s_mapper.put("Other SUSE Linux(32-bit)", VirtualMachineGuestOsIdentifier.SUSE_GUEST); s_mapper.put("Other SUSE Linux(64-bit)", VirtualMachineGuestOsIdentifier.SUSE_64_GUEST); - s_mapper.put("Suse Linux Enterprise Server 9", VirtualMachineGuestOsIdentifier.SLES_GUEST); - s_mapper.put("Suse Linux Enterprise Server 9 (64 bit)", VirtualMachineGuestOsIdentifier.SLES_64_GUEST); - s_mapper.put("SUSE Linux Enterprise Server 10 SP1 (32-bit)", VirtualMachineGuestOsIdentifier.SLES_10_GUEST); - s_mapper.put("SUSE Linux Enterprise Server 10 SP1 (64-bit)", VirtualMachineGuestOsIdentifier.SLES_10_64_GUEST); - s_mapper.put("SUSE Linux Enterprise Server 10 SP2 (32-bit)", VirtualMachineGuestOsIdentifier.SLES_10_GUEST); - s_mapper.put("SUSE Linux Enterprise Server 10 SP2 (64-bit)", VirtualMachineGuestOsIdentifier.SLES_10_64_GUEST); - s_mapper.put("SUSE Linux Enterprise Server 10 SP3 (32-bit)", VirtualMachineGuestOsIdentifier.SLES_10_GUEST); - s_mapper.put("SUSE Linux Enterprise Server 10 SP3 (64-bit)", VirtualMachineGuestOsIdentifier.SLES_10_64_GUEST); - s_mapper.put("SUSE Linux Enterprise Server 10 SP4 (32-bit)", VirtualMachineGuestOsIdentifier.SLES_10_GUEST); - s_mapper.put("SUSE Linux Enterprise Server 10 SP4 (64-bit)", VirtualMachineGuestOsIdentifier.SLES_10_64_GUEST); - s_mapper.put("SUSE Linux Enterprise Server 11 (32-bit)", VirtualMachineGuestOsIdentifier.SLES_11_GUEST); - s_mapper.put("SUSE Linux Enterprise Server 11 (64-bit)", VirtualMachineGuestOsIdentifier.SLES_11_64_GUEST); - s_mapper.put("SUSE Linux Enterprise Server 12 (32-bit)", VirtualMachineGuestOsIdentifier.SLES_12_GUEST); - s_mapper.put("SUSE Linux Enterprise Server 12 (64-bit)", VirtualMachineGuestOsIdentifier.SLES_12_64_GUEST); - s_mapper.put("SUSE Linux Enterprise Server 15 (64-bit)", VirtualMachineGuestOsIdentifier.SLES_15_64_GUEST); - s_mapper.put("CentOS 4.5 (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_GUEST); s_mapper.put("CentOS 4.6 (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_GUEST); s_mapper.put("CentOS 4.7 (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_GUEST); @@ -162,11 +120,8 @@ public class VmwareGuestOsMapper { s_mapper.put("CentOS 5.5 (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_64_GUEST); s_mapper.put("CentOS 5.6 (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_GUEST); s_mapper.put("CentOS 5.6 (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_64_GUEST); - s_mapper.put("CentOS 6.0 (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_6_GUEST); - s_mapper.put("CentOS 6.0 (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_6_64_GUEST); - s_mapper.put("CentOS 7 (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_7_GUEST); - s_mapper.put("CentOS 7 (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_7_64_GUEST); - s_mapper.put("CentOS 8 (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_8_64_GUEST); + s_mapper.put("CentOS 6.0 (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_GUEST); + s_mapper.put("CentOS 6.0 (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_64_GUEST); s_mapper.put("Other CentOS (32-bit)", VirtualMachineGuestOsIdentifier.CENTOS_GUEST); s_mapper.put("Other CentOS (64-bit)", VirtualMachineGuestOsIdentifier.CENTOS_64_GUEST); @@ -214,9 +169,6 @@ public class VmwareGuestOsMapper { s_mapper.put("Red Hat Enterprise Linux 6.3 (64-bit)", VirtualMachineGuestOsIdentifier.RHEL_6_64_GUEST); s_mapper.put("Red Hat Enterprise Linux 6.4 (32-bit)", VirtualMachineGuestOsIdentifier.RHEL_6_GUEST); s_mapper.put("Red Hat Enterprise Linux 6.4 (64-bit)", VirtualMachineGuestOsIdentifier.RHEL_6_64_GUEST); - s_mapper.put("Red Hat Enterprise Linux 7 (32-bit)", VirtualMachineGuestOsIdentifier.RHEL_7_GUEST); - s_mapper.put("Red Hat Enterprise Linux 7 (64-bit)", VirtualMachineGuestOsIdentifier.RHEL_7_64_GUEST); - s_mapper.put("Red Hat Enterprise Linux 8 (64-bit)", VirtualMachineGuestOsIdentifier.RHEL_8_64_GUEST); s_mapper.put("Ubuntu 8.04 (32-bit)", VirtualMachineGuestOsIdentifier.UBUNTU_GUEST); s_mapper.put("Ubuntu 8.04 (64-bit)", VirtualMachineGuestOsIdentifier.UBUNTU_64_GUEST); @@ -248,17 +200,4 @@ public static VirtualMachineGuestOsIdentifier getGuestOsIdentifier(String guestO return s_mapper.get(guestOsName); } - public static String getGuestOsName(VirtualMachineGuestOsIdentifier identifier) { - String guestOsName = null; - List keys = new ArrayList<>(); - for (Map.Entry entry : s_mapper.entrySet()) { - if (entry.getValue().equals(identifier)) { - keys.add(entry.getKey()); - } - } - if (CollectionUtils.isNotEmpty(keys)) { - guestOsName = keys.get(keys.size()-1); - } - return guestOsName; - } } From 3e44fdb2310eb373b995162c2fd439a87f04aa9d Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 18 Oct 2019 20:20:35 +0530 Subject: [PATCH 47/61] fix Signed-off-by: Abhishek Kumar --- .../main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 4656dedc9590..2ca155b8e874 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -1142,7 +1142,7 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { if (guestOS != null) { guestOSHypervisor = guestOSHypervisorDao.findByOsIdAndHypervisor(guestOS.getId(), host.getHypervisorType().toString(), host.getHypervisorVersion()); } - if (guestOSHypervisor == null && Strings.isNullOrEmpty(unmanagedInstance.getOperatingSystemId())) { + if (guestOSHypervisor == null && !Strings.isNullOrEmpty(unmanagedInstance.getOperatingSystemId())) { guestOSHypervisor = guestOSHypervisorDao.findByOsNameAndHypervisor(unmanagedInstance.getOperatingSystemId(), host.getHypervisorType().toString(), host.getHypervisorVersion()); } if (guestOSHypervisor == null) { From 1662579e6cae43572582af62358da7779ac7485d Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Sat, 19 Oct 2019 13:45:07 +0530 Subject: [PATCH 48/61] fix guest os selection order Signed-off-by: Abhishek Kumar --- .../com/cloud/storage/dao/GuestOSHypervisorDaoImpl.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDaoImpl.java b/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDaoImpl.java index 3ba1e4bb4bcc..699ce0bae020 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDaoImpl.java @@ -17,12 +17,14 @@ package com.cloud.storage.dao; import java.util.Date; +import java.util.List; - +import org.apache.commons.collections.CollectionUtils; import org.springframework.stereotype.Component; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.GuestOSHypervisorVO; +import com.cloud.utils.db.Filter; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; @@ -114,7 +116,9 @@ public GuestOSHypervisorVO findByOsNameAndHypervisor(String guestOsName, String sc.setParameters("guest_os_name", guestOsName); sc.setParameters("hypervisor_type", hypervisorType); sc.setParameters("hypervisor_version", version); - return findOneBy(sc); + final Filter filter = new Filter(GuestOSHypervisorVO.class, "guestOsId", true, null, null); + List results = listIncludingRemovedBy(sc, filter); + return CollectionUtils.isNotEmpty(results) ? results.get(0) : null; } } From 2257f04abfa2c98744762faa699b912b35f854d6 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 21 Oct 2019 15:35:21 +0530 Subject: [PATCH 49/61] fix stopped VM import, migration Signed-off-by: Abhishek Kumar --- .../org/apache/cloudstack/vm/VmImportManagerImpl.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 2ca155b8e874..ba1efc475374 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -725,7 +725,14 @@ private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate templ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during vm migration, no deployment destination found", vm.getInstanceName())); } try { - virtualMachineManager.migrate(vm.getUuid(), sourceHost.getId(), dest); + if (vm.getState().equals(VirtualMachine.State.Stopped)) { + VMInstanceVO vmInstanceVO = vmDao.findById(userVm.getId()); + vmInstanceVO.setHostId(dest.getHost().getId()); + vmInstanceVO.setLastHostId(dest.getHost().getId()); + vmDao.update(vmInstanceVO.getId(), vmInstanceVO); + } else { + virtualMachineManager.migrate(vm.getUuid(), sourceHost.getId(), dest); + } vm = userVmManager.getUserVm(vm.getId()); } catch (Exception e) { LOGGER.error(String.format("VM import failed for unmanaged vm: %s during vm migration", vm.getInstanceName()), e); @@ -788,6 +795,7 @@ private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate templ } } if (storagePool == null) { + cleanupFailedImportVM(vm); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume ID: %s migration as no suitable pool found", userVm.getInstanceName(), volumeVO.getUuid())); } else { LOGGER.debug(String.format("Found storage pool %s(%s) for migrating the volume %s to", storagePool.getName(), storagePool.getUuid(), volumeVO.getUuid())); From 6ece41794e51ceacd7df34be7ad13385d7fbc8c9 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 7 Nov 2019 11:26:17 +0530 Subject: [PATCH 50/61] added missing license Signed-off-by: Abhishek Kumar --- .../cloudstack/vm/VmImportManagerImplTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java index 9dc9fa82e048..4543eecf0543 100644 --- a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java @@ -1,3 +1,20 @@ +// 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.vm; import static org.mockito.Matchers.any; From a71321136f481817dac66fd6555a6c0294a3cbe3 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 7 Nov 2019 13:16:43 +0530 Subject: [PATCH 51/61] fixed static member naming Signed-off-by: Abhishek Kumar --- .../api/command/admin/vm/ImportUnmanagedInstanceCmd.java | 2 +- .../api/command/admin/vm/ListUnmanagedInstancesCmd.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java index ab42adea32f6..140f5787e79b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java @@ -65,7 +65,7 @@ authorized = {RoleType.Admin}, since = "4.14.0") public class ImportUnmanagedInstanceCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(ImportUnmanagedInstanceCmd.class); + public static final Logger LOGGER = Logger.getLogger(ImportUnmanagedInstanceCmd.class); public static final String API_NAME = "importUnmanagedInstance"; @Inject diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListUnmanagedInstancesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListUnmanagedInstancesCmd.java index aced2c621101..8ee71a071e56 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListUnmanagedInstancesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListUnmanagedInstancesCmd.java @@ -52,7 +52,7 @@ authorized = {RoleType.Admin}, since = "4.14.0") public class ListUnmanagedInstancesCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListUnmanagedInstancesCmd.class.getName()); + public static final Logger LOGGER = Logger.getLogger(ListUnmanagedInstancesCmd.class.getName()); public static final String API_NAME = "listUnmanagedInstances"; @Inject From 6e1abad5cd16637baeba2a04aaf18cb98a495859 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 18 Nov 2019 11:54:40 +0530 Subject: [PATCH 52/61] addressed loggin related review comments Signed-off-by: Abhishek Kumar --- .../cloudstack/vm/VmImportManagerImpl.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index ba1efc475374..54478b645261 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -111,6 +111,7 @@ import com.cloud.user.dao.UserDao; import com.cloud.uservm.UserVm; import com.cloud.utils.Pair; +import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; import com.cloud.vm.DiskProfile; import com.cloud.vm.NicProfile; @@ -329,6 +330,7 @@ private List getAdditionalNameFilters(Cluster cluster) { } } } catch (Exception e) { + LOGGER.warn(String.format("Unable to find volume file name for volume ID: %s while adding filters unmanaged VMs", volumeVO.getUuid()), e); } if (!volumeFileNames.isEmpty()) { additionalNameFilter.addAll(volumeFileNames); @@ -684,6 +686,7 @@ private void cleanupFailedImportVM(final UserVm userVm) { try { networkOrchestrationService.release(profile, true); } catch (Exception e) { + LOGGER.error(String.format("Unable to release NICs for unsuccessful import unmanaged VM: %s", userVm.getInstanceName()), e); nicDao.removeNicsForInstance(userVm.getId()); } // Remove vm @@ -808,7 +811,14 @@ private UserVm migrateImportedVM(HostVO sourceHost, VirtualMachineTemplate templ volume = volumeManager.migrateVolume(volumeVO, storagePool); } if (volume == null) { - throw new Exception(); + String msg = ""; + if (vm.getState().equals(VirtualMachine.State.Running)) { + msg = String.format("Live migration for volume ID: %s to destination pool ID: %s failed", volumeVO.getUuid(), storagePool.getUuid()); + } else { + msg = String.format("Migration for volume ID: %s to destination pool ID: %s failed", volumeVO.getUuid(), storagePool.getUuid()); + } + LOGGER.error(msg); + throw new CloudRuntimeException(msg); } } catch (Exception e) { LOGGER.error(String.format("VM import failed for unmanaged vm: %s during volume migration", vm.getInstanceName()), e); @@ -834,7 +844,7 @@ private void publishVMUsageUpdateResourceCount(final UserVm userVm, ServiceOffer userVm.getHypervisorType().toString(), VirtualMachine.class.getName(), userVm.getUuid(), userVm.getDetails(), userVm.isDisplayVm()); } } catch (Exception e) { - LOGGER.error("Failed to publish usage records during VM import"); + LOGGER.error(String.format("Failed to publish usage records during VM import for unmanaged vm %s", userVm.getInstanceName()), e); cleanupFailedImportVM(userVm); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm %s during publishing usage records", userVm.getInstanceName())); } @@ -848,7 +858,7 @@ private void publishVMUsageUpdateResourceCount(final UserVm userVm, ServiceOffer UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), volume.getDiskOfferingId(), null, volume.getSize(), Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); } catch (Exception e) { - LOGGER.error(String.format("Failed to publish volume usage records during VM import. %s", Strings.nullToEmpty(e.getMessage()))); + LOGGER.error(String.format("Failed to publish volume ID: %s usage records during VM import", volume.getUuid()), e); } resourceLimitService.incrementResourceCount(userVm.getAccountId(), Resource.ResourceType.volume, volume.isDisplayVolume()); resourceLimitService.incrementResourceCount(userVm.getAccountId(), Resource.ResourceType.primary_storage, volume.isDisplayVolume(), volume.getSize()); From 1eccd0052715e4108ba64199fb717e00a001f58a Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 18 Nov 2019 12:05:04 +0530 Subject: [PATCH 53/61] formatting refactoring Signed-off-by: Abhishek Kumar --- .../com/cloud/hypervisor/vmware/resource/VmwareResource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index cfbec6715b3f..983b83560b95 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -643,7 +643,7 @@ protected void reconfigureProcessorByHandler(EnumMap examineStorageSubSystemCommandFullCloneFlagForVmware(CopyCommand cmd, - EnumMap params) { + EnumMap params) { EnumMap paramsCopy = new EnumMap(params); HypervisorType hypervisor = cmd.getDestTO().getHypervisorType(); if (hypervisor != null && hypervisor.equals(HypervisorType.VMware)) { From 9d8411dc2c931214801d30f19da0d1bae3ea4730 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 18 Nov 2019 12:38:04 +0530 Subject: [PATCH 54/61] refactorings UnmanagedInstance to UnmanagedInstanceTO Template null check for importVolume javadoc for managed, unmanaged instances Signed-off-by: Abhishek Kumar --- .../admin/vm/ListUnmanagedInstancesCmd.java | 4 +- .../response/UnmanagedInstanceResponse.java | 4 +- ...Instance.java => UnmanagedInstanceTO.java} | 2 +- .../api/GetUnmanagedInstancesAnswer.java | 10 +-- .../api/GetUnmanagedInstancesCommand.java | 8 ++- .../orchestration/VolumeOrchestrator.java | 16 ++--- .../vmware/resource/VmwareResource.java | 42 ++++++------- .../cloudstack/vm/VmImportManagerImpl.java | 62 +++++++++---------- .../vm/VmImportManagerImplTest.java | 14 ++--- 9 files changed, 85 insertions(+), 77 deletions(-) rename api/src/main/java/org/apache/cloudstack/vm/{UnmanagedInstance.java => UnmanagedInstanceTO.java} (99%) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListUnmanagedInstancesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListUnmanagedInstancesCmd.java index 8ee71a071e56..a991ef4e03d6 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListUnmanagedInstancesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListUnmanagedInstancesCmd.java @@ -31,7 +31,7 @@ import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.UnmanagedInstanceResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.cloudstack.vm.UnmanagedInstance; +import org.apache.cloudstack.vm.UnmanagedInstanceTO; import org.apache.cloudstack.vm.VmImportService; import org.apache.log4j.Logger; @@ -46,7 +46,7 @@ description = "Lists unmanaged virtual machines for a given cluster.", responseObject = UnmanagedInstanceResponse.class, responseView = ResponseObject.ResponseView.Full, - entityType = {UnmanagedInstance.class}, + entityType = {UnmanagedInstanceTO.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true, authorized = {RoleType.Admin}, diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java index 36bf01a7e40f..5167f1788ce1 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java @@ -23,12 +23,12 @@ import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; -import org.apache.cloudstack.vm.UnmanagedInstance; +import org.apache.cloudstack.vm.UnmanagedInstanceTO; import com.cloud.serializer.Param; import com.google.gson.annotations.SerializedName; -@EntityReference(value = UnmanagedInstance.class) +@EntityReference(value = UnmanagedInstanceTO.class) public class UnmanagedInstanceResponse extends BaseResponse { @SerializedName(ApiConstants.NAME) diff --git a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java similarity index 99% rename from api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java rename to api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java index e008915457da..b7558789ab58 100644 --- a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstance.java +++ b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java @@ -19,7 +19,7 @@ import java.util.List; -public class UnmanagedInstance { +public class UnmanagedInstanceTO { public enum PowerState { PowerUnknown, diff --git a/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesAnswer.java b/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesAnswer.java index 682af8479c6e..3c6118d426e6 100644 --- a/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesAnswer.java +++ b/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesAnswer.java @@ -19,18 +19,18 @@ import java.util.HashMap; -import org.apache.cloudstack.vm.UnmanagedInstance; +import org.apache.cloudstack.vm.UnmanagedInstanceTO; @LogLevel(LogLevel.Log4jLevel.Trace) public class GetUnmanagedInstancesAnswer extends Answer { private String instanceName; - private HashMap unmanagedInstances; + private HashMap unmanagedInstances; GetUnmanagedInstancesAnswer() { } - public GetUnmanagedInstancesAnswer(GetUnmanagedInstancesCommand cmd, String details, HashMap unmanagedInstances) { + public GetUnmanagedInstancesAnswer(GetUnmanagedInstancesCommand cmd, String details, HashMap unmanagedInstances) { super(cmd, true, details); this.instanceName = cmd.getInstanceName(); this.unmanagedInstances = unmanagedInstances; @@ -44,11 +44,11 @@ public void setInstanceName(String instanceName) { this.instanceName = instanceName; } - public HashMap getUnmanagedInstances() { + public HashMap getUnmanagedInstances() { return unmanagedInstances; } - public void setUnmanagedInstances(HashMap unmanagedInstances) { + public void setUnmanagedInstances(HashMap unmanagedInstances) { this.unmanagedInstances = unmanagedInstances; } diff --git a/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesCommand.java b/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesCommand.java index 68b136dd196a..968c58611bb7 100644 --- a/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesCommand.java +++ b/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesCommand.java @@ -19,11 +19,17 @@ import java.util.List; +/** + * Unmanaged instances are those virtual machines which are present at hypervisor end but not available in CloudStack. + * Such virtual machines might have been created out of band, directly from hypervisor. + * Managed instances will be those virtual machines that are created from CloudStack or CloudStack have database record for them. + * All managed instances will be filtered while trying to find unmanaged instances. + */ + @LogLevel(LogLevel.Log4jLevel.Trace) public class GetUnmanagedInstancesCommand extends Command { String instanceName; - List managedInstancesNames; public GetUnmanagedInstancesCommand() { diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java index 1ab310093a11..f0cf170900ac 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java @@ -1654,14 +1654,16 @@ public DiskProfile importVolume(Type type, String name, DiskOffering offering, L } else { vol.setDeviceId(1l); } - if (template.getFormat() == ImageFormat.ISO) { - vol.setIsoId(template.getId()); - } else if (template.getTemplateType().equals(Storage.TemplateType.DATADISK)) { - vol.setTemplateId(template.getId()); - } - if (type == Type.ROOT) { - vol.setTemplateId(template.getId()); + if (template != null) { + if (template.getFormat() == ImageFormat.ISO) { + vol.setIsoId(template.getId()); + } else if (template.getTemplateType().equals(Storage.TemplateType.DATADISK)) { + vol.setTemplateId(template.getId()); + } + if (type == Type.ROOT) { + vol.setTemplateId(template.getId()); + } } // display flag matters only for the User vms diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 983b83560b95..ca0cbdb766b5 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -53,7 +53,7 @@ import org.apache.cloudstack.storage.to.TemplateObjectTO; import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo; -import org.apache.cloudstack.vm.UnmanagedInstance; +import org.apache.cloudstack.vm.UnmanagedInstanceTO; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; @@ -6796,8 +6796,8 @@ private static File fetchSystemVmKeyFile() { return keyFile; } - private List getUnmanageInstanceDisks(VirtualMachineMO vmMo) { - List instanceDisks = new ArrayList<>(); + private List getUnmanageInstanceDisks(VirtualMachineMO vmMo) { + List instanceDisks = new ArrayList<>(); VirtualDisk[] disks = null; try { disks = vmMo.getAllDiskDevice(); @@ -6808,7 +6808,7 @@ private List getUnmanageInstanceDisks(VirtualMachineMO v for (VirtualDevice diskDevice : disks) { try { if (diskDevice instanceof VirtualDisk) { - UnmanagedInstance.Disk instanceDisk = new UnmanagedInstance.Disk(); + UnmanagedInstanceTO.Disk instanceDisk = new UnmanagedInstanceTO.Disk(); VirtualDisk disk = (VirtualDisk) diskDevice; instanceDisk.setDiskId(disk.getDiskObjectId()); instanceDisk.setLabel(disk.getDeviceInfo() != null ? disk.getDeviceInfo().getLabel() : ""); @@ -6864,13 +6864,13 @@ private List getUnmanageInstanceDisks(VirtualMachineMO v s_logger.info("Unable to retrieve unmanaged instance disk info. " + e.getMessage()); } } - Collections.sort(instanceDisks, new Comparator() { + Collections.sort(instanceDisks, new Comparator() { @Override - public int compare(final UnmanagedInstance.Disk disk1, final UnmanagedInstance.Disk disk2) { + public int compare(final UnmanagedInstanceTO.Disk disk1, final UnmanagedInstanceTO.Disk disk2) { return extractInt(disk1) - extractInt(disk2); } - int extractInt(UnmanagedInstance.Disk disk) { + int extractInt(UnmanagedInstanceTO.Disk disk) { String num = disk.getLabel().replaceAll("\\D", ""); // return 0 if no digits found return num.isEmpty() ? 0 : Integer.parseInt(num); @@ -6880,8 +6880,8 @@ int extractInt(UnmanagedInstance.Disk disk) { return instanceDisks; } - private List getUnmanageInstanceNics(VmwareHypervisorHost hyperHost, VirtualMachineMO vmMo) { - List instanceNics = new ArrayList<>(); + private List getUnmanageInstanceNics(VmwareHypervisorHost hyperHost, VirtualMachineMO vmMo) { + List instanceNics = new ArrayList<>(); HashMap> guestNicMacIPAddressMap = new HashMap<>(); try { @@ -6915,7 +6915,7 @@ private List getUnmanageInstanceNics(VmwareHypervisorHost try { VirtualEthernetCard ethCardDevice = (VirtualEthernetCard) nic; s_logger.error(nic.getClass().getCanonicalName() + " " + nic.getBacking().getClass().getCanonicalName() + " " + ethCardDevice.getMacAddress()); - UnmanagedInstance.Nic instanceNic = new UnmanagedInstance.Nic(); + UnmanagedInstanceTO.Nic instanceNic = new UnmanagedInstanceTO.Nic(); instanceNic.setNicId(ethCardDevice.getDeviceInfo().getLabel()); if (ethCardDevice instanceof VirtualPCNet32) { instanceNic.setAdapterType(VirtualEthernetCardType.PCNet32.toString()); @@ -6986,13 +6986,13 @@ private List getUnmanageInstanceNics(VmwareHypervisorHost s_logger.info("Unable to retrieve unmanaged instance nic info. " + e.getMessage()); } } - Collections.sort(instanceNics, new Comparator() { + Collections.sort(instanceNics, new Comparator() { @Override - public int compare(final UnmanagedInstance.Nic nic1, final UnmanagedInstance.Nic nic2) { + public int compare(final UnmanagedInstanceTO.Nic nic1, final UnmanagedInstanceTO.Nic nic2) { return extractInt(nic1) - extractInt(nic2); } - int extractInt(UnmanagedInstance.Nic nic) { + int extractInt(UnmanagedInstanceTO.Nic nic) { String num = nic.getNicId().replaceAll("\\D", ""); // return 0 if no digits found return num.isEmpty() ? 0 : Integer.parseInt(num); @@ -7002,10 +7002,10 @@ int extractInt(UnmanagedInstance.Nic nic) { return instanceNics; } - private UnmanagedInstance getUnmanagedInstance(VmwareHypervisorHost hyperHost, VirtualMachineMO vmMo) { - UnmanagedInstance instance = null; + private UnmanagedInstanceTO getUnmanagedInstance(VmwareHypervisorHost hyperHost, VirtualMachineMO vmMo) { + UnmanagedInstanceTO instance = null; try { - instance = new UnmanagedInstance(); + instance = new UnmanagedInstanceTO(); instance.setName(vmMo.getVmName()); instance.setCpuCores(vmMo.getConfigSummary().getNumCpu()); instance.setCpuCoresPerSocket(vmMo.getCoresPerSocket()); @@ -7027,12 +7027,12 @@ private UnmanagedInstance getUnmanagedInstance(VmwareHypervisorHost hyperHost, V if (Strings.isNullOrEmpty(instance.getOperatingSystem())) { instance.setOperatingSystem(vmMo.getConfigSummary().getGuestFullName()); } - UnmanagedInstance.PowerState powerState = UnmanagedInstance.PowerState.PowerUnknown; + UnmanagedInstanceTO.PowerState powerState = UnmanagedInstanceTO.PowerState.PowerUnknown; if (vmMo.getPowerState().toString().equalsIgnoreCase("POWERED_ON")) { - powerState = UnmanagedInstance.PowerState.PowerOn; + powerState = UnmanagedInstanceTO.PowerState.PowerOn; } if (vmMo.getPowerState().toString().equalsIgnoreCase("POWERED_OFF")) { - powerState = UnmanagedInstance.PowerState.PowerOff; + powerState = UnmanagedInstanceTO.PowerState.PowerOff; } instance.setPowerState(powerState); instance.setDisks(getUnmanageInstanceDisks(vmMo)); @@ -7050,7 +7050,7 @@ private Answer execute(GetUnmanagedInstancesCommand cmd) { } VmwareContext context = getServiceContext(); - HashMap unmanagedInstances = new HashMap<>(); + HashMap unmanagedInstances = new HashMap<>(); try { VmwareHypervisorHost hyperHost = getHyperHost(context); @@ -7073,7 +7073,7 @@ private Answer execute(GetUnmanagedInstancesCommand cmd) { !cmd.getInstanceName().equals(vmMo.getVmName())) { continue; } - UnmanagedInstance instance = getUnmanagedInstance(hyperHost, vmMo); + UnmanagedInstanceTO instance = getUnmanagedInstance(hyperHost, vmMo); if (instance != null) { unmanagedInstances.put(instance.getName(), instance); } diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 54478b645261..20c4501cbdf3 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -217,7 +217,7 @@ private VMTemplateVO createDefaultDummyVmImportTemplate() { return template; } - private UnmanagedInstanceResponse createUnmanagedInstanceResponse(UnmanagedInstance instance, Cluster cluster, Host host) { + private UnmanagedInstanceResponse createUnmanagedInstanceResponse(UnmanagedInstanceTO instance, Cluster cluster, Host host) { UnmanagedInstanceResponse response = new UnmanagedInstanceResponse(); response.setName(instance.getName()); if (cluster != null) { @@ -233,10 +233,10 @@ private UnmanagedInstanceResponse createUnmanagedInstanceResponse(UnmanagedInsta response.setMemory(instance.getMemory()); response.setOperatingSystemId(instance.getOperatingSystemId()); response.setOperatingSystem(instance.getOperatingSystem()); - response.setObjectName(UnmanagedInstance.class.getSimpleName().toLowerCase()); + response.setObjectName("unmanagedinstance"); if (instance.getDisks() != null) { - for (UnmanagedInstance.Disk disk : instance.getDisks()) { + for (UnmanagedInstanceTO.Disk disk : instance.getDisks()) { UnmanagedInstanceDiskResponse diskResponse = new UnmanagedInstanceDiskResponse(); diskResponse.setDiskId(disk.getDiskId()); if (!Strings.isNullOrEmpty(disk.getLabel())) { @@ -256,7 +256,7 @@ private UnmanagedInstanceResponse createUnmanagedInstanceResponse(UnmanagedInsta } if (instance.getNics() != null) { - for (UnmanagedInstance.Nic nic : instance.getNics()) { + for (UnmanagedInstanceTO.Nic nic : instance.getNics()) { NicResponse nicResponse = new NicResponse(); nicResponse.setId(nic.getNicId()); nicResponse.setNetworkName(nic.getNetwork()); @@ -390,7 +390,7 @@ private boolean storagePoolSupportsServiceOffering(StoragePool pool, ServiceOffe return volumeApiService.doesTargetStorageSupportDiskOffering(pool, serviceOffering.getTags()); } - private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedInstance instance, ServiceOfferingVO serviceOffering, final Account owner, final DataCenter zone, final Map details) + private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedInstanceTO instance, ServiceOfferingVO serviceOffering, final Account owner, final DataCenter zone, final Map details) throws ServerApiException, PermissionDeniedException, ResourceAllocationException { if (instance == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM is not valid")); @@ -425,13 +425,13 @@ private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedIns userVmManager.validateCustomParameters(serviceOffering, parameters); serviceOffering = serviceOfferingDao.getComputeOffering(serviceOffering, parameters); } else { - if (!cpu.equals(serviceOffering.getCpu()) && !instance.getPowerState().equals(UnmanagedInstance.PowerState.PowerOff)) { + if (!cpu.equals(serviceOffering.getCpu()) && !instance.getPowerState().equals(UnmanagedInstanceTO.PowerState.PowerOff)) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %d CPU cores does not matches VM CPU cores %d and VM is not in powered off state (Power state: %s)", serviceOffering.getUuid(), serviceOffering.getCpu(), cpu, instance.getPowerState())); } - if (!memory.equals(serviceOffering.getRamSize()) && !instance.getPowerState().equals(UnmanagedInstance.PowerState.PowerOff)) { + if (!memory.equals(serviceOffering.getRamSize()) && !instance.getPowerState().equals(UnmanagedInstanceTO.PowerState.PowerOff)) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %dMB memory does not matches VM memory %dMB and VM is not in powered off state (Power state: %s)", serviceOffering.getUuid(), serviceOffering.getRamSize(), memory, instance.getPowerState())); } - if (cpuSpeed != null && cpuSpeed > 0 && !cpuSpeed.equals(serviceOffering.getSpeed()) && !instance.getPowerState().equals(UnmanagedInstance.PowerState.PowerOff)) { + if (cpuSpeed != null && cpuSpeed > 0 && !cpuSpeed.equals(serviceOffering.getSpeed()) && !instance.getPowerState().equals(UnmanagedInstanceTO.PowerState.PowerOff)) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %dMHz CPU speed does not matches VM CPU speed %dMHz and VM is not in powered off state (Power state: %s)", serviceOffering.getUuid(), serviceOffering.getSpeed(), cpuSpeed, instance.getPowerState())); } } @@ -440,9 +440,9 @@ private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedIns return serviceOffering; } - private Map getNicIpAddresses(final List nics, final Map callerNicIpAddressMap) { + private Map getNicIpAddresses(final List nics, final Map callerNicIpAddressMap) { Map nicIpAddresses = new HashMap<>(); - for (UnmanagedInstance.Nic nic : nics) { + for (UnmanagedInstanceTO.Nic nic : nics) { Network.IpAddresses ipAddresses = null; if (MapUtils.isNotEmpty(callerNicIpAddressMap) && callerNicIpAddressMap.containsKey(nic.getNicId())) { ipAddresses = callerNicIpAddressMap.get(nic.getNicId()); @@ -464,7 +464,7 @@ private Map getNicIpAddresses(final List disks, final Map diskOfferingMap, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed) + private void checkUnmanagedDiskAndOfferingForImport(List disks, final Map diskOfferingMap, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed) throws ServerApiException, PermissionDeniedException, ResourceAllocationException { String diskController = null; - for (UnmanagedInstance.Disk disk : disks) { + for (UnmanagedInstanceTO.Disk disk : disks) { if (disk == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve disk details for VM")); } @@ -544,7 +544,7 @@ private void checkUnmanagedDiskAndOfferingForImport(List } } - private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Network network, final DataCenter zone, final Account owner, final boolean autoAssign) throws ServerApiException { + private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstanceTO.Nic nic, Network network, final DataCenter zone, final Account owner, final boolean autoAssign) throws ServerApiException { if (nic == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import")); } @@ -563,7 +563,7 @@ private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstance.Nic nic, Net } } - private void checkUnmanagedNicAndNetworkHostnameForImport(UnmanagedInstance.Nic nic, Network network, final String hostName) throws ServerApiException { + private void checkUnmanagedNicAndNetworkHostnameForImport(UnmanagedInstanceTO.Nic nic, Network network, final String hostName) throws ServerApiException { if (nic == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import!")); } @@ -578,7 +578,7 @@ private void checkUnmanagedNicAndNetworkHostnameForImport(UnmanagedInstance.Nic } } - private void checkUnmanagedNicIpAndNetworkForImport(UnmanagedInstance.Nic nic, Network network, final Network.IpAddresses ipAddresses) throws ServerApiException { + private void checkUnmanagedNicIpAndNetworkForImport(UnmanagedInstanceTO.Nic nic, Network network, final Network.IpAddresses ipAddresses) throws ServerApiException { if (nic == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import")); } @@ -598,10 +598,10 @@ private void checkUnmanagedNicIpAndNetworkForImport(UnmanagedInstance.Nic nic, N } } - private Map getUnmanagedNicNetworkMap(List nics, final Map callerNicNetworkMap, final Map callerNicIpAddressMap, final DataCenter zone, final String hostName, final Account owner) throws ServerApiException { + private Map getUnmanagedNicNetworkMap(List nics, final Map callerNicNetworkMap, final Map callerNicIpAddressMap, final DataCenter zone, final String hostName, final Account owner) throws ServerApiException { Map nicNetworkMap = new HashMap<>(); String nicAdapter = null; - for (UnmanagedInstance.Nic nic : nics) { + for (UnmanagedInstanceTO.Nic nic : nics) { if (Strings.isNullOrEmpty(nicAdapter)) { nicAdapter = nic.getAdapterType(); } else { @@ -648,7 +648,7 @@ private Map getUnmanagedNicNetworkMap(List return nicNetworkMap; } - private Pair importDisk(UnmanagedInstance.Disk disk, VirtualMachine vm, Cluster cluster, DiskOffering diskOffering, + private Pair importDisk(UnmanagedInstanceTO.Disk disk, VirtualMachine vm, Cluster cluster, DiskOffering diskOffering, Volume.Type type, String name, Long diskSize, VirtualMachineTemplate template, Account owner, Long deviceId) { final DataCenter zone = dataCenterDao.findById(vm.getDataCenterId()); @@ -667,7 +667,7 @@ private Pair importDisk(UnmanagedInstance.Disk disk, V return new Pair(profile, storagePool); } - private NicProfile importNic(UnmanagedInstance.Nic nic, VirtualMachine vm, Network network, Network.IpAddresses ipAddresses, boolean isDefaultNic) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException { + private NicProfile importNic(UnmanagedInstanceTO.Nic nic, VirtualMachine vm, Network network, Network.IpAddresses ipAddresses, boolean isDefaultNic) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException { Pair result = networkOrchestrationService.importNic(nic.getMacAddress(), 0, network, isDefaultNic, vm, ipAddresses); if (result == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC ID: %s import failed", nic.getNicId())); @@ -865,7 +865,7 @@ private void publishVMUsageUpdateResourceCount(final UserVm userVm, ServiceOffer } } - private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedInstance, final String instanceName, final DataCenter zone, final Cluster cluster, final HostVO host, + private UserVm importVirtualMachineInternal(final UnmanagedInstanceTO unmanagedInstance, final String instanceName, final DataCenter zone, final Cluster cluster, final HostVO host, final VirtualMachineTemplate template, final String displayName, final String hostName, final Account caller, final Account owner, final Long userId, final ServiceOfferingVO serviceOffering, final DiskOffering diskOffering, final Map dataDiskOfferingMap, final Map nicNetworkMap, final Map callerNicIpAddressMap, @@ -893,16 +893,16 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns throw new InvalidParameterValueException(String.format("Service offering: %s is not compatible with host: %s of unmanaged VM: %s", serviceOffering.getUuid(), host.getUuid(), instanceName)); } // Check disks and supplied disk offerings - List unmanagedInstanceDisks = unmanagedInstance.getDisks(); + List unmanagedInstanceDisks = unmanagedInstance.getDisks(); if (CollectionUtils.isEmpty(unmanagedInstanceDisks)) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("No attached disks found for the unmanaged VM: %s", instanceName)); } - final UnmanagedInstance.Disk rootDisk = unmanagedInstance.getDisks().get(0); + final UnmanagedInstanceTO.Disk rootDisk = unmanagedInstance.getDisks().get(0); if (rootDisk == null || Strings.isNullOrEmpty(rootDisk.getController())) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed. Unable to retrieve root disk details for VM: %s ", instanceName)); } allDetails.put(VmDetailConstants.ROOT_DISK_CONTROLLER, rootDisk.getController()); - List dataDisks = new ArrayList<>(); + List dataDisks = new ArrayList<>(); try { checkUnmanagedDiskAndOfferingForImport(rootDisk, diskOffering, validatedServiceOffering, owner, zone, cluster, migrateAllowed); if (unmanagedInstanceDisks.size() > 1) { // Data disk(s) present @@ -923,7 +923,7 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns allDetails.put(VmDetailConstants.NIC_ADAPTER, unmanagedInstance.getNics().get(0).getAdapterType()); } VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff; - if (unmanagedInstance.getPowerState().equals(UnmanagedInstance.PowerState.PowerOn)) { + if (unmanagedInstance.getPowerState().equals(UnmanagedInstanceTO.PowerState.PowerOn)) { powerState = VirtualMachine.PowerState.PowerOn; } try { @@ -944,7 +944,7 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId())); } diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, cluster, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()), (rootDisk.getCapacity() / Resource.ResourceType.bytesToGiB), template, owner, null)); - for (UnmanagedInstance.Disk disk : dataDisks) { + for (UnmanagedInstanceTO.Disk disk : dataDisks) { if (disk.getCapacity() == null || disk.getCapacity() == 0) { throw new InvalidParameterValueException(String.format("Disk ID: %s size is invalid", rootDisk.getDiskId())); } @@ -958,7 +958,7 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstance unmanagedIns } try { boolean firstNic = true; - for (UnmanagedInstance.Nic nic : unmanagedInstance.getNics()) { + for (UnmanagedInstanceTO.Nic nic : unmanagedInstance.getNics()) { Network network = networkDao.findById(allNicNetworkMap.get(nic.getNicId())); Network.IpAddresses ipAddresses = nicIpAddressMap.get(nic.getNicId()); importNic(nic, userVm, network, ipAddresses, firstNic); @@ -1012,7 +1012,7 @@ public ListResponse listUnmanagedInstances(ListUnmana continue; } GetUnmanagedInstancesAnswer unmanagedInstancesAnswer = (GetUnmanagedInstancesAnswer) answer; - HashMap unmanagedInstances = new HashMap<>(); + HashMap unmanagedInstances = new HashMap<>(); unmanagedInstances.putAll(unmanagedInstancesAnswer.getUnmanagedInstances()); Set keys = unmanagedInstances.keySet(); for (String key : keys) { @@ -1139,14 +1139,14 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { continue; } GetUnmanagedInstancesAnswer unmanagedInstancesAnswer = (GetUnmanagedInstancesAnswer) answer; - HashMap unmanagedInstances = unmanagedInstancesAnswer.getUnmanagedInstances(); + HashMap unmanagedInstances = unmanagedInstancesAnswer.getUnmanagedInstances(); if (MapUtils.isEmpty(unmanagedInstances)) { continue; } Set names = unmanagedInstances.keySet(); for (String name : names) { if (instanceName.equals(name)) { - UnmanagedInstance unmanagedInstance = unmanagedInstances.get(name); + UnmanagedInstanceTO unmanagedInstance = unmanagedInstances.get(name); if (unmanagedInstance == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve details for unmanaged VM: %s", name)); } diff --git a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java index 4543eecf0543..efea0e736157 100644 --- a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java @@ -167,15 +167,15 @@ public void setUp() throws Exception { UserVO user = new UserVO(1, "adminuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN); CallContext.register(user, account); - UnmanagedInstance instance = new UnmanagedInstance(); + UnmanagedInstanceTO instance = new UnmanagedInstanceTO(); instance.setName("TestInstance"); instance.setCpuCores(2); instance.setCpuCoresPerSocket(1); instance.setCpuSpeed(1000); instance.setMemory(1024); instance.setOperatingSystem("CentOS 7"); - List instanceDisks = new ArrayList<>(); - UnmanagedInstance.Disk instanceDisk = new UnmanagedInstance.Disk(); + List instanceDisks = new ArrayList<>(); + UnmanagedInstanceTO.Disk instanceDisk = new UnmanagedInstanceTO.Disk(); instanceDisk.setDiskId("1000-1"); instanceDisk.setLabel("DiskLabel"); instanceDisk.setController("scsi"); @@ -187,15 +187,15 @@ public void setUp() throws Exception { instanceDisk.setDatastoreType("NFS"); instanceDisks.add(instanceDisk); instance.setDisks(instanceDisks); - List instanceNics = new ArrayList<>(); - UnmanagedInstance.Nic instanceNic = new UnmanagedInstance.Nic(); + List instanceNics = new ArrayList<>(); + UnmanagedInstanceTO.Nic instanceNic = new UnmanagedInstanceTO.Nic(); instanceNic.setNicId("NIC 1"); instanceNic.setAdapterType("VirtualE1000E"); instanceNic.setMacAddress("02:00:2e:0f:00:02"); instanceNic.setVlan(1024); instanceNics.add(instanceNic); instance.setNics(instanceNics); - instance.setPowerState(UnmanagedInstance.PowerState.PowerOn); + instance.setPowerState(UnmanagedInstanceTO.PowerState.PowerOn); ClusterVO clusterVO = new ClusterVO(1L, 1L, "Cluster"); clusterVO.setHypervisorType(Hypervisor.HypervisorType.VMware.toString()); @@ -215,7 +215,7 @@ public void setUp() throws Exception { when(vmDao.listByHostId(Mockito.anyLong())).thenReturn(vms); when(vmDao.listByLastHostIdAndStates(Mockito.anyLong())).thenReturn(vms); GetUnmanagedInstancesCommand cmd = Mockito.mock(GetUnmanagedInstancesCommand.class); - HashMap map = new HashMap<>(); + HashMap map = new HashMap<>(); map.put(instance.getName(), instance); Answer answer = new GetUnmanagedInstancesAnswer(cmd, "", map); when(agentManager.easySend(Mockito.anyLong(), Mockito.any(GetUnmanagedInstancesCommand.class))).thenReturn(answer); From 770f2412743275a376ee786a8c8002ddf6015b55 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 18 Nov 2019 12:53:56 +0530 Subject: [PATCH 55/61] refactored importNic Signed-off-by: Abhishek Kumar --- .../engine/orchestration/NetworkOrchestrator.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index 41fef83a2ac6..28dce9cb6ded 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -3971,7 +3971,7 @@ public Pair importNic(final String macAddress, int deviceId } } final String finalGuestIp = guestIp; - NicVO vo = Transaction.execute(new TransactionCallback() { + final NicVO vo = Transaction.execute(new TransactionCallback() { @Override public NicVO doInTransaction(TransactionStatus status) { NicVO vo = new NicVO(network.getGuruName(), vm.getId(), network.getId(), vm.getType()); @@ -3993,10 +3993,20 @@ public NicVO doInTransaction(TransactionStatus status) { vo.setDeviceId(deviceId); vo.setDefaultNic(isDefaultNic); vo = _nicDao.persist(vo); + + int count = 1; + if (vo.getVmType() == VirtualMachine.Type.User) { + s_logger.debug("Changing active number of nics for network id=" + network.getUuid() + " on " + count); + _networksDao.changeActiveNicsBy(network.getId(), count); + } + if (vo.getVmType() == VirtualMachine.Type.User + || vo.getVmType() == VirtualMachine.Type.DomainRouter && _networksDao.findById(network.getId()).getTrafficType() == TrafficType.Guest) { + _networksDao.setCheckForGc(network.getId()); + } + return vo; } }); - updateNic(vo, network.getId(), 1); final Integer networkRate = _networkModel.getNetworkRate(network.getId(), vm.getId()); final NicProfile vmNic = new NicProfile(vo, network, vo.getBroadcastUri(), vo.getIsolationUri(), networkRate, _networkModel.isSecurityGroupSupportedInNetwork(network), From 1f94c6715b9e2723edbd36edeae8919b6082848a Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 27 Nov 2019 11:28:15 +0530 Subject: [PATCH 56/61] refactoring: defensive check Signed-off-by: Abhishek Kumar --- .../cloudstack/engine/orchestration/VolumeOrchestrator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java index f0cf170900ac..593891ea068d 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java @@ -1656,9 +1656,9 @@ public DiskProfile importVolume(Type type, String name, DiskOffering offering, L } if (template != null) { - if (template.getFormat() == ImageFormat.ISO) { + if (ImageFormat.ISO.equals(template.getFormat())) { vol.setIsoId(template.getId()); - } else if (template.getTemplateType().equals(Storage.TemplateType.DATADISK)) { + } else if (Storage.TemplateType.DATADISK.equals(template.getTemplateType())) { vol.setTemplateId(template.getId()); } if (type == Type.ROOT) { @@ -1667,7 +1667,7 @@ public DiskProfile importVolume(Type type, String name, DiskOffering offering, L } // display flag matters only for the User vms - if (vm.getType() == VirtualMachine.Type.User) { + if (VirtualMachine.Type.User.equals(vm.getType())) { UserVmVO userVm = _userVmDao.findById(vm.getId()); vol.setDisplayVolume(userVm.isDisplayVm()); } From fe5853f1996aa4123d67422cbc43eaae850741e9 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 2 Dec 2019 11:03:31 +0530 Subject: [PATCH 57/61] changed ipAddress key to ip4Address Signed-off-by: Abhishek Kumar --- api/src/main/java/com/cloud/vm/VmDetailConstants.java | 2 +- .../api/command/admin/vm/ImportUnmanagedInstanceCmd.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/com/cloud/vm/VmDetailConstants.java b/api/src/main/java/com/cloud/vm/VmDetailConstants.java index 8ef71b750c33..7c40a7ba421c 100644 --- a/api/src/main/java/com/cloud/vm/VmDetailConstants.java +++ b/api/src/main/java/com/cloud/vm/VmDetailConstants.java @@ -58,7 +58,7 @@ public interface VmDetailConstants { // VM import with nic, disk and custom params for custom compute offering String NIC = "nic"; String NETWORK = "network"; - String IP_ADDRESS = "ipAddress"; + String IP4_ADDRESS = "ip4Address"; String IP6_ADDRESS = "ip6Address"; String DISK = "disk"; String DISK_OFFERING = "diskOffering"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java index 140f5787e79b..70f59461936b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java @@ -142,7 +142,7 @@ public class ImportUnmanagedInstanceCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.NIC_IP_ADDRESS_LIST, type = CommandType.MAP, - description = "VM nic to ip address mapping using keys nic, ipAddress") + description = "VM nic to ip address mapping using keys nic, ip4Address") private Map nicIpAddressList; @Parameter(name = ApiConstants.DATADISK_OFFERING_LIST, @@ -224,7 +224,7 @@ public Map getNicIpAddressList() { if (MapUtils.isNotEmpty(nicIpAddressList)) { for (Map entry : (Collection>)nicIpAddressList.values()) { String nic = entry.get(VmDetailConstants.NIC); - String ipAddress = Strings.emptyToNull(entry.get(VmDetailConstants.IP_ADDRESS)); + String ipAddress = Strings.emptyToNull(entry.get(VmDetailConstants.IP4_ADDRESS)); if (Strings.isNullOrEmpty(nic)) { throw new InvalidParameterValueException(String.format("NIC ID: '%s' is invalid for IP address mapping", nic)); } From 9fbafe691294daa6e0a87255bc8495c4a05b62ef Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 2 Jan 2020 12:27:45 +0530 Subject: [PATCH 58/61] vm import, pvlan support Signed-off-by: Abhishek Kumar --- .../apache/cloudstack/api/ApiConstants.java | 1 + .../cloudstack/api/response/NicResponse.java | 24 +++++++++++ .../cloudstack/vm/UnmanagedInstanceTO.java | 20 ++++++++++ .../vmware/resource/VmwareResource.java | 9 ++++- .../vm/hypervisor/vmware/discover_networks.py | 40 +++++++++++++------ .../cloudstack/vm/VmImportManagerImpl.java | 12 +++++- .../vmware/mo/DistributedVirtualSwitchMO.java | 28 ++++++++++++- 7 files changed, 118 insertions(+), 16 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index ac5ed614cc38..5e1cd1884c87 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -372,6 +372,7 @@ public class ApiConstants { public static final String REMOVE_VLAN = "removevlan"; public static final String VLAN_ID = "vlanid"; public static final String ISOLATED_PVLAN = "isolatedpvlan"; + public static final String ISOLATED_PVLAN_TYPE = "isolatedpvlantype"; public static final String ISOLATION_URI = "isolationuri"; public static final String VM_AVAILABLE = "vmavailable"; public static final String VM_LIMIT = "vmlimit"; diff --git a/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java index 09ac41604269..72a2bbcabfd5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java @@ -118,6 +118,14 @@ public class NicResponse extends BaseResponse { @Param(description = "ID of the VLAN/VNI if available", since="4.14.0") private Integer vlanId; + @SerializedName(ApiConstants.ISOLATED_PVLAN) + @Param(description = "the isolated private VLAN if available", since="4.14.0") + private Integer isolatedPvlanId; + + @SerializedName(ApiConstants.ISOLATED_PVLAN_TYPE) + @Param(description = "the isolated private VLAN type if available", since="4.14.0") + private String isolatedPvlanType; + @SerializedName(ApiConstants.ADAPTER_TYPE) @Param(description = "Type of adapter if available", since="4.14.0") private String adapterType; @@ -325,6 +333,22 @@ public void setVlanId(Integer vlanId) { this.vlanId = vlanId; } + public Integer getIsolatedPvlanId() { + return isolatedPvlanId; + } + + public void setIsolatedPvlanId(Integer isolatedPvlanId) { + this.isolatedPvlanId = isolatedPvlanId; + } + + public String getIsolatedPvlanType() { + return isolatedPvlanType; + } + + public void setIsolatedPvlanType(String isolatedPvlanType) { + this.isolatedPvlanType = isolatedPvlanType; + } + public String getAdapterType() { return adapterType; } diff --git a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java index b7558789ab58..860ecdc3ba14 100644 --- a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java +++ b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java @@ -270,6 +270,10 @@ public static class Nic { private Integer vlan; + private Integer pvlan; + + private String pvlanType; + private List ipAddress; private String pciSlot; @@ -314,6 +318,22 @@ public void setVlan(Integer vlan) { this.vlan = vlan; } + public Integer getPvlan() { + return pvlan; + } + + public void setPvlan(Integer pvlan) { + this.pvlan = pvlan; + } + + public String getPvlanType() { + return pvlanType; + } + + public void setPvlanType(String pvlanType) { + this.pvlanType = pvlanType; + } + public List getIpAddress() { return ipAddress; } diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index ca0cbdb766b5..b96ad215e808 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -209,6 +209,7 @@ 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.DistributedVirtualSwitchMO; import com.cloud.hypervisor.vmware.mo.FeatureKeyConstants; import com.cloud.hypervisor.vmware.mo.HostDatastoreSystemMO; import com.cloud.hypervisor.vmware.mo.HostMO; @@ -6966,7 +6967,13 @@ private List getUnmanageInstanceNics(VmwareHypervisorHo VmwareDistributedVirtualSwitchPvlanSpec pvlanSpec = (VmwareDistributedVirtualSwitchPvlanSpec) settings.getVlan(); s_logger.trace("Found port " + dvPort.getKey() + " with pvlan " + pvlanSpec.getPvlanId()); if (pvlanSpec.getPvlanId() > 0 && pvlanSpec.getPvlanId() < 4095) { - instanceNic.setVlan(pvlanSpec.getPvlanId()); + DistributedVirtualSwitchMO dvSwitchMo = new DistributedVirtualSwitchMO(vmMo.getContext(), dvSwitch); + Pair vlanDetails = dvSwitchMo.retrieveVlanFromPvlan(pvlanSpec.getPvlanId(), dvSwitch); + if (vlanDetails != null && vlanDetails.first() != null && vlanDetails.second() != null) { + instanceNic.setVlan(vlanDetails.first()); + instanceNic.setPvlan(pvlanSpec.getPvlanId()); + instanceNic.setPvlanType(vlanDetails.second().toString()); + } } } break; diff --git a/scripts/vm/hypervisor/vmware/discover_networks.py b/scripts/vm/hypervisor/vmware/discover_networks.py index cb5dbf131e4c..d19e7847a41c 100755 --- a/scripts/vm/hypervisor/vmware/discover_networks.py +++ b/scripts/vm/hypervisor/vmware/discover_networks.py @@ -110,6 +110,8 @@ def get_vm_nics(vm, hostPgDict): dev_backing = dev.backing portGroup = None vlanId = None + isolatedPvlan = None + isolatedPvlanType = None vSwitch = None if hasattr(dev_backing, 'port'): portGroupKey = dev.backing.port.portgroupKey @@ -117,16 +119,26 @@ def get_vm_nics(vm, hostPgDict): try: dvs = content.dvSwitchManager.QueryDvsByUuid(dvsUuid) except: - portGroup = "** Error: DVS not found **" - vlanId = "NA" - vSwitch = "NA" + log_message('\tError: Unable retrieve details for distributed vSwitch ' + dvsUuid) + portGroup = '' + vlanId = '' + vSwitch = '' else: pgObj = dvs.LookupDvPortGroup(portGroupKey) portGroup = pgObj.config.name try: - vlanId = str(pgObj.config.defaultPortConfig.vlan.vlanId) + if isinstance(pgObj.config.defaultPortConfig.vlan, vim.dvs.VmwareDistributedVirtualSwitch.PvlanSpec): + for pvlanConfig in dvs.config.pvlanConfig: + if pvlanConfig.secondaryVlanId == pgObj.config.defaultPortConfig.vlan.pvlanId: + vlanId = str(pvlanConfig.primaryVlanId) + isolatedPvlanType = pvlanConfig.pvlanType + isolatedPvlan = str(pgObj.config.defaultPortConfig.vlan.pvlanId) + break + else: + vlanId = str(pgObj.config.defaultPortConfig.vlan.vlanId) except AttributeError: - vlanId = '0' + log_message('\tError: Unable retrieve details for portgroup ' + portGroup) + vlanId = '' vSwitch = str(dvs.name) else: portGroup = dev.backing.network.name @@ -138,11 +150,9 @@ def get_vm_nics(vm, hostPgDict): vlanId = str(p.spec.vlanId) vSwitch = str(p.spec.vswitchName) if portGroup is None: - portGroup = 'NA' + portGroup = '' if vlanId is None: - vlanId = 'NA' - if vSwitch is None: - vSwitch = 'NA' + vlanId = '' vmHostName = None vmClusterName = None try: @@ -153,14 +163,14 @@ def get_vm_nics(vm, hostPgDict): vmClusterName = vm.runtime.host.parent.name except AttributeError: vmClusterName = '' - add_network(portGroup, vlanId, vSwitch, vm.name, dev.deviceInfo.label, dev.macAddress, vmClusterName, vmHostName) + add_network(portGroup, vlanId, isolatedPvlanType, isolatedPvlan, vSwitch, vm.name, dev.deviceInfo.label, dev.macAddress, vmClusterName, vmHostName) log_message('\t\t' + dev.deviceInfo.label + '->' + dev.macAddress + ' @ ' + vSwitch + '->' + portGroup + ' (VLAN ' + vlanId + ')') except AttributeError: log_message('\tError: Unable retrieve details for ' + vm.name) -def add_network(portGroup, vlanId, vSwitch, vmName, vmDeviceLabel, vmMacAddress, vmClusterName, vmHostName): +def add_network(portGroup, vlanId, isolatedPvlanType, isolatedPvlan, vSwitch, vmName, vmDeviceLabel, vmMacAddress, vmClusterName, vmHostName): key = vSwitch + '->' + portGroup + ' (VLAN ' + vlanId + ')' device = {"label": vmDeviceLabel, "macaddress": vmMacAddress} vm = {"name":vmName, "device": device} @@ -179,7 +189,13 @@ def add_network(portGroup, vlanId, vSwitch, vmName, vmDeviceLabel, vmMacAddress, except KeyError: cluster = vmClusterName - network = {"portgroup": portGroup, "cluster": cluster, "host": host, "vlanid": vlanId, "switch": vSwitch, "virtualmachines": vms} + network = {"portgroup": portGroup, "cluster": cluster, "host": host, "switch": vSwitch, "virtualmachines": vms} + if vlanId != '': + network["vlanid"] = vlanId + if isolatedPvlan is not None: + network["isolatedpvlan"] = isolatedPvlan + if isolatedPvlanType is not None: + network["isolatedpvlantype"] = isolatedPvlanType networksDict[key] = network diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 20c4501cbdf3..198a611afee5 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -268,6 +268,8 @@ private UnmanagedInstanceResponse createUnmanagedInstanceResponse(UnmanagedInsta nicResponse.setIpAddresses(nic.getIpAddress()); } nicResponse.setVlanId(nic.getVlan()); + nicResponse.setIsolatedPvlanId(nic.getPvlan()); + nicResponse.setIsolatedPvlanType(nic.getPvlanType()); response.addNic(nicResponse); } } @@ -558,9 +560,17 @@ private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstanceTO.Nic nic, N if (!autoAssign && network.getGuestType().equals(Network.GuestType.Isolated)) { return; } - if (nic.getVlan() != null && nic.getVlan() != 0 && (Strings.isNullOrEmpty(network.getBroadcastUri().toString()) || !network.getBroadcastUri().toString().equals(String.format("vlan://%d", nic.getVlan())))) { + + if (nic.getVlan() != null && nic.getVlan() != 0 && nic.getPvlan() == null && + (Strings.isNullOrEmpty(network.getBroadcastUri().toString()) || + !network.getBroadcastUri().toString().equals(String.format("vlan://%d", nic.getVlan())))) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VLAN of network(ID: %s) %s is found different from the VLAN of nic(ID: %s) vlan://%d during VM import", network.getUuid(), network.getBroadcastUri().toString(), nic.getNicId(), nic.getVlan())); } + if (nic.getVlan() != null && nic.getVlan() != 0 && nic.getPvlan() != null && nic.getPvlan() != 0 && + (Strings.isNullOrEmpty(network.getBroadcastUri().toString()) || + !network.getBroadcastUri().toString().equals(String.format("pvlan://%d-i%d", nic.getVlan(), nic.getPvlan())))) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("PVLAN of network(ID: %s) %s is found different from the VLAN of nic(ID: %s) pvlan://%d-i%d during VM import", network.getUuid(), network.getBroadcastUri().toString(), nic.getNicId(), nic.getVlan(), nic.getPvlan())); + } } private void checkUnmanagedNicAndNetworkHostnameForImport(UnmanagedInstanceTO.Nic nic, Network network, final String hostName) throws ServerApiException { diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DistributedVirtualSwitchMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DistributedVirtualSwitchMO.java index fbb4265bcfb9..40a0a64650a4 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DistributedVirtualSwitchMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DistributedVirtualSwitchMO.java @@ -24,6 +24,8 @@ import org.apache.log4j.Logger; +import com.cloud.hypervisor.vmware.util.VmwareContext; +import com.cloud.utils.Pair; import com.vmware.vim25.DVPortgroupConfigSpec; import com.vmware.vim25.DVSConfigInfo; import com.vmware.vim25.ManagedObjectReference; @@ -32,8 +34,6 @@ import com.vmware.vim25.VMwareDVSConfigSpec; import com.vmware.vim25.VMwareDVSPvlanMapEntry; -import com.cloud.hypervisor.vmware.util.VmwareContext; - public class DistributedVirtualSwitchMO extends BaseMO { @SuppressWarnings("unused") private static final Logger s_logger = Logger.getLogger(DistributedVirtualSwitchMO.class); @@ -169,4 +169,28 @@ public Map retrieveVlanPvlan(int vlanid return result; } + public Pair retrieveVlanFromPvlan(int pvlanid, ManagedObjectReference dvSwitchMor) throws Exception { + assert (dvSwitchMor != null); + + Pair result = null; + + VMwareDVSConfigInfo configinfo = (VMwareDVSConfigInfo)_context.getVimClient().getDynamicProperty(dvSwitchMor, "config"); + List pvlanConfig = null; + pvlanConfig = configinfo.getPvlanConfig(); + + if (null == pvlanConfig || 0 == pvlanConfig.size()) { + return result; + } + + // Iterate through the pvlanMapList and check if the specified pvlan id exist. If it does, set the fields in result accordingly. + for (VMwareDVSPvlanMapEntry mapEntry : pvlanConfig) { + int entryVlanid = mapEntry.getPrimaryVlanId(); + int entryPvlanid = mapEntry.getSecondaryVlanId(); + if (pvlanid == entryPvlanid) { + result = new Pair<>(entryVlanid, HypervisorHostHelper.PvlanType.valueOf(mapEntry.getPvlanType())); + break; + } + } + return result; + } } From 2c52a1b0f42848c12f057c8ff12b713ed572dfa8 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 17 Jan 2020 14:34:08 +0530 Subject: [PATCH 59/61] change for VirtualMachine state changes Signed-off-by: Abhishek Kumar --- .../main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 198a611afee5..6a4572ed1eb5 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -351,7 +351,7 @@ private List getHostManagedVms(Host host) { instances = vmDao.listByLastHostIdAndStates(host.getId(), VirtualMachine.State.Stopped, VirtualMachine.State.Destroyed, VirtualMachine.State.Expunging, VirtualMachine.State.Error, - VirtualMachine.State.Unknown, VirtualMachine.State.Shutdowned); + VirtualMachine.State.Unknown, VirtualMachine.State.Shutdown); for (VMInstanceVO instance : instances) { managedVms.add(instance.getInstanceName()); } From 08b26030f3b2fb0bdc798630a3aeb411c5d34b61 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 17 Jan 2020 18:28:37 +0530 Subject: [PATCH 60/61] removed diskofferingid param from import API Signed-off-by: Abhishek Kumar --- .../main/java/com/cloud/vm/UserVmService.java | 2 +- .../admin/vm/ImportUnmanagedInstanceCmd.java | 12 ----- .../java/com/cloud/vm/UserVmManagerImpl.java | 7 ++- .../cloudstack/vm/VmImportManagerImpl.java | 54 ++++++++++--------- .../vm/VmImportManagerImplTest.java | 2 +- 5 files changed, 35 insertions(+), 42 deletions(-) diff --git a/api/src/main/java/com/cloud/vm/UserVmService.java b/api/src/main/java/com/cloud/vm/UserVmService.java index 8349e00d7054..23c6b38d8aab 100644 --- a/api/src/main/java/com/cloud/vm/UserVmService.java +++ b/api/src/main/java/com/cloud/vm/UserVmService.java @@ -514,7 +514,7 @@ UserVm upgradeVirtualMachine(ScaleVMCmd cmd) throws ResourceUnavailableException void collectVmNetworkStatistics (UserVm userVm); UserVm importVM(final DataCenter zone, final Host host, final VirtualMachineTemplate template, final String instanceName, final String displayName, final Account owner, final String userData, final Account caller, final Boolean isDisplayVm, final String keyboard, - final long accountId, final long userId, final ServiceOffering serviceOffering, final DiskOffering rootDiskOffering, final String sshPublicKey, + final long accountId, final long userId, final ServiceOffering serviceOffering, final String sshPublicKey, final String hostName, final HypervisorType hypervisorType, final Map customParameters, final VirtualMachine.PowerState powerState) throws InsufficientCapacityException; } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java index 70f59461936b..4b367f8f08c9 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java @@ -31,7 +31,6 @@ import org.apache.cloudstack.api.ResponseObject; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.ClusterResponse; -import org.apache.cloudstack.api.response.DiskOfferingResponse; import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.ServiceOfferingResponse; @@ -128,13 +127,6 @@ public class ImportUnmanagedInstanceCmd extends BaseAsyncCmd { description = "the ID of the service offering for the virtual machine") private Long serviceOfferingId; - @Parameter(name = ApiConstants.DISK_OFFERING_ID, - type = CommandType.UUID, - entityType = DiskOfferingResponse.class, - required = true, - description = "the ID of the root disk offering for the virtual machine") - private Long diskOfferingId; - @Parameter(name = ApiConstants.NIC_NETWORK_LIST, type = CommandType.MAP, description = "VM nic to network id mapping using keys nic and network") @@ -200,10 +192,6 @@ public Long getServiceOfferingId() { return serviceOfferingId; } - public Long getDiskOfferingId() { - return diskOfferingId; - } - public Map getNicNetworkList() { Map nicNetworkMap = new HashMap<>(); if (MapUtils.isNotEmpty(nicNetworkList)) { diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index 7e72c81b90db..f016341ab4ec 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -7053,7 +7053,7 @@ private void deleteVolumesFromVm(List volumes) { @Override public UserVm importVM(final DataCenter zone, final Host host, final VirtualMachineTemplate template, final String instanceName, final String displayName, final Account owner, final String userData, final Account caller, final Boolean isDisplayVm, final String keyboard, - final long accountId, final long userId, final ServiceOffering serviceOffering, final DiskOffering rootDiskOffering, final String sshPublicKey, + final long accountId, final long userId, final ServiceOffering serviceOffering, final String sshPublicKey, final String hostName, final HypervisorType hypervisorType, final Map customParameters, final VirtualMachine.PowerState powerState) throws InsufficientCapacityException { if (zone == null) { throw new InvalidParameterValueException("Unable to import virtual machine with invalid zone"); @@ -7071,11 +7071,10 @@ public UserVm importVM(final DataCenter zone, final Host host, final VirtualMach final String uuidName = _uuidMgr.generateUuid(UserVm.class, null); final Host lastHost = powerState != VirtualMachine.PowerState.PowerOn ? host : null; - UserVmVO userVmVO = commitUserVm(true, zone, host, lastHost, template, hostName, displayName, owner, - rootDiskOffering.getId(), null, userData, caller, isDisplayVm, keyboard, + return commitUserVm(true, zone, host, lastHost, template, hostName, displayName, owner, + null, null, userData, caller, isDisplayVm, keyboard, accountId, userId, serviceOffering, template.getFormat().equals(ImageFormat.ISO), sshPublicKey, null, id, instanceName, uuidName, hypervisorType, customParameters, null, null, null, powerState); - return userVmVO; } } \ No newline at end of file diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index 6a4572ed1eb5..ea81973b6d99 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -502,26 +502,28 @@ private StoragePool getStoragePool(final UnmanagedInstanceTO.Disk disk, final Da private void checkUnmanagedDiskAndOfferingForImport(UnmanagedInstanceTO.Disk disk, DiskOffering diskOffering, ServiceOffering serviceOffering, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed) throws ServerApiException, PermissionDeniedException, ResourceAllocationException { - if (diskOffering == null) { + if (serviceOffering == null && diskOffering == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID: %s not found during VM import", disk.getDiskId())); } - accountService.checkAccess(owner, diskOffering, zone); + if (diskOffering != null) { + accountService.checkAccess(owner, diskOffering, zone); + } resourceLimitService.checkResourceLimit(owner, Resource.ResourceType.volume); if (disk.getCapacity() == null || disk.getCapacity() == 0) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk(ID: %s) is found invalid during VM import", disk.getDiskId())); } - if (!diskOffering.isCustomized() && diskOffering.getDiskSize() == 0) { + if (diskOffering != null && !diskOffering.isCustomized() && diskOffering.getDiskSize() == 0) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of fixed disk offering(ID: %s) is found invalid during VM import", diskOffering.getUuid())); } - if (!diskOffering.isCustomized() && diskOffering.getDiskSize() < disk.getCapacity()) { + if (diskOffering != null && !diskOffering.isCustomized() && diskOffering.getDiskSize() < disk.getCapacity()) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk offering(ID: %s) %dGB is found less than the size of disk(ID: %s) %dGB during VM import", diskOffering.getUuid(), (diskOffering.getDiskSize() / Resource.ResourceType.bytesToGiB), disk.getDiskId(), (disk.getCapacity() / (Resource.ResourceType.bytesToGiB)))); } StoragePool storagePool = getStoragePool(disk, zone, cluster); - if (!migrateAllowed && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) { + if (diskOffering != null && !migrateAllowed && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) { throw new InvalidParameterValueException(String.format("Disk offering: %s is not compatible with storage pool: %s of unmanaged disk: %s", diskOffering.getUuid(), storagePool.getUuid(), disk.getDiskId())); } if (serviceOffering != null && !migrateAllowed && !storagePoolSupportsServiceOffering(storagePool, serviceOffering)) { - throw new InvalidParameterValueException(String.format("Service offering: %s is not compatible with storage pool: %s of unmanaged disk: %s", diskOffering.getUuid(), storagePool.getUuid(), disk.getDiskId())); + throw new InvalidParameterValueException(String.format("Service offering: %s is not compatible with storage pool: %s of unmanaged disk: %s", serviceOffering.getUuid(), storagePool.getUuid(), disk.getDiskId())); } } @@ -575,10 +577,10 @@ private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstanceTO.Nic nic, N private void checkUnmanagedNicAndNetworkHostnameForImport(UnmanagedInstanceTO.Nic nic, Network network, final String hostName) throws ServerApiException { if (nic == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import!")); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve NIC details during VM import")); } if (network == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import!", nic.getNicId())); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import", nic.getNicId())); } // Check for duplicate hostname in network, get all vms hostNames in the network List hostNames = vmDao.listDistinctHostNames(network.getId()); @@ -659,7 +661,7 @@ private Map getUnmanagedNicNetworkMap(List importDisk(UnmanagedInstanceTO.Disk disk, VirtualMachine vm, Cluster cluster, DiskOffering diskOffering, - Volume.Type type, String name, Long diskSize, VirtualMachineTemplate template, + Volume.Type type, String name, Long diskSize, Long minIops, Long maxIops, VirtualMachineTemplate template, Account owner, Long deviceId) { final DataCenter zone = dataCenterDao.findById(vm.getDataCenterId()); final String path = Strings.isNullOrEmpty(disk.getFileBaseName()) ? disk.getImagePath() : disk.getFileBaseName(); @@ -672,7 +674,7 @@ private Pair importDisk(UnmanagedInstanceTO.Disk disk, } StoragePool storagePool = getStoragePool(disk, zone, cluster); DiskProfile profile = volumeManager.importVolume(type, name, diskOffering, diskSize, - diskOffering.getMinIops(), diskOffering.getMaxIops(), vm, template, owner, deviceId, storagePool.getId(), path, disk.getChainInfo()); + minIops, maxIops, vm, template, owner, deviceId, storagePool.getId(), path, chainInfo); return new Pair(profile, storagePool); } @@ -877,7 +879,7 @@ private void publishVMUsageUpdateResourceCount(final UserVm userVm, ServiceOffer private UserVm importVirtualMachineInternal(final UnmanagedInstanceTO unmanagedInstance, final String instanceName, final DataCenter zone, final Cluster cluster, final HostVO host, final VirtualMachineTemplate template, final String displayName, final String hostName, final Account caller, final Account owner, final Long userId, - final ServiceOfferingVO serviceOffering, final DiskOffering diskOffering, final Map dataDiskOfferingMap, + final ServiceOfferingVO serviceOffering, final Map dataDiskOfferingMap, final Map nicNetworkMap, final Map callerNicIpAddressMap, final Map details, final boolean migrateAllowed) { UserVm userVm = null; @@ -914,7 +916,7 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstanceTO unmanagedI allDetails.put(VmDetailConstants.ROOT_DISK_CONTROLLER, rootDisk.getController()); List dataDisks = new ArrayList<>(); try { - checkUnmanagedDiskAndOfferingForImport(rootDisk, diskOffering, validatedServiceOffering, owner, zone, cluster, migrateAllowed); + checkUnmanagedDiskAndOfferingForImport(rootDisk, null, validatedServiceOffering, owner, zone, cluster, migrateAllowed); if (unmanagedInstanceDisks.size() > 1) { // Data disk(s) present dataDisks.addAll(unmanagedInstanceDisks); dataDisks.remove(0); @@ -939,7 +941,7 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstanceTO unmanagedI try { userVm = userVmManager.importVM(zone, host, template, instanceName, displayName, owner, null, caller, true, null, owner.getAccountId(), userId, - validatedServiceOffering, diskOffering, null, hostName, + validatedServiceOffering, null, hostName, cluster.getHypervisorType(), allDetails, powerState); } catch (InsufficientCapacityException ice) { LOGGER.error(String.format("Failed to import vm name: %s", instanceName), ice); @@ -953,13 +955,25 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstanceTO unmanagedI if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) { throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId())); } - diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, cluster, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()), (rootDisk.getCapacity() / Resource.ResourceType.bytesToGiB), template, owner, null)); + Long minIops = null; + if (details.containsKey("minIops")) { + minIops = Long.parseLong(details.get("minIops")); + } + Long maxIops = null; + if (details.containsKey("maxIops")) { + maxIops = Long.parseLong(details.get("maxIops")); + } + diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, cluster, serviceOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()), + (rootDisk.getCapacity() / Resource.ResourceType.bytesToGiB), minIops, maxIops, + template, owner, null)); for (UnmanagedInstanceTO.Disk disk : dataDisks) { if (disk.getCapacity() == null || disk.getCapacity() == 0) { throw new InvalidParameterValueException(String.format("Disk ID: %s size is invalid", rootDisk.getDiskId())); } DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId())); - diskProfileStoragePoolList.add(importDisk(disk, userVm, cluster, offering, Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()), (disk.getCapacity() / Resource.ResourceType.bytesToGiB), template, owner, null)); + diskProfileStoragePoolList.add(importDisk(disk, userVm, cluster, offering, Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()), + (disk.getCapacity() / Resource.ResourceType.bytesToGiB), offering.getMinIops(), offering.getMaxIops(), + template, owner, null)); } } catch (Exception e) { LOGGER.error(String.format("Failed to import volumes while importing vm: %s", instanceName), e); @@ -1096,14 +1110,6 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { LOGGER.error(String.format("VM resource allocation error for account: %s", owner.getUuid()), e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM resource allocation error for account: %s. %s", owner.getUuid(), Strings.nullToEmpty(e.getMessage()))); } - final Long diskOfferingId = cmd.getDiskOfferingId(); - if (diskOfferingId == null) { - throw new InvalidParameterValueException(String.format("Service offering ID cannot be null")); - } - final DiskOffering diskOffering = diskOfferingDao.findById(diskOfferingId); - if (diskOffering == null) { - throw new InvalidParameterValueException(String.format("Disk offering ID: %d cannot be found", diskOfferingId)); - } String displayName = cmd.getDisplayName(); if (Strings.isNullOrEmpty(displayName)) { displayName = instanceName; @@ -1183,7 +1189,7 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { } userVm = importVirtualMachineInternal(unmanagedInstance, instanceName, zone, cluster, host, template, displayName, hostName, caller, owner, userId, - serviceOffering, diskOffering, dataDiskOfferingMap, + serviceOffering, dataDiskOfferingMap, nicNetworkMap, nicIpAddressMap, details, cmd.getMigrateAllowed()); break; diff --git a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java index efea0e736157..f24c8e8a373e 100644 --- a/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/vm/VmImportManagerImplTest.java @@ -263,7 +263,7 @@ public void setUp() throws Exception { when(primaryDataStoreDao.listPoolByHostPath(Mockito.anyString(), Mockito.anyString())).thenReturn(pools); when(userVmManager.importVM(Mockito.any(DataCenter.class), Mockito.any(Host.class), Mockito.any(VirtualMachineTemplate.class), Mockito.anyString(), Mockito.anyString(), Mockito.any(Account.class), Mockito.anyString(), Mockito.any(Account.class), Mockito.anyBoolean(), Mockito.anyString(), - Mockito.anyLong(), Mockito.anyLong(), Mockito.any(ServiceOffering.class), Mockito.any(DiskOffering.class), Mockito.anyString(), + Mockito.anyLong(), Mockito.anyLong(), Mockito.any(ServiceOffering.class), Mockito.anyString(), Mockito.anyString(), Mockito.any(Hypervisor.HypervisorType.class), Mockito.anyMap(), Mockito.any(VirtualMachine.PowerState.class))).thenReturn(userVm); when(volumeApiService.doesTargetStorageSupportDiskOffering(Mockito.any(StoragePool.class), Mockito.anyString())).thenReturn(true); NetworkVO networkVO = Mockito.mock(NetworkVO.class); From 0ec876fc8cfa97fd29126afe3ca0e14f8ba09c51 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 20 Jan 2020 19:16:25 +0530 Subject: [PATCH 61/61] added null check for network broadcast uri Signed-off-by: Abhishek Kumar --- .../org/apache/cloudstack/vm/VmImportManagerImpl.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java index ea81973b6d99..1856a125661e 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/VmImportManagerImpl.java @@ -563,15 +563,16 @@ private void checkUnmanagedNicAndNetworkForImport(UnmanagedInstanceTO.Nic nic, N return; } + String networkBroadcastUri = network.getBroadcastUri() == null ? null : network.getBroadcastUri().toString(); if (nic.getVlan() != null && nic.getVlan() != 0 && nic.getPvlan() == null && - (Strings.isNullOrEmpty(network.getBroadcastUri().toString()) || - !network.getBroadcastUri().toString().equals(String.format("vlan://%d", nic.getVlan())))) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VLAN of network(ID: %s) %s is found different from the VLAN of nic(ID: %s) vlan://%d during VM import", network.getUuid(), network.getBroadcastUri().toString(), nic.getNicId(), nic.getVlan())); + (Strings.isNullOrEmpty(networkBroadcastUri) || + !networkBroadcastUri.equals(String.format("vlan://%d", nic.getVlan())))) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VLAN of network(ID: %s) %s is found different from the VLAN of nic(ID: %s) vlan://%d during VM import", network.getUuid(), networkBroadcastUri, nic.getNicId(), nic.getVlan())); } if (nic.getVlan() != null && nic.getVlan() != 0 && nic.getPvlan() != null && nic.getPvlan() != 0 && (Strings.isNullOrEmpty(network.getBroadcastUri().toString()) || - !network.getBroadcastUri().toString().equals(String.format("pvlan://%d-i%d", nic.getVlan(), nic.getPvlan())))) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("PVLAN of network(ID: %s) %s is found different from the VLAN of nic(ID: %s) pvlan://%d-i%d during VM import", network.getUuid(), network.getBroadcastUri().toString(), nic.getNicId(), nic.getVlan(), nic.getPvlan())); + !networkBroadcastUri.equals(String.format("pvlan://%d-i%d", nic.getVlan(), nic.getPvlan())))) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("PVLAN of network(ID: %s) %s is found different from the VLAN of nic(ID: %s) pvlan://%d-i%d during VM import", network.getUuid(), networkBroadcastUri, nic.getNicId(), nic.getVlan(), nic.getPvlan())); } }