From ca9b052e8ea0c57afd8e7cc997d439ef0e01d1e4 Mon Sep 17 00:00:00 2001 From: Prashanth Reddy Date: Thu, 11 Jun 2026 20:32:09 +0000 Subject: [PATCH 01/10] feat: add nicmacaddresslist parameter to importUnmanagedInstance and importVM APIs Allow callers to specify per-NIC MAC addresses when importing a VM into CloudStack management, overriding the MAC address reported by the hypervisor. Problem ------- importUnmanagedInstance and importVM always used the MAC address reported by the hypervisor. There was no way to supply a specific MAC at import time. The only control was 'forced': reject conflicting MAC or silently replace it. Solution -------- Add new MAP parameter 'nicmacaddresslist' to ImportUnmanagedInstanceCmd (inherited by ImportVmCmd), following the pattern of 'nicnetworklist' and 'nicipaddresslist'. nicmacaddresslist[0].nic=nic1&nicmacaddresslist[0].mac=aa:bb:cc:dd:ee:ff nicmacaddresslist[1].nic=nic2&nicmacaddresslist[1].mac=aa:bb:cc:dd:ee:02 NICs not listed keep their hypervisor-reported MAC (backward compatible). Changes ------- - ApiConstants: add NIC_MAC_ADDRESS_LIST = "nicmacaddresslist" - VmDetailConstants: add NIC_MAC_ADDRESS = "mac" (map entry key) - ImportUnmanagedInstanceCmd: add @Parameter nicmacaddresslist with getNicMacAddressList() validation (isValidMac + isUnicastMac + standardizeMacAddress), matching BaseDeployVMCmd / AddNicToVMCmd - UnmanagedVMsManagerImpl: * mergeNicMacAddresses() merges caller MACs into the IpAddresses map * baseImportInstance() and importVm() call mergeNicMacAddresses() * importNic() prefers ipAddresses.getMacAddress() (caller) over nic.getMacAddress() (hypervisor) when non-empty * importNic() changed private -> protected for testability Tests ----- - ImportUnmanagedInstanceCmdTest: MAC format/unicast/empty validation - UnmanagedVMsManagerImplTest: mergeNicMacAddresses() edge cases + importNic() MAC selection (caller preferred, fallback to hypervisor) --- .../java/com/cloud/vm/VmDetailConstants.java | 277 +- .../apache/cloudstack/api/ApiConstants.java | 2987 ++++---- .../admin/vm/ImportUnmanagedInstanceCmd.java | 587 +- .../vm/ImportUnmanagedInstanceCmdTest.java | 139 + .../vm/UnmanagedVMsManagerImpl.java | 6360 ++++++++--------- .../vm/UnmanagedVMsManagerImplTest.java | 3288 +++++---- 6 files changed, 6958 insertions(+), 6680 deletions(-) create mode 100644 api/src/test/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmdTest.java diff --git a/api/src/main/java/com/cloud/vm/VmDetailConstants.java b/api/src/main/java/com/cloud/vm/VmDetailConstants.java index 33cc6da70812..bcee784512ba 100644 --- a/api/src/main/java/com/cloud/vm/VmDetailConstants.java +++ b/api/src/main/java/com/cloud/vm/VmDetailConstants.java @@ -1,139 +1,140 @@ -// 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.vm; - -public interface VmDetailConstants { - String KEYBOARD = "keyboard"; - String CPU_CORE_PER_SOCKET = "cpu.corespersocket"; - String CPU_THREAD_PER_CORE = "cpu.threadspercore"; - String ROOT_DISK_SIZE = "rootdisksize"; - String BOOT_MODE = "boot.mode"; - String NAME_ON_HYPERVISOR= "nameonhypervisor"; - - // VMware specific - String NIC_ADAPTER = "nicAdapter"; - String ROOT_DISK_CONTROLLER = "rootDiskController"; - String DATA_DISK_CONTROLLER = "dataDiskController"; - String SVGA_VRAM_SIZE = "svga.vramSize"; - String NESTED_VIRTUALIZATION_FLAG = "nestedVirtualizationFlag"; - String RAM_RESERVATION = "ramReservation"; - - // XenServer specific (internal) - String HYPERVISOR_TOOLS_VERSION = "hypervisortoolsversion"; - String PLATFORM = "platform"; - String TIME_OFFSET = "timeoffset"; - - // KVM specific (internal) - String KVM_VNC_PORT = "kvm.vnc.port"; - String KVM_VNC_ADDRESS = "kvm.vnc.address"; - String KVM_VNC_PASSWORD = "kvm.vnc.password"; - String KVM_GUEST_OS_MACHINE_TYPE = "kvm.guest.os.machine.type"; - - // KVM specific, custom virtual GPU hardware - String VIDEO_HARDWARE = "video.hardware"; - String VIDEO_RAM = "video.ram"; - - //KVM specific, loop threads for block IO requests - String IOTHREADS = "iothreads"; - String IO_POLICY = "io.policy"; - - // KVM specific, the number of queues for multiqueue NICs - String NIC_MULTIQUEUE_NUMBER = "nic.multiqueue.number"; - String NIC_PACKED_VIRTQUEUES_ENABLED = "nic.packed.virtqueues.enabled"; - - // KVM specific, disk controllers - String KVM_SKIP_FORCE_DISK_CONTROLLER = "skip.force.disk.controller"; - - // Mac OSX guest specific (internal) - String SMC_PRESENT = "smc.present"; - String FIRMWARE = "firmware"; - - // VM deployment with custom compute offering params - String CPU_NUMBER = "cpuNumber"; - String CPU_SPEED = "cpuSpeed"; - String MEMORY = "memory"; - - // Misc details for internal usage (not to be set/changed by user or admin) - String CPU_OVER_COMMIT_RATIO = "cpuOvercommitRatio"; - String MEMORY_OVER_COMMIT_RATIO = "memoryOvercommitRatio"; - String MESSAGE_RESERVED_CAPACITY_FREED_FLAG = "Message.ReservedCapacityFreed.Flag"; - String DEPLOY_VM = "deployvm"; - String SSH_PUBLIC_KEY = "SSH.PublicKey"; - String SSH_KEY_PAIR_NAMES = "SSH.KeyPairNames"; - String PASSWORD = "password"; - String ENCRYPTED_PASSWORD = "Encrypted.Password"; - - String CONFIG_DRIVE_LOCATION = "configDriveLocation"; - String LAST_CONFIG_DRIVE_LOCATION = "lastConfigDriveLocation"; - - String SKIP_DRS = "skipFromDRS"; - - // VM import with nic, disk and custom params for custom compute offering - String NIC = "nic"; - String NETWORK = "network"; - String IP4_ADDRESS = "ip4Address"; +// 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.vm; + +public interface VmDetailConstants { + String KEYBOARD = "keyboard"; + String CPU_CORE_PER_SOCKET = "cpu.corespersocket"; + String CPU_THREAD_PER_CORE = "cpu.threadspercore"; + String ROOT_DISK_SIZE = "rootdisksize"; + String BOOT_MODE = "boot.mode"; + String NAME_ON_HYPERVISOR= "nameonhypervisor"; + + // VMware specific + String NIC_ADAPTER = "nicAdapter"; + String ROOT_DISK_CONTROLLER = "rootDiskController"; + String DATA_DISK_CONTROLLER = "dataDiskController"; + String SVGA_VRAM_SIZE = "svga.vramSize"; + String NESTED_VIRTUALIZATION_FLAG = "nestedVirtualizationFlag"; + String RAM_RESERVATION = "ramReservation"; + + // XenServer specific (internal) + String HYPERVISOR_TOOLS_VERSION = "hypervisortoolsversion"; + String PLATFORM = "platform"; + String TIME_OFFSET = "timeoffset"; + + // KVM specific (internal) + String KVM_VNC_PORT = "kvm.vnc.port"; + String KVM_VNC_ADDRESS = "kvm.vnc.address"; + String KVM_VNC_PASSWORD = "kvm.vnc.password"; + String KVM_GUEST_OS_MACHINE_TYPE = "kvm.guest.os.machine.type"; + + // KVM specific, custom virtual GPU hardware + String VIDEO_HARDWARE = "video.hardware"; + String VIDEO_RAM = "video.ram"; + + //KVM specific, loop threads for block IO requests + String IOTHREADS = "iothreads"; + String IO_POLICY = "io.policy"; + + // KVM specific, the number of queues for multiqueue NICs + String NIC_MULTIQUEUE_NUMBER = "nic.multiqueue.number"; + String NIC_PACKED_VIRTQUEUES_ENABLED = "nic.packed.virtqueues.enabled"; + + // KVM specific, disk controllers + String KVM_SKIP_FORCE_DISK_CONTROLLER = "skip.force.disk.controller"; + + // Mac OSX guest specific (internal) + String SMC_PRESENT = "smc.present"; + String FIRMWARE = "firmware"; + + // VM deployment with custom compute offering params + String CPU_NUMBER = "cpuNumber"; + String CPU_SPEED = "cpuSpeed"; + String MEMORY = "memory"; + + // Misc details for internal usage (not to be set/changed by user or admin) + String CPU_OVER_COMMIT_RATIO = "cpuOvercommitRatio"; + String MEMORY_OVER_COMMIT_RATIO = "memoryOvercommitRatio"; + String MESSAGE_RESERVED_CAPACITY_FREED_FLAG = "Message.ReservedCapacityFreed.Flag"; + String DEPLOY_VM = "deployvm"; + String SSH_PUBLIC_KEY = "SSH.PublicKey"; + String SSH_KEY_PAIR_NAMES = "SSH.KeyPairNames"; + String PASSWORD = "password"; + String ENCRYPTED_PASSWORD = "Encrypted.Password"; + + String CONFIG_DRIVE_LOCATION = "configDriveLocation"; + String LAST_CONFIG_DRIVE_LOCATION = "lastConfigDriveLocation"; + + String SKIP_DRS = "skipFromDRS"; + + // VM import with nic, disk and custom params for custom compute offering + String NIC = "nic"; + String NETWORK = "network"; + String IP4_ADDRESS = "ip4Address"; String IP6_ADDRESS = "ip6Address"; - String DISK = "disk"; - String DISK_OFFERING = "diskOffering"; - - String DEPLOY_AS_IS_CONFIGURATION = "configurationId"; - String KEY_PAIR_NAMES = "keypairnames"; - String CKS_CONTROL_NODE_LOGIN_USER = "controlNodeLoginUser"; - String CKS_NODE_TYPE = "node"; - String OFFERING = "offering"; - String TEMPLATE = "template"; - String AFFINITY_GROUP = "affinitygroup"; - - // VMware to KVM VM migrations specific - String VMWARE_TO_KVM_PREFIX = "vmware-to-kvm"; - String VMWARE_VCENTER_HOST = String.format("%s-vcenter", VMWARE_TO_KVM_PREFIX); - String VMWARE_DATACENTER_NAME = String.format("%s-datacenter", VMWARE_TO_KVM_PREFIX); - String VMWARE_CLUSTER_NAME = String.format("%s-cluster", VMWARE_TO_KVM_PREFIX); - String VMWARE_VCENTER_USERNAME = String.format("%s-username", VMWARE_TO_KVM_PREFIX); - String VMWARE_VCENTER_PASSWORD = String.format("%s-password", VMWARE_TO_KVM_PREFIX); - String VMWARE_VM_NAME = String.format("%s-vmname", VMWARE_TO_KVM_PREFIX); - String VMWARE_HOST_NAME = String.format("%s-host", VMWARE_TO_KVM_PREFIX); - String VMWARE_DISK = String.format("%s-disk", VMWARE_TO_KVM_PREFIX); - String VMWARE_MAC_ADDRESSES = String.format("%s-mac-addresses", VMWARE_TO_KVM_PREFIX); - - // TPM - String VIRTUAL_TPM_ENABLED = "virtual.tpm.enabled"; - String VIRTUAL_TPM_MODEL = "virtual.tpm.model"; - String VIRTUAL_TPM_VERSION = "virtual.tpm.version"; - - // CPU mode and model, ADMIN only - String GUEST_CPU_MODE = "guest.cpu.mode"; - String GUEST_CPU_MODEL = "guest.cpu.model"; - - // Lease related - String INSTANCE_LEASE_EXPIRY_DATE = "leaseexpirydate"; - String INSTANCE_LEASE_EXPIRY_ACTION = "leaseexpiryaction"; - String INSTANCE_LEASE_EXECUTION = "leaseactionexecution"; - - // External orchestrator related - String MAC_ADDRESS = "mac_address"; - String EXPUNGE_EXTERNAL_VM = "expunge.external.vm"; - String EXTERNAL_DETAIL_PREFIX = "External:"; - String CLOUDSTACK_VM_DETAILS = "cloudstack.vm.details"; - String CLOUDSTACK_VLAN = "cloudstack.vlan"; - - // KVM Checkpoints related - String ACTIVE_CHECKPOINT_ID = "active.checkpoint.id"; - String ACTIVE_CHECKPOINT_CREATE_TIME = "active.checkpoint.create.time"; - String LAST_CHECKPOINT_ID = "last.checkpoint.id"; - String LAST_CHECKPOINT_CREATE_TIME = "last.checkpoint.create.time"; -} + String NIC_MAC_ADDRESS = "mac"; + String DISK = "disk"; + String DISK_OFFERING = "diskOffering"; + + String DEPLOY_AS_IS_CONFIGURATION = "configurationId"; + String KEY_PAIR_NAMES = "keypairnames"; + String CKS_CONTROL_NODE_LOGIN_USER = "controlNodeLoginUser"; + String CKS_NODE_TYPE = "node"; + String OFFERING = "offering"; + String TEMPLATE = "template"; + String AFFINITY_GROUP = "affinitygroup"; + + // VMware to KVM VM migrations specific + String VMWARE_TO_KVM_PREFIX = "vmware-to-kvm"; + String VMWARE_VCENTER_HOST = String.format("%s-vcenter", VMWARE_TO_KVM_PREFIX); + String VMWARE_DATACENTER_NAME = String.format("%s-datacenter", VMWARE_TO_KVM_PREFIX); + String VMWARE_CLUSTER_NAME = String.format("%s-cluster", VMWARE_TO_KVM_PREFIX); + String VMWARE_VCENTER_USERNAME = String.format("%s-username", VMWARE_TO_KVM_PREFIX); + String VMWARE_VCENTER_PASSWORD = String.format("%s-password", VMWARE_TO_KVM_PREFIX); + String VMWARE_VM_NAME = String.format("%s-vmname", VMWARE_TO_KVM_PREFIX); + String VMWARE_HOST_NAME = String.format("%s-host", VMWARE_TO_KVM_PREFIX); + String VMWARE_DISK = String.format("%s-disk", VMWARE_TO_KVM_PREFIX); + String VMWARE_MAC_ADDRESSES = String.format("%s-mac-addresses", VMWARE_TO_KVM_PREFIX); + + // TPM + String VIRTUAL_TPM_ENABLED = "virtual.tpm.enabled"; + String VIRTUAL_TPM_MODEL = "virtual.tpm.model"; + String VIRTUAL_TPM_VERSION = "virtual.tpm.version"; + + // CPU mode and model, ADMIN only + String GUEST_CPU_MODE = "guest.cpu.mode"; + String GUEST_CPU_MODEL = "guest.cpu.model"; + + // Lease related + String INSTANCE_LEASE_EXPIRY_DATE = "leaseexpirydate"; + String INSTANCE_LEASE_EXPIRY_ACTION = "leaseexpiryaction"; + String INSTANCE_LEASE_EXECUTION = "leaseactionexecution"; + + // External orchestrator related + String MAC_ADDRESS = "mac_address"; + String EXPUNGE_EXTERNAL_VM = "expunge.external.vm"; + String EXTERNAL_DETAIL_PREFIX = "External:"; + String CLOUDSTACK_VM_DETAILS = "cloudstack.vm.details"; + String CLOUDSTACK_VLAN = "cloudstack.vlan"; + + // KVM Checkpoints related + String ACTIVE_CHECKPOINT_ID = "active.checkpoint.id"; + String ACTIVE_CHECKPOINT_CREATE_TIME = "active.checkpoint.create.time"; + String LAST_CHECKPOINT_ID = "last.checkpoint.id"; + String LAST_CHECKPOINT_CREATE_TIME = "last.checkpoint.create.time"; +} 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 ee10db031ba7..a8820698e1a2 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -1,1494 +1,1495 @@ -// 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; - -public class ApiConstants { - public static final String ACCOUNT = "account"; - public static final String ACCOUNTS = "accounts"; - public static final String ACCOUNT_NAME = "accountname"; - public static final String ACCOUNT_STATE_TO_SHOW = "accountstatetoshow"; - public static final String ACCOUNT_TYPE = "accounttype"; - public static final String ACCOUNT_ID = "accountid"; - public static final String ACCOUNT_IDS = "accountids"; - public static final String ACCUMULATE = "accumulate"; - public static final String ACQUIRED = "acquired"; - public static final String ACTIVATION_RULE = "activationrule"; - public static final String ACTIVITY = "activity"; - public static final String ADAPTER_TYPE = "adaptertype"; - public static final String ADDITONAL_CONFIG_ENABLED = "additionalconfigenabled"; - public static final String ADDRESS = "address"; - public static final String ALGORITHM = "algorithm"; - public static final String ALIAS = "alias"; - public static final String ALLOCATED = "allocated"; - public static final String ALLOCATED_DATE = "allocateddate"; - public static final String ALLOCATED_ONLY = "allocatedonly"; - public static final String ALLOCATED_TIME = "allocated"; - public static final String ALLOWED_ROLE_TYPES = "allowedroletypes"; - public static final String ALLOW_USER_FORCE_STOP_VM = "allowuserforcestopvm"; - public static final String ANNOTATION = "annotation"; - public static final String API_KEY = "apikey"; - public static final String API_KEY_ACCESS = "apikeyaccess"; - public static final String ARCHIVED = "archived"; - public static final String ARCH = "arch"; - public static final String AS_NUMBER = "asnumber"; - public static final String AS_NUMBER_ID = "asnumberid"; - public static final String ASN_RANGE = "asnrange"; - public static final String ASN_RANGE_ID = "asnrangeid"; - public static final String API_KEY_FILTER = "apikeyfilter"; - public static final String ASYNC_BACKUP = "asyncbackup"; - public static final String AUTO_SELECT = "autoselect"; - public static final String USER_API_KEY = "userapikey"; - public static final String APPLIED = "applied"; - public static final String LIST_LB_VMIPS = "lbvmips"; - public static final String LIVE_PATCH = "livepatch"; - public static final String AVAILABLE = "available"; - public static final String AVAILABLE_SUBNETS = "availablesubnets"; - public static final String AVAILABLE_VIRTUAL_MACHINE_COUNT = "availablevirtualmachinecount"; - public static final String BACKUP_AVAILABLE = "backupavailable"; - public static final String BACKUP_ID = "backupid"; - public static final String BACKUP_LIMIT = "backuplimit"; - public static final String BACKUP_OFFERING_NAME = "backupofferingname"; - public static final String BACKUP_OFFERING_ID = "backupofferingid"; - public static final String BACKUP_STORAGE_AVAILABLE = "backupstorageavailable"; - public static final String BACKUP_STORAGE_LIMIT = "backupstoragelimit"; - public static final String BACKUP_STORAGE_TOTAL = "backupstoragetotal"; - public static final String BACKUP_VM_OFFERING_REMOVED = "vmbackupofferingremoved"; - public static final String IS_BACKUP_VM_EXPUNGED = "isbackupvmexpunged"; - public static final String BACKUP_TOTAL = "backuptotal"; - public static final String BALANCE = "balance"; - public static final String BALANCES = "balances"; - public static final String BASE64_IMAGE = "base64image"; - public static final String BGP_PEERS = "bgppeers"; - public static final String BGP_PEER_IDS = "bgppeerids"; - public static final String BATCH_SIZE = "batchsize"; - public static final String BITS = "bits"; - public static final String BOOTABLE = "bootable"; - public static final String BIND_DN = "binddn"; - public static final String BIND_PASSWORD = "bindpass"; - public static final String BLANK_INSTANCE = "blankinstance"; - public static final String BUS_ADDRESS = "busaddress"; - public static final String BYTES_READ_RATE = "bytesreadrate"; - public static final String BYTES_READ_RATE_MAX = "bytesreadratemax"; - public static final String BYTES_READ_RATE_MAX_LENGTH = "bytesreadratemaxlength"; - public static final String BYTES_WRITE_RATE = "byteswriterate"; - 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 CALLER = "caller"; - 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"; - public static final String CERTIFICATE = "certificate"; - 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 CERTIFICATE_ISSUER = "issuer"; - public static final String CERTIFICATE_SERIALNUM = "serialnum"; - public static final String CERTIFICATE_SUBJECT = "subject"; - public static final String CERTIFICATE_VALIDITY = "validity"; - public static final String CONVERT_INSTANCE_HOST_ID = "convertinstancehostid"; - public static final String CONVERT_INSTANCE_STORAGE_POOL_ID = "convertinstancepoolid"; - public static final String ENABLED_REVOCATION_CHECK = "enabledrevocationcheck"; - public static final String CLIENT_ADDRESS = "clientaddress"; - public static final String COMBINED_CAPACITY_ORDERING = "COMBINED"; - public static final String CONTROLLER = "controller"; - public static final String CONTROLLER_UNIT = "controllerunit"; - public static final String CONSOLE_ENDPOINT_CREATOR_ADDRESS = "consoleendpointcreatoraddress"; - public static final String COPY_IMAGE_TAGS = "copyimagetags"; - public static final String CPU_OVERCOMMIT_RATIO = "cpuOvercommitRatio"; - 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_ID = "datastoreid"; - public static final String DATASTORE_NAME = "datastorename"; - public static final String DATASTORE_PATH = "datastorepath"; - public static final String DATASTORE_STATE = "datastorestate"; - 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"; - public static final String CIDR = "cidr"; - public static final String CIDR_SIZE = "cidrsize"; - - public static final String IP6_CIDR = "ip6cidr"; - public static final String CIDR_LIST = "cidrlist"; - public static final String DEST_CIDR_LIST = "destcidrlist"; - public static final String CLEANUP = "cleanup"; - public static final String MAKEREDUNDANT = "makeredundant"; - public static final String CLUSTER_ID = "clusterid"; - public static final String CLUSTER_IDS = "clusterids"; - public static final String CLUSTER_NAME = "clustername"; - public static final String CLUSTER_TYPE = "clustertype"; - public static final String CN = "cn"; - public static final String COMMAND = "command"; - public static final String CMD_EVENT_TYPE = "cmdeventtype"; - public static final String CNI_CONFIG = "cniconfig"; - public static final String CNI_CONFIG_ID = "cniconfigurationid"; - public static final String CNI_CONFIG_DETAILS = "cniconfigdetails"; - public static final String CNI_CONFIG_NAME = "cniconfigname"; - public static final String CSI_ENABLED = "csienabled"; - public static final String COMPONENT = "component"; - public static final String CPU = "CPU"; - 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 CPU_LOAD_AVERAGE = "cpuloadaverage"; - public static final String CREATED = "created"; - public static final String CROSS_ZONE_INSTANCE_CREATION = "crosszoneinstancecreation"; - public static final String CTX_ACCOUNT_ID = "ctxaccountid"; - public static final String CTX_DETAILS = "ctxDetails"; - public static final String CTX_USER_ID = "ctxuserid"; - public static final String CTXSTARTEVENTID = "ctxstarteventid"; - public static final String CTX_START_EVENT_ID = "ctxStartEventId"; - public static final String CUSTOMIZED = "customized"; - public static final String CUSTOMIZED_IOPS = "customizediops"; - public static final String CUSTOM_ID = "customid"; - public static final String CUSTOM_ACTION_ID = "customactionid"; - public static final String CUSTOM_JOB_ID = "customjobid"; - public static final String CURRENCY = "currency"; - public static final String CURRENT_START_IP = "currentstartip"; - public static final String CURRENT_END_IP = "currentendip"; - public static final String ENCRYPT = "encrypt"; - public static final String ENCRYPT_FORMAT = "encryptformat"; - public static final String ENCRYPT_ROOT = "encryptroot"; - public static final String ENCRYPTION_SUPPORTED = "encryptionsupported"; - public static final String ETCD_IPS = "etcdips"; - public static final String MIN_IOPS = "miniops"; - public static final String MAX_IOPS = "maxiops"; - public static final String HYPERVISOR_SNAPSHOT_RESERVE = "hypervisorsnapshotreserve"; - public static final String DATACENTER_NAME = "datacentername"; - public static final String DATADISKS_DETAILS = "datadisksdetails"; - public static final String DATADISK_OFFERING_LIST = "datadiskofferinglist"; - public static final String DATE = "date"; - public static final String DEFAULT_VALUE = "defaultvalue"; - public static final String DELETE_PROTECTION = "deleteprotection"; - public static final String DESCRIPTION = "description"; - public static final String DESTINATION = "destination"; - public static final String DESTINATION_ZONE_ID = "destzoneid"; - public static final String DETAILS = "details"; - public static final String DEVICE_ID = "deviceid"; - public static final String DEVICE_IDS = "deviceids"; - public static final String DEVICE_NAME = "devicename"; - 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 ORCHESTRATOR_REQUIRES_PREPARE_VM = "orchestratorrequirespreparevm"; - public static final String OVERRIDE_DISK_OFFERING_ID = "overridediskofferingid"; - public static final String DISK_KBS_READ = "diskkbsread"; - public static final String DISK_KBS_WRITE = "diskkbswrite"; - public static final String DISK_IO_READ = "diskioread"; - public static final String DISK_IO_WRITE = "diskiowrite"; - public static final String DISK_IO_PSTOTAL = "diskiopstotal"; - public static final String DISK_SIZE = "disksize"; - public static final String DISK_SIZE_STRICTNESS = "disksizestrictness"; - public static final String DISK_OFFERING_STRICTNESS = "diskofferingstrictness"; - public static final String DOWNLOAD_DETAILS = "downloaddetails"; - public static final String UTILIZATION = "utilization"; - public static final String DRIVER = "driver"; - public static final String ROOT_DISK_SIZE = "rootdisksize"; - public static final String DHCP_OPTIONS_NETWORK_LIST = "dhcpoptionsnetworklist"; - public static final String DHCP_OPTIONS = "dhcpoptions"; - public static final String DHCP_PREFIX = "dhcp:"; - public static final String DISPLAY_NAME = "displayname"; - public static final String DISPLAY_NETWORK = "displaynetwork"; - public static final String DISPLAY_NIC = "displaynic"; - public static final String DISPLAY_TEXT = "displaytext"; - public static final String DISPLAY_VM = "displayvm"; - public static final String DISPLAY_OFFERING = "displayoffering"; - public static final String DISPLAY_VOLUME = "displayvolume"; - public static final String DNS1 = "dns1"; - public static final String DNS2 = "dns2"; - public static final String IP6_DNS1 = "ip6dns1"; - public static final String IP6_DNS2 = "ip6dns2"; - public static final String DOMAIN = "domain"; - public static final String DOMAIN_DETAILS = "domaindetails"; - public static final String DOMAIN_PATH = "domainpath"; - public static final String DOMAIN_ID = "domainid"; - public static final String DOMAIN__ID = "domainId"; - public static final String DUMMY = "dummy"; - public static final String DURATION = "duration"; - public static final String ELIGIBLE = "eligible"; - public static final String EMAIL = "email"; - public static final String ENABLE_CSI = "enablecsi"; - public static final String END_ASN = "endasn"; - public static final String END_DATE = "enddate"; - public static final String END_IP = "endip"; - public static final String END_IPV6 = "endipv6"; - public static final String END_PORT = "endport"; - public static final String ENTRY_TIME = "entrytime"; - public static final String ERROR_MESSAGE = "errormessage"; - public static final String EVENT_ID = "eventid"; - public static final String EVENT_TYPE = "eventtype"; - public static final String EXPIRES = "expires"; - public static final String EXTRA_CONFIG = "extraconfig"; - public static final String EXTRA_PARAMS = "extraparams"; - public static final String EXTRA_DHCP_OPTION = "extradhcpoption"; - public static final String EXTRA_DHCP_OPTION_NAME = "extradhcpoptionname"; - public static final String EXTRA_DHCP_OPTION_CODE = "extradhcpoptioncode"; - public static final String EXTRA_DHCP_OPTION_VALUE = "extradhcpvalue"; - public static final String EXTERNAL = "external"; - public static final String EXTERNAL_UUID = "externaluuid"; - public static final String EXTERNAL_DETAILS = "externaldetails"; - public static final String PARAMETERS = "parameters"; - public static final String EXTENSION = "extension"; - public static final String EXTENSION_ID = "extensionid"; - public static final String EXTENSION_NAME = "extensionname"; - public static final String EXTENSIONS_PATH = "extensionspath"; - public static final String FENCE = "fence"; - public static final String FETCH_LATEST = "fetchlatest"; - public static final String FILESYSTEM = "filesystem"; - public static final String FIRSTNAME = "firstname"; - public static final String FORCED = "forced"; - public static final String FORCED_DESTROY_LOCAL_STORAGE = "forcedestroylocalstorage"; - public static final String FORCE_CONVERT_TO_POOL = "forceconverttopool"; - - public static final String FORCE_DELETE_HOST = "forcedeletehost"; - public static final String FORCE_MS_TO_IMPORT_VM_FILES = "forcemstoimportvmfiles"; - public static final String FORCE_UPDATE_OS_TYPE = "forceupdateostype"; - public static final String FORMAT = "format"; - public static final String FOR_VIRTUAL_NETWORK = "forvirtualnetwork"; - public static final String FOR_SYSTEM_VMS = "forsystemvms"; - public static final String FOR_PROVIDER = "forprovider"; - public static final String FROM_CHECKPOINT_ID = "fromcheckpointid"; - public static final String FULL_PATH = "fullpath"; - public static final String GATEWAY = "gateway"; - public static final String IP6_GATEWAY = "ip6gateway"; - public static final String GROUP = "group"; - public static final String SUBGROUP = "subgroup"; - public static final String GROUP_ID = "groupid"; - public static final String GSLB_LB_METHOD = "gslblbmethod"; - public static final String GSLB_SERVICE_DOMAIN_NAME = "gslbdomainname"; - public static final String GSLB_SERVICE_TYPE = "gslbservicetype"; - public static final String GSLB_STICKY_SESSION_METHOD = "gslbstickysessionmethodname"; - public static final String GSLB_LBRULE_WEIGHT_MAP = "gslblbruleweightsmap"; - public static final String GUEST_CIDR_ADDRESS = "guestcidraddress"; - public static final String GUEST_VLAN_RANGE = "guestvlanrange"; - public static final String HA_ENABLE = "haenable"; - public static final String HA_PROVIDER = "haprovider"; - public static final String HA_STATE = "hastate"; - public static final String HEALTH = "health"; - public static final String HEADERS = "headers"; - public static final String HIDE_IP_ADDRESS_USAGE = "hideipaddressusage"; - public static final String HOST_ID = "hostid"; - public static final String HOST_IDS = "hostids"; - public static final String HOST_IP = "hostip"; - public static final String HOST_NAME = "hostname"; - public static final String HOST = "host"; - public static final String HOST_CONTROL_STATE = "hostcontrolstate"; - public static final String HOSTS_MAP = "hostsmap"; - public static final String HTTP_REQUEST_TYPE = "httprequesttype"; - public static final String HYPERVISOR = "hypervisor"; - public static final String INLINE = "inline"; - public static final String INSTANCE = "instance"; - public static final String ICMP_CODE = "icmpcode"; - public static final String ICMP_TYPE = "icmptype"; - public static final String ID = "id"; - public static final String IDS = "ids"; - public static final String IMPORT_INSTANCE_HOST_ID = "importinstancehostid"; - public static final String INDEX = "index"; - public static final String INSTANCES_DISKS_STATS_RETENTION_ENABLED = "instancesdisksstatsretentionenabled"; - public static final String INSTANCES_DISKS_STATS_RETENTION_TIME = "instancesdisksstatsretentiontime"; - public static final String INSTANCES_STATS_RETENTION_TIME = "instancesstatsretentiontime"; - public static final String INSTANCES_STATS_USER_ONLY = "instancesstatsuseronly"; - public static final String PREFIX = "prefix"; - public static final String PREVIOUS_ACL_RULE_ID = "previousaclruleid"; - public static final String PREVIOUS_OWNER_ID = "previousownerid"; - public static final String PREVIOUS_OWNER_NAME = "previousownername"; - public static final String NEXT_ACL_RULE_ID = "nextaclruleid"; - public static final String NEXT_HOP = "nexthop"; - public static final String MOVE_ACL_CONSISTENCY_HASH = "aclconsistencyhash"; - public static final String IMAGE_PATH = "imagepath"; - public static final String INSTANCE_CONVERSION_SUPPORTED = "instanceconversionsupported"; - public static final String INTERNAL_DNS1 = "internaldns1"; - public static final String INTERNAL_DNS2 = "internaldns2"; - public static final String INTERNET_PROTOCOL = "internetprotocol"; - public static final String INTERVAL_TYPE = "intervaltype"; - public static final String INSTANCE_LEASE_DURATION = "leaseduration"; - public static final String INSTANCE_LEASE_ENABLED = "instanceleaseenabled"; - public static final String INSTANCE_LEASE_EXPIRY_ACTION = "leaseexpiryaction"; - public static final String INSTANCE_LEASE_EXPIRY_DATE= "leaseexpirydate"; - public static final String IOPS_READ_RATE = "iopsreadrate"; - public static final String IOPS_READ_RATE_MAX = "iopsreadratemax"; - public static final String IOPS_READ_RATE_MAX_LENGTH = "iopsreadratemaxlength"; - public static final String IOPS_WRITE_RATE = "iopswriterate"; - 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 IP6_ADDRESSES = "ip6addresses"; - public static final String IP_ADDRESS_ID = "ipaddressid"; - public static final String IS_2FA_ENABLED = "is2faenabled"; - public static final String IS_2FA_VERIFIED = "is2faverified"; - - public static final String IS_2FA_MANDATED = "is2famandated"; - public static final String IS_ACTIVE = "isactive"; - public static final String IS_ASYNC = "isasync"; - public static final String IP_AVAILABLE = "ipavailable"; - public static final String IP_LIMIT = "iplimit"; - public static final String IP_TOTAL = "iptotal"; - public static final String IS_CONTROL_NODE = "iscontrolnode"; - public static final String IS_CLEANUP_REQUIRED = "iscleanuprequired"; - public static final String IS_DYNAMIC = "isdynamic"; - public static final String IS_EDGE = "isedge"; - public static final String IS_ENCRYPTED = "isencrypted"; - public static final String IS_EXTRACTABLE = "isextractable"; - public static final String IS_FEATURED = "isfeatured"; - public static final String IS_IMPLICIT = "isimplicit"; - public static final String IS_ISO = "isiso"; - public static final String IS_PORTABLE = "isportable"; - public static final String IS_PUBLIC = "ispublic"; - public static final String IS_PERSISTENT = "ispersistent"; - public static final String EGRESS_DEFAULT_POLICY = "egressdefaultpolicy"; - public static final String IS_READY = "isready"; - public static final String IS_RECURSIVE = "isrecursive"; - public static final String ISO_FILTER = "isofilter"; - public static final String ISO_ID = "isoid"; - public static final String ISO_GUEST_OS_NONE = "None"; - public static final String JAVA_DISTRIBUTION = "javadistribution"; - public static final String JAVA_VERSION = "javaversion"; - public static final String JOB_ID = "jobid"; - public static final String JOB_STATUS = "jobstatus"; - public static final String KEEPALIVE_ENABLED = "keepaliveenabled"; - public static final String KERNEL_VERSION = "kernelversion"; - public static final String KEYPAIR_ID = "keypairid"; - public static final String KEY = "key"; - public static final String LABEL = "label"; - public static final String LASTNAME = "lastname"; - public static final String LAST_BOOT = "lastboottime"; - public static final String LAST_SERVER_START = "lastserverstart"; - public static final String LAST_SERVER_STOP = "lastserverstop"; - public static final String LEASED = "leased"; - public static final String LEVEL = "level"; - public static final String LENGTH = "length"; - public static final String LIMIT = "limit"; - public static final String LIMIT_CPU_USE = "limitcpuuse"; - public static final String LIST_HOSTS = "listhosts"; - public static final String LOCATION_TYPE = "locationtype"; - public static final String LOCK = "lock"; - public static final String LUN = "lun"; - public static final String LBID = "lbruleid"; - public static final String LB_PROVIDER = "lbprovider"; - public static final String MAC_ADDRESS = "macaddress"; - public static final String MAC_ADDRESSES = "macaddresses"; - public static final String MANUAL_UPGRADE = "manualupgrade"; - public static final String MATCH_TYPE = "matchtype"; - public static final String MAX = "max"; - public static final String MAX_SNAPS = "maxsnaps"; - public static final String MAX_BACKUPS = "maxbackups"; - public static final String MAX_CPU_NUMBER = "maxcpunumber"; - public static final String MAX_MEMORY = "maxmemory"; - public static final String MEMORY_OVERCOMMIT_RATIO = "memoryOvercommitRatio"; - public static final String MESSAGE = "message"; - public static final String MIN_CPU_NUMBER = "mincpunumber"; - public static final String MIN_MEMORY = "minmemory"; - public static final String MIGRATION_TYPE = "migrationtype"; - public static final String MIGRATION_JOB_ID = "migrationjobid"; - public static final String MIGRATION_JOB_STATUS = "migrationjobstatus"; - public static final String MIGRATIONS = "migrations"; - public static final String MEMORY = "memory"; - public static final String MODE = "mode"; - public static final String MOUNT_CKS_ISO_ON_VR = "mountcksisoonvr"; - public static final String MULTI_ARCH = "ismultiarch"; - public static final String NSX_MODE = "nsxmode"; - public static final String NETWORK_MODE = "networkmode"; - public static final String NSX_ENABLED = "isnsxenabled"; - public static final String NAME = "name"; - public static final String METHOD_NAME = "methodname"; - 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 NICS = "nics"; - public static final String NIC_NETWORK_LIST = "nicnetworklist"; +// 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; + +public class ApiConstants { + public static final String ACCOUNT = "account"; + public static final String ACCOUNTS = "accounts"; + public static final String ACCOUNT_NAME = "accountname"; + public static final String ACCOUNT_STATE_TO_SHOW = "accountstatetoshow"; + public static final String ACCOUNT_TYPE = "accounttype"; + public static final String ACCOUNT_ID = "accountid"; + public static final String ACCOUNT_IDS = "accountids"; + public static final String ACCUMULATE = "accumulate"; + public static final String ACQUIRED = "acquired"; + public static final String ACTIVATION_RULE = "activationrule"; + public static final String ACTIVITY = "activity"; + public static final String ADAPTER_TYPE = "adaptertype"; + public static final String ADDITONAL_CONFIG_ENABLED = "additionalconfigenabled"; + public static final String ADDRESS = "address"; + public static final String ALGORITHM = "algorithm"; + public static final String ALIAS = "alias"; + public static final String ALLOCATED = "allocated"; + public static final String ALLOCATED_DATE = "allocateddate"; + public static final String ALLOCATED_ONLY = "allocatedonly"; + public static final String ALLOCATED_TIME = "allocated"; + public static final String ALLOWED_ROLE_TYPES = "allowedroletypes"; + public static final String ALLOW_USER_FORCE_STOP_VM = "allowuserforcestopvm"; + public static final String ANNOTATION = "annotation"; + public static final String API_KEY = "apikey"; + public static final String API_KEY_ACCESS = "apikeyaccess"; + public static final String ARCHIVED = "archived"; + public static final String ARCH = "arch"; + public static final String AS_NUMBER = "asnumber"; + public static final String AS_NUMBER_ID = "asnumberid"; + public static final String ASN_RANGE = "asnrange"; + public static final String ASN_RANGE_ID = "asnrangeid"; + public static final String API_KEY_FILTER = "apikeyfilter"; + public static final String ASYNC_BACKUP = "asyncbackup"; + public static final String AUTO_SELECT = "autoselect"; + public static final String USER_API_KEY = "userapikey"; + public static final String APPLIED = "applied"; + public static final String LIST_LB_VMIPS = "lbvmips"; + public static final String LIVE_PATCH = "livepatch"; + public static final String AVAILABLE = "available"; + public static final String AVAILABLE_SUBNETS = "availablesubnets"; + public static final String AVAILABLE_VIRTUAL_MACHINE_COUNT = "availablevirtualmachinecount"; + public static final String BACKUP_AVAILABLE = "backupavailable"; + public static final String BACKUP_ID = "backupid"; + public static final String BACKUP_LIMIT = "backuplimit"; + public static final String BACKUP_OFFERING_NAME = "backupofferingname"; + public static final String BACKUP_OFFERING_ID = "backupofferingid"; + public static final String BACKUP_STORAGE_AVAILABLE = "backupstorageavailable"; + public static final String BACKUP_STORAGE_LIMIT = "backupstoragelimit"; + public static final String BACKUP_STORAGE_TOTAL = "backupstoragetotal"; + public static final String BACKUP_VM_OFFERING_REMOVED = "vmbackupofferingremoved"; + public static final String IS_BACKUP_VM_EXPUNGED = "isbackupvmexpunged"; + public static final String BACKUP_TOTAL = "backuptotal"; + public static final String BALANCE = "balance"; + public static final String BALANCES = "balances"; + public static final String BASE64_IMAGE = "base64image"; + public static final String BGP_PEERS = "bgppeers"; + public static final String BGP_PEER_IDS = "bgppeerids"; + public static final String BATCH_SIZE = "batchsize"; + public static final String BITS = "bits"; + public static final String BOOTABLE = "bootable"; + public static final String BIND_DN = "binddn"; + public static final String BIND_PASSWORD = "bindpass"; + public static final String BLANK_INSTANCE = "blankinstance"; + public static final String BUS_ADDRESS = "busaddress"; + public static final String BYTES_READ_RATE = "bytesreadrate"; + public static final String BYTES_READ_RATE_MAX = "bytesreadratemax"; + public static final String BYTES_READ_RATE_MAX_LENGTH = "bytesreadratemaxlength"; + public static final String BYTES_WRITE_RATE = "byteswriterate"; + 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 CALLER = "caller"; + 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"; + public static final String CERTIFICATE = "certificate"; + 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 CERTIFICATE_ISSUER = "issuer"; + public static final String CERTIFICATE_SERIALNUM = "serialnum"; + public static final String CERTIFICATE_SUBJECT = "subject"; + public static final String CERTIFICATE_VALIDITY = "validity"; + public static final String CONVERT_INSTANCE_HOST_ID = "convertinstancehostid"; + public static final String CONVERT_INSTANCE_STORAGE_POOL_ID = "convertinstancepoolid"; + public static final String ENABLED_REVOCATION_CHECK = "enabledrevocationcheck"; + public static final String CLIENT_ADDRESS = "clientaddress"; + public static final String COMBINED_CAPACITY_ORDERING = "COMBINED"; + public static final String CONTROLLER = "controller"; + public static final String CONTROLLER_UNIT = "controllerunit"; + public static final String CONSOLE_ENDPOINT_CREATOR_ADDRESS = "consoleendpointcreatoraddress"; + public static final String COPY_IMAGE_TAGS = "copyimagetags"; + public static final String CPU_OVERCOMMIT_RATIO = "cpuOvercommitRatio"; + 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_ID = "datastoreid"; + public static final String DATASTORE_NAME = "datastorename"; + public static final String DATASTORE_PATH = "datastorepath"; + public static final String DATASTORE_STATE = "datastorestate"; + 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"; + public static final String CIDR = "cidr"; + public static final String CIDR_SIZE = "cidrsize"; + + public static final String IP6_CIDR = "ip6cidr"; + public static final String CIDR_LIST = "cidrlist"; + public static final String DEST_CIDR_LIST = "destcidrlist"; + public static final String CLEANUP = "cleanup"; + public static final String MAKEREDUNDANT = "makeredundant"; + public static final String CLUSTER_ID = "clusterid"; + public static final String CLUSTER_IDS = "clusterids"; + public static final String CLUSTER_NAME = "clustername"; + public static final String CLUSTER_TYPE = "clustertype"; + public static final String CN = "cn"; + public static final String COMMAND = "command"; + public static final String CMD_EVENT_TYPE = "cmdeventtype"; + public static final String CNI_CONFIG = "cniconfig"; + public static final String CNI_CONFIG_ID = "cniconfigurationid"; + public static final String CNI_CONFIG_DETAILS = "cniconfigdetails"; + public static final String CNI_CONFIG_NAME = "cniconfigname"; + public static final String CSI_ENABLED = "csienabled"; + public static final String COMPONENT = "component"; + public static final String CPU = "CPU"; + 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 CPU_LOAD_AVERAGE = "cpuloadaverage"; + public static final String CREATED = "created"; + public static final String CROSS_ZONE_INSTANCE_CREATION = "crosszoneinstancecreation"; + public static final String CTX_ACCOUNT_ID = "ctxaccountid"; + public static final String CTX_DETAILS = "ctxDetails"; + public static final String CTX_USER_ID = "ctxuserid"; + public static final String CTXSTARTEVENTID = "ctxstarteventid"; + public static final String CTX_START_EVENT_ID = "ctxStartEventId"; + public static final String CUSTOMIZED = "customized"; + public static final String CUSTOMIZED_IOPS = "customizediops"; + public static final String CUSTOM_ID = "customid"; + public static final String CUSTOM_ACTION_ID = "customactionid"; + public static final String CUSTOM_JOB_ID = "customjobid"; + public static final String CURRENCY = "currency"; + public static final String CURRENT_START_IP = "currentstartip"; + public static final String CURRENT_END_IP = "currentendip"; + public static final String ENCRYPT = "encrypt"; + public static final String ENCRYPT_FORMAT = "encryptformat"; + public static final String ENCRYPT_ROOT = "encryptroot"; + public static final String ENCRYPTION_SUPPORTED = "encryptionsupported"; + public static final String ETCD_IPS = "etcdips"; + public static final String MIN_IOPS = "miniops"; + public static final String MAX_IOPS = "maxiops"; + public static final String HYPERVISOR_SNAPSHOT_RESERVE = "hypervisorsnapshotreserve"; + public static final String DATACENTER_NAME = "datacentername"; + public static final String DATADISKS_DETAILS = "datadisksdetails"; + public static final String DATADISK_OFFERING_LIST = "datadiskofferinglist"; + public static final String DATE = "date"; + public static final String DEFAULT_VALUE = "defaultvalue"; + public static final String DELETE_PROTECTION = "deleteprotection"; + public static final String DESCRIPTION = "description"; + public static final String DESTINATION = "destination"; + public static final String DESTINATION_ZONE_ID = "destzoneid"; + public static final String DETAILS = "details"; + public static final String DEVICE_ID = "deviceid"; + public static final String DEVICE_IDS = "deviceids"; + public static final String DEVICE_NAME = "devicename"; + 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 ORCHESTRATOR_REQUIRES_PREPARE_VM = "orchestratorrequirespreparevm"; + public static final String OVERRIDE_DISK_OFFERING_ID = "overridediskofferingid"; + public static final String DISK_KBS_READ = "diskkbsread"; + public static final String DISK_KBS_WRITE = "diskkbswrite"; + public static final String DISK_IO_READ = "diskioread"; + public static final String DISK_IO_WRITE = "diskiowrite"; + public static final String DISK_IO_PSTOTAL = "diskiopstotal"; + public static final String DISK_SIZE = "disksize"; + public static final String DISK_SIZE_STRICTNESS = "disksizestrictness"; + public static final String DISK_OFFERING_STRICTNESS = "diskofferingstrictness"; + public static final String DOWNLOAD_DETAILS = "downloaddetails"; + public static final String UTILIZATION = "utilization"; + public static final String DRIVER = "driver"; + public static final String ROOT_DISK_SIZE = "rootdisksize"; + public static final String DHCP_OPTIONS_NETWORK_LIST = "dhcpoptionsnetworklist"; + public static final String DHCP_OPTIONS = "dhcpoptions"; + public static final String DHCP_PREFIX = "dhcp:"; + public static final String DISPLAY_NAME = "displayname"; + public static final String DISPLAY_NETWORK = "displaynetwork"; + public static final String DISPLAY_NIC = "displaynic"; + public static final String DISPLAY_TEXT = "displaytext"; + public static final String DISPLAY_VM = "displayvm"; + public static final String DISPLAY_OFFERING = "displayoffering"; + public static final String DISPLAY_VOLUME = "displayvolume"; + public static final String DNS1 = "dns1"; + public static final String DNS2 = "dns2"; + public static final String IP6_DNS1 = "ip6dns1"; + public static final String IP6_DNS2 = "ip6dns2"; + public static final String DOMAIN = "domain"; + public static final String DOMAIN_DETAILS = "domaindetails"; + public static final String DOMAIN_PATH = "domainpath"; + public static final String DOMAIN_ID = "domainid"; + public static final String DOMAIN__ID = "domainId"; + public static final String DUMMY = "dummy"; + public static final String DURATION = "duration"; + public static final String ELIGIBLE = "eligible"; + public static final String EMAIL = "email"; + public static final String ENABLE_CSI = "enablecsi"; + public static final String END_ASN = "endasn"; + public static final String END_DATE = "enddate"; + public static final String END_IP = "endip"; + public static final String END_IPV6 = "endipv6"; + public static final String END_PORT = "endport"; + public static final String ENTRY_TIME = "entrytime"; + public static final String ERROR_MESSAGE = "errormessage"; + public static final String EVENT_ID = "eventid"; + public static final String EVENT_TYPE = "eventtype"; + public static final String EXPIRES = "expires"; + public static final String EXTRA_CONFIG = "extraconfig"; + public static final String EXTRA_PARAMS = "extraparams"; + public static final String EXTRA_DHCP_OPTION = "extradhcpoption"; + public static final String EXTRA_DHCP_OPTION_NAME = "extradhcpoptionname"; + public static final String EXTRA_DHCP_OPTION_CODE = "extradhcpoptioncode"; + public static final String EXTRA_DHCP_OPTION_VALUE = "extradhcpvalue"; + public static final String EXTERNAL = "external"; + public static final String EXTERNAL_UUID = "externaluuid"; + public static final String EXTERNAL_DETAILS = "externaldetails"; + public static final String PARAMETERS = "parameters"; + public static final String EXTENSION = "extension"; + public static final String EXTENSION_ID = "extensionid"; + public static final String EXTENSION_NAME = "extensionname"; + public static final String EXTENSIONS_PATH = "extensionspath"; + public static final String FENCE = "fence"; + public static final String FETCH_LATEST = "fetchlatest"; + public static final String FILESYSTEM = "filesystem"; + public static final String FIRSTNAME = "firstname"; + public static final String FORCED = "forced"; + public static final String FORCED_DESTROY_LOCAL_STORAGE = "forcedestroylocalstorage"; + public static final String FORCE_CONVERT_TO_POOL = "forceconverttopool"; + + public static final String FORCE_DELETE_HOST = "forcedeletehost"; + public static final String FORCE_MS_TO_IMPORT_VM_FILES = "forcemstoimportvmfiles"; + public static final String FORCE_UPDATE_OS_TYPE = "forceupdateostype"; + public static final String FORMAT = "format"; + public static final String FOR_VIRTUAL_NETWORK = "forvirtualnetwork"; + public static final String FOR_SYSTEM_VMS = "forsystemvms"; + public static final String FOR_PROVIDER = "forprovider"; + public static final String FROM_CHECKPOINT_ID = "fromcheckpointid"; + public static final String FULL_PATH = "fullpath"; + public static final String GATEWAY = "gateway"; + public static final String IP6_GATEWAY = "ip6gateway"; + public static final String GROUP = "group"; + public static final String SUBGROUP = "subgroup"; + public static final String GROUP_ID = "groupid"; + public static final String GSLB_LB_METHOD = "gslblbmethod"; + public static final String GSLB_SERVICE_DOMAIN_NAME = "gslbdomainname"; + public static final String GSLB_SERVICE_TYPE = "gslbservicetype"; + public static final String GSLB_STICKY_SESSION_METHOD = "gslbstickysessionmethodname"; + public static final String GSLB_LBRULE_WEIGHT_MAP = "gslblbruleweightsmap"; + public static final String GUEST_CIDR_ADDRESS = "guestcidraddress"; + public static final String GUEST_VLAN_RANGE = "guestvlanrange"; + public static final String HA_ENABLE = "haenable"; + public static final String HA_PROVIDER = "haprovider"; + public static final String HA_STATE = "hastate"; + public static final String HEALTH = "health"; + public static final String HEADERS = "headers"; + public static final String HIDE_IP_ADDRESS_USAGE = "hideipaddressusage"; + public static final String HOST_ID = "hostid"; + public static final String HOST_IDS = "hostids"; + public static final String HOST_IP = "hostip"; + public static final String HOST_NAME = "hostname"; + public static final String HOST = "host"; + public static final String HOST_CONTROL_STATE = "hostcontrolstate"; + public static final String HOSTS_MAP = "hostsmap"; + public static final String HTTP_REQUEST_TYPE = "httprequesttype"; + public static final String HYPERVISOR = "hypervisor"; + public static final String INLINE = "inline"; + public static final String INSTANCE = "instance"; + public static final String ICMP_CODE = "icmpcode"; + public static final String ICMP_TYPE = "icmptype"; + public static final String ID = "id"; + public static final String IDS = "ids"; + public static final String IMPORT_INSTANCE_HOST_ID = "importinstancehostid"; + public static final String INDEX = "index"; + public static final String INSTANCES_DISKS_STATS_RETENTION_ENABLED = "instancesdisksstatsretentionenabled"; + public static final String INSTANCES_DISKS_STATS_RETENTION_TIME = "instancesdisksstatsretentiontime"; + public static final String INSTANCES_STATS_RETENTION_TIME = "instancesstatsretentiontime"; + public static final String INSTANCES_STATS_USER_ONLY = "instancesstatsuseronly"; + public static final String PREFIX = "prefix"; + public static final String PREVIOUS_ACL_RULE_ID = "previousaclruleid"; + public static final String PREVIOUS_OWNER_ID = "previousownerid"; + public static final String PREVIOUS_OWNER_NAME = "previousownername"; + public static final String NEXT_ACL_RULE_ID = "nextaclruleid"; + public static final String NEXT_HOP = "nexthop"; + public static final String MOVE_ACL_CONSISTENCY_HASH = "aclconsistencyhash"; + public static final String IMAGE_PATH = "imagepath"; + public static final String INSTANCE_CONVERSION_SUPPORTED = "instanceconversionsupported"; + public static final String INTERNAL_DNS1 = "internaldns1"; + public static final String INTERNAL_DNS2 = "internaldns2"; + public static final String INTERNET_PROTOCOL = "internetprotocol"; + public static final String INTERVAL_TYPE = "intervaltype"; + public static final String INSTANCE_LEASE_DURATION = "leaseduration"; + public static final String INSTANCE_LEASE_ENABLED = "instanceleaseenabled"; + public static final String INSTANCE_LEASE_EXPIRY_ACTION = "leaseexpiryaction"; + public static final String INSTANCE_LEASE_EXPIRY_DATE= "leaseexpirydate"; + public static final String IOPS_READ_RATE = "iopsreadrate"; + public static final String IOPS_READ_RATE_MAX = "iopsreadratemax"; + public static final String IOPS_READ_RATE_MAX_LENGTH = "iopsreadratemaxlength"; + public static final String IOPS_WRITE_RATE = "iopswriterate"; + 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 IP6_ADDRESSES = "ip6addresses"; + public static final String IP_ADDRESS_ID = "ipaddressid"; + public static final String IS_2FA_ENABLED = "is2faenabled"; + public static final String IS_2FA_VERIFIED = "is2faverified"; + + public static final String IS_2FA_MANDATED = "is2famandated"; + public static final String IS_ACTIVE = "isactive"; + public static final String IS_ASYNC = "isasync"; + public static final String IP_AVAILABLE = "ipavailable"; + public static final String IP_LIMIT = "iplimit"; + public static final String IP_TOTAL = "iptotal"; + public static final String IS_CONTROL_NODE = "iscontrolnode"; + public static final String IS_CLEANUP_REQUIRED = "iscleanuprequired"; + public static final String IS_DYNAMIC = "isdynamic"; + public static final String IS_EDGE = "isedge"; + public static final String IS_ENCRYPTED = "isencrypted"; + public static final String IS_EXTRACTABLE = "isextractable"; + public static final String IS_FEATURED = "isfeatured"; + public static final String IS_IMPLICIT = "isimplicit"; + public static final String IS_ISO = "isiso"; + public static final String IS_PORTABLE = "isportable"; + public static final String IS_PUBLIC = "ispublic"; + public static final String IS_PERSISTENT = "ispersistent"; + public static final String EGRESS_DEFAULT_POLICY = "egressdefaultpolicy"; + public static final String IS_READY = "isready"; + public static final String IS_RECURSIVE = "isrecursive"; + public static final String ISO_FILTER = "isofilter"; + public static final String ISO_ID = "isoid"; + public static final String ISO_GUEST_OS_NONE = "None"; + public static final String JAVA_DISTRIBUTION = "javadistribution"; + public static final String JAVA_VERSION = "javaversion"; + public static final String JOB_ID = "jobid"; + public static final String JOB_STATUS = "jobstatus"; + public static final String KEEPALIVE_ENABLED = "keepaliveenabled"; + public static final String KERNEL_VERSION = "kernelversion"; + public static final String KEYPAIR_ID = "keypairid"; + public static final String KEY = "key"; + public static final String LABEL = "label"; + public static final String LASTNAME = "lastname"; + public static final String LAST_BOOT = "lastboottime"; + public static final String LAST_SERVER_START = "lastserverstart"; + public static final String LAST_SERVER_STOP = "lastserverstop"; + public static final String LEASED = "leased"; + public static final String LEVEL = "level"; + public static final String LENGTH = "length"; + public static final String LIMIT = "limit"; + public static final String LIMIT_CPU_USE = "limitcpuuse"; + public static final String LIST_HOSTS = "listhosts"; + public static final String LOCATION_TYPE = "locationtype"; + public static final String LOCK = "lock"; + public static final String LUN = "lun"; + public static final String LBID = "lbruleid"; + public static final String LB_PROVIDER = "lbprovider"; + public static final String MAC_ADDRESS = "macaddress"; + public static final String MAC_ADDRESSES = "macaddresses"; + public static final String MANUAL_UPGRADE = "manualupgrade"; + public static final String MATCH_TYPE = "matchtype"; + public static final String MAX = "max"; + public static final String MAX_SNAPS = "maxsnaps"; + public static final String MAX_BACKUPS = "maxbackups"; + public static final String MAX_CPU_NUMBER = "maxcpunumber"; + public static final String MAX_MEMORY = "maxmemory"; + public static final String MEMORY_OVERCOMMIT_RATIO = "memoryOvercommitRatio"; + public static final String MESSAGE = "message"; + public static final String MIN_CPU_NUMBER = "mincpunumber"; + public static final String MIN_MEMORY = "minmemory"; + public static final String MIGRATION_TYPE = "migrationtype"; + public static final String MIGRATION_JOB_ID = "migrationjobid"; + public static final String MIGRATION_JOB_STATUS = "migrationjobstatus"; + public static final String MIGRATIONS = "migrations"; + public static final String MEMORY = "memory"; + public static final String MODE = "mode"; + public static final String MOUNT_CKS_ISO_ON_VR = "mountcksisoonvr"; + public static final String MULTI_ARCH = "ismultiarch"; + public static final String NSX_MODE = "nsxmode"; + public static final String NETWORK_MODE = "networkmode"; + public static final String NSX_ENABLED = "isnsxenabled"; + public static final String NAME = "name"; + public static final String METHOD_NAME = "methodname"; + 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 NICS = "nics"; + public static final String NIC_NETWORK_LIST = "nicnetworklist"; public static final String NIC_IP_ADDRESS_LIST = "nicipaddresslist"; - public static final String NIC_MULTIQUEUE_NUMBER = "nicmultiqueuenumber"; - public static final String NIC_PACKED_VIRTQUEUES_ENABLED = "nicpackedvirtqueuesenabled"; - public static final String NEW_START_IP = "newstartip"; - public static final String NEW_END_IP = "newendip"; - public static final String KUBERNETES_NODE_VERSION = "kubernetesnodeversion"; - public static final String NUMA_NODE = "numanode"; - public static final String NUM_RETRIES = "numretries"; - public static final String OFFER_HA = "offerha"; - public static final String OS_DISTRIBUTION = "osdistribution"; - public static final String IS_SYSTEM_OFFERING = "issystem"; - public static final String IS_DEFAULT_USE = "defaultuse"; - public static final String OLD_FORMAT = "oldformat"; - public static final String OP = "op"; - public static final String OPTION = "option"; - public static final String OPTIONS = "options"; - public static final String OS_CATEGORY_ID = "oscategoryid"; - public static final String OS_CATEGORY_NAME = "oscategoryname"; - public static final String OS_NAME = "osname"; - 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"; - public static final String GPU_CARD_ID = "gpucardid"; - public static final String GPU_CARD_NAME = "gpucardname"; - public static final String GPU_COUNT = "gpucount"; - public static final String GPU_DISPLAY = "gpudisplay"; - public static final String GPU_DEVICE_TYPE = "gpudevicetype"; - public static final String GPU_ENABLED = "gpuenabled"; - public static final String MAX_VGPU_PER_PHYSICAL_GPU = "maxvgpuperphysicalgpu"; - public static final String GUEST_OS_LIST = "guestoslist"; - public static final String GUEST_OS_COUNT = "guestoscount"; - public static final String OS_MAPPING_CHECK_ENABLED = "osmappingcheckenabled"; - public static final String OUTOFBANDMANAGEMENT_POWERSTATE = "outofbandmanagementpowerstate"; - public static final String OUTOFBANDMANAGEMENT_ENABLED = "outofbandmanagementenabled"; - public static final String OUTPUT = "output"; - public static final String PROPERTIES = "properties"; - public static final String PARAMS = "params"; - public static final String PARENT = "parent"; - public static final String PARENT_ID = "parentid"; - public static final String PARENT_DOMAIN_ID = "parentdomainid"; - public static final String PARENT_GPU_DEVICE_ID = "parentgpudeviceid"; - public static final String PARENT_SUBNET = "parentsubnet"; - public static final String PARENT_TEMPLATE_ID = "parenttemplateid"; - public static final String PASSWORD = "password"; - public static final String PCI_ROOT = "pciroot"; - public static final String CURRENT_PASSWORD = "currentpassword"; - public static final String SHOULD_UPDATE_PASSWORD = "update_passwd_on_host"; - public static final String PASSWORD_ENABLED = "passwordenabled"; - public static final String SSHKEY_ENABLED = "sshkeyenabled"; - public static final String PATH = "path"; - public static final String PATH_READY = "pathready"; - public static final String PAYLOAD = "payload"; - public static final String PAYLOAD_URL = "payloadurl"; - public static final String PEERS = "peers"; - public static final String PEER_ID = "peerid"; - public static final String PEER_NAME = "peername"; - public static final String PEER_MSID = "peermsid"; - public static final String PEER_RUNID = "peerrunid"; - public static final String PEER_SERVICE_IP = "peerserviceip"; - public static final String PEER_SERVICE_PORT = "peerserviceport"; - public static final String PEER_STATE = "peerstate"; - public static final String POD_ID = "podid"; - public static final String POD_NAME = "podname"; - public static final String POD_IDS = "podids"; - public static final String POLICY_ID = "policyid"; - public static final String PORT = "port"; - 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 PRECEDENCE = "precedence"; - public static final String PREPARE_VM = "preparevm"; - public static final String PRESERVE_IP = "preserveip"; - public static final String PRIVATE_INTERFACE = "privateinterface"; - public static final String PRIVATE_IP = "privateip"; - public static final String PRIVATE_PORT = "privateport"; - public static final String PRIVATE_START_PORT = "privateport"; - public static final String PRIVATE_END_PORT = "privateendport"; - public static final String PRIVATE_ZONE = "privatezone"; - public static final String PROTOCOL = "protocol"; - public static final String PROVISIONINGTYPE = "provisioningtype"; - public static final String PUBLIC_INTERFACE = "publicinterface"; - public static final String PUBLIC_IP_ID = "publicipid"; - public static final String PUBLIC_IP = "publicip"; - public static final String PUBLIC_PORT = "publicport"; - public static final String PUBLIC_START_PORT = "publicport"; - public static final String PUBLIC_END_PORT = "publicendport"; - public static final String PUBLIC_ZONE = "publiczone"; - public static final String PURGE_RESOURCES = "purgeresources"; - public static final String RAM = "RAM"; - public static final String REBALANCE = "rebalance"; - public static final String RECEIVED_BYTES = "receivedbytes"; - public static final String RECONNECT = "reconnect"; - public static final String RECOVER = "recover"; - public static final String REPAIR = "repair"; - public static final String REPETITION_ALLOWED = "repetitionallowed"; - public static final String REQUIRES_HVM = "requireshvm"; - public static final String RESERVED_RESOURCE_DETAILS = "reservedresourcedetails"; - public static final String RESOURCES = "resources"; - public static final String RESOURCE_COUNT = "resourcecount"; - public static final String RESOURCE_NAME = "resourcename"; - public static final String RESOURCE_TYPE = "resourcetype"; - public static final String RESOURCE_TYPE_NAME = "resourcetypename"; - public static final String RESPONSE = "response"; - public static final String RETRIEVE_ONLY_RESOURCE_COUNT = "retrieveonlyresourcecount"; - public static final String REVERTABLE = "revertable"; - public static final String REVOKED = "revoked"; - public static final String REGISTERED = "registered"; - public static final String QUALIFIERS = "qualifiers"; - public static final String QUERY_FILTER = "queryfilter"; - public static final String QUIESCE_VM = "quiescevm"; - public static final String SCHEDULE = "schedule"; - public static final String SCHEDULE_ID = "scheduleid"; - public static final String SCOPE = "scope"; - public static final String SEARCH_BASE = "searchbase"; - public static final String SECONDARY_IP = "secondaryip"; - public static final String SECURITY_GROUP_IDS = "securitygroupids"; - public static final String SECURITY_GROUP_NAMES = "securitygroupnames"; - public static final String SECURITY_GROUP_NAME = "securitygroupname"; - public static final String SECURITY_GROUP_ID = "securitygroupid"; - public static final String SENT = "sent"; - public static final String SENT_BYTES = "sentbytes"; - public static final String SERIAL = "serial"; - public static final String SERVICE_IP = "serviceip"; - public static final String SERVICE_OFFERING_ID = "serviceofferingid"; - public static final String SERVICE_OFFERING_NAME = "serviceofferingname"; - public static final String SESSIONKEY = "sessionkey"; - public static final String SHOW_CAPACITIES = "showcapacities"; - public static final String SHOW_REMOVED = "showremoved"; - public static final String SHOW_RESOURCES = "showresources"; - public static final String SHOW_RESOURCE_ICON = "showicon"; - public static final String SHOW_INACTIVE = "showinactive"; - public static final String SHOW_UNIQUE = "showunique"; - public static final String SHOW_PERMISSIONS = "showpermissions"; - public static final String SIGNATURE = "signature"; - public static final String SIGNATURE_VERSION = "signatureversion"; - public static final String SINCE = "since"; - public static final String SITE_NAME = "sitename"; - public static final String SIZE = "size"; - public static final String SIZEGB = "sizegb"; - public static final String SNAPSHOT = "snapshot"; - public static final String SNAPSHOT_ID = "snapshotid"; - public static final String SNAPSHOT_POLICY_ID = "snapshotpolicyid"; - public static final String SNAPSHOT_TYPE = "snapshottype"; - public static final String SNAPSHOT_QUIESCEVM = "quiescevm"; - - public static final String USE_STORAGE_REPLICATION = "usestoragereplication"; - - public static final String SOURCE_CIDR_LIST = "sourcecidrlist"; - public static final String SOURCE_OFFERING_ID = "sourceofferingid"; - public static final String SOURCE_ZONE_ID = "sourcezoneid"; - public static final String SSL_VERIFICATION = "sslverification"; - public static final String START_ASN = "startasn"; - public static final String START_DATE = "startdate"; - public static final String START_ID = "startid"; - public static final String START_IP = "startip"; - public static final String START_IPV6 = "startipv6"; - public static final String START_PORT = "startport"; - public static final String STATE = "state"; - public static final String STATS = "stats"; - public static final String STATUS = "status"; - public static final String STORAGE_TYPE = "storagetype"; - public static final String STORAGE_POLICY = "storagepolicy"; - public static final String STORAGE_MOTION_ENABLED = "storagemotionenabled"; - public static final String STORAGE_CAPABILITIES = "storagecapabilities"; - public static final String STORAGE_CUSTOM_STATS = "storagecustomstats"; - public static final String SUBNET = "subnet"; - public static final String OWNER = "owner"; - public static final String SWAP_OWNER = "swapowner"; - public static final String SYSTEM_VM_TYPE = "systemvmtype"; - public static final String TAGS = "tags"; - public static final String STORAGE_TAGS = "storagetags"; - public static final String STORAGE_ACCESS_GROUPS = "storageaccessgroups"; - public static final String STORAGE_ACCESS_GROUP = "storageaccessgroup"; - public static final String CLUSTER_STORAGE_ACCESS_GROUPS = "clusterstorageaccessgroups"; - public static final String POD_STORAGE_ACCESS_GROUPS = "podstorageaccessgroups"; - public static final String ZONE_STORAGE_ACCESS_GROUPS = "zonestorageaccessgroups"; - public static final String SUCCESS = "success"; - public static final String SUCCESS_MESSAGE = "successmessage"; - public static final String SUITABLE_FOR_VM = "suitableforvirtualmachine"; - public static final String SUPPORTS_STORAGE_SNAPSHOT = "supportsstoragesnapshot"; - public static final String TARGET_IQN = "targetiqn"; - public static final String TASKS_FILTER = "tasksfilter"; - public static final String TEMPLATE_FILTER = "templatefilter"; - public static final String TEMPLATE_ID = "templateid"; - public static final String TEMPLATE_IDS = "templateids"; - public static final String TEMPLATE_NAME = "templatename"; - public static final String TEMPLATE_TYPE = "templatetype"; - public static final String TEMPLATE_FORMAT = "templateformat"; - public static final String TIMEOUT = "timeout"; - public static final String TIMEZONE = "timezone"; - public static final String TIMEZONEOFFSET = "timezoneoffset"; - public static final String TENANT_NAME = "tenantname"; - public static final String TOTAL = "total"; - public static final String TOTAL_SUBNETS = "totalsubnets"; - public static final String TO_CHECKPOINT_ID = "tocheckpointid"; - public static final String TOTAL_QUOTA = "totalquota"; - public static final String TYPE = "type"; - public static final String TRUST_STORE = "truststore"; - public static final String TRUST_STORE_PASSWORD = "truststorepass"; - public static final String UNIT = "unit"; - public static final String URL = "url"; - public static final String USAGE_INTERFACE = "usageinterface"; - public static final String USED = "used"; - public static final String USED_SUBNETS = "usedsubnets"; - public static final String USED_IOPS = "usediops"; - public static final String USER_DATA = "userdata"; - - public static final String USER_DATA_NAME = "userdataname"; - public static final String USER_DATA_ID = "userdataid"; - public static final String USER_DATA_POLICY = "userdatapolicy"; - public static final String USER_DATA_DETAILS = "userdatadetails"; - public static final String USER_DATA_PARAMS = "userdataparams"; - public static final String USER_FILTER = "userfilter"; - public static final String USER_ID = "userid"; - public static final String USER_SOURCE = "usersource"; - public static final String USER_CONFLICT_SOURCE = "conflictingusersource"; - public static final String USE_SSL = "ssl"; - public static final String USERNAME = "username"; - public static final String USER_CONFIGURABLE = "userconfigurable"; - public static final String USER_SECURITY_GROUP_LIST = "usersecuritygrouplist"; - public static final String USER_SECRET_KEY = "usersecretkey"; - public static final String USE_VDDK = "usevddk"; - public static final String USE_VIRTUAL_NETWORK = "usevirtualnetwork"; - public static final String USE_VIRTUAL_ROUTER_IP_RESOLVER = "userouteripresolver"; - public static final String UPDATE_IN_SEQUENCE = "updateinsequence"; - public static final String VALIDATION_FORMAT = "validationformat"; - public static final String VALUE = "value"; - public static final String VALUE_OPTIONS = "valueoptions"; - public static final String VENDOR_ID = "vendorid"; - public static final String VENDOR_NAME = "vendorname"; - public static final String VGPU_PROFILE_ID = "vgpuprofileid"; - public static final String VGPU_PROFILE_NAME = "vgpuprofilename"; - public static final String VIRTUAL_MACHINE = "virtualmachine"; - public static final String VIRTUAL_MACHINE_ID = "virtualmachineid"; - public static final String VIRTUAL_MACHINE_IDS = "virtualmachineids"; - public static final String VIRTUAL_MACHINE_NAME = "virtualmachinename"; - public static final String VIRTUAL_MACHINE_ID_IP = "vmidipmap"; - public static final String VIRTUAL_MACHINE_COUNT = "virtualmachinecount"; - public static final String VIRTUAL_MACHINE_TYPE = "virtualmachinetype"; - public static final String VIRTUAL_MACHINE_STATE = "vmstate"; - public static final String VIRTUAL_MACHINES = "virtualmachines"; - public static final String USAGE_ID = "usageid"; - public static final String USAGE_TYPE = "usagetype"; - public static final String INCLUDE_TAGS = "includetags"; - - public static final String VLAN = "vlan"; - public static final String VLAN_RANGE = "vlanrange"; - public static final String WORKER_SERVICE_OFFERING_ID = "workerofferingid"; - public static final String WORKER_SERVICE_OFFERING_NAME = "workerofferingname"; - public static final String CONTROL_SERVICE_OFFERING_ID = "controlofferingid"; - public static final String CONTROL_SERVICE_OFFERING_NAME = "controlofferingname"; - public static final String ETCD_SERVICE_OFFERING_ID = "etcdofferingid"; - public static final String ETCD_SERVICE_OFFERING_NAME = "etcdofferingname"; - 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 IS_ALLOCATED = "isallocated"; - public static final String IS_DEDICATED = "isdedicated"; - public static final String TAKEN = "taken"; - public static final String VM_AVAILABLE = "vmavailable"; - public static final String VM_DETAILS = "vmdetails"; - public static final String VM_LIMIT = "vmlimit"; - public static final String VM_TOTAL = "vmtotal"; - public static final String VM_SETTINGS = "vmsettings"; - public static final String VM_TYPE = "vmtype"; - public static final String VNET = "vnet"; - public static final String IS_VOLATILE = "isvolatile"; - public static final String VOLUME_ID = "volumeid"; - public static final String VOLUMES = "volumes"; - public static final String VOLUME_CHECK_RESULT = "volumecheckresult"; - public static final String VOLUME_REPAIR_RESULT = "volumerepairresult"; - - public static final String ZONE = "zone"; - public static final String ZONE_ID = "zoneid"; - public static final String ZONE_NAME = "zonename"; - public static final String ZONE_WISE = "zonewise"; - public static final String NETWORK_TYPE = "networktype"; - public static final String PAGE = "page"; - public static final String PAGE_SIZE = "pagesize"; - public static final String COUNT = "count"; - public static final String TRAFFIC_TYPE = "traffictype"; - public static final String NETWORK_OFFERING_ID = "networkofferingid"; - public static final String TIER_NETWORK_OFFERINGS = "tiernetworkofferings"; - public static final String NETWORK_IDS = "networkids"; - public static final String NETWORK_ID = "networkid"; - public static final String NETWORK_FILTER = "networkfilter"; - public static final String NIC_ID = "nicid"; - public static final String SPECIFY_AS_NUMBER = "specifyasnumber"; - public static final String SPECIFY_VLAN = "specifyvlan"; - public static final String IS_DEFAULT = "isdefault"; - public static final String IS_SYSTEM = "issystem"; - public static final String IS_USER_DEFINED = "isuserdefined"; - public static final String AVAILABILITY = "availability"; - public static final String NETWORKRATE = "networkrate"; - public static final String HOST_TAGS = "hosttags"; - public static final String SSH_KEYPAIR = "keypair"; - public static final String SSH_KEYPAIRS = "keypairs"; - public static final String HTTPMETHOD = "httpmethod"; - public static final String HOST_CPU_CAPACITY = "hostcpucapacity"; - public static final String HOST_CPU_NUM = "hostcpunum"; - public static final String HOST_MEM_CAPACITY = "hostmemcapacity"; - public static final String HOST_MAC = "hostmac"; - public static final String HOST_TAG = "hosttag"; - public static final String PXE_SERVER_TYPE = "pxeservertype"; - public static final String LINMIN_USERNAME = "linminusername"; - public static final String LINMIN_PASSWORD = "linminpassword"; - public static final String LINMIN_APID = "linminapid"; - public static final String DHCP_SERVER_TYPE = "dhcpservertype"; - public static final String LINK_LOCAL_IP = "linklocalip"; - public static final String LINK_LOCAL_MAC_ADDRESS = "linklocalmacaddress"; - public static final String LINK_LOCAL_MAC_NETMASK = "linklocalnetmask"; - public static final String LINK_LOCAL_NETWORK_ID = "linklocalnetworkid"; - public static final String PRIVATE_MAC_ADDRESS = "privatemacaddress"; - public static final String PRIVATE_NETMASK = "privatenetmask"; - public static final String PRIVATE_NETWORK_ID = "privatenetworkid"; - public static final String ALLOCATION_STATE = "allocationstate"; - public static final String MANAGED_STATE = "managedstate"; - public static final String MANAGEMENT_SERVER_ID = "managementserverid"; - public static final String MANAGEMENT_SERVER_NAME = "managementservername"; - public static final String STORAGE = "storage"; - public static final String STORAGE_ID = "storageid"; - public static final String PING_STORAGE_SERVER_IP = "pingstorageserverip"; - public static final String PING_DIR = "pingdir"; - public static final String TFTP_DIR = "tftpdir"; - public static final String PING_CIFS_USERNAME = "pingcifsusername"; - public static final String PING_CIFS_PASSWORD = "pingcifspassword"; - public static final String CHECKSUM = "checksum"; - public static final String NETWORK_DEVICE_TYPE = "networkdevicetype"; - public static final String NETWORK_DEVICE_PARAMETER_LIST = "networkdeviceparameterlist"; - public static final String ZONE_TOKEN = "zonetoken"; - public static final String DHCP_PROVIDER = "dhcpprovider"; - public static final String RESULT = "result"; - public static final String RESUME = "resume"; - public static final String LUN_ID = "lunId"; - public static final String IQN = "iqn"; - public static final String AGGREGATE_NAME = "aggregatename"; - public static final String POOL_NAME = "poolname"; - public static final String VOLUME_NAME = "volumename"; - public static final String VOLUME_STATE = "volumestate"; - public static final String SNAPSHOT_POLICY = "snapshotpolicy"; - public static final String SNAPSHOT_RESERVATION = "snapshotreservation"; - public static final String IP_NETWORK_LIST = "iptonetworklist"; - public static final String PARAM_LIST = "param"; - public static final String FOR_LOAD_BALANCING = "forloadbalancing"; - public static final String KEYBOARD = "keyboard"; - public static final String OPEN_FIREWALL = "openfirewall"; - public static final String TEMPLATE_TAG = "templatetag"; - public static final String HYPERVISOR_VERSION = "hypervisorversion"; - public static final String MAX_GUESTS_LIMIT = "maxguestslimit"; - public static final String MAX_DATA_VOLUMES_LIMIT = "maxdatavolumeslimit"; - public static final String MAX_HOSTS_PER_CLUSTER = "maxhostspercluster"; - public static final String PROJECT_ID = "projectid"; - public static final String PROJECT_IDS = "projectids"; - public static final String PROJECT = "project"; - public static final String ROLE = "role"; - public static final String ROLE_ID = "roleid"; - public static final String PROJECT_ROLE_ID = "projectroleid"; - public static final String PROJECT_ROLE_NAME = "projectrolename"; - public static final String ROLE_TYPE = "roletype"; - public static final String ROLE_NAME = "rolename"; - public static final String PERMISSION = "permission"; - public static final String PERMISSIONS = "permissions"; - public static final String RULE = "rule"; - public static final String RULES = "rules"; - public static final String RULE_ID = "ruleid"; - public static final String PROJECT_ROLE_PERMISSION_ID = "projectrolepermissionid"; - public static final String RULE_ORDER = "ruleorder"; - public static final String USER = "user"; - public static final String ACTIVE_ONLY = "activeonly"; - public static final String TOKEN = "token"; - public static final String ACCEPT = "accept"; - public static final String SORT_KEY = "sortkey"; - public static final String ACCOUNT_DETAILS = "accountdetails"; - public static final String SERVICE_OFFERING_DETAILS = "serviceofferingdetails"; - public static final String SERVICE_PROVIDER_LIST = "serviceproviderlist"; - public static final String SERVICE_CAPABILITY_LIST = "servicecapabilitylist"; - public static final String CAN_CHOOSE_SERVICE_CAPABILITY = "canchooseservicecapability"; - public static final String PROVIDER = "provider"; - public static final String OAUTH_PROVIDER = "oauthprovider"; - public static final String OAUTH_SECRET_KEY = "secretkey"; - public static final String MANAGED = "managed"; - public static final String CAPACITY_BYTES = "capacitybytes"; - public static final String CAPACITY_IOPS = "capacityiops"; - public static final String NETWORK_SPEED = "networkspeed"; - public static final String BROADCAST_DOMAIN_RANGE = "broadcastdomainrange"; - public static final String BROADCAST_URI = "broadcasturi"; - public static final String ISOLATION_METHOD = "isolationmethod"; - public static final String ISOLATION_METHODS = "isolationmethods"; - public static final String PHYSICAL_NETWORK_ID = "physicalnetworkid"; - public static final String PHYSICAL_NETWORK_NAME = "physicalnetworkname"; - public static final String DEST_PHYSICAL_NETWORK_ID = "destinationphysicalnetworkid"; - public static final String ENABLE = "enable"; - public static final String ENABLED = "enabled"; - public static final String SERVICE_NAME = "servicename"; - public static final String DHCP_RANGE = "dhcprange"; - public static final String UUID = "uuid"; - public static final String SECURITY_GROUP_EANBLED = "securitygroupenabled"; - public static final String LOCAL_STORAGE_ENABLED = "localstorageenabled"; - public static final String GUEST_IP_TYPE = "guestiptype"; - public static final String GUEST_IP6_PREFIX = "guestip6prefix"; - public static final String XENSERVER_NETWORK_LABEL = "xennetworklabel"; - public static final String KVM_NETWORK_LABEL = "kvmnetworklabel"; - public static final String VMWARE_NETWORK_LABEL = "vmwarenetworklabel"; - public static final String HYPERV_NETWORK_LABEL = "hypervnetworklabel"; - public static final String OVM3_NETWORK_LABEL = "ovm3networklabel"; - public static final String NETWORK_SERVICE_PROVIDER_ID = "nspid"; - public static final String SERVICE_LIST = "servicelist"; - public static final String CAN_ENABLE_INDIVIDUAL_SERVICE = "canenableindividualservice"; - public static final String SUPPORTED_SERVICES = "supportedservices"; - public static final String NSP_ID = "nspid"; - public static final String ACL_TYPE = "acltype"; - public static final String ACL_REASON = "reason"; - public static final String ACL_RULE_PARTIAL_UPGRADE = "partialupgrade"; - public static final String SUBDOMAIN_ACCESS = "subdomainaccess"; - public static final String LOAD_BALANCER_DEVICE_ID = "lbdeviceid"; - public static final String LOAD_BALANCER_DEVICE_NAME = "lbdevicename"; - public static final String LOAD_BALANCER_DEVICE_STATE = "lbdevicestate"; - public static final String LOAD_BALANCER_DEVICE_CAPACITY = "lbdevicecapacity"; - public static final String LOAD_BALANCER_DEVICE_DEDICATED = "lbdevicededicated"; - public static final String LOAD_BALANCER_RULE = "loadbalancerrule"; - public static final String LOAD_BALANCER_RULE_LIST = "loadbalancerrulelist"; - public static final String FIREWALL_DEVICE_ID = "fwdeviceid"; - public static final String FIREWALL_DEVICE_NAME = "fwdevicename"; - public static final String FIREWALL_DEVICE_STATE = "fwdevicestate"; - public static final String FIREWALL_DEVICE_CAPACITY = "fwdevicecapacity"; - public static final String FIREWALL_DEVICE_DEDICATED = "fwdevicededicated"; - public static final String SERVICE = "service"; - public static final String ASSOCIATED_NETWORK = "associatednetwork"; - public static final String ASSOCIATED_NETWORK_ID = "associatednetworkid"; - public static final String ASSOCIATED_NETWORK_NAME = "associatednetworkname"; - public static final String ASSOCIATED_VPC_ID = "associatedvpcid"; - public static final String ASSOCIATED_VPC_NAME = "associatedvpcname"; - public static final String SOURCE_NAT_SUPPORTED = "sourcenatsupported"; - public static final String RESOURCE_STATE = "resourcestate"; - public static final String PROJECT_INVITE_REQUIRED = "projectinviterequired"; - public static final String REQUIRED = "required"; - public static final String RESTART_REQUIRED = "restartrequired"; - public static final String ALLOW_USER_CREATE_PROJECTS = "allowusercreateprojects"; - public static final String ALLOW_USER_DRIVEN_BACKUPS = "allowuserdrivenbackups"; - public static final String ALLOW_USER_SPECIFY_VR_MTU = "allowuserspecifyvrmtu"; - public static final String CONSERVE_MODE = "conservemode"; - public static final String TRAFFIC_TYPE_IMPLEMENTOR = "traffictypeimplementor"; - public static final String KEYWORD = "keyword"; - public static final String LIST_ALL = "listall"; - public static final String LIST_ONLY_REMOVED = "listonlyremoved"; - public static final String LIST_SYSTEM_VMS = "listsystemvms"; - public static final String LIST_VM_DETAILS = "listvmdetails"; - public static final String IP_RANGES = "ipranges"; - public static final String IPV4_ROUTING = "ip4routing"; - public static final String IPV4_ROUTES = "ip4routes"; - public static final String IPV6_ROUTING = "ip6routing"; - public static final String IPV6_ROUTES = "ip6routes"; - public static final String SPECIFY_IP_RANGES = "specifyipranges"; - public static final String IS_SOURCE_NAT = "issourcenat"; - public static final String IS_STATIC_NAT = "isstaticnat"; - public static final String ITERATIONS = "iterations"; - public static final String SORT_BY = "sortby"; - public static final String CHANGE_CIDR = "changecidr"; - public static final String PURPOSE = "purpose"; - public static final String IS_TAGGED = "istagged"; - public static final String INSTANCE_NAME = "instancename"; - public static final String CONSIDER_LAST_HOST = "considerlasthost"; - public static final String START_VM = "startvm"; - public static final String HA_HOST = "hahost"; - public static final String CUSTOM_DISK_OFF_MIN_SIZE = "customdiskofferingminsize"; - 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 AUTO_MIGRATE = "automigrate"; - public static final String GUID = "guid"; - public static final String VM_SNAPSHOT_ENABELD = "vmsnapshotenabled"; - public static final String VSWITCH_TYPE_GUEST_TRAFFIC = "guestvswitchtype"; - public static final String VSWITCH_TYPE_PUBLIC_TRAFFIC = "publicvswitchtype"; - public static final String VSWITCH_NAME_GUEST_TRAFFIC = "guestvswitchname"; - public static final String VSWITCH_NAME_PUBLIC_TRAFFIC = "publicvswitchname"; - - // NSX - public static final String EDGE_CLUSTER = "edgecluster"; - public static final String TIER0_GATEWAY = "tier0gateway"; - - public static final String TRANSPORT_ZONE = "transportzone"; - // Tungsten-Fabric - public static final String TUNGSTEN_VIRTUAL_ROUTER_UUID = "tungstenvirtualrouteruuid"; - public static final String TUNGSTEN_PROVIDER_HOSTNAME = "tungstenproviderhostname"; - public static final String TUNGSTEN_PROVIDER_PORT = "tungstenproviderport"; - public static final String TUNGSTEN_PROVIDER_UUID = "tungstenprovideruuid"; - public static final String TUNGSTEN_GATEWAY = "tungstengateway"; - public static final String TUNGSTEN_PROVIDER_VROUTER_PORT = "tungstenprovidervrouterport"; - public static final String TUNGSTEN_PROVIDER_INTROSPECT_PORT = "tungstenproviderintrospectport"; - public static final String SRC_NETWORK = "srcnetwork"; - public static final String SRC_IP_PREFIX = "srcipprefix"; - public static final String SRC_IP_PREFIX_LEN = "srcipprefixlen"; - public static final String SRC_START_PORT = "srcstartport"; - public static final String SRC_END_PORT = "srcendport"; - public static final String DEST_NETWORK = "destnetwork"; - public static final String DEST_IP_PREFIX = "destipprefix"; - public static final String DEST_IP_PREFIX_LEN = "destipprefixlen"; - public static final String DEST_START_PORT = "deststartport"; - public static final String DEST_END_PORT = "destendport"; - public static final String MAJOR_SEQUENCE = "majorsequence"; - public static final String MINOR_SEQUENCE = "minorsequence"; - public static final String POLICY_UUID = "policyuuid"; - public static final String RULE_UUID = "ruleuuid"; - public static final String DIRECTION = "direction"; - public static final String TAGGED_RESOURCES = "taggedresources"; - public static final String TAG_UUID = "taguuid"; - public static final String TAG_TYPE = "tagtype"; - public static final String TAG_VALUE = "tagvalue"; - public static final String TAG_TYPE_UUID = "tagtypeuuid"; - public static final String NETWORK_UUID = "networkuuid"; - public static final String NIC_UUID = "nicuuid"; - public static final String VM_UUID = "vmuuid"; - public static final String ONE_WAY = "oneway"; - public static final String POLICY = "policy"; - public static final String VM = "vm"; - public static final String FIREWALL_POLICY = "firewallpolicy"; - public static final String FIREWALL_RULE = "firewallrule"; - public static final String TAG = "tag"; - public static final String APPLICATION_POLICY_SET_UUID = "applicationpolicysetuuid"; - public static final String FIREWALL_POLICY_UUID = "firewallpolicyuuid"; - public static final String FIREWALL_RULE_UUID = "firewallruleuuid"; - public static final String ADDRESS_GROUP_UUID = "addressgroupuuid"; - public static final String SERVICE_GROUP_UUID = "servicegroupuuid"; - public static final String SEQUENCE = "sequence"; - public static final String SERVICE_GROUP = "servicegroup"; - public static final String SRC_ADDRESS_GROUP = "srcaddressgroup"; - public static final String DEST_ADDRESS_GROUP = "destaddressgroup"; - public static final String SRC_TAG = "srctag"; - public static final String DEST_TAG = "desttag"; - public static final String IP_PREFIX = "ipprefix"; - public static final String IP_PREFIX_LEN = "ipprefixlen"; - public static final String SRC_ADDRESS_GROUP_UUID = "srcaddressgroupuuid"; - public static final String DEST_ADDRESS_GROUP_UUID = "destaddressgroupuuid"; - public static final String SRC_TAG_UUID = "srctaguuid"; - public static final String DEST_TAG_UUID = "desttaguuid"; - public static final String SRC_NETWORK_UUID = "srcnetworkuuid"; - public static final String DEST_NETWORK_UUID = "destnetworkuuid"; - public static final String LOGICAL_ROUTER_UUID = "logicalrouteruuid"; - public static final String RETRY = "retry"; - public static final String HTTP_METHOD = "httpmethodtype"; - public static final String EXPECTED_CODE = "expectedcode"; - public static final String URL_PATH = "urlpath"; - - // Ovs controller - public static final String OVS_DEVICE_ID = "ovsdeviceid"; - public static final String OVS_DEVICE_NAME = "ovsdevicename"; - // OpenDaylight controller - public static final String ODL_DEVICE_ID = "odldeviceid"; - public static final String ODL_DEVICE_NAME = "odldevicename"; - public static final String ODL_TRANSPORT_ZONE_UUID = "transportzoneuuid"; - public static final String ODL_GATEWAYSERVICE_UUID = "l3gatewayserviceuuid"; - - public static final String EXTERNAL_SWITCH_MGMT_DEVICE_ID = "vsmdeviceid"; - public static final String EXTERNAL_SWITCH_MGMT_DEVICE_NAME = "vsmdevicename"; - public static final String EXTERNAL_SWITCH_MGMT_DEVICE_STATE = "vsmdevicestate"; - // Would we need to have a capacity field for Cisco N1KV VSM? Max hosts managed by it perhaps? May remove this - // later. - public static final String EXTERNAL_SWITCH_MGMT_DEVICE_CAPACITY = "vsmdevicecapacity"; - public static final String CISCO_NEXUS_VSM_NAME = "vsmname"; - public static final String VSM_USERNAME = "vsmusername"; - public static final String VSM_PASSWORD = "vsmpassword"; - public static final String VSM_IPADDRESS = "vsmipaddress"; - public static final String VSM_MGMT_VLAN_ID = "vsmmgmtvlanid"; - public static final String VSM_PKT_VLAN_ID = "vsmpktvlanid"; - public static final String VSM_CTRL_VLAN_ID = "vsmctrlvlanid"; - public static final String VSM_STORAGE_VLAN_ID = "vsmstoragevlanid"; - public static final String VSM_DOMAIN_ID = "vsmdomainid"; - public static final String VSM_CONFIG_MODE = "vsmconfigmode"; - public static final String VSM_CONFIG_STATE = "vsmconfigstate"; - public static final String VSM_DEVICE_STATE = "vsmdevicestate"; - public static final String VCENTER = "vcenter"; - public static final String EXISTING_VCENTER_ID = "existingvcenterid"; - public static final String ADD_VSM_FLAG = "addvsmflag"; - public static final String END_POINT = "endpoint"; - public static final String REGION_ID = "regionid"; - public static final String VPC_OFF_ID = "vpcofferingid"; - public static final String VPC_OFF_NAME = "vpcofferingname"; - public static final String VPC_OFFERING_CONSERVE_MODE = "vpcofferingconservemode"; - public static final String NETWORK = "network"; - public static final String VPC_ID = "vpcid"; - public static final String VPC_NAME = "vpcname"; - public static final String VPC_GATEWAY_ID = "vpcgatewayid"; - public static final String VPC_GATEWAY_IP = "vpcgatewayip"; - public static final String GATEWAY_ID = "gatewayid"; - public static final String CAN_USE_FOR_DEPLOY = "canusefordeploy"; - public static final String RESOURCE_IDS = "resourceids"; - public static final String RESOURCE_ID = "resourceid"; - public static final String CUSTOMER = "customer"; - public static final String S2S_VPN_GATEWAY_ID = "s2svpngatewayid"; - public static final String S2S_CUSTOMER_GATEWAY_ID = "s2scustomergatewayid"; - public static final String IPSEC_PSK = "ipsecpsk"; - public static final String GUEST_IP = "guestip"; - public static final String REMOVED = "removed"; - public static final String REMOVER_ACCOUNT_ID = "removeraccountid"; - public static final String REMOVAL_REASON = "removalreason"; - public static final String COMPLETED = "completed"; - public static final String IKE_VERSION = "ikeversion"; - public static final String IKE_POLICY = "ikepolicy"; - public static final String ESP_POLICY = "esppolicy"; - public static final String IKE_LIFETIME = "ikelifetime"; - public static final String ESP_LIFETIME = "esplifetime"; - public static final String DPD = "dpd"; - public static final String FORCE_ENCAP = "forceencap"; - public static final String SPLIT_CONNECTIONS = "splitconnections"; - public static final String FOR_VPC = "forvpc"; - public static final String FOR_NSX = "fornsx"; - public static final String FOR_CKS = "forcks"; - public static final String NSX_SUPPORT_LB = "nsxsupportlb"; - public static final String NSX_SUPPORTS_INTERNAL_LB = "nsxsupportsinternallb"; - public static final String FOR_TUNGSTEN = "fortungsten"; - public static final String SHRINK_OK = "shrinkok"; - public static final String NICIRA_NVP_DEVICE_ID = "nvpdeviceid"; - public static final String NICIRA_NVP_TRANSPORT_ZONE_UUID = "transportzoneuuid"; - public static final String NICIRA_NVP_DEVICE_NAME = "niciradevicename"; - public static final String NICIRA_NVP_GATEWAYSERVICE_UUID = "l3gatewayserviceuuid"; - public static final String NICIRA_NVP_L2_GATEWAYSERVICE_UUID = "l2gatewayserviceuuid"; - public static final String NSX_LOGICAL_SWITCH = "nsxlogicalswitch"; - public static final String NSX_LOGICAL_SWITCH_PORT = "nsxlogicalswitchport"; - public static final String NSX_PROVIDER_UUID = "nsxprovideruuid"; - public static final String NSX_PROVIDER_HOSTNAME = "nsxproviderhostname"; - - public static final String NSX_PROVIDER_PORT = "nsxproviderport"; - public static final String NSX_CONTROLLER_ID = "nsxcontrollerid"; - public static final String S3_ACCESS_KEY = "accesskey"; - public static final String SECRET_KEY = "secretkey"; - public static final String S3_END_POINT = "endpoint"; - public static final String S3_BUCKET_NAME = "bucket"; - public static final String S3_SIGNER = "s3signer"; - public static final String S3_V3_SIGNER = "S3SignerType"; - public static final String S3_V4_SIGNER = "AWSS3V4SignerType"; - public static final String S3_HTTPS_FLAG = "usehttps"; - public static final String S3_CONNECTION_TIMEOUT = "connectiontimeout"; - public static final String S3_CONNECTION_TTL = "connectionttl"; - public static final String S3_MAX_ERROR_RETRY = "maxerrorretry"; - public static final String S3_SOCKET_TIMEOUT = "sockettimeout"; - public static final String S3_USE_TCP_KEEPALIVE = "usetcpkeepalive"; - public static final String INCL_ZONES = "includezones"; - public static final String EXCL_ZONES = "excludezones"; - public static final String SOURCE = "source"; - public static final String COUNTER_ID = "counterid"; - public static final String AGGR_OPERATOR = "aggroperator"; - public static final String AGGR_FUNCTION = "aggrfunction"; - public static final String AGGR_VALUE = "aggrvalue"; - public static final String THRESHOLD = "threshold"; - public static final String RELATIONAL_OPERATOR = "relationaloperator"; - public static final String OTHER_DEPLOY_PARAMS = "otherdeployparams"; - public static final String MIN_MEMBERS = "minmembers"; - public static final String MAX_MEMBERS = "maxmembers"; - public static final String AUTOSCALE_EXPUNGE_VM_GRACE_PERIOD = "expungevmgraceperiod"; - public static final String VMPROFILE_ID = "vmprofileid"; - public static final String VMGROUP_ID = "vmgroupid"; - public static final String CS_URL = "csurl"; - public static final String IDP_ID = "idpid"; - public static final String SCALEUP_POLICY_IDS = "scaleuppolicyids"; - public static final String SCALEDOWN_POLICY_IDS = "scaledownpolicyids"; - public static final String SCALEUP_POLICIES = "scaleuppolicies"; - public static final String SCALEDOWN_POLICIES = "scaledownpolicies"; - public static final String INTERVAL = "interval"; - public static final String QUIETTIME = "quiettime"; - public static final String ACTION = "action"; - public static final String CONDITION_ID = "conditionid"; - public static final String CONDITION_IDS = "conditionids"; - public static final String COUNTERPARAM_LIST = "counterparam"; - public static final String AUTOSCALE_USER_ID = "autoscaleuserid"; - public static final String AUTOSCALE_VMGROUP_ID = "autoscalevmgroupid"; - public static final String AUTOSCALE_VMGROUP_NAME = "autoscalevmgroupname"; - public static final String BAREMETAL_DISCOVER_NAME = "baremetaldiscovername"; - public static final String BAREMETAL_RCT_URL = "baremetalrcturl"; - public static final String UCS_DN = "ucsdn"; - public static final String GSLB_PROVIDER = "gslbprovider"; - public static final String EXCLUSIVE_GSLB_PROVIDER = "isexclusivegslbprovider"; - public static final String GSLB_PROVIDER_PUBLIC_IP = "gslbproviderpublicip"; - public static final String GSLB_PROVIDER_PRIVATE_IP = "gslbproviderprivateip"; - public static final String VM_SNAPSHOT_DESCRIPTION = "description"; - public static final String VM_SNAPSHOT_DISPLAYNAME = "name"; - public static final String VM_SNAPSHOT_ID = "vmsnapshotid"; - public static final String VM_SNAPSHOT_IDS = "vmsnapshotids"; - public static final String VM_SNAPSHOT_DISK_IDS = "vmsnapshotdiskids"; - public static final String VM_SNAPSHOT_MEMORY = "snapshotmemory"; - public static final String VM_SNAPSHOT_QUIESCEVM = "quiescevm"; - public static final String IMAGE_STORE_UUID = "imagestoreuuid"; - public static final String IMAGE_STORE_ID = "imagestoreid"; - public static final String GUEST_VM_CIDR = "guestvmcidr"; - public static final String NETWORK_CIDR = "networkcidr"; - public static final String RESERVED_IP_RANGE = "reservediprange"; - public static final String UCS_MANAGER_ID = "ucsmanagerid"; - public static final String UCS_PROFILE_DN = "profiledn"; - public static final String UCS_BLADE_DN = "bladedn"; - public static final String UCS_BLADE_ID = "bladeid"; - public static final String VM_GUEST_IP = "vmguestip"; - public static final String HEALTHCHECK_FAILED = "healthchecksfailed"; - public static final String HEALTHCHECK_RESPONSE_TIMEOUT = "responsetimeout"; - public static final String HEALTHCHECK_INTERVAL_TIME = "intervaltime"; - public static final String HEALTHCHECK_HEALTHY_THRESHOLD = "healthythreshold"; - public static final String HEALTHCHECK_UNHEALTHY_THRESHOLD = "unhealthythreshold"; - public static final String HEALTHCHECK_PINGPATH = "pingpath"; - public static final String SOURCE_PORT = "sourceport"; - public static final String INSTANCE_PORT = "instanceport"; - public static final String SOURCE_IP = "sourceipaddress"; - public static final String SOURCE_IP_NETWORK_ID = "sourceipaddressnetworkid"; - public static final String SCHEME = "scheme"; - public static final String PROVIDER_TYPE = "providertype"; - public static final String AFFINITY_GROUP_IDS = "affinitygroupids"; - public static final String AFFINITY_GROUP_NAMES = "affinitygroupnames"; - public static final String ASA_INSIDE_PORT_PROFILE = "insideportprofile"; - public static final String AFFINITY_GROUP_ID = "affinitygroupid"; - public static final String DEPLOYMENT_PLANNER = "deploymentplanner"; - public static final String ACL_ID = "aclid"; - public static final String ACL_NAME = "aclname"; - public static final String NUMBER = "number"; - public static final String IS_DYNAMICALLY_SCALABLE = "isdynamicallyscalable"; - public static final String ROUTED_MODE_ENABLED = "routedmodeenabled"; - public static final String ROUTING = "isrouting"; - public static final String ROUTING_MODE = "routingmode"; - public static final String MAX_CONNECTIONS = "maxconnections"; - public static final String SERVICE_STATE = "servicestate"; - - public static final String IAM_GROUPS = "groups"; - public static final String ENTITY_TYPE = "entitytype"; - public static final String ENTITY_ID = "entityid"; - public static final String ENTITY_NAME = "entityname"; - public static final String EXTERNAL_ID = "externalid"; - public static final String ACCESS_TYPE = "accesstype"; - - public static final String RESOURCE_DETAILS = "resourcedetails"; - public static final String RESOURCE_ICON = "icon"; - public static final String RESOURCE_MAP = "resourcemap"; - public static final String EXPUNGE = "expunge"; - public static final String FOR_DISPLAY = "fordisplay"; - public static final String PASSIVE = "passive"; - public static final String VERSION = "version"; - public static final String START = "start"; - public static final String GPUGROUP = "gpugroup"; - public static final String GPUGROUPNAME = "gpugroupname"; - public static final String VGPU = "vgpu"; - public static final String VGPUTYPE = "vgputype"; - public static final String VIDEORAM = "videoram"; - public static final String MAXHEADS = "maxheads"; - public static final String MAXRESOLUTIONX = "maxresolutionx"; - public static final String MAXRESOLUTIONY = "maxresolutiony"; - public static final String MAXVGPUPERPGPU = "maxvgpuperpgpu"; - public static final String REMAININGCAPACITY = "remainingcapacity"; - public static final String MAXCAPACITY = "maxcapacity"; - public static final String DISTRIBUTED_VPC_ROUTER = "distributedvpcrouter"; - public static final String REDUNDANT_ROUTER = "redundantrouter"; - public static final String REDUNDANT_VPC_ROUTER = "redundantvpcrouter"; - public static final String READ_ONLY = "readonly"; - public static final String SUPPORTS_REGION_LEVEL_VPC = "supportsregionLevelvpc"; - public static final String SUPPORTS_STRECHED_L2_SUBNET = "supportsstrechedl2subnet"; - public static final String SUPPORTS_PUBLIC_ACCESS = "supportspublicaccess"; - public static final String SUPPORTS_INTERNAL_LB = "supportsinternallb"; - public static final String SUPPORTS_VM_AUTOSCALING = "supportsvmautoscaling"; - public static final String REGION_LEVEL_VPC = "regionlevelvpc"; - public static final String STRECHED_L2_SUBNET = "strechedl2subnet"; - public static final String NETWORK_NAME = "networkname"; - public static final String NETWORK_SPANNED_ZONES = "zonesnetworkspans"; - public static final String METADATA = "metadata"; - public static final String PHYSICAL_SIZE = "physicalsize"; - public static final String CHAIN_SIZE = "chainsize"; - public static final String OVM3_POOL = "ovm3pool"; - public static final String OVM3_CLUSTER = "ovm3cluster"; - public static final String OVM3_VIP = "ovm3vip"; - public static final String CLEAN_UP_DETAILS = "cleanupdetails"; - public static final String CLEAN_UP_EXTERNAL_DETAILS = "cleanupexternaldetails"; - public static final String CLEAN_UP_EXTRA_CONFIG = "cleanupextraconfig"; - public static final String CLEAN_UP_PARAMETERS = "cleanupparameters"; - public static final String VIRTUAL_SIZE = "virtualsize"; - public static final String NETSCALER_CONTROLCENTER_ID = "netscalercontrolcenterid"; - public static final String NETSCALER_SERVICEPACKAGE_ID = "netscalerservicepackageid"; - public static final String FETCH_ROUTER_HEALTH_CHECK_RESULTS = "fetchhealthcheckresults"; - - public static final String ZONE_ID_LIST = "zoneids"; - public static final String DESTINATION_ZONE_ID_LIST = "destzoneids"; - public static final String STORAGE_ID_LIST = "storageids"; - public static final String ADMIN = "admin"; - public static final String CHECKSUM_PARAMETER_PREFIX_DESCRIPTION = "The parameter containing the checksum will be considered a MD5sum if it is not prefixed\n" - + " and just a plain ascii/utf8 representation of a hexadecimal string. If it is required to\n" - + " use another algorithm the hexadecimal string is to be prefixed with a string of the form,\n" - + " \"{}\", not including the double quotes. In this is the exact string\n" - + " representing the java supported algorithm, i.e. MD5 or SHA-256. Note that java does not\n" + " contain an algorithm called SHA256 or one called sha-256, only SHA-256."; - - public static final String HAS_ANNOTATIONS = "hasannotations"; - public static final String LAST_ANNOTATED = "lastannotated"; - public static final String LDAP_DOMAIN = "ldapdomain"; - - public static final String STDOUT = "stdout"; - public static final String STDERR = "stderr"; - public static final String EXITCODE = "exitcode"; - public static final String TARGET_ID = "targetid"; - public static final String FILES = "files"; - public static final String SRC_POOL = "srcpool"; - public static final String DEST_POOL = "destpool"; - public static final String DEST_POOLS = "destpools"; - public static final String VOLUME_IDS = "volumeids"; - - public static final String ROUTER_ID = "routerid"; - public static final String ROUTER_HEALTH_CHECKS = "healthchecks"; - public static final String ROUTER_CHECK_NAME = "checkname"; - public static final String ROUTER_CHECK_TYPE = "checktype"; - public static final String ROUTER_IP = "routerip"; - public static final String ROUTER_IPV6 = "routeripv6"; - public static final String ROUTER_PRIVATE_INTERFACE_MAX_MTU = "routerprivateinterfacemaxmtu"; - public static final String ROUTER_PUBLIC_INTERFACE_MAX_MTU = "routerpublicinterfacemaxmtu"; - public static final String LAST_UPDATED = "lastupdated"; - public static final String PERFORM_FRESH_CHECKS = "performfreshchecks"; - public static final String CACHE_MODE = "cachemode"; - - public static final String CONSOLE_END_POINT = "consoleendpoint"; - public static final String EXTERNAL_LOAD_BALANCER_IP_ADDRESS = "externalloadbalanceripaddress"; - public static final String DOCKER_REGISTRY_USER_NAME = "dockerregistryusername"; - public static final String DOCKER_REGISTRY_PASSWORD = "dockerregistrypassword"; - public static final String DOCKER_REGISTRY_URL = "dockerregistryurl"; - public static final String DOCKER_REGISTRY_EMAIL = "dockerregistryemail"; - public static final String ISO_NAME = "isoname"; - public static final String ISO_STATE = "isostate"; - public static final String ISO_URL = "isourl"; - public static final String SEMANTIC_VERSION = "semanticversion"; - public static final String KUBERNETES_VERSION_ID = "kubernetesversionid"; - public static final String KUBERNETES_VERSION_NAME = "kubernetesversionname"; - public static final String MASTER_NODES = "masternodes"; - public static final String NODE_IDS = "nodeids"; - public static final String CONTROL_NODES = "controlnodes"; - public static final String ETCD_NODES = "etcdnodes"; - public static final String EXTERNAL_NODES = "externalnodes"; - public static final String IS_EXTERNAL_NODE = "isexternalnode"; - public static final String IS_ETCD_NODE = "isetcdnode"; - public static final String MIN_SEMANTIC_VERSION = "minimumsemanticversion"; - public static final String MIN_KUBERNETES_VERSION_ID = "minimumkubernetesversionid"; - public static final String NODE_ROOT_DISK_SIZE = "noderootdisksize"; - public static final String SUPPORTS_HA = "supportsha"; - public static final String SUPPORTS_AUTOSCALING = "supportsautoscaling"; - public static final String AUTOSCALING_ENABLED = "autoscalingenabled"; - public static final String MIN_SIZE = "minsize"; - public static final String MAX_SIZE = "maxsize"; - public static final String NODE_TYPE_OFFERING_MAP = "nodeofferings"; - public static final String NODE_TYPE_TEMPLATE_MAP = "nodetemplates"; - public static final String NODE_TYPE_AFFINITY_GROUP_MAP = "nodeaffinitygroups"; - public static final String CONTROL_AFFINITY_GROUP_IDS = "controlaffinitygroupids"; - public static final String CONTROL_AFFINITY_GROUP_NAMES = "controlaffinitygroupnames"; - public static final String WORKER_AFFINITY_GROUP_IDS = "workeraffinitygroupids"; - public static final String WORKER_AFFINITY_GROUP_NAMES = "workeraffinitygroupnames"; - public static final String ETCD_AFFINITY_GROUP_IDS = "etcdaffinitygroupids"; - public static final String ETCD_AFFINITY_GROUP_NAMES = "etcdaffinitygroupnames"; - - public static final String BOOT_TYPE = "boottype"; - public static final String BOOT_MODE = "bootmode"; - public static final String BOOT_INTO_SETUP = "bootintosetup"; - public static final String DEPLOY_AS_IS = "deployasis"; - public static final String DEPLOY_AS_IS_DETAILS = "deployasisdetails"; - public static final String CROSS_ZONES = "crossZones"; - public static final String SOURCETEMPLATEID = "sourcetemplateid"; - public static final String DYNAMIC_SCALING_ENABLED = "dynamicscalingenabled"; - public static final String IOTHREADS_ENABLED = "iothreadsenabled"; - public static final String IO_DRIVER_POLICY = "iodriverpolicy"; - - public static final String POOL_TYPE = "pooltype"; - public static final String REDUNDANT_STATE = "redundantstate"; - - public static final String ADMINS_ONLY = "adminsonly"; - public static final String ANNOTATION_FILTER = "annotationfilter"; - public static final String CODE_FOR_2FA = "codefor2fa"; - public static final String PROVIDER_FOR_2FA = "providerfor2fa"; - public static final String ISSUER_FOR_2FA = "issuerfor2fa"; - public static final String MANDATE_2FA = "mandate2fa"; - public static final String PASSWORD_CHANGE_REQUIRED = "passwordchangerequired"; - public static final String SECRET_CODE = "secretcode"; - public static final String LOGIN = "login"; - public static final String LOGOUT = "logout"; - public static final String LIST_IDPS = "listIdps"; - - public static final String MAINTENANCE_INITIATED = "maintenanceinitiated"; - public static final String SHUTDOWN_TRIGGERED = "shutdowntriggered"; - public static final String READY_FOR_SHUTDOWN = "readyforshutdown"; - public static final String PENDING_JOBS_COUNT = "pendingjobscount"; - public static final String AGENTS_COUNT = "agentscount"; - public static final String AGENTS = "agents"; - public static final String LAST_AGENTS = "lastagents"; - - public static final String PUBLIC_MTU = "publicmtu"; - public static final String PRIVATE_MTU = "privatemtu"; - public static final String MTU = "mtu"; - public static final String AUTO_ENABLE_KVM_HOST = "autoenablekvmhost"; - public static final String LIST_APIS = "listApis"; - public static final String VERSIONING = "versioning"; - public static final String OBJECT_LOCKING = "objectlocking"; - public static final String ENCRYPTION = "encryption"; - public static final String QUOTA = "quota"; - public static final String QUOTA_CONSUMED = "quotaconsumed"; - public static final String QUOTA_USAGE = "quotausage"; - public static final String ACCESS_KEY = "accesskey"; - - public static final String SOURCE_NAT_IP = "sourcenatipaddress"; - public static final String SOURCE_NAT_IP_ID = "sourcenatipaddressid"; - public static final String HAS_RULES = "hasrules"; - public static final String NSX_DETAIL_KEY = "forNsx"; - public static final String NETRIS_DETAIL_KEY = "forNetris"; - public static final String NETRIS_TAG = "netristag"; - public static final String NETRIS_VXLAN_ID = "netrisvxlanid"; - public static final String NETRIS_URL = "netrisurl"; - public static final String DISK_PATH = "diskpath"; - public static final String IMPORT_SOURCE = "importsource"; - public static final String TEMP_PATH = "temppath"; - public static final String HEURISTIC_RULE = "heuristicrule"; - public static final String HEURISTIC_TYPE_VALID_OPTIONS = "Valid options are: ISO, SNAPSHOT, TEMPLATE and VOLUME."; - public static final String MANAGEMENT = "management"; - public static final String IS_VNF = "isvnf"; - public static final String VNF_NICS = "vnfnics"; - public static final String VNF_DETAILS = "vnfdetails"; - public static final String CLEAN_UP_VNF_DETAILS = "cleanupvnfdetails"; - public static final String CLEAN_UP_VNF_NICS = "cleanupvnfnics"; - public static final String VNF_CONFIGURE_MANAGEMENT = "vnfconfiguremanagement"; - public static final String VNF_CIDR_LIST = "vnfcidrlist"; - - public static final String CLIENT_ID = "clientid"; - public static final String REDIRECT_URI = "redirecturi"; - - public static final String IS_TAG_A_RULE = "istagarule"; - - public static final String PARAMETER_DESCRIPTION_IS_TAG_A_RULE = "Whether the informed tag is a JS interpretable rule or not."; - - public static final String WEBHOOK_ID = "webhookid"; - public static final String WEBHOOK_NAME = "webhookname"; - - public static final String NFS_MOUNT_OPTIONS = "nfsmountopts"; - public static final String MOUNT_OPTIONS = "mountopts"; - - public static final String SHAREDFSVM_MIN_CPU_COUNT = "sharedfsvmmincpucount"; - public static final String SHAREDFSVM_MIN_RAM_SIZE = "sharedfsvmminramsize"; - - // Object Storage related - public static final String BUCKET_AVAILABLE = "bucketavailable"; - public static final String BUCKET_LIMIT = "bucketlimit"; - public static final String BUCKET_TOTAL = "buckettotal"; - public static final String OBJECT_STORAGE_ID = "objectstorageid"; - public static final String OBJECT_STORAGE = "objectstore"; - public static final String OBJECT_STORAGE_AVAILABLE = "objectstorageavailable"; - public static final String OBJECT_STORAGE_LIMIT = "objectstoragelimit"; - public static final String OBJECT_STORAGE_TOTAL = "objectstoragetotal"; - - public static final String KEEP_MAC_ADDRESS_ON_PUBLIC_NIC = "keepmacaddressonpublicnic"; - - public static final String PARAMETER_DESCRIPTION_KEEP_MAC_ADDRESS_ON_PUBLIC_NIC = - "Indicates whether to use the same MAC address for the public NIC of VRs on the same network. If \"true\", when creating redundant routers or recreating" + - " a VR, CloudStack will use the same MAC address for the public NIC of all VRs. Otherwise, if \"false\", new public NICs will always have " + - " a new MAC address."; - - public static final String PARAMETER_DESCRIPTION_ACTIVATION_RULE = "Quota tariff's activation rule. It can receive a JS script that results in either " + - "a boolean or a numeric value: if it results in a boolean value, the tariff value will be applied according to the result; if it results in a numeric value, the " + - "numeric value will be applied; if the result is neither a boolean nor a numeric value, the tariff will not be applied. If the rule is not informed, the tariff " + - "value will be applied."; - - public static final String PARAMETER_DESCRIPTION_START_DATE_POSSIBLE_FORMATS = "The recommended format is \"yyyy-MM-dd'T'HH:mm:ssZ\" (e.g.: \"2023-01-01T12:00:00+0100\"); " + - "however, the following formats are also accepted: \"yyyy-MM-dd HH:mm:ss\" (e.g.: \"2023-01-01 12:00:00\") and \"yyyy-MM-dd\" (e.g.: \"2023-01-01\" - if the time is not " + - "added, it will be interpreted as \"00:00:00\"). If the recommended format is not used, the date will be considered in the server timezone."; - - public static final String PARAMETER_DESCRIPTION_END_DATE_POSSIBLE_FORMATS = "The recommended format is \"yyyy-MM-dd'T'HH:mm:ssZ\" (e.g.: \"2023-01-01T12:00:00+0100\"); " + - "however, the following formats are also accepted: \"yyyy-MM-dd HH:mm:ss\" (e.g.: \"2023-01-01 12:00:00\") and \"yyyy-MM-dd\" (e.g.: \"2023-01-01\" - if the time is not " + - "added, it will be interpreted as \"23:59:59\"). If the recommended format is not used, the date will be considered in the server timezone."; - - public static final String PARAMETER_DESCRIPTION_MAX_BACKUPS = "The maximum number of backups to keep for a VM. " + - "If \"0\", no retention policy will be applied and, thus, no backups from the schedule will be automatically deleted. " + - "This parameter is only supported for the Dummy, NAS and EMC Networker backup provider."; - - public static final String VMWARE_DC = "vmwaredc"; - - public static final String CSS = "css"; - - public static final String JSON_CONFIGURATION = "jsonconfiguration"; - - public static final String COMMON_NAMES = "commonnames"; - - public static final String COMMON_NAME = "commonname"; - - public static final String DOMAIN_IDS = "domainids"; - - public static final String SHOW_PUBLIC = "showpublic"; - - public static final String LIST_ONLY_DEFAULT_THEME = "listonlydefaulttheme"; - - public static final String RECURSIVE_DOMAINS = "recursivedomains"; - - public static final String VPN_CUSTOMER_GATEWAY_PARAMETERS = "vpncustomergatewayparameters"; - public static final String OBSOLETE_PARAMETERS = "obsoleteparameters"; - public static final String EXCLUDED_PARAMETERS = "excludedparameters"; - - /** - * This enum specifies IO Drivers, each option controls specific policies on I/O. - * Qemu guests support "threads" and "native" options Since 0.8.8 ; "io_uring" is supported Since 6.3.0 (QEMU 5.0). - */ - public enum IoDriverPolicy { - NATIVE("native"), - THREADS("threads"), - IO_URING("io_uring"), - STORAGE_SPECIFIC("storage_specific"); - - String ioDriver; - - IoDriverPolicy(String driver) { - ioDriver = driver; - } - - @Override - public String toString() { - return ioDriver; - } - } - - public enum BootType { - UEFI, BIOS; - - @Override - public String toString() { - return this.name(); - } - } - - public enum BootMode { - LEGACY, SECURE; - - @Override - public String toString() { - return this.name(); - } - } - - public enum HostDetails { - all, capacity, events, stats, min; - } - - public enum VMDetails { - all, group, nics, stats, secgrp, tmpl, servoff, diskoff, backoff, iso, volume, min, affgrp, vnfnics; - } - - public enum DomainDetails { - all, resource, min; - } - - public enum ExtensionDetails { - all, resource, external, min; - } - - public enum ApiKeyAccess { - DISABLED(false), - ENABLED(true), - INHERIT(null); - - Boolean apiKeyAccess; - - ApiKeyAccess(Boolean keyAccess) { - apiKeyAccess = keyAccess; - } - - public Boolean toBoolean() { - return apiKeyAccess; - } - - public static ApiKeyAccess fromBoolean(Boolean value) { - if (value == null) { - return INHERIT; - } else if (value) { - return ENABLED; - } else { - return DISABLED; - } - } - } -} + public static final String NIC_MAC_ADDRESS_LIST = "nicmacaddresslist"; + public static final String NIC_MULTIQUEUE_NUMBER = "nicmultiqueuenumber"; + public static final String NIC_PACKED_VIRTQUEUES_ENABLED = "nicpackedvirtqueuesenabled"; + public static final String NEW_START_IP = "newstartip"; + public static final String NEW_END_IP = "newendip"; + public static final String KUBERNETES_NODE_VERSION = "kubernetesnodeversion"; + public static final String NUMA_NODE = "numanode"; + public static final String NUM_RETRIES = "numretries"; + public static final String OFFER_HA = "offerha"; + public static final String OS_DISTRIBUTION = "osdistribution"; + public static final String IS_SYSTEM_OFFERING = "issystem"; + public static final String IS_DEFAULT_USE = "defaultuse"; + public static final String OLD_FORMAT = "oldformat"; + public static final String OP = "op"; + public static final String OPTION = "option"; + public static final String OPTIONS = "options"; + public static final String OS_CATEGORY_ID = "oscategoryid"; + public static final String OS_CATEGORY_NAME = "oscategoryname"; + public static final String OS_NAME = "osname"; + 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"; + public static final String GPU_CARD_ID = "gpucardid"; + public static final String GPU_CARD_NAME = "gpucardname"; + public static final String GPU_COUNT = "gpucount"; + public static final String GPU_DISPLAY = "gpudisplay"; + public static final String GPU_DEVICE_TYPE = "gpudevicetype"; + public static final String GPU_ENABLED = "gpuenabled"; + public static final String MAX_VGPU_PER_PHYSICAL_GPU = "maxvgpuperphysicalgpu"; + public static final String GUEST_OS_LIST = "guestoslist"; + public static final String GUEST_OS_COUNT = "guestoscount"; + public static final String OS_MAPPING_CHECK_ENABLED = "osmappingcheckenabled"; + public static final String OUTOFBANDMANAGEMENT_POWERSTATE = "outofbandmanagementpowerstate"; + public static final String OUTOFBANDMANAGEMENT_ENABLED = "outofbandmanagementenabled"; + public static final String OUTPUT = "output"; + public static final String PROPERTIES = "properties"; + public static final String PARAMS = "params"; + public static final String PARENT = "parent"; + public static final String PARENT_ID = "parentid"; + public static final String PARENT_DOMAIN_ID = "parentdomainid"; + public static final String PARENT_GPU_DEVICE_ID = "parentgpudeviceid"; + public static final String PARENT_SUBNET = "parentsubnet"; + public static final String PARENT_TEMPLATE_ID = "parenttemplateid"; + public static final String PASSWORD = "password"; + public static final String PCI_ROOT = "pciroot"; + public static final String CURRENT_PASSWORD = "currentpassword"; + public static final String SHOULD_UPDATE_PASSWORD = "update_passwd_on_host"; + public static final String PASSWORD_ENABLED = "passwordenabled"; + public static final String SSHKEY_ENABLED = "sshkeyenabled"; + public static final String PATH = "path"; + public static final String PATH_READY = "pathready"; + public static final String PAYLOAD = "payload"; + public static final String PAYLOAD_URL = "payloadurl"; + public static final String PEERS = "peers"; + public static final String PEER_ID = "peerid"; + public static final String PEER_NAME = "peername"; + public static final String PEER_MSID = "peermsid"; + public static final String PEER_RUNID = "peerrunid"; + public static final String PEER_SERVICE_IP = "peerserviceip"; + public static final String PEER_SERVICE_PORT = "peerserviceport"; + public static final String PEER_STATE = "peerstate"; + public static final String POD_ID = "podid"; + public static final String POD_NAME = "podname"; + public static final String POD_IDS = "podids"; + public static final String POLICY_ID = "policyid"; + public static final String PORT = "port"; + 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 PRECEDENCE = "precedence"; + public static final String PREPARE_VM = "preparevm"; + public static final String PRESERVE_IP = "preserveip"; + public static final String PRIVATE_INTERFACE = "privateinterface"; + public static final String PRIVATE_IP = "privateip"; + public static final String PRIVATE_PORT = "privateport"; + public static final String PRIVATE_START_PORT = "privateport"; + public static final String PRIVATE_END_PORT = "privateendport"; + public static final String PRIVATE_ZONE = "privatezone"; + public static final String PROTOCOL = "protocol"; + public static final String PROVISIONINGTYPE = "provisioningtype"; + public static final String PUBLIC_INTERFACE = "publicinterface"; + public static final String PUBLIC_IP_ID = "publicipid"; + public static final String PUBLIC_IP = "publicip"; + public static final String PUBLIC_PORT = "publicport"; + public static final String PUBLIC_START_PORT = "publicport"; + public static final String PUBLIC_END_PORT = "publicendport"; + public static final String PUBLIC_ZONE = "publiczone"; + public static final String PURGE_RESOURCES = "purgeresources"; + public static final String RAM = "RAM"; + public static final String REBALANCE = "rebalance"; + public static final String RECEIVED_BYTES = "receivedbytes"; + public static final String RECONNECT = "reconnect"; + public static final String RECOVER = "recover"; + public static final String REPAIR = "repair"; + public static final String REPETITION_ALLOWED = "repetitionallowed"; + public static final String REQUIRES_HVM = "requireshvm"; + public static final String RESERVED_RESOURCE_DETAILS = "reservedresourcedetails"; + public static final String RESOURCES = "resources"; + public static final String RESOURCE_COUNT = "resourcecount"; + public static final String RESOURCE_NAME = "resourcename"; + public static final String RESOURCE_TYPE = "resourcetype"; + public static final String RESOURCE_TYPE_NAME = "resourcetypename"; + public static final String RESPONSE = "response"; + public static final String RETRIEVE_ONLY_RESOURCE_COUNT = "retrieveonlyresourcecount"; + public static final String REVERTABLE = "revertable"; + public static final String REVOKED = "revoked"; + public static final String REGISTERED = "registered"; + public static final String QUALIFIERS = "qualifiers"; + public static final String QUERY_FILTER = "queryfilter"; + public static final String QUIESCE_VM = "quiescevm"; + public static final String SCHEDULE = "schedule"; + public static final String SCHEDULE_ID = "scheduleid"; + public static final String SCOPE = "scope"; + public static final String SEARCH_BASE = "searchbase"; + public static final String SECONDARY_IP = "secondaryip"; + public static final String SECURITY_GROUP_IDS = "securitygroupids"; + public static final String SECURITY_GROUP_NAMES = "securitygroupnames"; + public static final String SECURITY_GROUP_NAME = "securitygroupname"; + public static final String SECURITY_GROUP_ID = "securitygroupid"; + public static final String SENT = "sent"; + public static final String SENT_BYTES = "sentbytes"; + public static final String SERIAL = "serial"; + public static final String SERVICE_IP = "serviceip"; + public static final String SERVICE_OFFERING_ID = "serviceofferingid"; + public static final String SERVICE_OFFERING_NAME = "serviceofferingname"; + public static final String SESSIONKEY = "sessionkey"; + public static final String SHOW_CAPACITIES = "showcapacities"; + public static final String SHOW_REMOVED = "showremoved"; + public static final String SHOW_RESOURCES = "showresources"; + public static final String SHOW_RESOURCE_ICON = "showicon"; + public static final String SHOW_INACTIVE = "showinactive"; + public static final String SHOW_UNIQUE = "showunique"; + public static final String SHOW_PERMISSIONS = "showpermissions"; + public static final String SIGNATURE = "signature"; + public static final String SIGNATURE_VERSION = "signatureversion"; + public static final String SINCE = "since"; + public static final String SITE_NAME = "sitename"; + public static final String SIZE = "size"; + public static final String SIZEGB = "sizegb"; + public static final String SNAPSHOT = "snapshot"; + public static final String SNAPSHOT_ID = "snapshotid"; + public static final String SNAPSHOT_POLICY_ID = "snapshotpolicyid"; + public static final String SNAPSHOT_TYPE = "snapshottype"; + public static final String SNAPSHOT_QUIESCEVM = "quiescevm"; + + public static final String USE_STORAGE_REPLICATION = "usestoragereplication"; + + public static final String SOURCE_CIDR_LIST = "sourcecidrlist"; + public static final String SOURCE_OFFERING_ID = "sourceofferingid"; + public static final String SOURCE_ZONE_ID = "sourcezoneid"; + public static final String SSL_VERIFICATION = "sslverification"; + public static final String START_ASN = "startasn"; + public static final String START_DATE = "startdate"; + public static final String START_ID = "startid"; + public static final String START_IP = "startip"; + public static final String START_IPV6 = "startipv6"; + public static final String START_PORT = "startport"; + public static final String STATE = "state"; + public static final String STATS = "stats"; + public static final String STATUS = "status"; + public static final String STORAGE_TYPE = "storagetype"; + public static final String STORAGE_POLICY = "storagepolicy"; + public static final String STORAGE_MOTION_ENABLED = "storagemotionenabled"; + public static final String STORAGE_CAPABILITIES = "storagecapabilities"; + public static final String STORAGE_CUSTOM_STATS = "storagecustomstats"; + public static final String SUBNET = "subnet"; + public static final String OWNER = "owner"; + public static final String SWAP_OWNER = "swapowner"; + public static final String SYSTEM_VM_TYPE = "systemvmtype"; + public static final String TAGS = "tags"; + public static final String STORAGE_TAGS = "storagetags"; + public static final String STORAGE_ACCESS_GROUPS = "storageaccessgroups"; + public static final String STORAGE_ACCESS_GROUP = "storageaccessgroup"; + public static final String CLUSTER_STORAGE_ACCESS_GROUPS = "clusterstorageaccessgroups"; + public static final String POD_STORAGE_ACCESS_GROUPS = "podstorageaccessgroups"; + public static final String ZONE_STORAGE_ACCESS_GROUPS = "zonestorageaccessgroups"; + public static final String SUCCESS = "success"; + public static final String SUCCESS_MESSAGE = "successmessage"; + public static final String SUITABLE_FOR_VM = "suitableforvirtualmachine"; + public static final String SUPPORTS_STORAGE_SNAPSHOT = "supportsstoragesnapshot"; + public static final String TARGET_IQN = "targetiqn"; + public static final String TASKS_FILTER = "tasksfilter"; + public static final String TEMPLATE_FILTER = "templatefilter"; + public static final String TEMPLATE_ID = "templateid"; + public static final String TEMPLATE_IDS = "templateids"; + public static final String TEMPLATE_NAME = "templatename"; + public static final String TEMPLATE_TYPE = "templatetype"; + public static final String TEMPLATE_FORMAT = "templateformat"; + public static final String TIMEOUT = "timeout"; + public static final String TIMEZONE = "timezone"; + public static final String TIMEZONEOFFSET = "timezoneoffset"; + public static final String TENANT_NAME = "tenantname"; + public static final String TOTAL = "total"; + public static final String TOTAL_SUBNETS = "totalsubnets"; + public static final String TO_CHECKPOINT_ID = "tocheckpointid"; + public static final String TOTAL_QUOTA = "totalquota"; + public static final String TYPE = "type"; + public static final String TRUST_STORE = "truststore"; + public static final String TRUST_STORE_PASSWORD = "truststorepass"; + public static final String UNIT = "unit"; + public static final String URL = "url"; + public static final String USAGE_INTERFACE = "usageinterface"; + public static final String USED = "used"; + public static final String USED_SUBNETS = "usedsubnets"; + public static final String USED_IOPS = "usediops"; + public static final String USER_DATA = "userdata"; + + public static final String USER_DATA_NAME = "userdataname"; + public static final String USER_DATA_ID = "userdataid"; + public static final String USER_DATA_POLICY = "userdatapolicy"; + public static final String USER_DATA_DETAILS = "userdatadetails"; + public static final String USER_DATA_PARAMS = "userdataparams"; + public static final String USER_FILTER = "userfilter"; + public static final String USER_ID = "userid"; + public static final String USER_SOURCE = "usersource"; + public static final String USER_CONFLICT_SOURCE = "conflictingusersource"; + public static final String USE_SSL = "ssl"; + public static final String USERNAME = "username"; + public static final String USER_CONFIGURABLE = "userconfigurable"; + public static final String USER_SECURITY_GROUP_LIST = "usersecuritygrouplist"; + public static final String USER_SECRET_KEY = "usersecretkey"; + public static final String USE_VDDK = "usevddk"; + public static final String USE_VIRTUAL_NETWORK = "usevirtualnetwork"; + public static final String USE_VIRTUAL_ROUTER_IP_RESOLVER = "userouteripresolver"; + public static final String UPDATE_IN_SEQUENCE = "updateinsequence"; + public static final String VALIDATION_FORMAT = "validationformat"; + public static final String VALUE = "value"; + public static final String VALUE_OPTIONS = "valueoptions"; + public static final String VENDOR_ID = "vendorid"; + public static final String VENDOR_NAME = "vendorname"; + public static final String VGPU_PROFILE_ID = "vgpuprofileid"; + public static final String VGPU_PROFILE_NAME = "vgpuprofilename"; + public static final String VIRTUAL_MACHINE = "virtualmachine"; + public static final String VIRTUAL_MACHINE_ID = "virtualmachineid"; + public static final String VIRTUAL_MACHINE_IDS = "virtualmachineids"; + public static final String VIRTUAL_MACHINE_NAME = "virtualmachinename"; + public static final String VIRTUAL_MACHINE_ID_IP = "vmidipmap"; + public static final String VIRTUAL_MACHINE_COUNT = "virtualmachinecount"; + public static final String VIRTUAL_MACHINE_TYPE = "virtualmachinetype"; + public static final String VIRTUAL_MACHINE_STATE = "vmstate"; + public static final String VIRTUAL_MACHINES = "virtualmachines"; + public static final String USAGE_ID = "usageid"; + public static final String USAGE_TYPE = "usagetype"; + public static final String INCLUDE_TAGS = "includetags"; + + public static final String VLAN = "vlan"; + public static final String VLAN_RANGE = "vlanrange"; + public static final String WORKER_SERVICE_OFFERING_ID = "workerofferingid"; + public static final String WORKER_SERVICE_OFFERING_NAME = "workerofferingname"; + public static final String CONTROL_SERVICE_OFFERING_ID = "controlofferingid"; + public static final String CONTROL_SERVICE_OFFERING_NAME = "controlofferingname"; + public static final String ETCD_SERVICE_OFFERING_ID = "etcdofferingid"; + public static final String ETCD_SERVICE_OFFERING_NAME = "etcdofferingname"; + 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 IS_ALLOCATED = "isallocated"; + public static final String IS_DEDICATED = "isdedicated"; + public static final String TAKEN = "taken"; + public static final String VM_AVAILABLE = "vmavailable"; + public static final String VM_DETAILS = "vmdetails"; + public static final String VM_LIMIT = "vmlimit"; + public static final String VM_TOTAL = "vmtotal"; + public static final String VM_SETTINGS = "vmsettings"; + public static final String VM_TYPE = "vmtype"; + public static final String VNET = "vnet"; + public static final String IS_VOLATILE = "isvolatile"; + public static final String VOLUME_ID = "volumeid"; + public static final String VOLUMES = "volumes"; + public static final String VOLUME_CHECK_RESULT = "volumecheckresult"; + public static final String VOLUME_REPAIR_RESULT = "volumerepairresult"; + + public static final String ZONE = "zone"; + public static final String ZONE_ID = "zoneid"; + public static final String ZONE_NAME = "zonename"; + public static final String ZONE_WISE = "zonewise"; + public static final String NETWORK_TYPE = "networktype"; + public static final String PAGE = "page"; + public static final String PAGE_SIZE = "pagesize"; + public static final String COUNT = "count"; + public static final String TRAFFIC_TYPE = "traffictype"; + public static final String NETWORK_OFFERING_ID = "networkofferingid"; + public static final String TIER_NETWORK_OFFERINGS = "tiernetworkofferings"; + public static final String NETWORK_IDS = "networkids"; + public static final String NETWORK_ID = "networkid"; + public static final String NETWORK_FILTER = "networkfilter"; + public static final String NIC_ID = "nicid"; + public static final String SPECIFY_AS_NUMBER = "specifyasnumber"; + public static final String SPECIFY_VLAN = "specifyvlan"; + public static final String IS_DEFAULT = "isdefault"; + public static final String IS_SYSTEM = "issystem"; + public static final String IS_USER_DEFINED = "isuserdefined"; + public static final String AVAILABILITY = "availability"; + public static final String NETWORKRATE = "networkrate"; + public static final String HOST_TAGS = "hosttags"; + public static final String SSH_KEYPAIR = "keypair"; + public static final String SSH_KEYPAIRS = "keypairs"; + public static final String HTTPMETHOD = "httpmethod"; + public static final String HOST_CPU_CAPACITY = "hostcpucapacity"; + public static final String HOST_CPU_NUM = "hostcpunum"; + public static final String HOST_MEM_CAPACITY = "hostmemcapacity"; + public static final String HOST_MAC = "hostmac"; + public static final String HOST_TAG = "hosttag"; + public static final String PXE_SERVER_TYPE = "pxeservertype"; + public static final String LINMIN_USERNAME = "linminusername"; + public static final String LINMIN_PASSWORD = "linminpassword"; + public static final String LINMIN_APID = "linminapid"; + public static final String DHCP_SERVER_TYPE = "dhcpservertype"; + public static final String LINK_LOCAL_IP = "linklocalip"; + public static final String LINK_LOCAL_MAC_ADDRESS = "linklocalmacaddress"; + public static final String LINK_LOCAL_MAC_NETMASK = "linklocalnetmask"; + public static final String LINK_LOCAL_NETWORK_ID = "linklocalnetworkid"; + public static final String PRIVATE_MAC_ADDRESS = "privatemacaddress"; + public static final String PRIVATE_NETMASK = "privatenetmask"; + public static final String PRIVATE_NETWORK_ID = "privatenetworkid"; + public static final String ALLOCATION_STATE = "allocationstate"; + public static final String MANAGED_STATE = "managedstate"; + public static final String MANAGEMENT_SERVER_ID = "managementserverid"; + public static final String MANAGEMENT_SERVER_NAME = "managementservername"; + public static final String STORAGE = "storage"; + public static final String STORAGE_ID = "storageid"; + public static final String PING_STORAGE_SERVER_IP = "pingstorageserverip"; + public static final String PING_DIR = "pingdir"; + public static final String TFTP_DIR = "tftpdir"; + public static final String PING_CIFS_USERNAME = "pingcifsusername"; + public static final String PING_CIFS_PASSWORD = "pingcifspassword"; + public static final String CHECKSUM = "checksum"; + public static final String NETWORK_DEVICE_TYPE = "networkdevicetype"; + public static final String NETWORK_DEVICE_PARAMETER_LIST = "networkdeviceparameterlist"; + public static final String ZONE_TOKEN = "zonetoken"; + public static final String DHCP_PROVIDER = "dhcpprovider"; + public static final String RESULT = "result"; + public static final String RESUME = "resume"; + public static final String LUN_ID = "lunId"; + public static final String IQN = "iqn"; + public static final String AGGREGATE_NAME = "aggregatename"; + public static final String POOL_NAME = "poolname"; + public static final String VOLUME_NAME = "volumename"; + public static final String VOLUME_STATE = "volumestate"; + public static final String SNAPSHOT_POLICY = "snapshotpolicy"; + public static final String SNAPSHOT_RESERVATION = "snapshotreservation"; + public static final String IP_NETWORK_LIST = "iptonetworklist"; + public static final String PARAM_LIST = "param"; + public static final String FOR_LOAD_BALANCING = "forloadbalancing"; + public static final String KEYBOARD = "keyboard"; + public static final String OPEN_FIREWALL = "openfirewall"; + public static final String TEMPLATE_TAG = "templatetag"; + public static final String HYPERVISOR_VERSION = "hypervisorversion"; + public static final String MAX_GUESTS_LIMIT = "maxguestslimit"; + public static final String MAX_DATA_VOLUMES_LIMIT = "maxdatavolumeslimit"; + public static final String MAX_HOSTS_PER_CLUSTER = "maxhostspercluster"; + public static final String PROJECT_ID = "projectid"; + public static final String PROJECT_IDS = "projectids"; + public static final String PROJECT = "project"; + public static final String ROLE = "role"; + public static final String ROLE_ID = "roleid"; + public static final String PROJECT_ROLE_ID = "projectroleid"; + public static final String PROJECT_ROLE_NAME = "projectrolename"; + public static final String ROLE_TYPE = "roletype"; + public static final String ROLE_NAME = "rolename"; + public static final String PERMISSION = "permission"; + public static final String PERMISSIONS = "permissions"; + public static final String RULE = "rule"; + public static final String RULES = "rules"; + public static final String RULE_ID = "ruleid"; + public static final String PROJECT_ROLE_PERMISSION_ID = "projectrolepermissionid"; + public static final String RULE_ORDER = "ruleorder"; + public static final String USER = "user"; + public static final String ACTIVE_ONLY = "activeonly"; + public static final String TOKEN = "token"; + public static final String ACCEPT = "accept"; + public static final String SORT_KEY = "sortkey"; + public static final String ACCOUNT_DETAILS = "accountdetails"; + public static final String SERVICE_OFFERING_DETAILS = "serviceofferingdetails"; + public static final String SERVICE_PROVIDER_LIST = "serviceproviderlist"; + public static final String SERVICE_CAPABILITY_LIST = "servicecapabilitylist"; + public static final String CAN_CHOOSE_SERVICE_CAPABILITY = "canchooseservicecapability"; + public static final String PROVIDER = "provider"; + public static final String OAUTH_PROVIDER = "oauthprovider"; + public static final String OAUTH_SECRET_KEY = "secretkey"; + public static final String MANAGED = "managed"; + public static final String CAPACITY_BYTES = "capacitybytes"; + public static final String CAPACITY_IOPS = "capacityiops"; + public static final String NETWORK_SPEED = "networkspeed"; + public static final String BROADCAST_DOMAIN_RANGE = "broadcastdomainrange"; + public static final String BROADCAST_URI = "broadcasturi"; + public static final String ISOLATION_METHOD = "isolationmethod"; + public static final String ISOLATION_METHODS = "isolationmethods"; + public static final String PHYSICAL_NETWORK_ID = "physicalnetworkid"; + public static final String PHYSICAL_NETWORK_NAME = "physicalnetworkname"; + public static final String DEST_PHYSICAL_NETWORK_ID = "destinationphysicalnetworkid"; + public static final String ENABLE = "enable"; + public static final String ENABLED = "enabled"; + public static final String SERVICE_NAME = "servicename"; + public static final String DHCP_RANGE = "dhcprange"; + public static final String UUID = "uuid"; + public static final String SECURITY_GROUP_EANBLED = "securitygroupenabled"; + public static final String LOCAL_STORAGE_ENABLED = "localstorageenabled"; + public static final String GUEST_IP_TYPE = "guestiptype"; + public static final String GUEST_IP6_PREFIX = "guestip6prefix"; + public static final String XENSERVER_NETWORK_LABEL = "xennetworklabel"; + public static final String KVM_NETWORK_LABEL = "kvmnetworklabel"; + public static final String VMWARE_NETWORK_LABEL = "vmwarenetworklabel"; + public static final String HYPERV_NETWORK_LABEL = "hypervnetworklabel"; + public static final String OVM3_NETWORK_LABEL = "ovm3networklabel"; + public static final String NETWORK_SERVICE_PROVIDER_ID = "nspid"; + public static final String SERVICE_LIST = "servicelist"; + public static final String CAN_ENABLE_INDIVIDUAL_SERVICE = "canenableindividualservice"; + public static final String SUPPORTED_SERVICES = "supportedservices"; + public static final String NSP_ID = "nspid"; + public static final String ACL_TYPE = "acltype"; + public static final String ACL_REASON = "reason"; + public static final String ACL_RULE_PARTIAL_UPGRADE = "partialupgrade"; + public static final String SUBDOMAIN_ACCESS = "subdomainaccess"; + public static final String LOAD_BALANCER_DEVICE_ID = "lbdeviceid"; + public static final String LOAD_BALANCER_DEVICE_NAME = "lbdevicename"; + public static final String LOAD_BALANCER_DEVICE_STATE = "lbdevicestate"; + public static final String LOAD_BALANCER_DEVICE_CAPACITY = "lbdevicecapacity"; + public static final String LOAD_BALANCER_DEVICE_DEDICATED = "lbdevicededicated"; + public static final String LOAD_BALANCER_RULE = "loadbalancerrule"; + public static final String LOAD_BALANCER_RULE_LIST = "loadbalancerrulelist"; + public static final String FIREWALL_DEVICE_ID = "fwdeviceid"; + public static final String FIREWALL_DEVICE_NAME = "fwdevicename"; + public static final String FIREWALL_DEVICE_STATE = "fwdevicestate"; + public static final String FIREWALL_DEVICE_CAPACITY = "fwdevicecapacity"; + public static final String FIREWALL_DEVICE_DEDICATED = "fwdevicededicated"; + public static final String SERVICE = "service"; + public static final String ASSOCIATED_NETWORK = "associatednetwork"; + public static final String ASSOCIATED_NETWORK_ID = "associatednetworkid"; + public static final String ASSOCIATED_NETWORK_NAME = "associatednetworkname"; + public static final String ASSOCIATED_VPC_ID = "associatedvpcid"; + public static final String ASSOCIATED_VPC_NAME = "associatedvpcname"; + public static final String SOURCE_NAT_SUPPORTED = "sourcenatsupported"; + public static final String RESOURCE_STATE = "resourcestate"; + public static final String PROJECT_INVITE_REQUIRED = "projectinviterequired"; + public static final String REQUIRED = "required"; + public static final String RESTART_REQUIRED = "restartrequired"; + public static final String ALLOW_USER_CREATE_PROJECTS = "allowusercreateprojects"; + public static final String ALLOW_USER_DRIVEN_BACKUPS = "allowuserdrivenbackups"; + public static final String ALLOW_USER_SPECIFY_VR_MTU = "allowuserspecifyvrmtu"; + public static final String CONSERVE_MODE = "conservemode"; + public static final String TRAFFIC_TYPE_IMPLEMENTOR = "traffictypeimplementor"; + public static final String KEYWORD = "keyword"; + public static final String LIST_ALL = "listall"; + public static final String LIST_ONLY_REMOVED = "listonlyremoved"; + public static final String LIST_SYSTEM_VMS = "listsystemvms"; + public static final String LIST_VM_DETAILS = "listvmdetails"; + public static final String IP_RANGES = "ipranges"; + public static final String IPV4_ROUTING = "ip4routing"; + public static final String IPV4_ROUTES = "ip4routes"; + public static final String IPV6_ROUTING = "ip6routing"; + public static final String IPV6_ROUTES = "ip6routes"; + public static final String SPECIFY_IP_RANGES = "specifyipranges"; + public static final String IS_SOURCE_NAT = "issourcenat"; + public static final String IS_STATIC_NAT = "isstaticnat"; + public static final String ITERATIONS = "iterations"; + public static final String SORT_BY = "sortby"; + public static final String CHANGE_CIDR = "changecidr"; + public static final String PURPOSE = "purpose"; + public static final String IS_TAGGED = "istagged"; + public static final String INSTANCE_NAME = "instancename"; + public static final String CONSIDER_LAST_HOST = "considerlasthost"; + public static final String START_VM = "startvm"; + public static final String HA_HOST = "hahost"; + public static final String CUSTOM_DISK_OFF_MIN_SIZE = "customdiskofferingminsize"; + 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 AUTO_MIGRATE = "automigrate"; + public static final String GUID = "guid"; + public static final String VM_SNAPSHOT_ENABELD = "vmsnapshotenabled"; + public static final String VSWITCH_TYPE_GUEST_TRAFFIC = "guestvswitchtype"; + public static final String VSWITCH_TYPE_PUBLIC_TRAFFIC = "publicvswitchtype"; + public static final String VSWITCH_NAME_GUEST_TRAFFIC = "guestvswitchname"; + public static final String VSWITCH_NAME_PUBLIC_TRAFFIC = "publicvswitchname"; + + // NSX + public static final String EDGE_CLUSTER = "edgecluster"; + public static final String TIER0_GATEWAY = "tier0gateway"; + + public static final String TRANSPORT_ZONE = "transportzone"; + // Tungsten-Fabric + public static final String TUNGSTEN_VIRTUAL_ROUTER_UUID = "tungstenvirtualrouteruuid"; + public static final String TUNGSTEN_PROVIDER_HOSTNAME = "tungstenproviderhostname"; + public static final String TUNGSTEN_PROVIDER_PORT = "tungstenproviderport"; + public static final String TUNGSTEN_PROVIDER_UUID = "tungstenprovideruuid"; + public static final String TUNGSTEN_GATEWAY = "tungstengateway"; + public static final String TUNGSTEN_PROVIDER_VROUTER_PORT = "tungstenprovidervrouterport"; + public static final String TUNGSTEN_PROVIDER_INTROSPECT_PORT = "tungstenproviderintrospectport"; + public static final String SRC_NETWORK = "srcnetwork"; + public static final String SRC_IP_PREFIX = "srcipprefix"; + public static final String SRC_IP_PREFIX_LEN = "srcipprefixlen"; + public static final String SRC_START_PORT = "srcstartport"; + public static final String SRC_END_PORT = "srcendport"; + public static final String DEST_NETWORK = "destnetwork"; + public static final String DEST_IP_PREFIX = "destipprefix"; + public static final String DEST_IP_PREFIX_LEN = "destipprefixlen"; + public static final String DEST_START_PORT = "deststartport"; + public static final String DEST_END_PORT = "destendport"; + public static final String MAJOR_SEQUENCE = "majorsequence"; + public static final String MINOR_SEQUENCE = "minorsequence"; + public static final String POLICY_UUID = "policyuuid"; + public static final String RULE_UUID = "ruleuuid"; + public static final String DIRECTION = "direction"; + public static final String TAGGED_RESOURCES = "taggedresources"; + public static final String TAG_UUID = "taguuid"; + public static final String TAG_TYPE = "tagtype"; + public static final String TAG_VALUE = "tagvalue"; + public static final String TAG_TYPE_UUID = "tagtypeuuid"; + public static final String NETWORK_UUID = "networkuuid"; + public static final String NIC_UUID = "nicuuid"; + public static final String VM_UUID = "vmuuid"; + public static final String ONE_WAY = "oneway"; + public static final String POLICY = "policy"; + public static final String VM = "vm"; + public static final String FIREWALL_POLICY = "firewallpolicy"; + public static final String FIREWALL_RULE = "firewallrule"; + public static final String TAG = "tag"; + public static final String APPLICATION_POLICY_SET_UUID = "applicationpolicysetuuid"; + public static final String FIREWALL_POLICY_UUID = "firewallpolicyuuid"; + public static final String FIREWALL_RULE_UUID = "firewallruleuuid"; + public static final String ADDRESS_GROUP_UUID = "addressgroupuuid"; + public static final String SERVICE_GROUP_UUID = "servicegroupuuid"; + public static final String SEQUENCE = "sequence"; + public static final String SERVICE_GROUP = "servicegroup"; + public static final String SRC_ADDRESS_GROUP = "srcaddressgroup"; + public static final String DEST_ADDRESS_GROUP = "destaddressgroup"; + public static final String SRC_TAG = "srctag"; + public static final String DEST_TAG = "desttag"; + public static final String IP_PREFIX = "ipprefix"; + public static final String IP_PREFIX_LEN = "ipprefixlen"; + public static final String SRC_ADDRESS_GROUP_UUID = "srcaddressgroupuuid"; + public static final String DEST_ADDRESS_GROUP_UUID = "destaddressgroupuuid"; + public static final String SRC_TAG_UUID = "srctaguuid"; + public static final String DEST_TAG_UUID = "desttaguuid"; + public static final String SRC_NETWORK_UUID = "srcnetworkuuid"; + public static final String DEST_NETWORK_UUID = "destnetworkuuid"; + public static final String LOGICAL_ROUTER_UUID = "logicalrouteruuid"; + public static final String RETRY = "retry"; + public static final String HTTP_METHOD = "httpmethodtype"; + public static final String EXPECTED_CODE = "expectedcode"; + public static final String URL_PATH = "urlpath"; + + // Ovs controller + public static final String OVS_DEVICE_ID = "ovsdeviceid"; + public static final String OVS_DEVICE_NAME = "ovsdevicename"; + // OpenDaylight controller + public static final String ODL_DEVICE_ID = "odldeviceid"; + public static final String ODL_DEVICE_NAME = "odldevicename"; + public static final String ODL_TRANSPORT_ZONE_UUID = "transportzoneuuid"; + public static final String ODL_GATEWAYSERVICE_UUID = "l3gatewayserviceuuid"; + + public static final String EXTERNAL_SWITCH_MGMT_DEVICE_ID = "vsmdeviceid"; + public static final String EXTERNAL_SWITCH_MGMT_DEVICE_NAME = "vsmdevicename"; + public static final String EXTERNAL_SWITCH_MGMT_DEVICE_STATE = "vsmdevicestate"; + // Would we need to have a capacity field for Cisco N1KV VSM? Max hosts managed by it perhaps? May remove this + // later. + public static final String EXTERNAL_SWITCH_MGMT_DEVICE_CAPACITY = "vsmdevicecapacity"; + public static final String CISCO_NEXUS_VSM_NAME = "vsmname"; + public static final String VSM_USERNAME = "vsmusername"; + public static final String VSM_PASSWORD = "vsmpassword"; + public static final String VSM_IPADDRESS = "vsmipaddress"; + public static final String VSM_MGMT_VLAN_ID = "vsmmgmtvlanid"; + public static final String VSM_PKT_VLAN_ID = "vsmpktvlanid"; + public static final String VSM_CTRL_VLAN_ID = "vsmctrlvlanid"; + public static final String VSM_STORAGE_VLAN_ID = "vsmstoragevlanid"; + public static final String VSM_DOMAIN_ID = "vsmdomainid"; + public static final String VSM_CONFIG_MODE = "vsmconfigmode"; + public static final String VSM_CONFIG_STATE = "vsmconfigstate"; + public static final String VSM_DEVICE_STATE = "vsmdevicestate"; + public static final String VCENTER = "vcenter"; + public static final String EXISTING_VCENTER_ID = "existingvcenterid"; + public static final String ADD_VSM_FLAG = "addvsmflag"; + public static final String END_POINT = "endpoint"; + public static final String REGION_ID = "regionid"; + public static final String VPC_OFF_ID = "vpcofferingid"; + public static final String VPC_OFF_NAME = "vpcofferingname"; + public static final String VPC_OFFERING_CONSERVE_MODE = "vpcofferingconservemode"; + public static final String NETWORK = "network"; + public static final String VPC_ID = "vpcid"; + public static final String VPC_NAME = "vpcname"; + public static final String VPC_GATEWAY_ID = "vpcgatewayid"; + public static final String VPC_GATEWAY_IP = "vpcgatewayip"; + public static final String GATEWAY_ID = "gatewayid"; + public static final String CAN_USE_FOR_DEPLOY = "canusefordeploy"; + public static final String RESOURCE_IDS = "resourceids"; + public static final String RESOURCE_ID = "resourceid"; + public static final String CUSTOMER = "customer"; + public static final String S2S_VPN_GATEWAY_ID = "s2svpngatewayid"; + public static final String S2S_CUSTOMER_GATEWAY_ID = "s2scustomergatewayid"; + public static final String IPSEC_PSK = "ipsecpsk"; + public static final String GUEST_IP = "guestip"; + public static final String REMOVED = "removed"; + public static final String REMOVER_ACCOUNT_ID = "removeraccountid"; + public static final String REMOVAL_REASON = "removalreason"; + public static final String COMPLETED = "completed"; + public static final String IKE_VERSION = "ikeversion"; + public static final String IKE_POLICY = "ikepolicy"; + public static final String ESP_POLICY = "esppolicy"; + public static final String IKE_LIFETIME = "ikelifetime"; + public static final String ESP_LIFETIME = "esplifetime"; + public static final String DPD = "dpd"; + public static final String FORCE_ENCAP = "forceencap"; + public static final String SPLIT_CONNECTIONS = "splitconnections"; + public static final String FOR_VPC = "forvpc"; + public static final String FOR_NSX = "fornsx"; + public static final String FOR_CKS = "forcks"; + public static final String NSX_SUPPORT_LB = "nsxsupportlb"; + public static final String NSX_SUPPORTS_INTERNAL_LB = "nsxsupportsinternallb"; + public static final String FOR_TUNGSTEN = "fortungsten"; + public static final String SHRINK_OK = "shrinkok"; + public static final String NICIRA_NVP_DEVICE_ID = "nvpdeviceid"; + public static final String NICIRA_NVP_TRANSPORT_ZONE_UUID = "transportzoneuuid"; + public static final String NICIRA_NVP_DEVICE_NAME = "niciradevicename"; + public static final String NICIRA_NVP_GATEWAYSERVICE_UUID = "l3gatewayserviceuuid"; + public static final String NICIRA_NVP_L2_GATEWAYSERVICE_UUID = "l2gatewayserviceuuid"; + public static final String NSX_LOGICAL_SWITCH = "nsxlogicalswitch"; + public static final String NSX_LOGICAL_SWITCH_PORT = "nsxlogicalswitchport"; + public static final String NSX_PROVIDER_UUID = "nsxprovideruuid"; + public static final String NSX_PROVIDER_HOSTNAME = "nsxproviderhostname"; + + public static final String NSX_PROVIDER_PORT = "nsxproviderport"; + public static final String NSX_CONTROLLER_ID = "nsxcontrollerid"; + public static final String S3_ACCESS_KEY = "accesskey"; + public static final String SECRET_KEY = "secretkey"; + public static final String S3_END_POINT = "endpoint"; + public static final String S3_BUCKET_NAME = "bucket"; + public static final String S3_SIGNER = "s3signer"; + public static final String S3_V3_SIGNER = "S3SignerType"; + public static final String S3_V4_SIGNER = "AWSS3V4SignerType"; + public static final String S3_HTTPS_FLAG = "usehttps"; + public static final String S3_CONNECTION_TIMEOUT = "connectiontimeout"; + public static final String S3_CONNECTION_TTL = "connectionttl"; + public static final String S3_MAX_ERROR_RETRY = "maxerrorretry"; + public static final String S3_SOCKET_TIMEOUT = "sockettimeout"; + public static final String S3_USE_TCP_KEEPALIVE = "usetcpkeepalive"; + public static final String INCL_ZONES = "includezones"; + public static final String EXCL_ZONES = "excludezones"; + public static final String SOURCE = "source"; + public static final String COUNTER_ID = "counterid"; + public static final String AGGR_OPERATOR = "aggroperator"; + public static final String AGGR_FUNCTION = "aggrfunction"; + public static final String AGGR_VALUE = "aggrvalue"; + public static final String THRESHOLD = "threshold"; + public static final String RELATIONAL_OPERATOR = "relationaloperator"; + public static final String OTHER_DEPLOY_PARAMS = "otherdeployparams"; + public static final String MIN_MEMBERS = "minmembers"; + public static final String MAX_MEMBERS = "maxmembers"; + public static final String AUTOSCALE_EXPUNGE_VM_GRACE_PERIOD = "expungevmgraceperiod"; + public static final String VMPROFILE_ID = "vmprofileid"; + public static final String VMGROUP_ID = "vmgroupid"; + public static final String CS_URL = "csurl"; + public static final String IDP_ID = "idpid"; + public static final String SCALEUP_POLICY_IDS = "scaleuppolicyids"; + public static final String SCALEDOWN_POLICY_IDS = "scaledownpolicyids"; + public static final String SCALEUP_POLICIES = "scaleuppolicies"; + public static final String SCALEDOWN_POLICIES = "scaledownpolicies"; + public static final String INTERVAL = "interval"; + public static final String QUIETTIME = "quiettime"; + public static final String ACTION = "action"; + public static final String CONDITION_ID = "conditionid"; + public static final String CONDITION_IDS = "conditionids"; + public static final String COUNTERPARAM_LIST = "counterparam"; + public static final String AUTOSCALE_USER_ID = "autoscaleuserid"; + public static final String AUTOSCALE_VMGROUP_ID = "autoscalevmgroupid"; + public static final String AUTOSCALE_VMGROUP_NAME = "autoscalevmgroupname"; + public static final String BAREMETAL_DISCOVER_NAME = "baremetaldiscovername"; + public static final String BAREMETAL_RCT_URL = "baremetalrcturl"; + public static final String UCS_DN = "ucsdn"; + public static final String GSLB_PROVIDER = "gslbprovider"; + public static final String EXCLUSIVE_GSLB_PROVIDER = "isexclusivegslbprovider"; + public static final String GSLB_PROVIDER_PUBLIC_IP = "gslbproviderpublicip"; + public static final String GSLB_PROVIDER_PRIVATE_IP = "gslbproviderprivateip"; + public static final String VM_SNAPSHOT_DESCRIPTION = "description"; + public static final String VM_SNAPSHOT_DISPLAYNAME = "name"; + public static final String VM_SNAPSHOT_ID = "vmsnapshotid"; + public static final String VM_SNAPSHOT_IDS = "vmsnapshotids"; + public static final String VM_SNAPSHOT_DISK_IDS = "vmsnapshotdiskids"; + public static final String VM_SNAPSHOT_MEMORY = "snapshotmemory"; + public static final String VM_SNAPSHOT_QUIESCEVM = "quiescevm"; + public static final String IMAGE_STORE_UUID = "imagestoreuuid"; + public static final String IMAGE_STORE_ID = "imagestoreid"; + public static final String GUEST_VM_CIDR = "guestvmcidr"; + public static final String NETWORK_CIDR = "networkcidr"; + public static final String RESERVED_IP_RANGE = "reservediprange"; + public static final String UCS_MANAGER_ID = "ucsmanagerid"; + public static final String UCS_PROFILE_DN = "profiledn"; + public static final String UCS_BLADE_DN = "bladedn"; + public static final String UCS_BLADE_ID = "bladeid"; + public static final String VM_GUEST_IP = "vmguestip"; + public static final String HEALTHCHECK_FAILED = "healthchecksfailed"; + public static final String HEALTHCHECK_RESPONSE_TIMEOUT = "responsetimeout"; + public static final String HEALTHCHECK_INTERVAL_TIME = "intervaltime"; + public static final String HEALTHCHECK_HEALTHY_THRESHOLD = "healthythreshold"; + public static final String HEALTHCHECK_UNHEALTHY_THRESHOLD = "unhealthythreshold"; + public static final String HEALTHCHECK_PINGPATH = "pingpath"; + public static final String SOURCE_PORT = "sourceport"; + public static final String INSTANCE_PORT = "instanceport"; + public static final String SOURCE_IP = "sourceipaddress"; + public static final String SOURCE_IP_NETWORK_ID = "sourceipaddressnetworkid"; + public static final String SCHEME = "scheme"; + public static final String PROVIDER_TYPE = "providertype"; + public static final String AFFINITY_GROUP_IDS = "affinitygroupids"; + public static final String AFFINITY_GROUP_NAMES = "affinitygroupnames"; + public static final String ASA_INSIDE_PORT_PROFILE = "insideportprofile"; + public static final String AFFINITY_GROUP_ID = "affinitygroupid"; + public static final String DEPLOYMENT_PLANNER = "deploymentplanner"; + public static final String ACL_ID = "aclid"; + public static final String ACL_NAME = "aclname"; + public static final String NUMBER = "number"; + public static final String IS_DYNAMICALLY_SCALABLE = "isdynamicallyscalable"; + public static final String ROUTED_MODE_ENABLED = "routedmodeenabled"; + public static final String ROUTING = "isrouting"; + public static final String ROUTING_MODE = "routingmode"; + public static final String MAX_CONNECTIONS = "maxconnections"; + public static final String SERVICE_STATE = "servicestate"; + + public static final String IAM_GROUPS = "groups"; + public static final String ENTITY_TYPE = "entitytype"; + public static final String ENTITY_ID = "entityid"; + public static final String ENTITY_NAME = "entityname"; + public static final String EXTERNAL_ID = "externalid"; + public static final String ACCESS_TYPE = "accesstype"; + + public static final String RESOURCE_DETAILS = "resourcedetails"; + public static final String RESOURCE_ICON = "icon"; + public static final String RESOURCE_MAP = "resourcemap"; + public static final String EXPUNGE = "expunge"; + public static final String FOR_DISPLAY = "fordisplay"; + public static final String PASSIVE = "passive"; + public static final String VERSION = "version"; + public static final String START = "start"; + public static final String GPUGROUP = "gpugroup"; + public static final String GPUGROUPNAME = "gpugroupname"; + public static final String VGPU = "vgpu"; + public static final String VGPUTYPE = "vgputype"; + public static final String VIDEORAM = "videoram"; + public static final String MAXHEADS = "maxheads"; + public static final String MAXRESOLUTIONX = "maxresolutionx"; + public static final String MAXRESOLUTIONY = "maxresolutiony"; + public static final String MAXVGPUPERPGPU = "maxvgpuperpgpu"; + public static final String REMAININGCAPACITY = "remainingcapacity"; + public static final String MAXCAPACITY = "maxcapacity"; + public static final String DISTRIBUTED_VPC_ROUTER = "distributedvpcrouter"; + public static final String REDUNDANT_ROUTER = "redundantrouter"; + public static final String REDUNDANT_VPC_ROUTER = "redundantvpcrouter"; + public static final String READ_ONLY = "readonly"; + public static final String SUPPORTS_REGION_LEVEL_VPC = "supportsregionLevelvpc"; + public static final String SUPPORTS_STRECHED_L2_SUBNET = "supportsstrechedl2subnet"; + public static final String SUPPORTS_PUBLIC_ACCESS = "supportspublicaccess"; + public static final String SUPPORTS_INTERNAL_LB = "supportsinternallb"; + public static final String SUPPORTS_VM_AUTOSCALING = "supportsvmautoscaling"; + public static final String REGION_LEVEL_VPC = "regionlevelvpc"; + public static final String STRECHED_L2_SUBNET = "strechedl2subnet"; + public static final String NETWORK_NAME = "networkname"; + public static final String NETWORK_SPANNED_ZONES = "zonesnetworkspans"; + public static final String METADATA = "metadata"; + public static final String PHYSICAL_SIZE = "physicalsize"; + public static final String CHAIN_SIZE = "chainsize"; + public static final String OVM3_POOL = "ovm3pool"; + public static final String OVM3_CLUSTER = "ovm3cluster"; + public static final String OVM3_VIP = "ovm3vip"; + public static final String CLEAN_UP_DETAILS = "cleanupdetails"; + public static final String CLEAN_UP_EXTERNAL_DETAILS = "cleanupexternaldetails"; + public static final String CLEAN_UP_EXTRA_CONFIG = "cleanupextraconfig"; + public static final String CLEAN_UP_PARAMETERS = "cleanupparameters"; + public static final String VIRTUAL_SIZE = "virtualsize"; + public static final String NETSCALER_CONTROLCENTER_ID = "netscalercontrolcenterid"; + public static final String NETSCALER_SERVICEPACKAGE_ID = "netscalerservicepackageid"; + public static final String FETCH_ROUTER_HEALTH_CHECK_RESULTS = "fetchhealthcheckresults"; + + public static final String ZONE_ID_LIST = "zoneids"; + public static final String DESTINATION_ZONE_ID_LIST = "destzoneids"; + public static final String STORAGE_ID_LIST = "storageids"; + public static final String ADMIN = "admin"; + public static final String CHECKSUM_PARAMETER_PREFIX_DESCRIPTION = "The parameter containing the checksum will be considered a MD5sum if it is not prefixed\n" + + " and just a plain ascii/utf8 representation of a hexadecimal string. If it is required to\n" + + " use another algorithm the hexadecimal string is to be prefixed with a string of the form,\n" + + " \"{}\", not including the double quotes. In this is the exact string\n" + + " representing the java supported algorithm, i.e. MD5 or SHA-256. Note that java does not\n" + " contain an algorithm called SHA256 or one called sha-256, only SHA-256."; + + public static final String HAS_ANNOTATIONS = "hasannotations"; + public static final String LAST_ANNOTATED = "lastannotated"; + public static final String LDAP_DOMAIN = "ldapdomain"; + + public static final String STDOUT = "stdout"; + public static final String STDERR = "stderr"; + public static final String EXITCODE = "exitcode"; + public static final String TARGET_ID = "targetid"; + public static final String FILES = "files"; + public static final String SRC_POOL = "srcpool"; + public static final String DEST_POOL = "destpool"; + public static final String DEST_POOLS = "destpools"; + public static final String VOLUME_IDS = "volumeids"; + + public static final String ROUTER_ID = "routerid"; + public static final String ROUTER_HEALTH_CHECKS = "healthchecks"; + public static final String ROUTER_CHECK_NAME = "checkname"; + public static final String ROUTER_CHECK_TYPE = "checktype"; + public static final String ROUTER_IP = "routerip"; + public static final String ROUTER_IPV6 = "routeripv6"; + public static final String ROUTER_PRIVATE_INTERFACE_MAX_MTU = "routerprivateinterfacemaxmtu"; + public static final String ROUTER_PUBLIC_INTERFACE_MAX_MTU = "routerpublicinterfacemaxmtu"; + public static final String LAST_UPDATED = "lastupdated"; + public static final String PERFORM_FRESH_CHECKS = "performfreshchecks"; + public static final String CACHE_MODE = "cachemode"; + + public static final String CONSOLE_END_POINT = "consoleendpoint"; + public static final String EXTERNAL_LOAD_BALANCER_IP_ADDRESS = "externalloadbalanceripaddress"; + public static final String DOCKER_REGISTRY_USER_NAME = "dockerregistryusername"; + public static final String DOCKER_REGISTRY_PASSWORD = "dockerregistrypassword"; + public static final String DOCKER_REGISTRY_URL = "dockerregistryurl"; + public static final String DOCKER_REGISTRY_EMAIL = "dockerregistryemail"; + public static final String ISO_NAME = "isoname"; + public static final String ISO_STATE = "isostate"; + public static final String ISO_URL = "isourl"; + public static final String SEMANTIC_VERSION = "semanticversion"; + public static final String KUBERNETES_VERSION_ID = "kubernetesversionid"; + public static final String KUBERNETES_VERSION_NAME = "kubernetesversionname"; + public static final String MASTER_NODES = "masternodes"; + public static final String NODE_IDS = "nodeids"; + public static final String CONTROL_NODES = "controlnodes"; + public static final String ETCD_NODES = "etcdnodes"; + public static final String EXTERNAL_NODES = "externalnodes"; + public static final String IS_EXTERNAL_NODE = "isexternalnode"; + public static final String IS_ETCD_NODE = "isetcdnode"; + public static final String MIN_SEMANTIC_VERSION = "minimumsemanticversion"; + public static final String MIN_KUBERNETES_VERSION_ID = "minimumkubernetesversionid"; + public static final String NODE_ROOT_DISK_SIZE = "noderootdisksize"; + public static final String SUPPORTS_HA = "supportsha"; + public static final String SUPPORTS_AUTOSCALING = "supportsautoscaling"; + public static final String AUTOSCALING_ENABLED = "autoscalingenabled"; + public static final String MIN_SIZE = "minsize"; + public static final String MAX_SIZE = "maxsize"; + public static final String NODE_TYPE_OFFERING_MAP = "nodeofferings"; + public static final String NODE_TYPE_TEMPLATE_MAP = "nodetemplates"; + public static final String NODE_TYPE_AFFINITY_GROUP_MAP = "nodeaffinitygroups"; + public static final String CONTROL_AFFINITY_GROUP_IDS = "controlaffinitygroupids"; + public static final String CONTROL_AFFINITY_GROUP_NAMES = "controlaffinitygroupnames"; + public static final String WORKER_AFFINITY_GROUP_IDS = "workeraffinitygroupids"; + public static final String WORKER_AFFINITY_GROUP_NAMES = "workeraffinitygroupnames"; + public static final String ETCD_AFFINITY_GROUP_IDS = "etcdaffinitygroupids"; + public static final String ETCD_AFFINITY_GROUP_NAMES = "etcdaffinitygroupnames"; + + public static final String BOOT_TYPE = "boottype"; + public static final String BOOT_MODE = "bootmode"; + public static final String BOOT_INTO_SETUP = "bootintosetup"; + public static final String DEPLOY_AS_IS = "deployasis"; + public static final String DEPLOY_AS_IS_DETAILS = "deployasisdetails"; + public static final String CROSS_ZONES = "crossZones"; + public static final String SOURCETEMPLATEID = "sourcetemplateid"; + public static final String DYNAMIC_SCALING_ENABLED = "dynamicscalingenabled"; + public static final String IOTHREADS_ENABLED = "iothreadsenabled"; + public static final String IO_DRIVER_POLICY = "iodriverpolicy"; + + public static final String POOL_TYPE = "pooltype"; + public static final String REDUNDANT_STATE = "redundantstate"; + + public static final String ADMINS_ONLY = "adminsonly"; + public static final String ANNOTATION_FILTER = "annotationfilter"; + public static final String CODE_FOR_2FA = "codefor2fa"; + public static final String PROVIDER_FOR_2FA = "providerfor2fa"; + public static final String ISSUER_FOR_2FA = "issuerfor2fa"; + public static final String MANDATE_2FA = "mandate2fa"; + public static final String PASSWORD_CHANGE_REQUIRED = "passwordchangerequired"; + public static final String SECRET_CODE = "secretcode"; + public static final String LOGIN = "login"; + public static final String LOGOUT = "logout"; + public static final String LIST_IDPS = "listIdps"; + + public static final String MAINTENANCE_INITIATED = "maintenanceinitiated"; + public static final String SHUTDOWN_TRIGGERED = "shutdowntriggered"; + public static final String READY_FOR_SHUTDOWN = "readyforshutdown"; + public static final String PENDING_JOBS_COUNT = "pendingjobscount"; + public static final String AGENTS_COUNT = "agentscount"; + public static final String AGENTS = "agents"; + public static final String LAST_AGENTS = "lastagents"; + + public static final String PUBLIC_MTU = "publicmtu"; + public static final String PRIVATE_MTU = "privatemtu"; + public static final String MTU = "mtu"; + public static final String AUTO_ENABLE_KVM_HOST = "autoenablekvmhost"; + public static final String LIST_APIS = "listApis"; + public static final String VERSIONING = "versioning"; + public static final String OBJECT_LOCKING = "objectlocking"; + public static final String ENCRYPTION = "encryption"; + public static final String QUOTA = "quota"; + public static final String QUOTA_CONSUMED = "quotaconsumed"; + public static final String QUOTA_USAGE = "quotausage"; + public static final String ACCESS_KEY = "accesskey"; + + public static final String SOURCE_NAT_IP = "sourcenatipaddress"; + public static final String SOURCE_NAT_IP_ID = "sourcenatipaddressid"; + public static final String HAS_RULES = "hasrules"; + public static final String NSX_DETAIL_KEY = "forNsx"; + public static final String NETRIS_DETAIL_KEY = "forNetris"; + public static final String NETRIS_TAG = "netristag"; + public static final String NETRIS_VXLAN_ID = "netrisvxlanid"; + public static final String NETRIS_URL = "netrisurl"; + public static final String DISK_PATH = "diskpath"; + public static final String IMPORT_SOURCE = "importsource"; + public static final String TEMP_PATH = "temppath"; + public static final String HEURISTIC_RULE = "heuristicrule"; + public static final String HEURISTIC_TYPE_VALID_OPTIONS = "Valid options are: ISO, SNAPSHOT, TEMPLATE and VOLUME."; + public static final String MANAGEMENT = "management"; + public static final String IS_VNF = "isvnf"; + public static final String VNF_NICS = "vnfnics"; + public static final String VNF_DETAILS = "vnfdetails"; + public static final String CLEAN_UP_VNF_DETAILS = "cleanupvnfdetails"; + public static final String CLEAN_UP_VNF_NICS = "cleanupvnfnics"; + public static final String VNF_CONFIGURE_MANAGEMENT = "vnfconfiguremanagement"; + public static final String VNF_CIDR_LIST = "vnfcidrlist"; + + public static final String CLIENT_ID = "clientid"; + public static final String REDIRECT_URI = "redirecturi"; + + public static final String IS_TAG_A_RULE = "istagarule"; + + public static final String PARAMETER_DESCRIPTION_IS_TAG_A_RULE = "Whether the informed tag is a JS interpretable rule or not."; + + public static final String WEBHOOK_ID = "webhookid"; + public static final String WEBHOOK_NAME = "webhookname"; + + public static final String NFS_MOUNT_OPTIONS = "nfsmountopts"; + public static final String MOUNT_OPTIONS = "mountopts"; + + public static final String SHAREDFSVM_MIN_CPU_COUNT = "sharedfsvmmincpucount"; + public static final String SHAREDFSVM_MIN_RAM_SIZE = "sharedfsvmminramsize"; + + // Object Storage related + public static final String BUCKET_AVAILABLE = "bucketavailable"; + public static final String BUCKET_LIMIT = "bucketlimit"; + public static final String BUCKET_TOTAL = "buckettotal"; + public static final String OBJECT_STORAGE_ID = "objectstorageid"; + public static final String OBJECT_STORAGE = "objectstore"; + public static final String OBJECT_STORAGE_AVAILABLE = "objectstorageavailable"; + public static final String OBJECT_STORAGE_LIMIT = "objectstoragelimit"; + public static final String OBJECT_STORAGE_TOTAL = "objectstoragetotal"; + + public static final String KEEP_MAC_ADDRESS_ON_PUBLIC_NIC = "keepmacaddressonpublicnic"; + + public static final String PARAMETER_DESCRIPTION_KEEP_MAC_ADDRESS_ON_PUBLIC_NIC = + "Indicates whether to use the same MAC address for the public NIC of VRs on the same network. If \"true\", when creating redundant routers or recreating" + + " a VR, CloudStack will use the same MAC address for the public NIC of all VRs. Otherwise, if \"false\", new public NICs will always have " + + " a new MAC address."; + + public static final String PARAMETER_DESCRIPTION_ACTIVATION_RULE = "Quota tariff's activation rule. It can receive a JS script that results in either " + + "a boolean or a numeric value: if it results in a boolean value, the tariff value will be applied according to the result; if it results in a numeric value, the " + + "numeric value will be applied; if the result is neither a boolean nor a numeric value, the tariff will not be applied. If the rule is not informed, the tariff " + + "value will be applied."; + + public static final String PARAMETER_DESCRIPTION_START_DATE_POSSIBLE_FORMATS = "The recommended format is \"yyyy-MM-dd'T'HH:mm:ssZ\" (e.g.: \"2023-01-01T12:00:00+0100\"); " + + "however, the following formats are also accepted: \"yyyy-MM-dd HH:mm:ss\" (e.g.: \"2023-01-01 12:00:00\") and \"yyyy-MM-dd\" (e.g.: \"2023-01-01\" - if the time is not " + + "added, it will be interpreted as \"00:00:00\"). If the recommended format is not used, the date will be considered in the server timezone."; + + public static final String PARAMETER_DESCRIPTION_END_DATE_POSSIBLE_FORMATS = "The recommended format is \"yyyy-MM-dd'T'HH:mm:ssZ\" (e.g.: \"2023-01-01T12:00:00+0100\"); " + + "however, the following formats are also accepted: \"yyyy-MM-dd HH:mm:ss\" (e.g.: \"2023-01-01 12:00:00\") and \"yyyy-MM-dd\" (e.g.: \"2023-01-01\" - if the time is not " + + "added, it will be interpreted as \"23:59:59\"). If the recommended format is not used, the date will be considered in the server timezone."; + + public static final String PARAMETER_DESCRIPTION_MAX_BACKUPS = "The maximum number of backups to keep for a VM. " + + "If \"0\", no retention policy will be applied and, thus, no backups from the schedule will be automatically deleted. " + + "This parameter is only supported for the Dummy, NAS and EMC Networker backup provider."; + + public static final String VMWARE_DC = "vmwaredc"; + + public static final String CSS = "css"; + + public static final String JSON_CONFIGURATION = "jsonconfiguration"; + + public static final String COMMON_NAMES = "commonnames"; + + public static final String COMMON_NAME = "commonname"; + + public static final String DOMAIN_IDS = "domainids"; + + public static final String SHOW_PUBLIC = "showpublic"; + + public static final String LIST_ONLY_DEFAULT_THEME = "listonlydefaulttheme"; + + public static final String RECURSIVE_DOMAINS = "recursivedomains"; + + public static final String VPN_CUSTOMER_GATEWAY_PARAMETERS = "vpncustomergatewayparameters"; + public static final String OBSOLETE_PARAMETERS = "obsoleteparameters"; + public static final String EXCLUDED_PARAMETERS = "excludedparameters"; + + /** + * This enum specifies IO Drivers, each option controls specific policies on I/O. + * Qemu guests support "threads" and "native" options Since 0.8.8 ; "io_uring" is supported Since 6.3.0 (QEMU 5.0). + */ + public enum IoDriverPolicy { + NATIVE("native"), + THREADS("threads"), + IO_URING("io_uring"), + STORAGE_SPECIFIC("storage_specific"); + + String ioDriver; + + IoDriverPolicy(String driver) { + ioDriver = driver; + } + + @Override + public String toString() { + return ioDriver; + } + } + + public enum BootType { + UEFI, BIOS; + + @Override + public String toString() { + return this.name(); + } + } + + public enum BootMode { + LEGACY, SECURE; + + @Override + public String toString() { + return this.name(); + } + } + + public enum HostDetails { + all, capacity, events, stats, min; + } + + public enum VMDetails { + all, group, nics, stats, secgrp, tmpl, servoff, diskoff, backoff, iso, volume, min, affgrp, vnfnics; + } + + public enum DomainDetails { + all, resource, min; + } + + public enum ExtensionDetails { + all, resource, external, min; + } + + public enum ApiKeyAccess { + DISABLED(false), + ENABLED(true), + INHERIT(null); + + Boolean apiKeyAccess; + + ApiKeyAccess(Boolean keyAccess) { + apiKeyAccess = keyAccess; + } + + public Boolean toBoolean() { + return apiKeyAccess; + } + + public static ApiKeyAccess fromBoolean(Boolean value) { + if (value == null) { + return INHERIT; + } else if (value) { + return ENABLED; + } else { + return DISABLED; + } + } + } +} 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 3284dbafe7ca..396418aaaa0c 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 @@ -1,305 +1,282 @@ -// 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.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.commons.lang.BooleanUtils; -import org.apache.commons.lang3.StringUtils; - -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; - -@APICommand(name = "importUnmanagedInstance", - description = "Import unmanaged Instance 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 { - - @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 name of the Instance as it is known to the hypervisor") - 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 Instance. 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, - description = "The ID of the Template for the Instance") - private Long templateId; - - @Parameter(name = ApiConstants.SERVICE_OFFERING_ID, - type = CommandType.UUID, - entityType = ServiceOfferingResponse.class, - required = true, - description = "The service offering for the Instance") - private Long serviceOfferingId; - - @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, ip4Address") - 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 = "Instance and its volumes are allowed to migrate to different host/pool when offerings passed are incompatible with current host/pool") - private Boolean migrateAllowed; - - @Parameter(name = ApiConstants.FORCED, - type = CommandType.BOOLEAN, - description = "Instance is imported despite some of its NIC's MAC addresses are already present, in case the MAC address exists then a new MAC address is generated") - private Boolean forced; - - ///////////////////////////////////////////////////// - /////////////////// 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 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); - logger.debug("Checking if NIC '{}' can be mapped on network '{}'", nic, networkUuid); - if (StringUtils.isAnyEmpty(nic, 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 = StringUtils.defaultIfEmpty(entry.get(VmDetailConstants.IP4_ADDRESS), null); - logger.debug("Checking if IP address '{}' can be mapped to NIC '{}'", ipAddress, nic); - if (StringUtils.isEmpty(nic)) { - throw new InvalidParameterValueException(String.format("NIC ID: '%s' is invalid for IP address mapping", nic)); - } - if (StringUtils.isEmpty(ipAddress)) { - throw new InvalidParameterValueException(String.format("Empty address for NIC ID: %s is invalid", nic)); - } - if (StringUtils.isNotEmpty(ipAddress) && !ipAddress.equals("auto") && !NetUtils.isValidIp4(ipAddress)) { - throw new InvalidParameterValueException(String.format("IP address '%s' for NIC ID: %s is invalid", ipAddress, nic)); - } - Network.IpAddresses ipAddresses = new Network.IpAddresses(ipAddress, null); - nicIpAddressMap.put(nic, ipAddresses); - } - } - return nicIpAddressMap; - } - - public Map getDataDiskToDiskOfferingList() { - Map dataDiskToDiskOfferingMap = new HashMap<>(); - if (MapUtils.isNotEmpty(dataDiskToDiskOfferingList)) { - for (Map entry : (Collection>)dataDiskToDiskOfferingList.values()) { - String disk = entry.get(VmDetailConstants.DISK); - String offeringUuid = entry.get(VmDetailConstants.DISK_OFFERING); - logger.trace("Checking if offering '{}' can be used on disk '{}'", offeringUuid, disk); - if (StringUtils.isAnyEmpty(disk, offeringUuid) || _entityMgr.findByUuid(DiskOffering.class, offeringUuid) == null) { - throw new InvalidParameterValueException(String.format("Disk offering ID: %s for disk ID: %s is invalid", offeringUuid, disk)); - } - dataDiskToDiskOfferingMap.put(disk, _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 Instance: " + name; - } - - public boolean isForced() { - return BooleanUtils.isTrue(forced); - } - - ///////////////////////////////////////////////////// - /////////////// 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 long getEntityOwnerId() { - Long accountId = _accountService.finalizeAccountId(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; - } -} +// 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.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.commons.lang.BooleanUtils; +import org.apache.commons.lang3.StringUtils; + +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; + +@APICommand(name = "importUnmanagedInstance", + description = "Import unmanaged Instance 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 { + + @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 name of the Instance as it is known to the hypervisor") + 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 Instance. 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, + description = "The ID of the Template for the Instance") + private Long templateId; + + @Parameter(name = ApiConstants.SERVICE_OFFERING_ID, + type = CommandType.UUID, + entityType = ServiceOfferingResponse.class, + required = true, + description = "The service offering for the Instance") + private Long serviceOfferingId; + + @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, ip4Address") + private Map nicIpAddressList; + + @Parameter(name = ApiConstants.NIC_MAC_ADDRESS_LIST, + type = CommandType.MAP, + description = "VM NIC to MAC address mapping using keys nic and mac. " + + "Example: nicmacaddresslist[0].nic=nic1&nicmacaddresslist[0].mac=aa:bb:cc:dd:ee:ff. " + + "Overrides the MAC address reported by the hypervisor for the given NIC.", + since = "4.21.0") + private Map nicMacAddressList; + + @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 = "Instance and its volumes are allowed to migrate to different host/pool when offerings passed are incompatible with current host/pool") + private Boolean migrateAllowed; + + @Parameter(name = ApiConstants.FORCED, + type = CommandType.BOOLEAN, + description = "Instance is imported despite some of its NIC's MAC addresses are already present, in case the MAC address exists then a new MAC address is generated") + private Boolean forced; + + ///////////////////////////////////////////////////// + /////////////////// 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 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); + logger.debug("Checking if NIC '{}' can be mapped on network '{}'", nic, networkUuid); + if (StringUtils.isAnyEmpty(nic, 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 = StringUtils.defaultIfEmpty(entry.get(VmDetailConstants.IP4_ADDRESS), null); + logger.debug("Checking if IP address '{}' can be mapped to NIC '{}'", ipAddress, nic); + if (StringUtils.isEmpty(nic)) { + throw new InvalidParameterValueException(String.format("NIC ID: '%s' is invalid for IP address mapping", nic)); + } + if (StringUtils.isEmpty(ipAddress)) { + throw new InvalidParameterValueException(String.format("Empty address for NIC ID: %s is invalid", nic)); + } + if (StringUtils.isNotEmpty(ipAddress) && !ipAddress.equals("auto") && !NetUtils.isValidIp4(ipAddress)) { + throw new InvalidParameterValueException(String.format("IP address '%s' for NIC ID: %s is invalid", ipAddress, nic)); + } + Network.IpAddresses ipAddresses = new Network.IpAddresses(ipAddress, null); + nicIpAddressMap.put(nic, ipAddresses); + } + } + return nicIpAddressMap; + } + + public Map getNicMacAddressList() { + Map nicMacMap = new HashMap<>(); + if (MapUtils.isEmpty(nicMacAddressList)) { + return nicMacMap; + } + for (Map entry : (Collection>) nicMacAddressList.values()) { + String nic = entry.get(VmDetailConstants.NIC); + String mac = entry.get(VmDetailConstants.NIC_MAC_ADDRESS); + logger.debug("Checking if MAC address '{}' can be mapped to NIC '{}'", mac, nic); + if (StringUtils.isEmpty(nic)) { + throw new InvalidParameterValueException(String.format("NIC ID: '%s' is invalid for MAC address mapping", nic)); + } + if (StringUtils.isEmpty(mac)) { + throw new InvalidParameterValueException(String.format("Empty MAC address for NIC ID: %s is invalid", nic)); + } + if (!NetUtils.isValidMac(mac)) { + throw new InvalidParameterValueException(String.format("MAC address '%s' for NIC ID: %s is not valid", mac, nic)); + } + if (!NetUtils.isUnicastMac(mac)) { + throw new InvalidParameterValueException(String.format("MAC address '%s' for NIC ID: %s is not a unicast address", mac, nic)); + } + nicMacMap.put(nic, NetUtils.standardizeMacAddress(mac)); + } + return nicMacMap; + } + + public Map getDataDiskToDiskOfferingList() { + Map dataDiskToDiskOfferingMap = new HashMap<>(); + if (MapUtils.isNotEmpty(dataDiskToDiskOfferingList)) { + for (Map entry : (Collection>)dataDiskToDiskOfferingList.values()) { + String disk = entry.get(VmDetailConstants.DISK); + String offeringUuid = entry.get(VmDetailConstants.DISK_OFFERING); + logger.trace("Checking if offering '{}' can be used on disk '{}'", offeringUuid, disk); + if (StringUtils.isAnyEmpty(disk, offeringUuid) || _entityMgr.findByUuid(DiskOffering.class, offeringUuid) == null) { + throw new InvalidParameterValueException(String.format("Disk offering ID: %s for disk ID: %s is invalid", offeringUuid, disk)); + } + dataDiskToDiskOfferingMap.put(disk, _entityMgr.findByUuid(DiskOffering.class, offeringUuid).getId()); + \ No newline at end of file diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmdTest.java new file mode 100644 index 000000000000..a37129f30d25 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmdTest.java @@ -0,0 +1,139 @@ +// 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.LinkedHashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.vm.VmDetailConstants; + +@RunWith(MockitoJUnitRunner.class) +public class ImportUnmanagedInstanceCmdTest { + + private ImportUnmanagedInstanceCmd buildCmd(Map nicMacAddressList) { + ImportUnmanagedInstanceCmd cmd = new ImportUnmanagedInstanceCmd(); + ReflectionTestUtils.setField(cmd, "nicMacAddressList", nicMacAddressList); + return cmd; + } + + private Map entry(String nic, String mac) { + Map e = new LinkedHashMap<>(); + if (nic != null) { + e.put(VmDetailConstants.NIC, nic); + } + if (mac != null) { + e.put(VmDetailConstants.NIC_MAC_ADDRESS, mac); + } + return e; + } + + @Test + public void testGetNicMacAddressListNullReturnsEmpty() { + ImportUnmanagedInstanceCmd cmd = buildCmd(null); + Map result = cmd.getNicMacAddressList(); + Assert.assertNotNull(result); + Assert.assertTrue(result.isEmpty()); + } + + @Test + public void testGetNicMacAddressListEmptyMapReturnsEmpty() { + ImportUnmanagedInstanceCmd cmd = buildCmd(new LinkedHashMap<>()); + Assert.assertTrue(cmd.getNicMacAddressList().isEmpty()); + } + + @Test + public void testGetNicMacAddressListValidMac() { + Map outer = new LinkedHashMap<>(); + outer.put("0", entry("nic1", "AA:BB:CC:DD:EE:FF")); + ImportUnmanagedInstanceCmd cmd = buildCmd(outer); + + Map result = cmd.getNicMacAddressList(); + + Assert.assertEquals(1, result.size()); + // standardizeMacAddress lowercases the address + Assert.assertEquals("aa:bb:cc:dd:ee:ff", result.get("nic1")); + } + + @Test + public void testGetNicMacAddressListMultipleNics() { + Map outer = new LinkedHashMap<>(); + outer.put("0", entry("nic1", "aa:bb:cc:dd:ee:01")); + outer.put("1", entry("nic2", "aa:bb:cc:dd:ee:02")); + ImportUnmanagedInstanceCmd cmd = buildCmd(outer); + + Map result = cmd.getNicMacAddressList(); + + Assert.assertEquals(2, result.size()); + Assert.assertEquals("aa:bb:cc:dd:ee:01", result.get("nic1")); + Assert.assertEquals("aa:bb:cc:dd:ee:02", result.get("nic2")); + } + + @Test(expected = InvalidParameterValueException.class) + public void testGetNicMacAddressListInvalidMacFormat() { + Map outer = new LinkedHashMap<>(); + outer.put("0", entry("nic1", "not-a-mac")); + buildCmd(outer).getNicMacAddressList(); + } + + @Test(expected = InvalidParameterValueException.class) + public void testGetNicMacAddressListBroadcastMacRejected() { + // FF:FF:FF:FF:FF:FF is a broadcast (non-unicast) address + Map outer = new LinkedHashMap<>(); + outer.put("0", entry("nic1", "FF:FF:FF:FF:FF:FF")); + buildCmd(outer).getNicMacAddressList(); + } + + @Test(expected = InvalidParameterValueException.class) + public void testGetNicMacAddressListMulticastMacRejected() { + // Bit 0 of first octet set → multicast, not unicast + Map outer = new LinkedHashMap<>(); + outer.put("0", entry("nic1", "01:bb:cc:dd:ee:ff")); + buildCmd(outer).getNicMacAddressList(); + } + + @Test(expected = InvalidParameterValueException.class) + public void testGetNicMacAddressListEmptyNicIdRejected() { + Map outer = new LinkedHashMap<>(); + outer.put("0", entry("", "aa:bb:cc:dd:ee:ff")); + buildCmd(outer).getNicMacAddressList(); + } + + @Test(expected = InvalidParameterValueException.class) + public void testGetNicMacAddressListEmptyMacRejected() { + Map outer = new LinkedHashMap<>(); + outer.put("0", entry("nic1", "")); + buildCmd(outer).getNicMacAddressList(); + } + + @Test(expected = InvalidParameterValueException.class) + public void testGetNicMacAddressListNullMacRejected() { + Map outer = new LinkedHashMap<>(); + // entry without mac key + Map e = new LinkedHashMap<>(); + e.put(VmDetailConstants.NIC, "nic1"); + outer.put("0", e); + buildCmd(outer).getNicMacAddressList(); + } +} diff --git a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java index 846eab599fd1..07e965fd6fb6 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java @@ -1,3183 +1,3177 @@ -// 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 com.cloud.agent.AgentManager; -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.CheckConvertInstanceAnswer; -import com.cloud.agent.api.CheckConvertInstanceCommand; -import com.cloud.agent.api.CheckVolumeAnswer; -import com.cloud.agent.api.CheckVolumeCommand; -import com.cloud.agent.api.ConvertInstanceAnswer; -import com.cloud.agent.api.ConvertInstanceCommand; -import com.cloud.agent.api.CopyRemoteVolumeAnswer; -import com.cloud.agent.api.CopyRemoteVolumeCommand; -import com.cloud.agent.api.GetRemoteVmsAnswer; -import com.cloud.agent.api.GetRemoteVmsCommand; -import com.cloud.agent.api.GetUnmanagedInstancesAnswer; -import com.cloud.agent.api.GetUnmanagedInstancesCommand; -import com.cloud.agent.api.ImportConvertedInstanceAnswer; -import com.cloud.agent.api.ImportConvertedInstanceCommand; -import com.cloud.agent.api.PrepareUnmanageVMInstanceAnswer; -import com.cloud.agent.api.PrepareUnmanageVMInstanceCommand; -import com.cloud.agent.api.to.DataStoreTO; -import com.cloud.agent.api.to.RemoteInstanceTO; -import com.cloud.agent.api.to.StorageFilerTO; -import com.cloud.configuration.Config; -import com.cloud.configuration.Resource; -import com.cloud.dc.DataCenter; -import com.cloud.dc.DataCenterVO; -import com.cloud.dc.VmwareDatacenterVO; -import com.cloud.dc.dao.ClusterDao; -import com.cloud.dc.dao.DataCenterDao; -import com.cloud.dc.dao.VmwareDatacenterDao; -import com.cloud.deploy.DataCenterDeployment; -import com.cloud.deploy.DeployDestination; -import com.cloud.deploy.DeploymentPlanner; -import com.cloud.deploy.DeploymentPlanningManager; -import com.cloud.event.ActionEvent; -import com.cloud.event.ActionEventUtils; -import com.cloud.event.EventTypes; -import com.cloud.event.EventVO; -import com.cloud.event.UsageEventUtils; -import com.cloud.exception.AgentUnavailableException; -import com.cloud.exception.InsufficientAddressCapacityException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.InsufficientVirtualNetworkCapacityException; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.OperationTimedoutException; -import com.cloud.exception.PermissionDeniedException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.UnsupportedServiceException; -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.hypervisor.HypervisorGuru; -import com.cloud.hypervisor.HypervisorGuruManager; -import com.cloud.network.Network; -import com.cloud.network.NetworkModel; -import com.cloud.network.Networks; -import com.cloud.network.PhysicalNetwork; -import com.cloud.network.dao.NetworkDao; -import com.cloud.network.dao.NetworkVO; -import com.cloud.network.dao.PhysicalNetworkDao; -import com.cloud.offering.DiskOffering; -import com.cloud.offering.NetworkOffering; -import com.cloud.offering.ServiceOffering; -import com.cloud.offerings.NetworkOfferingVO; -import com.cloud.offerings.dao.NetworkOfferingDao; -import com.cloud.org.Cluster; -import com.cloud.resource.ResourceManager; -import com.cloud.resource.ResourceState; -import com.cloud.resourcelimit.CheckedReservation; -import com.cloud.resourcelimit.ReservationHelper; -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.DataStoreRole; -import com.cloud.storage.DiskOfferingVO; -import com.cloud.storage.GuestOS; -import com.cloud.storage.GuestOSHypervisor; -import com.cloud.storage.ScopeType; -import com.cloud.storage.Snapshot; -import com.cloud.storage.SnapshotVO; -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.SnapshotDao; -import com.cloud.storage.dao.StoragePoolHostDao; -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.LogUtils; -import com.cloud.utils.Pair; -import com.cloud.utils.UuidUtils; -import com.cloud.utils.db.EntityManager; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.net.NetUtils; -import com.cloud.vm.DiskProfile; -import com.cloud.vm.NicProfile; -import com.cloud.vm.NicVO; -import com.cloud.vm.UserVmManager; -import com.cloud.vm.UserVmVO; -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.UserVmDao; -import com.cloud.vm.dao.VMInstanceDetailsDao; -import com.cloud.vm.dao.VMInstanceDao; -import com.google.gson.Gson; -import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.cloudstack.api.ApiConstants; -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.ImportVmCmd; -import org.apache.cloudstack.api.command.admin.vm.ListImportVMTasksCmd; -import org.apache.cloudstack.api.command.admin.vm.ListUnmanagedInstancesCmd; -import org.apache.cloudstack.api.command.admin.vm.ListVmsForImportCmd; -import org.apache.cloudstack.api.command.admin.vm.UnmanageVMInstanceCmd; -import org.apache.cloudstack.api.response.ListResponse; -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.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; -import org.apache.cloudstack.framework.config.ConfigKey; -import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.cloudstack.reservation.dao.ReservationDao; -import org.apache.cloudstack.resourcelimit.Reserver; -import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; -import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.cloudstack.storage.volume.VolumeOnStorageTO; -import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.collections.MapUtils; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.commons.lang3.ObjectUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import javax.inject.Inject; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.stream.Collectors; - -import static org.apache.cloudstack.api.ApiConstants.MAX_IOPS; -import static org.apache.cloudstack.api.ApiConstants.MIN_IOPS; -import static org.apache.cloudstack.storage.volume.VolumeImportUnmanageService.AllowImportVolumeWithBackingFile; -import static org.apache.cloudstack.vm.ImportVmTask.Step.CloningInstance; -import static org.apache.cloudstack.vm.ImportVmTask.Step.Completed; -import static org.apache.cloudstack.vm.ImportVmTask.Step.ConvertingInstance; -import static org.apache.cloudstack.vm.ImportVmTask.Step.Importing; - -public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { - protected Logger logger = LogManager.getLogger(UnmanagedVMsManagerImpl.class); - private static final long OTHER_LINUX_64_GUEST_OS_ID = 99; - private static final List importUnmanagedInstancesSupportedHypervisors = - Arrays.asList(Hypervisor.HypervisorType.VMware, Hypervisor.HypervisorType.KVM); - - private static final List forceConvertToPoolAllowedTypes = - Arrays.asList(Storage.StoragePoolType.NetworkFilesystem, Storage.StoragePoolType.Filesystem, - Storage.StoragePoolType.SharedMountPoint); - private static final String DETAIL_VDDK_TRANSPORTS = "vddk.transports"; - private static final String DETAIL_VDDK_THUMBPRINT = "vddk.thumbprint"; - - ConfigKey ConvertVmwareInstanceToKvmExtraParamsAllowed = new ConfigKey<>(Boolean.class, - "convert.vmware.instance.to.kvm.extra.params.allowed", - "Advanced", - "false", - "Disabled by default. If enabled, allows extra parameters to be passed to the virt-v2v binary on KVM conversion hosts", - true, - ConfigKey.Scope.Global, - null); - - ConfigKey ConvertVmwareInstanceToKvmExtraParamsAllowedList = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED, - String.class, - "convert.vmware.instance.to.kvm.extra.params.allowed.list", - "", - "Comma separated list of allowed extra parameters to be passed to the virt-v2v binary on KVM conversion hosts", - true, - ConfigKey.Kind.CSV, - null); - - @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 ReservationDao reservationDao; - @Inject - private VMInstanceDetailsDao vmInstanceDetailsDao; - @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 VolumeApiService volumeApiService; - @Inject - private DeploymentPlanningManager deploymentPlanningManager; - @Inject - private VirtualMachineManager virtualMachineManager; - @Inject - private ManagementService managementService; - @Inject - private NicDao nicDao; - @Inject - private NetworkModel networkModel; - @Inject - private ConfigurationDao configurationDao; - @Inject - private GuestOSDao guestOSDao; - @Inject - private GuestOSHypervisorDao guestOSHypervisorDao; - @Inject - private SnapshotDao snapshotDao; - @Inject - private UserVmDao userVmDao; - @Inject - private NetworkOfferingDao networkOfferingDao; - @Inject - EntityManager entityMgr; - @Inject - private NetworkOrchestrationService networkMgr; - @Inject - private PhysicalNetworkDao physicalNetworkDao; - @Inject - private StoragePoolHostDao storagePoolHostDao; - @Inject - private HypervisorGuruManager hypervisorGuruManager; - @Inject - private VmwareDatacenterDao vmwareDatacenterDao; - @Inject - private ImageStoreDao imageStoreDao; - @Inject - private DataStoreManager dataStoreManager; - @Inject - private ImportVmTasksManager importVmTasksManager; - - protected Gson gson; - - public UnmanagedVMsManagerImpl() { - gson = GsonHelper.getGsonLogger(); - } - - private VMTemplateVO createDefaultDummyVmImportTemplate(boolean isKVM) { - String templateName = (isKVM) ? KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME : VM_IMPORT_DEFAULT_TEMPLATE_NAME; - VMTemplateVO template = null; - try { - template = VMTemplateVO.createSystemIso(templateDao.getNextInSequence(Long.class, "id"), templateName, templateName, true, - "", true, 64, Account.ACCOUNT_ID_SYSTEM, "", - "VM Import Default Template", false, OTHER_LINUX_64_GUEST_OS_ID); - template.setState(VirtualMachineTemplate.State.Inactive); - template = templateDao.persist(template); - if (template == null) { - return null; - } - templateDao.remove(template.getId()); - template = templateDao.findByName(templateName); - } catch (Exception e) { - logger.error("Unable to create default dummy template for VM import", e); - } - return template; - } - - private List getAdditionalNameFilters(Cluster cluster) { - List additionalNameFilter = new ArrayList<>(); - if (cluster == null) { - return additionalNameFilter; - } - 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 (StringUtils.isEmpty(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 (StringUtils.isNotEmpty(path)) { - if (!additionalNameFilter.contains(path)) { - volumeFileNames.add(path); - } - if (path.contains("-")) { - split = path.split("-"); - path = split[0]; - if (StringUtils.isNotEmpty(path) && !path.equals("ROOT") && !additionalNameFilter.contains(path)) { - volumeFileNames.add(path); - } - } - } - } - } catch (Exception e) { - logger.warn("Unable to find volume file name for volume: {} while adding filters unmanaged VMs", volumeVO, e); - } - if (!volumeFileNames.isEmpty()) { - additionalNameFilter.addAll(volumeFileNames); - } - } - } - return additionalNameFilter; - } - - private List getHostsManagedVms(List hosts) { - if (CollectionUtils.isEmpty(hosts)) { - return new ArrayList<>(); - } - List instances = vmDao.listByHostOrLastHostOrHostPod(hosts.stream().map(HostVO::getId).collect(Collectors.toList()), hosts.get(0).getPodId()); - List managedVms = instances.stream().map(VMInstanceVO::getInstanceName).collect(Collectors.toList()); - return managedVms; - } - - private boolean hostSupportsServiceOfferingAndTemplate(HostVO host, ServiceOffering serviceOffering, VirtualMachineTemplate template) { - if (StringUtils.isAllEmpty(serviceOffering.getHostTag(), template.getTemplateTag())) { - return true; - } - hostDao.loadHostTags(host); - return host.checkHostServiceOfferingAndTemplateTags(serviceOffering, template, UserVmManager.getStrictHostTags()); - } - - private boolean storagePoolSupportsDiskOffering(StoragePool pool, DiskOffering diskOffering) { - if (pool == null) { - return false; - } - if (diskOffering == null) { - return false; - } - return volumeApiService.doesStoragePoolSupportDiskOffering(pool, diskOffering); - } - - private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedInstanceTO instance, ServiceOfferingVO serviceOffering, final Account owner, final DataCenter zone, final Map details, Hypervisor.HypervisorType hypervisorType) - throws ServerApiException, PermissionDeniedException, ResourceAllocationException { - if (instance == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Cannot find VM to import."); - } - if (serviceOffering == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Cannot find service offering used to import VM [%s].", instance.getName())); - } - 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 [%s] is not valid for importing VM [%s].", cpu, instance.getName())); - } - if (memory == null || memory == 0) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Memory [%s] is not valid for importing VM [%s].", memory, instance.getName())); - } - - if (serviceOffering.isDynamic()) { - if (details.containsKey(VmDetailConstants.CPU_SPEED)) { - try { - cpuSpeed = Integer.parseInt(details.get(VmDetailConstants.CPU_SPEED)); - } catch (Exception e) { - logger.error("Failed to get CPU speed for importing VM [{}] due to [{}].", instance, e.getMessage(), e); - } - } - 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(UnmanagedInstanceTO.PowerState.PowerOff)) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %d CPU cores do not match 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(UnmanagedInstanceTO.PowerState.PowerOff)) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %dMB memory does not match VM memory %dMB and VM is not in powered off state (Power state: %s)", serviceOffering.getUuid(), serviceOffering.getRamSize(), memory, instance.getPowerState())); - } - if (hypervisorType == Hypervisor.HypervisorType.VMware && 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 match VM CPU speed %dMHz and VM is not in powered off state (Power state: %s)", serviceOffering.getUuid(), serviceOffering.getSpeed(), cpuSpeed, instance.getPowerState())); - } - } - return serviceOffering; - } - - private Map getNicIpAddresses(final List nics, final Map callerNicIpAddressMap) { - Map nicIpAddresses = new HashMap<>(); - for (UnmanagedInstanceTO.Nic nic : nics) { - Network.IpAddresses ipAddresses = null; - if (MapUtils.isNotEmpty(callerNicIpAddressMap) && callerNicIpAddressMap.containsKey(nic.getNicId())) { - ipAddresses = callerNicIpAddressMap.get(nic.getNicId()); - } - // If IP is set to auto-assign, check NIC doesn't have more that one IP from SDK - if (ipAddresses != null && ipAddresses.getIp4Address() != null && ipAddresses.getIp4Address().equals("auto") && !CollectionUtils.isEmpty(nic.getIpAddress())) { - if (nic.getIpAddress().size() > 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())); - } - String address = nic.getIpAddress().get(0); - if (NetUtils.isValidIp4(address)) { - ipAddresses.setIp4Address(address); - } - } - if (ipAddresses != null) { - nicIpAddresses.put(nic.getNicId(), ipAddresses); - } - } - return nicIpAddresses; - } - - private StoragePool getStoragePool(final UnmanagedInstanceTO.Disk disk, final DataCenter zone, final Cluster cluster, DiskOffering diskOffering) { - StoragePool storagePool = null; - final String dsHost = disk.getDatastoreHost(); - final String dsPath = disk.getDatastorePath(); - final String dsType = disk.getDatastoreType(); - final String dsName = disk.getDatastoreName(); - if (dsType != null) { - List pools = primaryDataStoreDao.listPoolByHostPath(dsHost, dsPath); - for (StoragePool pool : pools) { - if (pool.getDataCenterId() == zone.getId() && - (pool.getClusterId() == null || pool.getClusterId().equals(cluster.getId())) && - volumeApiService.doesStoragePoolSupportDiskOffering(pool, diskOffering)) { - storagePool = pool; - break; - } - } - } - - if (storagePool == null) { - Set pools = new HashSet<>(primaryDataStoreDao.listPoolsByCluster(cluster.getId())); - pools.addAll(primaryDataStoreDao.listByDataCenterId(zone.getId())); - boolean isNameUuid = StringUtils.isNotBlank(dsName) && UuidUtils.isUuid(dsName); - for (StoragePool pool : pools) { - String searchPoolParam = StringUtils.isNotBlank(dsPath) ? dsPath : dsName; - if ((StringUtils.contains(pool.getPath(), searchPoolParam) || isNameUuid && pool.getUuid().equals(dsName)) && - volumeApiService.doesStoragePoolSupportDiskOffering(pool, diskOffering)) { - 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; - } - - private Pair> getRootAndDataDisks( - List disks, - final Map dataDiskOfferingMap) { - UnmanagedInstanceTO.Disk rootDisk = null; - List dataDisks = new ArrayList<>(); - - Set callerDiskIds = dataDiskOfferingMap.keySet(); - if (callerDiskIds.size() != disks.size() - 1) { - String msg = String.format("VM has total %d disks for which %d disk offering mappings provided. %d disks need a disk offering for import", disks.size(), callerDiskIds.size(), disks.size() - 1); - logger.error(String.format("%s. %s parameter can be used to provide disk offerings for the disks", msg, ApiConstants.DATADISK_OFFERING_LIST)); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, msg); - } - List diskIdsWithoutOffering = new ArrayList<>(); - for (UnmanagedInstanceTO.Disk disk : disks) { - String diskId = disk.getDiskId(); - if (!callerDiskIds.contains(diskId)) { - diskIdsWithoutOffering.add(diskId); - rootDisk = disk; - } else { - dataDisks.add(disk); - DiskOffering diskOffering = diskOfferingDao.findById(dataDiskOfferingMap.getOrDefault(disk.getDiskId(), null)); - if ((disk.getCapacity() == null || disk.getCapacity() <= 0) && diskOffering != null) { - disk.setCapacity(diskOffering.getDiskSize()); - } - } - } - if (diskIdsWithoutOffering.size() > 1 || rootDisk == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM has total %d disks, disk offering mapping not provided for %d disks. Disk IDs that may need a disk offering - %s", disks.size(), diskIdsWithoutOffering.size() - 1, String.join(", ", diskIdsWithoutOffering))); - } - - return new Pair<>(rootDisk, dataDisks); - } - - private void checkUnmanagedDiskAndOfferingForImport(String instanceName, UnmanagedInstanceTO.Disk disk, DiskOffering diskOffering, ServiceOffering serviceOffering, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed, List reservations) - throws ServerApiException, PermissionDeniedException, ResourceAllocationException { - if (serviceOffering == null && diskOffering == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID [%s] not found during VM [%s] import.", disk.getDiskId(), instanceName)); - } - if (diskOffering != null) { - accountService.checkAccess(owner, diskOffering, zone); - } - 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 != 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 != 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)))); - } - diskOffering = diskOffering != null ? diskOffering : diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); - StoragePool storagePool = getStoragePool(disk, zone, cluster, 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())); - } - resourceLimitService.checkVolumeResourceLimit(owner, true, disk.getCapacity(), diskOffering, reservations); - } - - private void checkUnmanagedDiskAndOfferingForImport(String intanceName, List disks, final Map diskOfferingMap, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed, List reservations) - throws ServerApiException, PermissionDeniedException, ResourceAllocationException { - String diskController = null; - for (UnmanagedInstanceTO.Disk disk : disks) { - if (disk == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve disk details for VM [%s].", intanceName)); - } - 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 (StringUtils.isEmpty(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 data disk controllers are of the same type", diskController, disk.getController())); - } - } - checkUnmanagedDiskAndOfferingForImport(intanceName, disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), null, owner, zone, cluster, migrateAllowed, reservations); - } - } - - private void checkUnmanagedNicAndNetworkForImport(String instanceName, UnmanagedInstanceTO.Nic nic, Network network, final DataCenter zone, final Account owner, final boolean autoAssign, Hypervisor.HypervisorType hypervisorType) throws ServerApiException { - basicNetworkChecks(instanceName, nic, network); - 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 (!autoAssign && network.getGuestType().equals(Network.GuestType.Isolated)) { - return; - } - checksOnlyNeededForVmware(nic, network, hypervisorType); - } - - private void checksOnlyNeededForVmware(UnmanagedInstanceTO.Nic nic, Network network, final Hypervisor.HypervisorType hypervisorType) { - if (hypervisorType == Hypervisor.HypervisorType.VMware) { - String networkBroadcastUri = network.getBroadcastUri() == null ? null : network.getBroadcastUri().toString(); - if (nic.getVlan() != null && nic.getVlan() != 0 && nic.getPvlan() == null && - (StringUtils.isEmpty(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())); - } - String pvLanType = nic.getPvlanType() == null ? "" : nic.getPvlanType().toLowerCase().substring(0, 1); - if (nic.getVlan() != null && nic.getVlan() != 0 && nic.getPvlan() != null && nic.getPvlan() != 0 && - (StringUtils.isEmpty(networkBroadcastUri) || !String.format("pvlan://%d-%s%d", nic.getVlan(), pvLanType, nic.getPvlan()).equals(networkBroadcastUri))) { - 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-%s%d during VM import", network.getUuid(), networkBroadcastUri, nic.getNicId(), nic.getVlan(), pvLanType, nic.getPvlan())); - } - } - } - - private void basicNetworkChecks(String instanceName, UnmanagedInstanceTO.Nic nic, Network network) { - if (nic == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve the NIC details used by VM [%s] from VMware. Please check if this VM have NICs in VMWare.", instanceName)); - } - if (network == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import.", nic.getNicId())); - } - } - - private void checkUnmanagedNicAndNetworkHostnameForImport(String instanceName, UnmanagedInstanceTO.Nic nic, Network network, final String hostName) throws ServerApiException { - basicNetworkChecks(instanceName, nic, network); - // 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(String.format("VM with Name [%s] already exists in the network [%s] domain [%s]. Cannot import another VM with the same name. Please try again with a different name.", hostName, network, network.getNetworkDomain())); - } - } - - private void checkUnmanagedNicIpAndNetworkForImport(String instanceName, UnmanagedInstanceTO.Nic nic, Network network, final Network.IpAddresses ipAddresses) throws ServerApiException { - basicNetworkChecks(instanceName, nic, network); - // Check IP is assigned for non L2 networks - if (!network.getGuestType().equals(Network.GuestType.L2) && (ipAddresses == null || StringUtils.isEmpty(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 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 && StringUtils.isNotEmpty(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())); - } - } - } - - private Map getUnmanagedNicNetworkMap(String instanceName, List nics, final Map callerNicNetworkMap, - final Map callerNicIpAddressMap, final DataCenter zone, final String hostName, - final Account owner, Hypervisor.HypervisorType hypervisorType) throws ServerApiException { - Map nicNetworkMap = new HashMap<>(); - String nicAdapter = null; - for (int i = 0; i < nics.size(); i++) { - UnmanagedInstanceTO.Nic nic = nics.get(i); - if (StringUtils.isEmpty(nicAdapter)) { - 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())); - } - } - 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 && nic.getVlan() != 0) { - // 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(instanceName, nic, networkVO, zone, owner, true, hypervisorType); - network = networkVO; - } catch (Exception e) { - logger.error(String.format("Error when checking NIC [%s] of unmanaged instance to import due to [%s].", nic.getNicId(), e.getMessage()), e); - } - if (network != null) { - checkUnmanagedNicAndNetworkHostnameForImport(instanceName, nic, network, hostName); - checkUnmanagedNicIpAndNetworkForImport(instanceName, nic, network, ipAddresses); - break; - } - } - } - } else { - network = networkDao.findById(callerNicNetworkMap.get(nic.getNicId())); - boolean autoImport = false; - if (hypervisorType == Hypervisor.HypervisorType.KVM) { - autoImport = ipAddresses != null && ipAddresses.getIp4Address() != null && ipAddresses.getIp4Address().equalsIgnoreCase("auto"); - } - checkUnmanagedNicAndNetworkForImport(instanceName, nic, network, zone, owner, autoImport, hypervisorType); - checkUnmanagedNicAndNetworkHostnameForImport(instanceName, nic, network, hostName); - checkUnmanagedNicIpAndNetworkForImport(instanceName, 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())); - } - nicNetworkMap.put(nic.getNicId(), network.getId()); - } - return nicNetworkMap; - } - - private Pair importExternalDisk(UnmanagedInstanceTO.Disk disk, VirtualMachine vm, DeployDestination dest, DiskOffering diskOffering, - Volume.Type type, VirtualMachineTemplate template,Long deviceId, String remoteUrl, String username, String password, - String tmpPath, DiskProfile diskProfile) { - final String path = StringUtils.isEmpty(disk.getDatastorePath()) ? disk.getImagePath() : disk.getDatastorePath(); - String chainInfo = disk.getChainInfo(); - if (StringUtils.isEmpty(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); - } - Map storage = dest.getStorageForDisks(); - Volume volume = volumeDao.findById(diskProfile.getVolumeId()); - StoragePool storagePool = storage.get(volume); - CopyRemoteVolumeCommand copyRemoteVolumeCommand = new CopyRemoteVolumeCommand(); - copyRemoteVolumeCommand.setRemoteIp(remoteUrl); - copyRemoteVolumeCommand.setUsername(username); - copyRemoteVolumeCommand.setPassword(password); - copyRemoteVolumeCommand.setSrcFile(path); - StorageFilerTO storageTO = new StorageFilerTO(storagePool); - copyRemoteVolumeCommand.setStorageFilerTO(storageTO); - if(tmpPath == null || tmpPath.length() < 1) { - tmpPath = "/tmp/"; - } else { - // Add / if path doesn't end with / - if(tmpPath.charAt(tmpPath.length() - 1) != '/') { - tmpPath += "/"; - } - } - copyRemoteVolumeCommand.setTempPath(tmpPath); - int copyTimeout = UnmanagedVMsManager.RemoteKvmInstanceDisksCopyTimeout.value(); - if (copyTimeout <= 0) { - copyTimeout = Integer.valueOf(UnmanagedVMsManager.RemoteKvmInstanceDisksCopyTimeout.defaultValue()); - } - int copyTimeoutInSecs = copyTimeout * 60; - copyRemoteVolumeCommand.setWait(copyTimeoutInSecs); - logger.error(String.format("Initiating copy remote volume %s from %s, timeout %d secs", path, remoteUrl, copyTimeoutInSecs)); - Answer answer = agentManager.easySend(dest.getHost().getId(), copyRemoteVolumeCommand); - if (!(answer instanceof CopyRemoteVolumeAnswer)) { - throw new CloudRuntimeException("Error while copying volume of remote instance: " + answer.getDetails()); - } - CopyRemoteVolumeAnswer copyRemoteVolumeAnswer = (CopyRemoteVolumeAnswer) answer; - checkVolume(copyRemoteVolumeAnswer.getVolumeDetails()); - if (!copyRemoteVolumeAnswer.getResult()) { - throw new CloudRuntimeException("Unable to copy volume of remote instance"); - } - diskProfile.setSize(copyRemoteVolumeAnswer.getSize()); - DiskProfile profile = volumeManager.updateImportedVolume(type, diskOffering, vm, template, deviceId, - storagePool.getId(), storagePool.getPoolType(), copyRemoteVolumeAnswer.getFilename(), chainInfo, diskProfile); - - return new Pair<>(profile, storagePool); - } - - private Pair importKVMLocalDisk(VirtualMachine vm, DiskOffering diskOffering, - Volume.Type type, VirtualMachineTemplate template, - Long deviceId, Long hostId, String diskPath, DiskProfile diskProfile) { - List storagePools = primaryDataStoreDao.findLocalStoragePoolsByHostAndTags(hostId, null); - if(storagePools.size() < 1) { - throw new CloudRuntimeException("Local Storage not found for host"); - } - - StoragePool storagePool = storagePools.get(0); - - DiskProfile profile = volumeManager.updateImportedVolume(type, diskOffering, vm, template, deviceId, - storagePool.getId(), storagePool.getPoolType(), diskPath, null, diskProfile); - - return new Pair<>(profile, storagePool); - } - - private Pair importKVMSharedDisk(VirtualMachine vm, DiskOffering diskOffering, - Volume.Type type, VirtualMachineTemplate template, - Long deviceId, Long poolId, String diskPath, DiskProfile diskProfile) { - StoragePool storagePool = primaryDataStoreDao.findById(poolId); - - DiskProfile profile = volumeManager.updateImportedVolume(type, diskOffering, vm, template, deviceId, - poolId, storagePool.getPoolType(), diskPath, null, diskProfile); - - return new Pair<>(profile, storagePool); - } - - private Pair importDisk(UnmanagedInstanceTO.Disk disk, VirtualMachine vm, Cluster cluster, DiskOffering diskOffering, - 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 = StringUtils.isEmpty(disk.getFileBaseName()) ? disk.getImagePath() : disk.getFileBaseName(); - String chainInfo = disk.getChainInfo(); - if (vm.getHypervisorType() == Hypervisor.HypervisorType.VMware && StringUtils.isEmpty(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, diskOffering); - DiskProfile profile = volumeManager.importVolume(type, name, diskOffering, diskSize, - minIops, maxIops, vm.getDataCenterId(), vm.getHypervisorType(), vm, template, owner, deviceId, storagePool.getId(), storagePool.getPoolType(), path, chainInfo); - - return new Pair(profile, storagePool); - } - - private NicProfile importNic(UnmanagedInstanceTO.Nic nic, VirtualMachine vm, Network network, Network.IpAddresses ipAddresses, int deviceId, boolean isDefaultNic, boolean forced) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException { - DataCenterVO dataCenterVO = dataCenterDao.findById(network.getDataCenterId()); - Pair result = networkOrchestrationService.importNic(nic.getMacAddress(), deviceId, network, isDefaultNic, vm, ipAddresses, dataCenterVO, forced); - if (result == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC ID: %s import failed", nic.getNicId())); - } - return result.first(); - } - - 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 - try { - networkOrchestrationService.release(profile, true); - } catch (Exception e) { - logger.error("Unable to release NICs for unsuccessful import unmanaged VM: {}", userVm, e); - nicDao.removeNicsForInstance(userVm.getId()); - } - // Remove vm - vmDao.remove(userVm.getId()); - } - - 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")); - } - if (sourceHost == null || serviceOffering == null || diskProfileStoragePoolList == null) { - logger.error(String.format("Failed to check migrations need during import, VM: %s", userVm)); - cleanupFailedImportVM(vm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to check migrations need during import, VM: %s", userVm.getInstanceName())); - } - if (!hostSupportsServiceOfferingAndTemplate(sourceHost, serviceOffering, template)) { - logger.debug("VM {} needs to be migrated", vm); - final VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm, template, serviceOffering, owner, null); - profile.setServiceOffering(serviceOfferingDao.findById(vm.getId(), serviceOffering.getId())); - 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) { - String errorMsg = String.format("VM import failed for Unmanaged VM [%s] during VM migration, cannot find deployment destination due to [%s].", vm, e.getMessage()); - logger.warn(errorMsg, e); - cleanupFailedImportVM(vm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg); - } - 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())); - } - try { - 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) { - String errorMsg = String.format("VM import failed for Unmanaged VM [%s] during VM migration due to [%s].", vm, e.getMessage()); - logger.error(errorMsg, e); - cleanupFailedImportVM(vm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg); - } - } - 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; - } - boolean poolSupportsOfferings = storagePoolSupportsDiskOffering(diskProfileStoragePool.second(), dOffering); - if (poolSupportsOfferings) { - continue; - } - logger.debug("Volume {} needs to be migrated", volumeVO); - Pair, List> poolsPair = managementService.listStoragePoolsForSystemMigrationOfVolume(profile.getVolumeId(), null, null, null, null, false, true); - 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(s) found", userVm.getInstanceName(), volumeVO.getUuid())); - } - List storagePools = poolsPair.second(); - StoragePool storagePool = null; - if (CollectionUtils.isNotEmpty(storagePools)) { - for (StoragePool pool : storagePools) { - if (diskProfileStoragePool.second().getId() != pool.getId() && - storagePoolSupportsDiskOffering(pool, dOffering) - ) { - 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) - ) { - storagePool = pool; - break; - } - } - } - 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("Found storage pool {} for migrating the volume {} to", storagePool, volumeVO); - } - try { - Volume volume = null; - if (vm.getState().equals(VirtualMachine.State.Running)) { - volume = volumeManager.liveMigrateVolume(volumeVO, storagePool); - } else { - volume = volumeManager.migrateVolume(volumeVO, storagePool); - } - if (volume == null) { - String msg = ""; - if (vm.getState().equals(VirtualMachine.State.Running)) { - msg = String.format("Live migration for volume: %s to destination pool: %s failed", volumeVO, storagePool); - } else { - msg = String.format("Migration for volume: %s to destination pool: %s failed", volumeVO, storagePool); - } - logger.error(msg); - throw new CloudRuntimeException(msg); - } - } catch (Exception e) { - logger.error("VM import failed for unmanaged vm: {} during volume migration", vm, e); - cleanupFailedImportVM(vm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume migration. %s", userVm.getInstanceName(), StringUtils.defaultString(e.getMessage()))); - } - } - return userVm; - } - - private void publishVMUsageUpdateResourceCount(final UserVm userVm, ServiceOfferingVO serviceOfferingVO, VirtualMachineTemplate templateVO) { - if (userVm == null || serviceOfferingVO == null) { - logger.error("Failed to publish usage records during VM import because VM [{}] or ServiceOffering [{}] is null.", userVm, serviceOfferingVO); - cleanupFailedImportVM(userVm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "VM import failed for Unmanaged VM during publishing Usage Records."); - } - try { - if (!serviceOfferingVO.isDynamic()) { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, 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_CREATE, userVm.getAccountId(), userVm.getAccountId(), userVm.getDataCenterId(), userVm.getHostName(), serviceOfferingVO.getId(), userVm.getTemplateId(), - userVm.getHypervisorType().toString(), VirtualMachine.class.getName(), userVm.getUuid(), userVm.getDetails(), userVm.isDisplayVm()); - } - if (userVm.getState() == VirtualMachine.State.Running) { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_START, userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), userVm.getHostName(), serviceOfferingVO.getId(), userVm.getTemplateId(), - userVm.getHypervisorType().toString(), VirtualMachine.class.getName(), userVm.getUuid(), userVm.isDisplayVm()); - } - } catch (Exception e) { - logger.error("Failed to publish usage records during VM import for unmanaged VM [{}] due to [{}].", userVm, e.getMessage(), e); - cleanupFailedImportVM(userVm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm %s during publishing usage records", userVm.getInstanceName())); - } - resourceLimitService.incrementVmResourceCount(userVm.getAccountId(), userVm.isDisplayVm(), serviceOfferingVO, templateVO); - // Save usage event and update resource count for user vm volumes - List volumes = volumeDao.findByInstance(userVm.getId()); - for (VolumeVO volume : volumes) { - 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("Failed to publish volume ID: {} usage records during VM import", volume, e); - } - resourceLimitService.incrementVolumeResourceCount(userVm.getAccountId(), volume.isDisplayVolume(), - volume.getSize(), diskOfferingDao.findById(volume.getDiskOfferingId())); - } - - List nics = nicDao.listByVmId(userVm.getId()); - for (NicVO nic : nics) { - try { - NetworkVO network = networkDao.findById(nic.getNetworkId()); - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), - Long.toString(nic.getId()), network.getNetworkOfferingId(), null, 1L, VirtualMachine.class.getName(), userVm.getUuid(), userVm.isDisplay()); - } catch (Exception e) { - logger.error(String.format("Failed to publish network usage records during VM import. %s", StringUtils.defaultString(e.getMessage()))); - } - } - } - - private UserVm importVirtualMachineInternal(final UnmanagedInstanceTO unmanagedInstance, final String instanceNameInternal, 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 Map dataDiskOfferingMap, - final Map nicNetworkMap, final Map callerNicIpAddressMap, final Long guestOsId, - final Map details, final boolean migrateAllowed, final boolean forced, final boolean isImportUnmanagedFromSameHypervisor) { - logger.debug(LogUtils.logGsonWithoutException("Trying to import VM [%s] with name [%s], in zone [%s], cluster [%s], and host [%s], using template [%s], service offering [%s], disks map [%s], NICs map [%s] and details [%s].", - unmanagedInstance, displayName, zone, cluster, host, template, serviceOffering, dataDiskOfferingMap, nicNetworkMap, details)); - UserVm userVm = null; - ServiceOfferingVO validatedServiceOffering = null; - try { - validatedServiceOffering = getUnmanagedInstanceServiceOffering(unmanagedInstance, serviceOffering, owner, zone, details, cluster.getHypervisorType()); - } catch (Exception e) { - String errorMsg = String.format("Failed to import Unmanaged VM [%s] because the service offering [%s] is not compatible due to [%s].", unmanagedInstance, serviceOffering, StringUtils.defaultIfEmpty(e.getMessage(), "")); - logger.error(errorMsg, e); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg); - } - - String internalCSName = unmanagedInstance.getInternalCSName(); - if (StringUtils.isEmpty(internalCSName)) { - internalCSName = instanceNameInternal; - } - 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 && host != null && !hostSupportsServiceOfferingAndTemplate(host, validatedServiceOffering, template)) { - throw new InvalidParameterValueException(String.format("Service offering: %s or template: %s is not compatible with host: %s of unmanaged VM: %s", serviceOffering.getUuid(), template.getUuid(), host.getUuid(), displayName)); - } - // 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", displayName)); - } - Pair> rootAndDataDisksPair = getRootAndDataDisks(unmanagedInstanceDisks, dataDiskOfferingMap); - final UnmanagedInstanceTO.Disk rootDisk = rootAndDataDisksPair.first(); - final List dataDisks = rootAndDataDisksPair.second(); - if (rootDisk == null || StringUtils.isEmpty(rootDisk.getController())) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed. Unable to retrieve root disk details for VM: %s ", displayName)); - } - if (cluster.getHypervisorType() == Hypervisor.HypervisorType.KVM) { - Long rootDiskOfferingId = validatedServiceOffering.getDiskOfferingId(); - DiskOffering rootDiskOffering = diskOfferingDao.findById(rootDiskOfferingId); - if ((rootDisk.getCapacity() == null || rootDisk.getCapacity() <= 0) && rootDiskOffering != null) { - rootDisk.setCapacity(rootDiskOffering.getDiskSize()); - } - } - allDetails.put(VmDetailConstants.ROOT_DISK_CONTROLLER, rootDisk.getController()); - if (cluster.getHypervisorType() == Hypervisor.HypervisorType.KVM && isImportUnmanagedFromSameHypervisor) { - long size = Double.valueOf(Math.ceil((double)rootDisk.getCapacity() / Resource.ResourceType.bytesToGiB)).longValue(); - allDetails.put(VmDetailConstants.ROOT_DISK_SIZE, String.valueOf(size)); - } - - List reservations = new ArrayList<>(); - try { - checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), rootDisk, null, validatedServiceOffering, owner, zone, cluster, migrateAllowed, reservations); - if (CollectionUtils.isNotEmpty(dataDisks)) { // Data disk(s) present - checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), dataDisks, dataDiskOfferingMap, owner, zone, cluster, migrateAllowed, reservations); - allDetails.put(VmDetailConstants.DATA_DISK_CONTROLLER, dataDisks.get(0).getController()); - } - - // Check NICs and supplied networks - Map nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap); - Map allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getName(), unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner, cluster.getHypervisorType()); - if (!CollectionUtils.isEmpty(unmanagedInstance.getNics())) { - allDetails.put(VmDetailConstants.NIC_ADAPTER, unmanagedInstance.getNics().get(0).getAdapterType()); - } - - if (StringUtils.isNotEmpty(unmanagedInstance.getVncPassword())) { - allDetails.put(VmDetailConstants.KVM_VNC_PASSWORD, unmanagedInstance.getVncPassword()); - } - - addImportingVMBootTypeAndModeDetails(unmanagedInstance.getBootType(), unmanagedInstance.getBootMode(), allDetails); - - VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff; - if (unmanagedInstance.getPowerState().equals(UnmanagedInstanceTO.PowerState.PowerOn)) { - powerState = VirtualMachine.PowerState.PowerOn; - } - - try { - userVm = userVmManager.importVM(zone, host, template, internalCSName, displayName, owner, - null, caller, true, null, owner.getAccountId(), userId, - validatedServiceOffering, null, guestOsId, hostName, - cluster.getHypervisorType(), allDetails, powerState, null); - } catch (InsufficientCapacityException ice) { - String errorMsg = String.format("Failed to import VM [%s] due to [%s].", displayName, ice.getMessage()); - logger.error(errorMsg, ice); - throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, errorMsg); - } - - if (userVm == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import vm name: %s", displayName)); - } - List> diskProfileStoragePoolList = new ArrayList<>(); - try { - if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) { - throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId())); - } - Long minIops = null; - if (details.containsKey(MIN_IOPS)) { - minIops = Long.parseLong(details.get(MIN_IOPS)); - } - Long maxIops = null; - if (details.containsKey(MAX_IOPS)) { - maxIops = Long.parseLong(details.get(MAX_IOPS)); - } - DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); - diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, cluster, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()), - rootDisk.getCapacity(), minIops, maxIops, template, owner, null)); - long deviceId = 1L; - 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(), offering.getMinIops(), offering.getMaxIops(), - template, owner, deviceId)); - deviceId++; - } - } catch (Exception e) { - logger.error(String.format("Failed to import volumes while importing vm: %s", displayName), e); - cleanupFailedImportVM(userVm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", displayName, StringUtils.defaultString(e.getMessage()))); - } - try { - int nicIndex = 0; - 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, nicIndex, nicIndex == 0, forced); - nicIndex++; - } - } catch (Exception e) { - logger.error(String.format("Failed to import NICs while importing vm: %s", displayName), e); - cleanupFailedImportVM(userVm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import NICs while importing vm: %s. %s", displayName, StringUtils.defaultString(e.getMessage()))); - } - if (migrateAllowed) { - userVm = migrateImportedVM(host, template, validatedServiceOffering, userVm, owner, diskProfileStoragePoolList); - } - publishVMUsageUpdateResourceCount(userVm, validatedServiceOffering, template); - return userVm; - - } catch (ResourceAllocationException e) { // This will be thrown by checkUnmanagedDiskAndOfferingForImport, so the VM was not imported yet - logger.error("Volume resource allocation error for owner: {}", owner, e); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resource allocation error for owner: %s. %s", owner.getUuid(), StringUtils.defaultString(e.getMessage()))); - } finally { - ReservationHelper.closeAll(reservations); - } - } - - private void addImportingVMBootTypeAndModeDetails(String bootType, String bootMode, Map allDetails) { - if (StringUtils.isNotBlank(bootType) && bootType.equalsIgnoreCase("uefi") && StringUtils.isNotBlank(bootMode)) { - allDetails.put("UEFI", bootMode); - } - } - - private HashMap getUnmanagedInstancesForHost(HostVO host, String instanceName, List managedVms) { - HashMap unmanagedInstances = new HashMap<>(); - if (host.isInMaintenanceStates()) { - return unmanagedInstances; - } - - GetUnmanagedInstancesCommand command = new GetUnmanagedInstancesCommand(); - command.setInstanceName(instanceName); - command.setManagedInstancesNames(managedVms); - Answer answer = agentManager.easySend(host.getId(), command); - if (!(answer instanceof GetUnmanagedInstancesAnswer) || !answer.getResult()) { - return unmanagedInstances; - } - GetUnmanagedInstancesAnswer unmanagedInstancesAnswer = (GetUnmanagedInstancesAnswer) answer; - unmanagedInstances = unmanagedInstancesAnswer.getUnmanagedInstances(); - return unmanagedInstances; - } - - protected Cluster basicAccessChecks(Long clusterId) { - final Account caller = CallContext.current().getCallingAccount(); - if (caller.getType() != Account.Type.ADMIN) { - throw new PermissionDeniedException(String.format("Cannot perform this operation, caller account [%s] is not ROOT Admin.", caller.getUuid())); - } - if (clusterId == null) { - throw new InvalidParameterValueException("Cluster ID cannot be null."); - } - final Cluster cluster = clusterDao.findById(clusterId); - if (cluster == null) { - throw new InvalidParameterValueException(String.format("Cluster with ID [%d] cannot be found.", clusterId)); - } - - if (!importUnmanagedInstancesSupportedHypervisors.contains(cluster.getHypervisorType())) { - throw new InvalidParameterValueException(String.format("VM import is currently not supported for hypervisor [%s].", cluster.getHypervisorType().toString())); - } - return cluster; - } - - @Override - public ListResponse listUnmanagedInstances(ListUnmanagedInstancesCmd cmd) { - Long clusterId = cmd.getClusterId(); - Cluster cluster = basicAccessChecks(clusterId); - String keyword = cmd.getKeyword(); - if (StringUtils.isNotEmpty(keyword)) { - keyword = keyword.toLowerCase(); - } - List hosts = resourceManager.listHostsInClusterByStatus(clusterId, Status.Up); - List additionalNameFilters = getAdditionalNameFilters(cluster); - List managedVms = new ArrayList<>(additionalNameFilters); - managedVms.addAll(getHostsManagedVms(hosts)); - List responses = new ArrayList<>(); - for (HostVO host : hosts) { - HashMap unmanagedInstances = getUnmanagedInstancesForHost(host, cmd.getName(), managedVms); - Set keys = unmanagedInstances.keySet(); - for (String key : keys) { - UnmanagedInstanceTO instance = unmanagedInstances.get(key); - if (StringUtils.isNotEmpty(keyword) && - !instance.getName().toLowerCase().contains(keyword)) { - continue; - } - responses.add(responseGenerator.createUnmanagedInstanceResponse(instance, cluster, host)); - } - } - ListResponse listResponses = new ListResponse<>(); - listResponses.setResponses(responses, responses.size()); - return listResponses; - } - - @Override - public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { - return baseImportInstance(cmd); - } - - /** - * Base logic for import virtual machines (unmanaged, external) into CloudStack - * @param cmd importVM or importUnmanagedInstance command - * @return imported user vm - */ - private UserVmResponse baseImportInstance(ImportUnmanagedInstanceCmd cmd) { - basicParametersCheckForImportInstance(cmd.getName(), cmd.getDomainId(), cmd.getAccountName()); - - final String instanceName = cmd.getName(); - Long clusterId = cmd.getClusterId(); - Cluster cluster = basicAccessChecks(clusterId); - - if (!cluster.getAllocationState().equals(Cluster.AllocationState.Enabled)) { - throw new InvalidParameterValueException(String.format("Cluster [%s] is not enabled.", cluster)); - } - - final Account caller = CallContext.current().getCallingAccount(); - final DataCenter zone = dataCenterDao.findById(cluster.getDataCenterId()); - final Account owner = accountService.getActiveAccountById(cmd.getEntityOwnerId()); - long userId = getUserIdForImportInstance(owner); - - VMTemplateVO template = getTemplateForImportInstance(cmd.getTemplateId(), cluster.getHypervisorType()); - ServiceOfferingVO serviceOffering = getServiceOfferingForImportInstance(cmd.getServiceOfferingId(), owner, zone); - - String displayName = getDisplayNameForImportInstance(cmd.getDisplayName(), instanceName); - String hostName = getHostNameForImportInstance(cmd.getHostName(), cluster.getHypervisorType(), instanceName, displayName); - - checkVmwareInstanceNameForImportInstance(cluster.getHypervisorType(), instanceName, hostName, zone); - final Map nicNetworkMap = cmd.getNicNetworkList(); - final Map nicIpAddressMap = cmd.getNicIpAddressList(); - final Map dataDiskOfferingMap = cmd.getDataDiskToDiskOfferingList(); - final Map details = cmd.getDetails(); - final boolean forced = cmd.isForced(); - List hosts = resourceManager.listHostsInClusterByStatus(clusterId, Status.Up); - UserVm userVm = null; - List additionalNameFilters = getAdditionalNameFilters(cluster); - List managedVms = new ArrayList<>(additionalNameFilters); - managedVms.addAll(getHostsManagedVms(hosts)); - - try { - - ActionEventUtils.onStartedActionEvent(userId, owner.getId(), EventTypes.EVENT_VM_IMPORT, - cmd.getEventDescription(), null, null, true, 0); - - if (cmd instanceof ImportVmCmd) { - ImportVmCmd importVmCmd = (ImportVmCmd) cmd; - if (StringUtils.isBlank(importVmCmd.getImportSource())) { - throw new CloudRuntimeException("Please provide an import source for importing the VM"); - } - String source = importVmCmd.getImportSource().toUpperCase(); - ImportSource importSource = Enum.valueOf(ImportSource.class, source); - if (ImportSource.VMWARE == importSource) { - userVm = importUnmanagedInstanceFromVmwareToKvm(zone, cluster, - template, instanceName, displayName, hostName, caller, owner, userId, - serviceOffering, dataDiskOfferingMap, - nicNetworkMap, nicIpAddressMap, - details, importVmCmd, forced); - } - } else { - if (List.of(Hypervisor.HypervisorType.VMware, Hypervisor.HypervisorType.KVM).contains(cluster.getHypervisorType())) { - userVm = importUnmanagedInstanceFromHypervisor(zone, cluster, hosts, additionalNameFilters, - template, instanceName, displayName, hostName, caller, owner, userId, - serviceOffering, dataDiskOfferingMap, - nicNetworkMap, nicIpAddressMap, - details, cmd.getMigrateAllowed(), managedVms, forced); - } - } - - } 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(), StringUtils.defaultString(e.getMessage()))); - } - - if (userVm == null) { - ActionEventUtils.onCompletedActionEvent(userId, owner.getId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_IMPORT, - cmd.getEventDescription(), null, null, 0); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to find unmanaged vm with name: %s in cluster: %s", instanceName, cluster.getUuid())); - } - ActionEventUtils.onCompletedActionEvent(userId, owner.getId(), EventVO.LEVEL_INFO, EventTypes.EVENT_VM_IMPORT, - cmd.getEventDescription(), userVm.getId(), ApiCommandResourceType.VirtualMachine.toString(), 0); - return responseGenerator.createUserVmResponse(ResponseObject.ResponseView.Full, "virtualmachine", userVm).get(0); - } - - protected void checkExtraParamsAllowed(String extraParams) { - if (StringUtils.isBlank(extraParams)) { - return; - } - if (BooleanUtils.isFalse(ConvertVmwareInstanceToKvmExtraParamsAllowed.value())) { - throw new ServerApiException(ApiErrorCode.PARAM_ERROR, - "Extra parameters for Vmware to KVM conversion are disabled by the administrator"); - } - String allowedParamsStr = ConvertVmwareInstanceToKvmExtraParamsAllowedList.value(); - if (StringUtils.isBlank(allowedParamsStr)) { - throw new ServerApiException(ApiErrorCode.PARAM_ERROR, - "Extra parameters for Vmware to KVM conversion are enabled but the allowed list of parameters is empty"); - } - List allowedParams = Arrays.asList(allowedParamsStr.split(",")); - List sanitizedParams = Arrays.asList(extraParams.split(" ")) - .stream() - .filter(x -> x.startsWith("-")) - .map(s -> s.replaceFirst("^-+", "").trim()) //Remove the starting hyphens as in --X or -x - .collect(Collectors.toList()); - for (String param : sanitizedParams) { - if (!allowedParams.contains(param)) { - throw new ServerApiException(ApiErrorCode.PARAM_ERROR, - String.format("The parameter %s is not allowed by the administrator", param)); - } - } - } - - private long getUserIdForImportInstance(Account owner) { - long userId = CallContext.current().getCallingUserId(); - List userVOs = userDao.listByAccount(owner.getAccountId()); - if (CollectionUtils.isNotEmpty(userVOs)) { - userId = userVOs.get(0).getId(); - } - return userId; - } - - protected void basicParametersCheckForImportInstance(String name, Long domainId, String accountName) { - if (StringUtils.isEmpty(name)) { - throw new InvalidParameterValueException("Instance name cannot be empty"); - } - if (domainId != null && StringUtils.isEmpty(accountName)) { - throw new InvalidParameterValueException(String.format("%s parameter must be specified with %s parameter", ApiConstants.DOMAIN_ID, ApiConstants.ACCOUNT)); - } - } - - private void checkVmwareInstanceNameForImportInstance(Hypervisor.HypervisorType hypervisorType, String instanceName, String hostName, DataCenter zone) { - if (hypervisorType.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())); - } - } - } - - private String getHostNameForImportInstance(String hostName, Hypervisor.HypervisorType hypervisorType, - String instanceName, String displayName) { - if (StringUtils.isEmpty(hostName)) { - hostName = hypervisorType == Hypervisor.HypervisorType.VMware ? instanceName : displayName; - if (!NetUtils.verifyDomainNameLabel(hostName, true)) { - throw new InvalidParameterValueException("Please provide a valid hostname for the VM. VM name contains unsupported characters that cannot be used as hostname."); - } - } - 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"); - } - return hostName; - } - - private String getDisplayNameForImportInstance(String displayName, String instanceName) { - return StringUtils.isEmpty(displayName) ? instanceName : displayName; - } - - private ServiceOfferingVO getServiceOfferingForImportInstance(Long serviceOfferingId, Account owner, DataCenter zone) { - if (serviceOfferingId == null) { - throw new InvalidParameterValueException("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); - return serviceOffering; - } - - protected VMTemplateVO getTemplateForImportInstance(Long templateId, Hypervisor.HypervisorType hypervisorType) { - VMTemplateVO template; - if (templateId == null) { - boolean isKVMHypervisor = Hypervisor.HypervisorType.KVM.equals(hypervisorType); - String templateName = (isKVMHypervisor) ? KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME : VM_IMPORT_DEFAULT_TEMPLATE_NAME; - template = templateDao.findByName(templateName); - if (template == null) { - template = createDefaultDummyVmImportTemplate(isKVMHypervisor); - 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 parameter for import", templateName, hypervisorType.toString())); - } - } - } else { - template = templateDao.findById(templateId); - } - if (template == null) { - throw new InvalidParameterValueException(String.format("Template ID: %d cannot be found", templateId)); - } - return template; - } - - @Override - @ActionEvent(eventType = EventTypes.EVENT_VM_IMPORT, eventDescription = "importing VM", async = true) - public UserVmResponse importVm(ImportVmCmd cmd) { - String source = cmd.getImportSource().toUpperCase(); - ImportSource importSource = Enum.valueOf(ImportSource.class, source); - if (ImportSource.VMWARE == importSource || ImportSource.UNMANAGED == importSource) { - checkExtraParamsAllowed(cmd.getExtraParams()); - return baseImportInstance(cmd); - } else { - return importKvmInstance(cmd); - } - } - - private UserVm importUnmanagedInstanceFromHypervisor(DataCenter zone, Cluster cluster, - List hosts, List additionalNameFilters, - VMTemplateVO template, String instanceName, String displayName, - String hostName, Account caller, Account owner, long userId, - ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap, - Map nicNetworkMap, Map nicIpAddressMap, - Map details, Boolean migrateAllowed, List managedVms, boolean forced) throws ResourceAllocationException { - UserVm userVm = null; - for (HostVO host : hosts) { - HashMap unmanagedInstances = getUnmanagedInstancesForHost(host, instanceName, managedVms); - if (MapUtils.isEmpty(unmanagedInstances)) { - continue; - } - Set names = unmanagedInstances.keySet(); - for (String name : names) { - if (!instanceName.equals(name)) { - continue; - } - 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)); - } - - if (template.getName().equals(VM_IMPORT_DEFAULT_TEMPLATE_NAME) && cluster.getHypervisorType().equals(Hypervisor.HypervisorType.KVM)) { - throw new InvalidParameterValueException("Template is needed and unable to use default template for hypervisor " + host.getHypervisorType().toString()); - } - - if (template.getName().equals(VM_IMPORT_DEFAULT_TEMPLATE_NAME)) { - String osName = unmanagedInstance.getOperatingSystem(); - GuestOS guestOS = null; - if (StringUtils.isNotEmpty(osName)) { - guestOS = guestOSDao.findOneByDisplayName(osName); - } - - GuestOSHypervisor guestOSHypervisor = null; - if (guestOS != null) { - guestOSHypervisor = guestOSHypervisorDao.findByOsIdAndHypervisor(guestOS.getId(), host.getHypervisorType().toString(), host.getHypervisorVersion()); - } - if (guestOSHypervisor == null && StringUtils.isNotEmpty(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())); - } - 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(guestOSHypervisor.getGuestOsId()); - } - - List reservations = new ArrayList<>(); - try { - checkVmResourceLimitsForUnmanagedInstanceImport(owner, unmanagedInstance, serviceOffering, template, reservations); - userVm = importVirtualMachineInternal(unmanagedInstance, instanceName, zone, cluster, host, - template, displayName, hostName, CallContext.current().getCallingAccount(), owner, userId, - serviceOffering, dataDiskOfferingMap, - nicNetworkMap, nicIpAddressMap, null, - details, migrateAllowed, forced, true); - } finally { - ReservationHelper.closeAll(reservations); - } - break; - } - if (userVm != null) { - break; - } - } - return userVm; - } - - protected void checkVmResourceLimitsForUnmanagedInstanceImport(Account owner, UnmanagedInstanceTO unmanagedInstance, ServiceOfferingVO serviceOffering, VMTemplateVO template, List reservations) throws ResourceAllocationException { - // When importing an unmanaged instance, the amount of CPUs and memory is obtained from the hypervisor unless powered off - // and not using a dynamic offering, unlike the external VM import that always obtains it from the compute offering - Integer cpu = serviceOffering.getCpu(); - Integer memory = serviceOffering.getRamSize(); - - if (serviceOffering.isDynamic() || !UnmanagedInstanceTO.PowerState.PowerOff.equals(unmanagedInstance.getPowerState())) { - cpu = unmanagedInstance.getCpuCores(); - memory = unmanagedInstance.getMemory(); - } - - if (cpu == null || cpu == 0) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("CPU cores [%s] is not valid for importing VM [%s].", cpu, unmanagedInstance.getName())); - } - if (memory == null || memory == 0) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Memory [%s] is not valid for importing VM [%s].", memory, unmanagedInstance.getName())); - } - - List resourceLimitHostTags = resourceLimitService.getResourceLimitHostTags(serviceOffering, template); - - CheckedReservation vmReservation = new CheckedReservation(owner, Resource.ResourceType.user_vm, resourceLimitHostTags, 1L, reservationDao, resourceLimitService); - reservations.add(vmReservation); - - CheckedReservation cpuReservation = new CheckedReservation(owner, Resource.ResourceType.cpu, resourceLimitHostTags, cpu.longValue(), reservationDao, resourceLimitService); - reservations.add(cpuReservation); - - CheckedReservation memReservation = new CheckedReservation(owner, Resource.ResourceType.memory, resourceLimitHostTags, memory.longValue(), reservationDao, resourceLimitService); - reservations.add(memReservation); - } - - private Pair getSourceVmwareUnmanagedInstance(String vcenter, String datacenterName, String username, - String password, String clusterName, String sourceHostName, - String sourceVM, ServiceOfferingVO serviceOffering) { - HypervisorGuru vmwareGuru = hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware); - - Map params = createParamsForTemplateFromVmwareVmMigration(vcenter, datacenterName, - username, password, clusterName, sourceHostName, sourceVM); - addServiceOfferingDetailsToParams(params, serviceOffering); - - return vmwareGuru.getHypervisorVMOutOfBandAndCloneIfRequired(sourceHostName, sourceVM, params); - } - - /** - * Add the minimum resources to check on the hypervisor source VM before converting the instance against the selected offering resources - * @param params sets the minimum CPU number, CPU speed and memory to be checked against the source VM - * @param serviceOffering service offering for the converted VM - */ - protected void addServiceOfferingDetailsToParams(Map params, ServiceOfferingVO serviceOffering) { - if (serviceOffering != null) { - serviceOfferingDao.loadDetails(serviceOffering); - Map serviceOfferingDetails = serviceOffering.getDetails(); - - if (serviceOffering.getCpu() != null) { - params.put(VmDetailConstants.CPU_NUMBER, String.valueOf(serviceOffering.getCpu())); - } else if (MapUtils.isNotEmpty(serviceOfferingDetails) && serviceOfferingDetails.containsKey(ApiConstants.MIN_CPU_NUMBER)) { - params.put(VmDetailConstants.CPU_NUMBER, serviceOfferingDetails.get(ApiConstants.MIN_CPU_NUMBER)); - } - - if (serviceOffering.getSpeed() != null) { - params.put(VmDetailConstants.CPU_SPEED, String.valueOf(serviceOffering.getSpeed())); - } - - if (serviceOffering.getRamSize() != null) { - params.put(VmDetailConstants.MEMORY, String.valueOf(serviceOffering.getRamSize())); - } else if (MapUtils.isNotEmpty(serviceOfferingDetails) && serviceOfferingDetails.containsKey(ApiConstants.MIN_MEMORY)) { - params.put(VmDetailConstants.MEMORY, serviceOfferingDetails.get(ApiConstants.MIN_MEMORY)); - } - } - } - - private String createOvfTemplateOfSourceVmwareUnmanagedInstance(String vcenter, String datacenterName, String username, - String password, String clusterName, String sourceHostName, - String sourceVMwareInstanceName, DataStoreTO convertLocation, int threadsCountToExportOvf) { - HypervisorGuru vmwareGuru = hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware); - - Map params = createParamsForTemplateFromVmwareVmMigration(vcenter, datacenterName, - username, password, clusterName, sourceHostName, sourceVMwareInstanceName); - - return vmwareGuru.createVMTemplateOutOfBand(sourceHostName, sourceVMwareInstanceName, params, convertLocation, threadsCountToExportOvf); - } - - protected UserVm importUnmanagedInstanceFromVmwareToKvm(DataCenter zone, Cluster destinationCluster, VMTemplateVO template, - String sourceVMName, String displayName, String hostName, - Account caller, Account owner, long userId, - ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap, - Map nicNetworkMap, Map nicIpAddressMap, - Map details, ImportVmCmd cmd, boolean forced) throws ResourceAllocationException { - Long existingVcenterId = cmd.getExistingVcenterId(); - String vcenter = cmd.getVcenter(); - String datacenterName = cmd.getDatacenterName(); - String username = cmd.getUsername(); - String password = cmd.getPassword(); - String clusterName = cmd.getClusterName(); - String sourceHostName = cmd.getHostIp(); - Long convertInstanceHostId = cmd.getConvertInstanceHostId(); - Long importInstanceHostId = cmd.getImportInstanceHostId(); - Long convertStoragePoolId = cmd.getConvertStoragePoolId(); - String extraParams = cmd.getExtraParams(); - boolean forceConvertToPool = cmd.getForceConvertToPool(); - Long guestOsId = cmd.getGuestOsId(); - boolean forceMsToImportVmFiles = Boolean.TRUE.equals(cmd.getForceMsToImportVmFiles()); - boolean useVddk = cmd.getUseVddk(); - - if ((existingVcenterId == null && vcenter == null) || (existingVcenterId != null && vcenter != null)) { - throw new ServerApiException(ApiErrorCode.PARAM_ERROR, - "Please provide an existing vCenter ID or a vCenter IP/Name, parameters are mutually exclusive"); - } - if (existingVcenterId == null && StringUtils.isAnyBlank(vcenter, datacenterName, username, password)) { - throw new ServerApiException(ApiErrorCode.PARAM_ERROR, - "Please set all the information for a vCenter IP/Name, datacenter, username and password"); - } - if (forceMsToImportVmFiles && useVddk) { - throw new ServerApiException(ApiErrorCode.PARAM_ERROR, - String.format("Parameters %s and %s are mutually exclusive", - ApiConstants.FORCE_MS_TO_IMPORT_VM_FILES, ApiConstants.USE_VDDK)); - } - - checkConversionStoragePool(convertStoragePoolId, forceConvertToPool); - validateSelectedConversionStoragePoolForVddk(useVddk, convertStoragePoolId, serviceOffering, dataDiskOfferingMap); - - checkExtraParamsAllowed(extraParams); - - if (existingVcenterId != null) { - VmwareDatacenterVO existingDC = vmwareDatacenterDao.findById(existingVcenterId); - if (existingDC == null) { - String err = String.format("Cannot find any existing VMware DC with ID %s", existingVcenterId); - logger.error(err); - throw new CloudRuntimeException(err); - } - vcenter = existingDC.getVcenterHost(); - datacenterName = existingDC.getVmwareDatacenterName(); - username = existingDC.getUser(); - password = existingDC.getPassword(); - } - - boolean isClonedInstance = false; - UnmanagedInstanceTO sourceVMwareInstance = null; - DataStoreTO temporaryConvertLocation = null; - String ovfTemplateOnConvertLocation = null; - ImportVmTask importVMTask = null; - List reservations = new ArrayList<>(); - try { - HostVO convertHost = selectKVMHostForConversionInCluster(destinationCluster, convertInstanceHostId, useVddk); - HostVO importHost = (useVddk && importInstanceHostId == null) - ? convertHost - : selectKVMHostForImportingInCluster(destinationCluster, importInstanceHostId); - - boolean isOvfExportSupported = false; - CheckConvertInstanceAnswer conversionSupportAnswer = checkConversionSupportOnHost(convertHost, sourceVMName, false, useVddk, details); - if (!useVddk) { - isOvfExportSupported = conversionSupportAnswer.isOvfExportSupported(); - } - logger.debug("The host {} is selected to execute the conversion of the " + - "instance {} from VMware to KVM ", convertHost, sourceVMName); - - temporaryConvertLocation = selectInstanceConversionTemporaryLocation( - destinationCluster, convertHost, importHost, convertStoragePoolId, forceConvertToPool); - List convertStoragePools = findInstanceConversionDestinationStoragePoolsInCluster(destinationCluster, serviceOffering, dataDiskOfferingMap, temporaryConvertLocation, forceConvertToPool); - - long importStartTime = System.currentTimeMillis(); - importVMTask = importVmTasksManager.createImportVMTaskRecord(zone, owner, userId, displayName, vcenter, datacenterName, sourceVMName, - convertHost, importHost); - importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, null, CloningInstance); - - // sourceVMwareInstance could be a cloned instance from sourceVMName, of the sourceVMName itself if its powered off. - // isClonedInstance indicates if the VM is a clone of sourceVMName - - Pair sourceInstanceDetails = getSourceVmwareUnmanagedInstance(vcenter, datacenterName, username, password, clusterName, sourceHostName, sourceVMName, serviceOffering); - sourceVMwareInstance = sourceInstanceDetails.first(); - isClonedInstance = sourceInstanceDetails.second(); - - // Ensure that the configured resource limits will not be exceeded before beginning the conversion process - checkVmResourceLimitsForUnmanagedInstanceImport(owner, sourceVMwareInstance, serviceOffering, template, reservations); - - boolean isWindowsVm = sourceVMwareInstance.getOperatingSystem().toLowerCase().contains("windows"); - if (isWindowsVm) { - checkConversionSupportOnHost(convertHost, sourceVMName, true, useVddk, details); - } - - checkNetworkingBeforeConvertingVmwareInstance(zone, owner, displayName, hostName, sourceVMwareInstance, nicNetworkMap, nicIpAddressMap, forced); - UnmanagedInstanceTO convertedInstance; - if (!useVddk && (forceMsToImportVmFiles || !isOvfExportSupported)) { - // Uses MS for OVF export to temporary conversion location - int noOfThreads = UnmanagedVMsManager.ThreadsOnMSToImportVMwareVMFiles.value(); - importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, null, ConvertingInstance); - ovfTemplateOnConvertLocation = createOvfTemplateOfSourceVmwareUnmanagedInstance( - vcenter, datacenterName, username, password, clusterName, sourceHostName, - sourceVMwareInstance.getName(), temporaryConvertLocation, noOfThreads); - convertedInstance = convertVmwareInstanceToKVMWithOVFOnConvertLocation(sourceVMName, - sourceVMwareInstance, convertHost, importHost, convertStoragePools, - serviceOffering, dataDiskOfferingMap, temporaryConvertLocation, - ovfTemplateOnConvertLocation, forceConvertToPool, extraParams); - } else { - // Uses KVM Host for direct conversion using VDDK, or for OVF export to temporary conversion location through ovftool - importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, null, ConvertingInstance); - convertedInstance = convertVmwareInstanceToKVMUsingVDDKOrAfterExportingOVFToConvertLocation( - sourceVMName, sourceVMwareInstance, convertHost, importHost, - convertStoragePools, serviceOffering, dataDiskOfferingMap, - temporaryConvertLocation, vcenter, username, password, datacenterName, forceConvertToPool, extraParams, useVddk, details); - } - - sanitizeConvertedInstance(convertedInstance, sourceVMwareInstance); - importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, null, Importing); - UserVm userVm = importVirtualMachineInternal(convertedInstance, null, zone, destinationCluster, null, - template, displayName, hostName, caller, owner, userId, - serviceOffering, dataDiskOfferingMap, - nicNetworkMap, nicIpAddressMap, guestOsId, - details, false, forced, false); - long timeElapsedInSecs = (System.currentTimeMillis() - importStartTime) / 1000; - logger.debug(String.format("VMware VM %s imported successfully to CloudStack instance %s (%s), Time taken: %d secs, OVF files imported from %s, Source VMware VM details - OS: %s, PowerState: %s, Disks: %s, NICs: %s", - sourceVMName, displayName, displayName, timeElapsedInSecs, (ovfTemplateOnConvertLocation != null)? "MS" : "KVM Host", sourceVMwareInstance.getOperatingSystem(), sourceVMwareInstance.getPowerState(), sourceVMwareInstance.getDisks(), sourceVMwareInstance.getNics())); - importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, userVm.getId(), Completed); - return userVm; - } catch (CloudRuntimeException e) { - logger.error(String.format("Error importing VM: %s", e.getMessage()), e); - importVmTasksManager.updateImportVMTaskErrorState(importVMTask, ImportVmTask.TaskState.Failed, e.getMessage()); - ActionEventUtils.onCompletedActionEvent(userId, owner.getId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_IMPORT, - cmd.getEventDescription(), null, null, 0); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); - } finally { - if (isClonedInstance && sourceVMwareInstance != null) { - removeClonedInstance(vcenter, datacenterName, username, password, sourceHostName, sourceVMwareInstance.getName(), sourceVMName); - } - if (temporaryConvertLocation != null && StringUtils.isNotBlank(ovfTemplateOnConvertLocation)) { - removeTemplate(temporaryConvertLocation, ovfTemplateOnConvertLocation); - } - ReservationHelper.closeAll(reservations); - } - } - - /** - * Check whether the conversion storage pool exists and is suitable for the conversion or not. - * Secondary storage is only allowed when forceConvertToPool is false. - * @param convertStoragePoolId the ID of the storage pool (primary or secondary) - * @param forceConvertToPool when true, only primary storage pool must be allowed - * @throws CloudRuntimeException in case these requirements are not met - */ - protected void checkConversionStoragePool(Long convertStoragePoolId, boolean forceConvertToPool) { - if (forceConvertToPool && convertStoragePoolId == null) { - String msg = "The parameter forceconverttopool is set to true, but a primary storage pool has not been provided for conversion"; - logFailureAndThrowException(msg); - } - if (convertStoragePoolId != null) { - StoragePoolVO selectedStoragePool = primaryDataStoreDao.findById(convertStoragePoolId); - if (selectedStoragePool == null) { - logFailureAndThrowException(String.format("Cannot find a storage pool with ID %s", convertStoragePoolId)); - } - if (forceConvertToPool && !forceConvertToPoolAllowedTypes.contains(selectedStoragePool.getPoolType())) { - logFailureAndThrowException(String.format("The selected storage pool %s does not support direct conversion " + - "as its type %s", selectedStoragePool.getName(), selectedStoragePool.getPoolType().name())); - } - } - } - - protected void validateSelectedConversionStoragePoolForVddk(boolean useVddk, Long convertStoragePoolId, - ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap) { - if (!useVddk || convertStoragePoolId == null) { - return; - } - - StoragePoolVO selectedStoragePool = primaryDataStoreDao.findById(convertStoragePoolId); - if (selectedStoragePool == null) { - return; - } - - if (serviceOffering.getDiskOfferingId() != null) { - DiskOfferingVO rootDiskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); - if (rootDiskOffering == null) { - throw new InvalidParameterValueException(String.format("Cannot find disk offering with ID %s that belongs to the service offering %s", - serviceOffering.getDiskOfferingId(), serviceOffering.getName())); - } - if (!volumeApiService.doesStoragePoolSupportDiskOffering(selectedStoragePool, rootDiskOffering)) { - throw new InvalidParameterValueException(String.format("The root disk offering '%s' is not supported by the selected conversion storage pool '%s'. " + - "When using VDDK, all selected disk offerings must be compatible with the conversion storage pool, as it will become the primary storage for the imported volumes.", - rootDiskOffering.getName(), selectedStoragePool.getName())); - } - } - - if (MapUtils.isNotEmpty(dataDiskOfferingMap)) { - for (Long diskOfferingId : dataDiskOfferingMap.values()) { - DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId); - if (diskOffering == null) { - throw new InvalidParameterValueException(String.format("Cannot find disk offering with ID %s", diskOfferingId)); - } - if (!volumeApiService.doesStoragePoolSupportDiskOffering(selectedStoragePool, diskOffering)) { - throw new InvalidParameterValueException(String.format("The data disk offering '%s' is not supported by the selected conversion storage pool '%s'. " + - "When using VDDK, all selected disk offerings must be compatible with the conversion storage pool, as it will become the primary storage for the imported volumes.", - diskOffering.getName(), selectedStoragePool.getName())); - } - } - } - } - - private void checkNetworkingBeforeConvertingVmwareInstance(DataCenter zone, Account owner, String displayName, - String hostName, UnmanagedInstanceTO sourceVMwareInstance, - Map nicNetworkMap, - Map nicIpAddressMap, - boolean forced) { - List nics = sourceVMwareInstance.getNics(); - List networkIds = new ArrayList<>(nicNetworkMap.values()); - if (nics.size() != networkIds.size()) { - String msg = String.format("Different number of nics found on instance %s: %s vs %s nics provided", - sourceVMwareInstance.getName(), nics.size(), networkIds.size()); - logger.error(msg); - throw new CloudRuntimeException(msg); - } - - for (UnmanagedInstanceTO.Nic nic : nics) { - Long networkId = nicNetworkMap.get(nic.getNicId()); - NetworkVO network = networkDao.findById(networkId); - if (network == null) { - String err = String.format("Cannot find a network with id = %s", networkId); - logger.error(err); - throw new CloudRuntimeException(err); - } - Network.IpAddresses ipAddresses = null; - if (MapUtils.isNotEmpty(nicIpAddressMap) && nicIpAddressMap.containsKey(nic.getNicId())) { - ipAddresses = nicIpAddressMap.get(nic.getNicId()); - } - boolean autoImport = ipAddresses != null && ipAddresses.getIp4Address() != null && ipAddresses.getIp4Address().equalsIgnoreCase("auto"); - checkUnmanagedNicAndNetworkMacAddressForImport(network, nic, forced); - checkUnmanagedNicAndNetworkForImport(displayName, nic, network, zone, owner, autoImport, Hypervisor.HypervisorType.KVM); - checkUnmanagedNicAndNetworkHostnameForImport(displayName, nic, network, hostName); - checkUnmanagedNicIpAndNetworkForImport(displayName, nic, network, ipAddresses); - } - } - - private void checkUnmanagedNicAndNetworkMacAddressForImport(NetworkVO network, UnmanagedInstanceTO.Nic nic, boolean forced) { - NicVO existingNic = nicDao.findByNetworkIdAndMacAddress(network.getId(), nic.getMacAddress()); - if (existingNic != null && !forced) { - String err = String.format("NIC %s with MAC address %s already exists on network %s and forced flag is disabled. " + - "Retry with forced flag enabled if a new MAC address to be generated.", nic, nic.getMacAddress(), network); - logger.error(err); - throw new CloudRuntimeException(err); - } - } - - private void sanitizeConvertedInstance(UnmanagedInstanceTO convertedInstance, UnmanagedInstanceTO sourceVMwareInstance) { - convertedInstance.setCpuCores(sourceVMwareInstance.getCpuCores()); - convertedInstance.setCpuSpeed(sourceVMwareInstance.getCpuSpeed()); - convertedInstance.setCpuCoresPerSocket(sourceVMwareInstance.getCpuCoresPerSocket()); - convertedInstance.setMemory(sourceVMwareInstance.getMemory()); - convertedInstance.setPowerState(UnmanagedInstanceTO.PowerState.PowerOff); - List convertedInstanceDisks = convertedInstance.getDisks(); - List sourceVMwareInstanceDisks = sourceVMwareInstance.getDisks(); - for (int i = 0; i < convertedInstanceDisks.size(); i++) { - UnmanagedInstanceTO.Disk disk = convertedInstanceDisks.get(i); - disk.setDiskId(sourceVMwareInstanceDisks.get(i).getDiskId()); - } - List convertedInstanceNics = convertedInstance.getNics(); - List sourceVMwareInstanceNics = sourceVMwareInstance.getNics(); - if (CollectionUtils.isEmpty(convertedInstanceNics) && CollectionUtils.isNotEmpty(sourceVMwareInstanceNics)) { - for (UnmanagedInstanceTO.Nic nic : sourceVMwareInstanceNics) { - // In case the NICs information is not parsed from the converted XML domain, use the cloned instance NICs with virtio adapter - nic.setAdapterType("virtio"); - } - convertedInstance.setNics(sourceVMwareInstanceNics); - for (int i = 0; i < convertedInstanceNics.size(); i++) { - UnmanagedInstanceTO.Nic nic = convertedInstanceNics.get(i); - nic.setNicId(sourceVMwareInstanceNics.get(i).getNicId()); - } - } else if (CollectionUtils.isNotEmpty(convertedInstanceNics) && CollectionUtils.isNotEmpty(sourceVMwareInstanceNics) - && convertedInstanceNics.size() == sourceVMwareInstanceNics.size()) { - for (int i = 0; i < convertedInstanceNics.size(); i++) { - UnmanagedInstanceTO.Nic nic = convertedInstanceNics.get(i); - nic.setNicId(sourceVMwareInstanceNics.get(i).getNicId()); - if (nic.getMacAddress() == null) { - nic.setMacAddress(sourceVMwareInstanceNics.get(i).getMacAddress()); - } - } - } - } - - private void removeClonedInstance(String vcenter, String datacenterName, String username, String password, - String sourceHostName, String clonedInstanceName, String sourceVM) { - HypervisorGuru vmwareGuru = hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware); - Map params = createParamsForRemoveClonedInstance(vcenter, datacenterName, username, password, sourceVM); - boolean result = vmwareGuru.removeClonedHypervisorVMOutOfBand(sourceHostName, clonedInstanceName, params); - if (!result) { - String msg = String.format("Could not properly remove the cloned instance %s from VMware datacenter %s:%s", - clonedInstanceName, vcenter, datacenterName); - logger.warn(msg); - return; - } - logger.debug(String.format("Removed the cloned instance %s from VMWare datacenter %s/%s", - clonedInstanceName, vcenter, datacenterName)); - } - - private void removeTemplate(DataStoreTO convertLocation, String ovfTemplateOnConvertLocation) { - HypervisorGuru vmwareGuru = hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware); - boolean result = vmwareGuru.removeVMTemplateOutOfBand(convertLocation, ovfTemplateOnConvertLocation); - if (!result) { - String msg = String.format("Could not remove the template file %s on datastore %s", - ovfTemplateOnConvertLocation, convertLocation.getUrl()); - logger.warn(msg); - return; - } - logger.debug(String.format("Removed the template file %s on datastore %s", - ovfTemplateOnConvertLocation, convertLocation.getUrl())); - } - - private Map createParamsForRemoveClonedInstance(String vcenter, String datacenterName, String username, - String password, String sourceVM) { - Map params = new HashMap<>(); - params.put(VmDetailConstants.VMWARE_VCENTER_HOST, vcenter); - params.put(VmDetailConstants.VMWARE_DATACENTER_NAME, datacenterName); - params.put(VmDetailConstants.VMWARE_VCENTER_USERNAME, username); - params.put(VmDetailConstants.VMWARE_VCENTER_PASSWORD, password); - return params; - } - - HostVO selectKVMHostForImportingInCluster(Cluster destinationCluster, Long importInstanceHostId) { - if (importInstanceHostId != null) { - String err = null; - HostVO selectedHost = hostDao.findById(importInstanceHostId); - if (selectedHost == null) { - err = String.format("Cannot find host with ID %s to import the instance", - importInstanceHostId); - } else if (selectedHost.getResourceState() != ResourceState.Enabled) { - err = String.format( - "Cannot import the converted instance on the host %s as it is not in Enabled state", - selectedHost); - } else if (selectedHost.getStatus() != Status.Up) { - err = String.format( - "Cannot import the converted instance on the host %s as it is not running", - selectedHost); - } else if (selectedHost.getType() != Host.Type.Routing) { - err = String.format( - "Cannot import the converted instance on the host %s as it is not a routing host", - selectedHost); - } else if (destinationCluster.getId() != selectedHost.getClusterId()) { - err = String.format( - "Cannot import the converted instance on the host %s as it is not in the same cluster as the destination cluster", - selectedHost); - } - - if (err != null) { - logger.error(err); - throw new CloudRuntimeException(err); - } - return selectedHost; - } - - List hosts = hostDao.listByClusterAndHypervisorType(destinationCluster.getId(), destinationCluster.getHypervisorType()); - if (CollectionUtils.isNotEmpty(hosts)) { - return hosts.get(new Random().nextInt(hosts.size())); - } - - String err = String.format( - "Could not find any suitable %s host in cluster %s to import the converted instance", - destinationCluster.getHypervisorType(), destinationCluster); - logger.error(err); - throw new CloudRuntimeException(err); - } - - HostVO selectKVMHostForConversionInCluster(Cluster destinationCluster, Long convertInstanceHostId, boolean useVddk) { - if (convertInstanceHostId != null) { - HostVO selectedHost = hostDao.findById(convertInstanceHostId); - String err = null; - if (selectedHost == null) { - err = String.format("Cannot find host with ID %s for conversion", - convertInstanceHostId); - } else if (!List.of(ResourceState.Enabled, ResourceState.Disabled).contains(selectedHost.getResourceState())) { - err = String.format( - "Cannot perform the conversion on the host %s as the host is in %s state", - selectedHost, selectedHost.getResourceState()); - } else if (selectedHost.getStatus() != Status.Up) { - err = String.format( - "Cannot perform the conversion on the host %s as it is not running", - selectedHost); - } else if (selectedHost.getType() != Host.Type.Routing) { - err = String.format( - "Cannot perform the conversion on the host %s as it is not a routing host", - selectedHost); - } else if (destinationCluster.getDataCenterId() != selectedHost.getDataCenterId()) { - err = String.format( - "Cannot perform the conversion on the host %s as it is not in the same zone as the destination cluster", - selectedHost); - } - if (err != null) { - logger.error(err); - throw new CloudRuntimeException(err); - } - return selectedHost; - } - - // Auto select host with conversion capability - List hosts = hostDao.listByClusterHypervisorTypeAndHostCapability(destinationCluster.getId(), destinationCluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION); - if (CollectionUtils.isNotEmpty(hosts)) { - if (useVddk) { - List vddkHosts = filterHostsWithVddkSupport(hosts); - if (CollectionUtils.isNotEmpty(vddkHosts)) { - hosts = vddkHosts; - } - } - if (CollectionUtils.isNotEmpty(hosts)) { - return hosts.get(new Random().nextInt(hosts.size())); - } - } - - // Try without host capability check - hosts = hostDao.listByClusterAndHypervisorType(destinationCluster.getId(), destinationCluster.getHypervisorType()); - if (CollectionUtils.isNotEmpty(hosts)) { - if (useVddk) { - List vddkHosts = filterHostsWithVddkSupport(hosts); - if (CollectionUtils.isNotEmpty(vddkHosts)) { - hosts = vddkHosts; - } - } - if (CollectionUtils.isNotEmpty(hosts)) { - return hosts.get(new Random().nextInt(hosts.size())); - } - } - - String err = useVddk - ? String.format("Could not find any suitable %s host in cluster %s with '%s' configured to perform the VDDK-based instance conversion", - destinationCluster.getHypervisorType(), destinationCluster, Host.HOST_VDDK_SUPPORT) - : String.format("Could not find any suitable %s host in cluster %s to perform the instance conversion", - destinationCluster.getHypervisorType(), destinationCluster); - logger.error(err); - throw new CloudRuntimeException(err); - } - - private List filterHostsWithVddkSupport(List hosts) { - return hosts.stream().filter(h -> { - hostDao.loadDetails(h); - return Boolean.parseBoolean(h.getDetail(Host.HOST_VDDK_SUPPORT)); - }).collect(Collectors.toList()); - } - - private CheckConvertInstanceAnswer checkConversionSupportOnHost(HostVO convertHost, String sourceVM, - boolean checkWindowsGuestConversionSupport, - boolean useVddk, Map details) { - logger.debug(String.format("Checking the %s%s conversion support on the host %s", - useVddk ? "VDDK " : "", - checkWindowsGuestConversionSupport ? "windows guest " : "", - convertHost)); - CheckConvertInstanceCommand cmd = new CheckConvertInstanceCommand(checkWindowsGuestConversionSupport, useVddk); - if (MapUtils.isNotEmpty(details)) { - cmd.setVddkLibDir(StringUtils.trimToNull(details.get(Host.HOST_VDDK_LIB_DIR))); - } - int timeoutSeconds = 60; - cmd.setWait(timeoutSeconds); - - CheckConvertInstanceAnswer checkConvertInstanceAnswer; - try { - checkConvertInstanceAnswer = (CheckConvertInstanceAnswer) agentManager.send(convertHost.getId(), cmd); - } catch (AgentUnavailableException | OperationTimedoutException e) { - String err = String.format("Failed to check %s conversion support on the host %s for converting instance %s from VMware to KVM due to: %s", - checkWindowsGuestConversionSupport? "windows guest" : "", convertHost, sourceVM, e.getMessage()); - logger.error(err); - throw new CloudRuntimeException(err); - } - - if (!checkConvertInstanceAnswer.getResult()) { - String err = String.format("The host %s doesn't support conversion of instance %s from VMware to KVM due to: %s", - convertHost, sourceVM, checkConvertInstanceAnswer.getDetails()); - logger.error(err); - throw new CloudRuntimeException(err); - } - - return checkConvertInstanceAnswer; - } - - private UnmanagedInstanceTO convertVmwareInstanceToKVMWithOVFOnConvertLocation( - String sourceVM, UnmanagedInstanceTO sourceVMwareInstance, HostVO convertHost, - HostVO importHost, List convertStoragePools, - ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap, - DataStoreTO temporaryConvertLocation, String ovfTemplateDirConvertLocation, - boolean forceConvertToPool, String extraParams) { - - logger.debug("Delegating the conversion of instance {} from VMware to KVM to the host {} using OVF {} on conversion datastore", - sourceVM, convertHost, ovfTemplateDirConvertLocation); - - RemoteInstanceTO remoteInstanceTO = new RemoteInstanceTO(sourceVM, sourceVMwareInstance.getClusterName(), sourceVMwareInstance.getHostName()); - List destinationStoragePools = selectInstanceConversionStoragePools(convertStoragePools, sourceVMwareInstance.getDisks(), serviceOffering, dataDiskOfferingMap); - ConvertInstanceCommand cmd = new ConvertInstanceCommand(remoteInstanceTO, - Hypervisor.HypervisorType.KVM, temporaryConvertLocation, - ovfTemplateDirConvertLocation, false, false, sourceVM); - if (StringUtils.isNotBlank(extraParams)) { - cmd.setExtraParams(extraParams); - } - int timeoutSeconds = UnmanagedVMsManager.ConvertVmwareInstanceToKvmTimeout.value() * 60 * 60; - cmd.setWait(timeoutSeconds); - - return convertAndImportToKVM(cmd, convertHost, importHost, sourceVM, - remoteInstanceTO, destinationStoragePools, temporaryConvertLocation, forceConvertToPool); - } - - private UnmanagedInstanceTO convertVmwareInstanceToKVMUsingVDDKOrAfterExportingOVFToConvertLocation( - String sourceVM, UnmanagedInstanceTO sourceVMwareInstance, HostVO convertHost, - HostVO importHost, List convertStoragePools, - ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap, - DataStoreTO temporaryConvertLocation, String vcenterHost, String vcenterUsername, - String vcenterPassword, String datacenterName, boolean forceConvertToPool, String extraParams, - boolean useVddk, Map details) { - logger.debug("Delegating the conversion of instance {} from VMware to KVM to the host {} after OVF export through ovftool", sourceVM, convertHost); - - RemoteInstanceTO remoteInstanceTO = new RemoteInstanceTO(sourceVMwareInstance.getName(), sourceVMwareInstance.getPath(), vcenterHost, vcenterUsername, vcenterPassword, datacenterName, sourceVMwareInstance.getClusterName(), sourceVMwareInstance.getHostName()); - List destinationStoragePools = selectInstanceConversionStoragePools(convertStoragePools, sourceVMwareInstance.getDisks(), serviceOffering, dataDiskOfferingMap); - ConvertInstanceCommand cmd = new ConvertInstanceCommand(remoteInstanceTO, - Hypervisor.HypervisorType.KVM, temporaryConvertLocation, null, false, true, sourceVM); - int timeoutSeconds = UnmanagedVMsManager.ConvertVmwareInstanceToKvmTimeout.value() * 60 * 60; - cmd.setWait(timeoutSeconds); - int noOfThreads = UnmanagedVMsManager.ThreadsOnKVMHostToImportVMwareVMFiles.value(); - if (noOfThreads == 0) { - // Use no. of threads as the disks count - noOfThreads = sourceVMwareInstance.getDisks().size(); - } - cmd.setThreadsCountToExportOvf(noOfThreads); - if (StringUtils.isNotBlank(extraParams)) { - cmd.setExtraParams(extraParams); - } - cmd.setUseVddk(useVddk); - applyVddkOverridesFromDetails(cmd, details); - return convertAndImportToKVM(cmd, convertHost, importHost, sourceVM, - remoteInstanceTO, destinationStoragePools, temporaryConvertLocation, forceConvertToPool); - } - - private void applyVddkOverridesFromDetails(ConvertInstanceCommand cmd, Map details) { - if (MapUtils.isEmpty(details)) { - return; - } - - cmd.setVddkLibDir(StringUtils.trimToNull(details.get(Host.HOST_VDDK_LIB_DIR))); - cmd.setVddkTransports(StringUtils.trimToNull(details.get(DETAIL_VDDK_TRANSPORTS))); - cmd.setVddkThumbprint(StringUtils.trimToNull(details.get(DETAIL_VDDK_THUMBPRINT))); - } - - private UnmanagedInstanceTO convertAndImportToKVM(ConvertInstanceCommand convertInstanceCommand, HostVO convertHost, HostVO importHost, - String sourceVM, - RemoteInstanceTO remoteInstanceTO, - List destinationStoragePools, - DataStoreTO temporaryConvertLocation, - boolean forceConvertToPool) { - Answer convertAnswer; - try { - convertAnswer = agentManager.send(convertHost.getId(), convertInstanceCommand); - } catch (AgentUnavailableException | OperationTimedoutException e) { - String err = String.format("Could not send the convert instance command to host %s due to: %s", - convertHost, e.getMessage()); - logger.error(err, e); - throw new CloudRuntimeException(err); - } - - if (!convertAnswer.getResult()) { - String err = String.format("The convert process failed for instance %s from VMware to KVM on host %s: %s", - sourceVM, convertHost, convertAnswer.getDetails()); - logger.error(err); - throw new CloudRuntimeException(err); - } - - Answer importAnswer; - try { - ImportConvertedInstanceCommand importCmd = new ImportConvertedInstanceCommand( - remoteInstanceTO, destinationStoragePools, temporaryConvertLocation, - ((ConvertInstanceAnswer)convertAnswer).getTemporaryConvertUuid(), forceConvertToPool); - importAnswer = agentManager.send(importHost.getId(), importCmd); - } catch (AgentUnavailableException | OperationTimedoutException e) { - String err = String.format( - "Could not send the import converted instance command to host %s due to: %s", - importHost, e.getMessage()); - logger.error(err, e); - throw new CloudRuntimeException(err); - } - - if (!importAnswer.getResult()) { - String err = String.format( - "The import process failed for instance %s from VMware to KVM on host %s: %s", - sourceVM, importHost, importAnswer.getDetails()); - logger.error(err); - throw new CloudRuntimeException(err); - } - - return ((ImportConvertedInstanceAnswer) importAnswer).getConvertedInstance(); - } - - private List findInstanceConversionDestinationStoragePoolsInCluster( - Cluster destinationCluster, ServiceOfferingVO serviceOffering, - Map dataDiskOfferingMap, - DataStoreTO temporaryConvertLocation, boolean forceConvertToPool) { - List poolsList; - if (!forceConvertToPool) { - Set pools = new HashSet<>(primaryDataStoreDao.findClusterWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)); - pools.addAll(primaryDataStoreDao.findZoneWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getDataCenterId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)); - if (pools.isEmpty()) { - String msg = String.format("Cannot find suitable storage pools in the cluster %s for the conversion", destinationCluster.getName()); - logger.error(msg); - throw new CloudRuntimeException(msg); - } - poolsList = new ArrayList<>(pools); - } else { - DataStore dataStore = dataStoreManager.getDataStore(temporaryConvertLocation.getUuid(), temporaryConvertLocation.getRole()); - poolsList = Collections.singletonList(primaryDataStoreDao.findById(dataStore.getId())); - } - - if (serviceOffering.getDiskOfferingId() != null) { - DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); - if (diskOffering == null) { - String msg = String.format("Cannot find disk offering with ID %s that belongs to the service offering %s", serviceOffering.getDiskOfferingId(), serviceOffering.getName()); - logger.error(msg); - throw new CloudRuntimeException(msg); - } - if (getStoragePoolWithTags(poolsList, diskOffering.getTags()) == null) { - String msg = String.format("Cannot find suitable storage pool for disk offering %s that belongs to the service offering %s", diskOffering.getName(), serviceOffering.getName()); - logger.error(msg); - throw new CloudRuntimeException(msg); - } - } - for (Long diskOfferingId : dataDiskOfferingMap.values()) { - DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId); - if (diskOffering == null) { - String msg = String.format("Cannot find disk offering with ID %s", diskOfferingId); - logger.error(msg); - throw new CloudRuntimeException(msg); - } - if (getStoragePoolWithTags(poolsList, diskOffering.getTags()) == null) { - String msg = String.format("Cannot find suitable storage pool for disk offering %s", diskOffering.getName()); - logger.error(msg); - throw new CloudRuntimeException(msg); - } - } - - return poolsList; - } - - private StoragePoolVO getStoragePoolWithTags(List pools, String tags) { - if (StringUtils.isEmpty(tags)) { - return pools.get(0); - } - for (StoragePoolVO pool : pools) { - if (volumeApiService.doesStoragePoolSupportDiskOfferingTags(pool, tags)) { - return pool; - } - } - return null; - } - - private List selectInstanceConversionStoragePools( - List pools, List disks, - ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap - ) { - List storagePools = new ArrayList<>(disks.size()); - Set dataDiskIds = dataDiskOfferingMap.keySet(); - for (UnmanagedInstanceTO.Disk disk : disks) { - Long diskOfferingId = null; - if (dataDiskIds.contains(disk.getDiskId())) { - diskOfferingId = dataDiskOfferingMap.get(disk.getDiskId()); - } else { - diskOfferingId = serviceOffering.getDiskOfferingId(); - } - - //TODO: Choose pools by capacity - if (diskOfferingId == null) { - storagePools.add(pools.get(0).getUuid()); - } else { - DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId); - StoragePoolVO pool = getStoragePoolWithTags(pools, diskOffering.getTags()); - storagePools.add(pool.getUuid()); - } - } - return storagePools; - } - - private void logFailureAndThrowException(String msg) { - logger.error(msg); - throw new CloudRuntimeException(msg); - } - - private void checkBeforeSelectingTemporaryConversionStoragePool(StoragePoolVO selectedStoragePool, Long convertStoragePoolId, Cluster destinationCluster, HostVO convertHost) { - if (selectedStoragePool == null) { - logFailureAndThrowException(String.format("Cannot find a storage pool with ID %s", convertStoragePoolId)); - } - if ((selectedStoragePool.getScope() == ScopeType.CLUSTER && selectedStoragePool.getClusterId() != destinationCluster.getId()) || - (selectedStoragePool.getScope() == ScopeType.ZONE && selectedStoragePool.getDataCenterId() != destinationCluster.getDataCenterId())) { - logFailureAndThrowException(String.format("Cannot use the storage pool %s for the instance conversion as " + - "it is not in the scope of the cluster %s", selectedStoragePool.getName(), destinationCluster.getName())); - } - if (convertHost != null && selectedStoragePool.getScope() == ScopeType.CLUSTER && !selectedStoragePool.getClusterId().equals(convertHost.getClusterId())) { - logFailureAndThrowException(String.format("Cannot use the storage pool %s for the instance conversion as " + - "the host %s for conversion is in a different cluster", selectedStoragePool.getName(), convertHost.getName())); - } - } - - private DataStoreTO getImageStoreOnDestinationZoneForTemporaryConversion(Cluster destinationCluster, boolean forceConvertToPool) { - if (forceConvertToPool) { - logFailureAndThrowException("Please select a primary storage pool when the parameter forceconverttopool is set to true"); - } - long zoneId = destinationCluster.getDataCenterId(); - ImageStoreVO imageStore = imageStoreDao.findOneByZoneAndProtocol(zoneId, "nfs"); - if (imageStore == null) { - logFailureAndThrowException(String.format("Could not find an NFS secondary storage pool on zone %s to use as a temporary location " + - "for instance conversion", zoneId)); - } - DataStore dataStore = dataStoreManager.getDataStore(imageStore.getId(), DataStoreRole.Image); - return dataStore.getTO(); - } - - private void checkDestinationOrTemporaryStoragePoolForConversion(StoragePoolVO selectedStoragePool, boolean forceConvertToPool, HostVO convertHost, HostVO importHost) { - if (selectedStoragePool.getScope() == ScopeType.HOST && (ObjectUtils.anyNull(convertHost, importHost) || - ObjectUtils.allNotNull(convertHost, importHost) && convertHost.getId() != importHost.getId() || - !forceConvertToPool) ) { - logFailureAndThrowException("Please select the same host as convert and importing host and " + - "set forceconvertopool to true to use a local storage pool for conversion"); - } - if (!forceConvertToPool && selectedStoragePool.getPoolType() != Storage.StoragePoolType.NetworkFilesystem) { - logFailureAndThrowException(String.format("The storage pool %s is not supported for temporary conversion location," + - "only NFS storage pools are supported when forceconverttopool is set to false", selectedStoragePool.getName())); - } - } - - protected DataStoreTO selectInstanceConversionTemporaryLocation(Cluster destinationCluster, - HostVO convertHost, HostVO importHost, - Long convertStoragePoolId, boolean forceConvertToPool) { - if (convertStoragePoolId == null) { - String msg = String.format("No convert storage pool has been provided, " + - "selecting an NFS secondary storage pool from the destination cluster (%s) zone", destinationCluster.getName()); - logger.debug(msg); - return getImageStoreOnDestinationZoneForTemporaryConversion(destinationCluster, forceConvertToPool); - } - - StoragePoolVO selectedStoragePool = primaryDataStoreDao.findById(convertStoragePoolId); - checkBeforeSelectingTemporaryConversionStoragePool(selectedStoragePool, convertStoragePoolId, destinationCluster, convertHost); - checkDestinationOrTemporaryStoragePoolForConversion(selectedStoragePool, forceConvertToPool, convertHost, importHost); - - return dataStoreManager.getPrimaryDataStore(convertStoragePoolId).getTO(); - } - - protected Map createParamsForTemplateFromVmwareVmMigration(String vcenterHost, String datacenterName, - String username, String password, - String clusterName, String sourceHostName, - String sourceVMName) { - Map params = new HashMap<>(); - params.put(VmDetailConstants.VMWARE_VCENTER_HOST, vcenterHost); - params.put(VmDetailConstants.VMWARE_DATACENTER_NAME, datacenterName); - params.put(VmDetailConstants.VMWARE_VCENTER_USERNAME, username); - params.put(VmDetailConstants.VMWARE_VCENTER_PASSWORD, password); - params.put(VmDetailConstants.VMWARE_CLUSTER_NAME, clusterName); - params.put(VmDetailConstants.VMWARE_HOST_NAME, sourceHostName); - params.put(VmDetailConstants.VMWARE_VM_NAME, sourceVMName); - return params; - } - - @Override - public List> getCommands() { - final List> cmdList = new ArrayList>(); - cmdList.add(ListUnmanagedInstancesCmd.class); - cmdList.add(ImportUnmanagedInstanceCmd.class); - cmdList.add(UnmanageVMInstanceCmd.class); - cmdList.add(ListVmsForImportCmd.class); - cmdList.add(ImportVmCmd.class); - cmdList.add(ListImportVMTasksCmd.class); - return cmdList; - } - - /** - * Perform validations before attempting to unmanage a VM from CloudStack: - * - VM must not have any associated volume snapshot - * - VM must not have an attached ISO - * - VM must not belong to any CKS cluster - * @throws UnsupportedServiceException in case any of the validations above fail - */ - void performUnmanageVMInstancePrechecks(VMInstanceVO vmVO) { - if (hasVolumeSnapshotsPriorToUnmanageVM(vmVO)) { - throw new UnsupportedServiceException("Cannot unmanage VM with id = " + vmVO.getUuid() + - " as there are volume snapshots for its volume(s). Please remove snapshots before unmanaging."); - } - - if (hasISOAttached(vmVO)) { - throw new UnsupportedServiceException("Cannot unmanage VM with id = " + vmVO.getUuid() + - " as there is an ISO attached. Please detach ISO before unmanaging."); - } - - if (userVmManager.isVMPartOfAnyCKSCluster(vmVO)) { - throw new UnsupportedServiceException("Cannot unmanage VM with id = " + vmVO.getUuid() + - " as it belongs to a CKS cluster. Please remove the VM from the CKS cluster before unmanaging."); - } - } - - private boolean hasVolumeSnapshotsPriorToUnmanageVM(VMInstanceVO vmVO) { - List volumes = volumeDao.findByInstance(vmVO.getId()); - for (VolumeVO volume : volumes) { - List snaps = snapshotDao.listByVolumeId(volume.getId()); - if (CollectionUtils.isNotEmpty(snaps)) { - for (SnapshotVO snap : snaps) { - if (snap.getState() != Snapshot.State.Destroyed && snap.getRemoved() == null) { - return true; - } - } - } - } - return false; - } - - private boolean hasISOAttached(VMInstanceVO vmVO) { - UserVmVO userVM = userVmDao.findById(vmVO.getId()); - if (userVM == null) { - throw new InvalidParameterValueException("Could not find user VM with ID = " + vmVO.getUuid()); - } - return userVM.getIsoId() != null; - } - - /** - * Find a suitable host within the scope of the VM to unmanage to verify the VM exists - */ - private Long findSuitableHostId(VMInstanceVO vmVO) { - Long hostId = vmVO.getHostId(); - if (hostId == null) { - long zoneId = vmVO.getDataCenterId(); - List hosts = hostDao.listAllHostsUpByZoneAndHypervisor(zoneId, vmVO.getHypervisorType()); - for (HostVO host : hosts) { - if (host.isInMaintenanceStates() || host.getState() != Status.Up || host.getStatus() != Status.Up) { - continue; - } - hostId = host.getId(); - break; - } - } - - if (hostId == null) { - throw new CloudRuntimeException(String.format("Cannot find a host to verify if the VM [%s] exists. Thus we are unable to unmanage it.", vmVO.getUuid())); - } - return hostId; - } - - @Override - @ActionEvent(eventType = EventTypes.EVENT_VM_UNMANAGE, eventDescription = "unmanaging VM", async = true) - public Pair unmanageVMInstance(long vmId, Long paramHostId, boolean isForced) { - VMInstanceVO vmVO = vmDao.findById(vmId); - if (vmVO == null || vmVO.getRemoved() != null) { - throw new InvalidParameterValueException("Could not find VM to unmanage, it is either removed or not existing VM"); - } else if (vmVO.getState() != VirtualMachine.State.Running && vmVO.getState() != VirtualMachine.State.Stopped) { - throw new InvalidParameterValueException("VM with id = " + vmVO.getUuid() + " must be running or stopped to be unmanaged"); - } else if (!UnmanagedVMsManager.isSupported(vmVO.getHypervisorType())) { - throw new UnsupportedServiceException("Unmanage VM is currently not allowed for hypervisor " + - vmVO.getHypervisorType().toString()); - } else if (vmVO.getType() != VirtualMachine.Type.User) { - throw new UnsupportedServiceException("Unmanage VM is currently allowed for guest VMs only"); - } else if (paramHostId != null && - (vmVO.getHypervisorType() != Hypervisor.HypervisorType.KVM || vmVO.getState() != VirtualMachine.State.Stopped)) { - throw new UnsupportedServiceException("Param hostid is only supported for KVM hypervisor for stopped Instances."); - } else if (!isForced && vmVO.getHypervisorType() == Hypervisor.HypervisorType.KVM - && vmInstanceDetailsDao.findDetail(vmId, VmDetailConstants.CONFIG_DRIVE_LOCATION) != null) { - throw new UnsupportedServiceException("Config drive is attached to Instance, use forced param true from API to unmanage it."); - } - - if (vmVO.getType().equals(VirtualMachine.Type.User)) { - UserVmVO userVm = userVmDao.findById(vmId); - if (UserVmManager.SHAREDFSVM.equals(userVm.getUserVmType())) { - throw new InvalidParameterValueException("Operation not supported on Shared FileSystem Instance"); - } - } - - performUnmanageVMInstancePrechecks(vmVO); - - boolean isKvmVmStopped = VirtualMachine.State.Stopped.equals(vmVO.getState()) && vmVO.getHypervisorType() == Hypervisor.HypervisorType.KVM; - Long hostId = isKvmVmStopped ? vmVO.getLastHostId() : findSuitableHostId(vmVO); - String instanceName = vmVO.getInstanceName(); - - if (!isKvmVmStopped && !existsVMToUnmanage(instanceName, hostId)) { - throw new CloudRuntimeException(String.format("VM %s is not found in the hypervisor", vmVO)); - } - - return userVmManager.unmanageUserVM(vmId, paramHostId); - } - - /** - * Verify the VM to unmanage exists on the hypervisor - */ - private boolean existsVMToUnmanage(String instanceName, Long hostId) { - PrepareUnmanageVMInstanceCommand command = new PrepareUnmanageVMInstanceCommand(); - command.setInstanceName(instanceName); - Answer ans = agentManager.easySend(hostId, command); - if (!(ans instanceof PrepareUnmanageVMInstanceAnswer)) { - throw new CloudRuntimeException(String.format("Error communicating with host %s", hostDao.findById(hostId))); - } - PrepareUnmanageVMInstanceAnswer answer = (PrepareUnmanageVMInstanceAnswer) ans; - if (!answer.getResult()) { - logger.error("Error verifying VM {} exists on host {}: {}", instanceName::toString, () -> hostDao.findById(hostId), answer::getDetails); - } - return answer.getResult(); - } - - private UserVmResponse importKvmInstance(ImportVmCmd cmd) { - final Account caller = CallContext.current().getCallingAccount(); - if (caller.getType() != Account.Type.ADMIN) { - throw new PermissionDeniedException(String.format("Cannot perform this operation, Calling account is not root admin: %s", caller.getUuid())); - } - final Long zoneId = cmd.getZoneId(); - final DataCenterVO zone = dataCenterDao.findById(zoneId); - if (zone == null) { - throw new InvalidParameterValueException("Please specify a valid zone."); - } - final String hypervisorType = cmd.getHypervisor(); - if (!Hypervisor.HypervisorType.KVM.toString().equalsIgnoreCase(hypervisorType)) { - throw new InvalidParameterValueException(String.format("VM import is currently not supported for hypervisor: %s", hypervisorType)); - } - - final String instanceName = cmd.getName(); - if (StringUtils.isEmpty(instanceName)) { - throw new InvalidParameterValueException(String.format("Instance name cannot be empty")); - } - if (cmd.getDomainId() != null && StringUtils.isEmpty(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()); - if (CollectionUtils.isNotEmpty(userVOs)) { - userId = userVOs.get(0).getId(); - } - VMTemplateVO template = getTemplateForImportInstance(cmd.getTemplateId(), Hypervisor.HypervisorType.KVM); - 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); - String displayName = cmd.getDisplayName(); - if (StringUtils.isEmpty(displayName)) { - displayName = instanceName; - } - String hostName = cmd.getHostName(); - if (StringUtils.isEmpty(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(); - - String remoteUrl = cmd.getHost(); - String source = cmd.getImportSource().toUpperCase(); - String diskPath = cmd.getDiskPath(); - ImportSource importSource = Enum.valueOf(ImportSource.class, source); - Long hostId = cmd.getHostId(); - Long poolId = cmd.getStoragePoolId(); - Long networkId = cmd.getNetworkId(); - - UnmanagedInstanceTO unmanagedInstanceTO = null; - if (ImportSource.EXTERNAL == importSource) { - if (StringUtils.isBlank(cmd.getUsername())) { - throw new InvalidParameterValueException("Username need to be provided."); - } - - HashMap instancesMap = getRemoteVmsOnKVMHost(zoneId, remoteUrl, cmd.getUsername(), cmd.getPassword()); - unmanagedInstanceTO = instancesMap.get(cmd.getName()); - if (unmanagedInstanceTO == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM with name: %s not found on remote host %s", instanceName, remoteUrl)); - } - } - - if (ImportSource.SHARED == importSource || ImportSource.LOCAL == importSource) { - if (diskPath == null) { - throw new InvalidParameterValueException("Disk Path is required for Import from shared/local storage"); - } - - if (networkId == null) { - throw new InvalidParameterValueException("Network is required for Import from shared/local storage"); - } - - if (poolId == null) { - throw new InvalidParameterValueException("Storage Pool is required for Import from shared/local storage"); - } - - StoragePool storagePool = primaryDataStoreDao.findById(poolId); - if (storagePool == null) { - throw new InvalidParameterValueException("Storage Pool not found"); - } - - if (volumeDao.findByPoolIdAndPath(poolId, diskPath) != null) { - throw new InvalidParameterValueException("Disk image is already in use"); - } - - DiskOffering diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); - - if (diskOffering != null && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) { - throw new InvalidParameterValueException(String.format("Service offering: %s storage tags are not compatible with selected storage pool: %s", serviceOffering.getUuid(), storagePool.getUuid())); - } - } - - if (ImportSource.LOCAL == importSource) { - if (hostId == null) { - throw new InvalidParameterValueException("Host is required for Import from local storage"); - } - - if (hostDao.findById(hostId) == null) { - throw new InvalidParameterValueException("Host not found"); - } - - if(storagePoolHostDao.findByPoolHost(poolId, hostId) == null) { - throw new InvalidParameterValueException("Specified Local Storage Pool not found on Host"); - } - } - - UserVm userVm = null; - - try { - - if (ImportSource.EXTERNAL == importSource) { - String username = cmd.getUsername(); - String password = cmd.getPassword(); - String tmpPath = cmd.getTmpPath(); - userVm = importExternalKvmVirtualMachine(unmanagedInstanceTO, instanceName, zone, - template, displayName, hostName, caller, owner, userId, - serviceOffering, dataDiskOfferingMap, - nicNetworkMap, nicIpAddressMap, remoteUrl, username, password, tmpPath, details); - } else if (ImportSource.SHARED == importSource || ImportSource.LOCAL == importSource) { - try { - userVm = importKvmVirtualMachineFromDisk(importSource, instanceName, zone, - template, displayName, hostName, caller, owner, userId, - serviceOffering, dataDiskOfferingMap, networkId, hostId, poolId, diskPath, - details); - } catch (InsufficientCapacityException e) { - throw new RuntimeException(e); - } catch (ResourceAllocationException e) { - throw new RuntimeException(e); - } - } - - } 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(), StringUtils.defaultString(e.getMessage()))); - } - - if (userVm == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import Vm with name: %s ", instanceName)); - } - - CallContext.current().setEventResourceId(userVm.getId()); - CallContext.current().setEventResourceType(ApiCommandResourceType.VirtualMachine); - return responseGenerator.createUserVmResponse(ResponseObject.ResponseView.Full, "virtualmachine", userVm).get(0); - } - - private UserVm importExternalKvmVirtualMachine(final UnmanagedInstanceTO unmanagedInstance, final String instanceName, final DataCenter zone, - final VirtualMachineTemplate template, final String displayName, final String hostName, final Account caller, final Account owner, final Long userId, - final ServiceOfferingVO serviceOffering, final Map dataDiskOfferingMap, - final Map nicNetworkMap, final Map callerNicIpAddressMap, - final String remoteUrl, String username, String password, String tmpPath, final Map details) throws ResourceAllocationException { - UserVm userVm = null; - - Map allDetails = new HashMap<>(details); - // 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)); - } - - DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); - Pair> rootAndDataDisksPair = getRootAndDataDisks(unmanagedInstanceDisks, dataDiskOfferingMap); - final UnmanagedInstanceTO.Disk rootDisk = rootAndDataDisksPair.first(); - final List dataDisks = rootAndDataDisksPair.second(); - if (rootDisk == null || StringUtils.isEmpty(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 reservations = new ArrayList<>(); - try { - checkVmResourceLimitsForExternalKvmVmImport(owner, serviceOffering, (VMTemplateVO) template, details, reservations); - checkVolumeResourceLimitsForExternalKvmVmImport(owner, rootDisk, dataDisks, diskOffering, dataDiskOfferingMap, reservations); - - // Check NICs and supplied networks - Map nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap); - Map allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getName(), unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner, Hypervisor.HypervisorType.KVM); - if (!CollectionUtils.isEmpty(unmanagedInstance.getNics())) { - allDetails.put(VmDetailConstants.NIC_ADAPTER, unmanagedInstance.getNics().get(0).getAdapterType()); - } - VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff; - - try { - userVm = userVmManager.importVM(zone, null, template, null, displayName, owner, - null, caller, true, null, owner.getAccountId(), userId, - serviceOffering, null, null, hostName, - Hypervisor.HypervisorType.KVM, allDetails, powerState, null); - } 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)); - } - String rootVolumeName = String.format("ROOT-%s", userVm.getId()); - DiskProfile diskProfile = volumeManager.allocateRawVolume(Volume.Type.ROOT, rootVolumeName, diskOffering, null, null, null, userVm, template, owner, null, false); - - DiskProfile[] dataDiskProfiles = new DiskProfile[dataDisks.size()]; - int diskSeq = 0; - for (UnmanagedInstanceTO.Disk disk : dataDisks) { - DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId())); - DiskProfile dataDiskProfile = volumeManager.allocateRawVolume(Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()), offering, null, null, null, userVm, template, owner, null, false); - dataDiskProfiles[diskSeq++] = dataDiskProfile; - } - - final VirtualMachineProfile profile = new VirtualMachineProfileImpl(userVm, template, serviceOffering, owner, null); - ServiceOfferingVO dummyOffering = serviceOfferingDao.findById(userVm.getId(), serviceOffering.getId()); - profile.setServiceOffering(dummyOffering); - DeploymentPlanner.ExcludeList excludeList = new DeploymentPlanner.ExcludeList(); - final DataCenterDeployment plan = new DataCenterDeployment(zone.getId(), null, null, null, null, null); - DeployDestination dest = null; - try { - dest = deploymentPlanningManager.planDeployment(profile, plan, excludeList, null); - } catch (Exception e) { - logger.warn("Import failed for Vm: {} while finding deployment destination", userVm, e); - cleanupFailedImportVM(userVm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s while finding deployment destination", userVm.getInstanceName())); - } - if(dest == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s. Suitable deployment destination not found", userVm.getInstanceName())); - } - - List> diskProfileStoragePoolList = new ArrayList<>(); - try { - diskProfileStoragePoolList.add(importExternalDisk(rootDisk, userVm, dest, diskOffering, Volume.Type.ROOT, - template, null, remoteUrl, username, password, tmpPath, diskProfile)); - - long deviceId = 1L; - diskSeq = 0; - for (UnmanagedInstanceTO.Disk disk : dataDisks) { - DiskProfile dataDiskProfile = dataDiskProfiles[diskSeq++]; - DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId())); - - diskProfileStoragePoolList.add(importExternalDisk(disk, userVm, dest, offering, Volume.Type.DATADISK, - template, deviceId, remoteUrl, username, password, tmpPath, dataDiskProfile)); - deviceId++; - } - } catch (Exception e) { - logger.error(String.format("Failed to import volumes while importing vm: %s", instanceName), e); - cleanupFailedImportVM(userVm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", instanceName, StringUtils.defaultString(e.getMessage()))); - } - try { - int nicIndex = 0; - 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, nicIndex, nicIndex==0, true); - nicIndex++; - } - } catch (Exception e) { - logger.error(String.format("Failed to import NICs while importing vm: %s", instanceName), e); - cleanupFailedImportVM(userVm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import NICs while importing vm: %s. %s", instanceName, StringUtils.defaultString(e.getMessage()))); - } - publishVMUsageUpdateResourceCount(userVm, dummyOffering, template); - return userVm; - - } finally { - ReservationHelper.closeAll(reservations); - } - } - - protected void checkVolumeResourceLimitsForExternalKvmVmImport(Account owner, UnmanagedInstanceTO.Disk rootDisk, - List dataDisks, DiskOfferingVO rootDiskOffering, - Map dataDiskOfferingMap, List reservations) throws ResourceAllocationException { - if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) { - throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId())); - } - resourceLimitService.checkVolumeResourceLimit(owner, true, rootDisk.getCapacity(), rootDiskOffering, reservations); - - if (CollectionUtils.isEmpty(dataDisks)) { - return; - } - for (UnmanagedInstanceTO.Disk disk : dataDisks) { - if (disk.getCapacity() == null || disk.getCapacity() == 0) { - throw new InvalidParameterValueException(String.format("Data disk ID: %s size is invalid", disk.getDiskId())); - } - DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId())); - resourceLimitService.checkVolumeResourceLimit(owner, true, disk.getCapacity(), offering, reservations); - } - } - - private UserVm importKvmVirtualMachineFromDisk(final ImportSource importSource, final String instanceName, final DataCenter zone, - final VirtualMachineTemplate template, final String displayName, final String hostName, final Account caller, final Account owner, final Long userId, - final ServiceOfferingVO serviceOffering, final Map dataDiskOfferingMap, final Long networkId, - final Long hostId, final Long poolId, final String diskPath, final Map details) throws InsufficientCapacityException, ResourceAllocationException { - - UserVm userVm = null; - - Map allDetails = new HashMap<>(details); - - VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff; - - NetworkVO network = networkDao.findById(networkId); - if (network == null) { - throw new InvalidParameterValueException("Unable to find network by id " + networkId); - } - - networkModel.checkNetworkPermissions(owner, network); - - // don't allow to use system networks - NetworkOffering networkOffering = entityMgr.findById(NetworkOffering.class, network.getNetworkOfferingId()); - if (networkOffering.isSystemOnly()) { - throw new InvalidParameterValueException("Network id=" + networkId + " is system only and can't be used for vm deployment"); - } - - LinkedHashMap> networkNicMap = new LinkedHashMap<>(); - - if ((network.getDataCenterId() != zone.getId())) { - if (!network.isStrechedL2Network()) { - throw new InvalidParameterValueException("Network id=" + network.getId() + - " doesn't belong to zone " + zone.getId()); - } - } - - String macAddress = networkModel.getNextAvailableMacAddressInNetwork(networkId); - - String ipAddress = network.getGuestType() != Network.GuestType.L2 ? "auto" : null; - - Network.IpAddresses requestedIpPair = new Network.IpAddresses(ipAddress, null, macAddress); - - NicProfile nicProfile = new NicProfile(requestedIpPair.getIp4Address(), requestedIpPair.getIp6Address(), requestedIpPair.getMacAddress()); - nicProfile.setOrderIndex(0); - - boolean securityGroupEnabled = false; - if (networkModel.isSecurityGroupSupportedInNetwork(network)) { - securityGroupEnabled = true; - } - List profiles = networkNicMap.get(network.getUuid()); - if (CollectionUtils.isEmpty(profiles)) { - profiles = new ArrayList<>(); - } - profiles.add(nicProfile); - networkNicMap.put(network.getUuid(), profiles); - - List reservations = new ArrayList<>(); - try { - checkVmResourceLimitsForExternalKvmVmImport(owner, serviceOffering, (VMTemplateVO) template, details, reservations); - userVm = userVmManager.importVM(zone, null, template, null, displayName, owner, - null, caller, true, null, owner.getAccountId(), userId, - serviceOffering, null, null, hostName, - Hypervisor.HypervisorType.KVM, allDetails, powerState, networkNicMap); - - if (userVm == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import vm name: %s", instanceName)); - } - - DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); - List resourceLimitStorageTags = resourceLimitService.getResourceLimitStorageTagsForResourceCountOperation(true, diskOffering); - CheckedReservation volumeReservation = new CheckedReservation(owner, Resource.ResourceType.volume, resourceLimitStorageTags, - CollectionUtils.isNotEmpty(resourceLimitStorageTags) ? 1L : 0L, reservationDao, resourceLimitService); - reservations.add(volumeReservation); - - String rootVolumeName = String.format("ROOT-%s", userVm.getId()); - DiskProfile diskProfile = volumeManager.allocateRawVolume(Volume.Type.ROOT, rootVolumeName, diskOffering, null, null, null, userVm, template, owner, null, false); - - final VirtualMachineProfile profile = new VirtualMachineProfileImpl(userVm, template, serviceOffering, owner, null); - ServiceOfferingVO dummyOffering = serviceOfferingDao.findById(userVm.getId(), serviceOffering.getId()); - profile.setServiceOffering(dummyOffering); - DeploymentPlanner.ExcludeList excludeList = new DeploymentPlanner.ExcludeList(); - final DataCenterDeployment plan = new DataCenterDeployment(zone.getId(), null, null, hostId, poolId, null); - DeployDestination dest = null; - try { - dest = deploymentPlanningManager.planDeployment(profile, plan, excludeList, null); - } catch (Exception e) { - logger.warn("Import failed for Vm: {} while finding deployment destination", userVm, e); - cleanupFailedImportVM(userVm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s while finding deployment destination", userVm.getInstanceName())); - } - if(dest == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s. Suitable deployment destination not found", userVm.getInstanceName())); - } - - Map storage = dest.getStorageForDisks(); - Volume volume = volumeDao.findById(diskProfile.getVolumeId()); - StoragePool storagePool = storage.get(volume); - CheckVolumeCommand checkVolumeCommand = new CheckVolumeCommand(); - checkVolumeCommand.setSrcFile(diskPath); - StorageFilerTO storageTO = new StorageFilerTO(storagePool); - checkVolumeCommand.setStorageFilerTO(storageTO); - Answer answer = agentManager.easySend(dest.getHost().getId(), checkVolumeCommand); - if (!(answer instanceof CheckVolumeAnswer)) { - cleanupFailedImportVM(userVm); - throw new CloudRuntimeException("Disk not found or is invalid"); - } - CheckVolumeAnswer checkVolumeAnswer = (CheckVolumeAnswer) answer; - try { - checkVolume(checkVolumeAnswer.getVolumeDetails()); - } catch (CloudRuntimeException e) { - cleanupFailedImportVM(userVm); - throw e; - } - if (!checkVolumeAnswer.getResult()) { - cleanupFailedImportVM(userVm); - throw new CloudRuntimeException("Disk not found or is invalid"); - } - diskProfile.setSize(checkVolumeAnswer.getSize()); - - CheckedReservation primaryStorageReservation = new CheckedReservation(owner, Resource.ResourceType.primary_storage, resourceLimitStorageTags, - CollectionUtils.isNotEmpty(resourceLimitStorageTags) ? diskProfile.getSize() : 0L, reservationDao, resourceLimitService); - reservations.add(primaryStorageReservation); - - List> diskProfileStoragePoolList = new ArrayList<>(); - try { - long deviceId = 1L; - if(ImportSource.SHARED == importSource) { - diskProfileStoragePoolList.add(importKVMSharedDisk(userVm, diskOffering, Volume.Type.ROOT, - template, deviceId, poolId, diskPath, diskProfile)); - } else if(ImportSource.LOCAL == importSource) { - diskProfileStoragePoolList.add(importKVMLocalDisk(userVm, diskOffering, Volume.Type.ROOT, - template, deviceId, hostId, diskPath, diskProfile)); - } - } catch (Exception e) { - logger.error(String.format("Failed to import volumes while importing vm: %s", instanceName), e); - cleanupFailedImportVM(userVm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", instanceName, StringUtils.defaultString(e.getMessage()))); - } - networkOrchestrationService.importNic(macAddress, 0, network, true, userVm, requestedIpPair, zone, true); - publishVMUsageUpdateResourceCount(userVm, dummyOffering, template); - return userVm; - - } catch (InsufficientCapacityException ice) { // This will be thrown by com.cloud.vm.UserVmService.importVM - logger.error(String.format("Failed to import vm name: %s", instanceName), ice); - throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ice.getMessage()); - } catch (ResourceAllocationException e) { - cleanupFailedImportVM(userVm); - throw e; - } finally { - ReservationHelper.closeAll(reservations); - } - } - - protected void checkVmResourceLimitsForExternalKvmVmImport(Account owner, ServiceOfferingVO serviceOffering, VMTemplateVO template, Map details, List reservations) throws ResourceAllocationException { - // When importing an external VM, the amount of CPUs and memory is always obtained from the compute offering, - // unlike the unmanaged instance import that obtains it from the hypervisor unless the VM is powered off and the offering is fixed - Integer cpu = serviceOffering.getCpu(); - Integer memory = serviceOffering.getRamSize(); - - if (serviceOffering.isDynamic()) { - cpu = getDetailAsInteger(VmDetailConstants.CPU_NUMBER, details); - memory = getDetailAsInteger(VmDetailConstants.MEMORY, details); - } - - List resourceLimitHostTags = resourceLimitService.getResourceLimitHostTags(serviceOffering, template); - - CheckedReservation vmReservation = new CheckedReservation(owner, Resource.ResourceType.user_vm, resourceLimitHostTags, 1L, reservationDao, resourceLimitService); - reservations.add(vmReservation); - - CheckedReservation cpuReservation = new CheckedReservation(owner, Resource.ResourceType.cpu, resourceLimitHostTags, cpu.longValue(), reservationDao, resourceLimitService); - reservations.add(cpuReservation); - - CheckedReservation memReservation = new CheckedReservation(owner, Resource.ResourceType.memory, resourceLimitHostTags, memory.longValue(), reservationDao, resourceLimitService); - reservations.add(memReservation); - } - - protected Integer getDetailAsInteger(String key, Map details) { - String detail = details.get(key); - if (detail == null) { - throw new InvalidParameterValueException(String.format("Detail '%s' must be provided.", key)); - } - try { - return Integer.valueOf(detail); - } catch (NumberFormatException e) { - throw new InvalidParameterValueException(String.format("Please provide a valid integer value for detail '%s'.", key)); - } - } - - private void checkVolume(Map volumeDetails) { - if (MapUtils.isEmpty(volumeDetails)) { - return; - } - - if (volumeDetails.containsKey(VolumeOnStorageTO.Detail.IS_LOCKED)) { - String isLocked = volumeDetails.get(VolumeOnStorageTO.Detail.IS_LOCKED); - if (Boolean.parseBoolean(isLocked)) { - logFailureAndThrowException("Locked volume cannot be imported or unmanaged."); - } - } - if (volumeDetails.containsKey(VolumeOnStorageTO.Detail.IS_ENCRYPTED)) { - String isEncrypted = volumeDetails.get(VolumeOnStorageTO.Detail.IS_ENCRYPTED); - if (Boolean.parseBoolean(isEncrypted)) { - logFailureAndThrowException("Encrypted volume cannot be imported or unmanaged."); - } - } - if (volumeDetails.containsKey(VolumeOnStorageTO.Detail.BACKING_FILE)) { - String backingFile = volumeDetails.get(VolumeOnStorageTO.Detail.BACKING_FILE); - if (StringUtils.isNotBlank(backingFile) && !AllowImportVolumeWithBackingFile.value()) { - logFailureAndThrowException("Volume with backing file cannot be imported or unmanaged."); - } - } - } - - private NetworkVO getDefaultNetwork(DataCenter zone, Account owner, boolean selectAny) throws InsufficientCapacityException, ResourceAllocationException { - NetworkVO defaultNetwork = null; - - // if no network is passed in - // Check if default virtual network offering has - // Availability=Required. If it's true, search for corresponding - // network - // * if network is found, use it. If more than 1 virtual network is - // found, throw an error - // * if network is not found, create a new one and use it - - List requiredOfferings = networkOfferingDao.listByAvailability(NetworkOffering.Availability.Required, false); - if (requiredOfferings.size() < 1) { - throw new InvalidParameterValueException("Unable to find network offering with availability=" + NetworkOffering.Availability.Required - + " to automatically create the network as a part of vm creation"); - } - - if (requiredOfferings.get(0).getState() == NetworkOffering.State.Enabled) { - // get Virtual networks - List virtualNetworks = networkModel.listNetworksForAccount(owner.getId(), zone.getId(), Network.GuestType.Isolated); - if (virtualNetworks == null) { - throw new InvalidParameterValueException("No (virtual) networks are found for account " + owner); - } - if (virtualNetworks.isEmpty()) { - defaultNetwork = createDefaultNetworkForAccount(zone, owner, requiredOfferings); - } else if (virtualNetworks.size() > 1 && !selectAny) { - throw new InvalidParameterValueException("More than 1 default Isolated networks are found for account " + owner + "; please specify networkIds"); - } else { - defaultNetwork = networkDao.findById(virtualNetworks.get(0).getId()); - } - } else { - throw new InvalidParameterValueException("Required network offering id=" + requiredOfferings.get(0).getId() + " is not in " + NetworkOffering.State.Enabled); - } - - return defaultNetwork; - } - - private NetworkVO createDefaultNetworkForAccount(DataCenter zone, Account owner, List requiredOfferings) - throws InsufficientCapacityException, ResourceAllocationException { - NetworkVO defaultNetwork = null; - long physicalNetworkId = networkModel.findPhysicalNetworkId(zone.getId(), requiredOfferings.get(0).getTags(), requiredOfferings.get(0).getTrafficType()); - // Validate physical network - PhysicalNetwork physicalNetwork = physicalNetworkDao.findById(physicalNetworkId); - if (physicalNetwork == null) { - throw new InvalidParameterValueException("Unable to find physical network with id: " + physicalNetworkId + " and tag: " - + requiredOfferings.get(0).getTags()); - } - logger.debug("Creating network for account {} from the network offering {} as a part of deployVM process", owner, requiredOfferings.get(0)); - Network newNetwork = networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName() + "-network", - null, null, null, false, null, owner, null, physicalNetwork, zone.getId(), ControlledEntity.ACLType.Account, null, null, null, null, true, null, null, - null, null, null, null, null, null, null, null, null); - if (newNetwork != null) { - defaultNetwork = networkDao.findById(newNetwork.getId()); - } - return defaultNetwork; - } - - public ListResponse listVmsForImport(ListVmsForImportCmd cmd) { - final Account caller = CallContext.current().getCallingAccount(); - if (caller.getType() != Account.Type.ADMIN) { - throw new PermissionDeniedException(String.format("Cannot perform this operation, Calling account is not root admin: %s", caller.getUuid())); - } - final Long zoneId = cmd.getZoneId(); - final DataCenterVO zone = dataCenterDao.findById(zoneId); - if (zone == null) { - throw new InvalidParameterValueException("Please specify a valid zone."); - } - final String hypervisorType = cmd.getHypervisor(); - if (!Hypervisor.HypervisorType.KVM.toString().equalsIgnoreCase(hypervisorType)) { - throw new InvalidParameterValueException(String.format("VM Import is currently not supported for hypervisor: %s", hypervisorType)); - } - - String keyword = cmd.getKeyword(); - if (StringUtils.isNotEmpty(keyword)) { - keyword = keyword.toLowerCase(); - } - - List responses = new ArrayList<>(); - HashMap vmMap = getRemoteVmsOnKVMHost(zoneId, cmd.getHost(), cmd.getUsername(), cmd.getPassword()); - for (String key : vmMap.keySet()) { - UnmanagedInstanceTO instance = vmMap.get(key); - if (StringUtils.isNotEmpty(keyword) && - !instance.getName().toLowerCase().contains(keyword)) { - continue; - } - responses.add(responseGenerator.createUnmanagedInstanceResponse(instance, null, null)); - } - ListResponse listResponses = new ListResponse<>(); - listResponses.setResponses(responses, responses.size()); - return listResponses; - } - - private HashMap getRemoteVmsOnKVMHost(long zoneId, String remoteHostUrl, String username, String password) { - //ToDo: add option to list one Vm by name - List hosts = resourceManager.listAllUpAndEnabledHostsInOneZoneByHypervisor(Hypervisor.HypervisorType.KVM, zoneId); - if (hosts.size() < 1) { - throw new CloudRuntimeException("No hosts available to list VMs on remote host " + remoteHostUrl); - } - HostVO host = hosts.get(0); - GetRemoteVmsCommand getRemoteVmsCommand = new GetRemoteVmsCommand(remoteHostUrl, username, password); - Answer answer = agentManager.easySend(host.getId(), getRemoteVmsCommand); - if (!(answer instanceof GetRemoteVmsAnswer)) { - throw new CloudRuntimeException("Failed to list VMs, due to: " + answer.getDetails()); - } - GetRemoteVmsAnswer getRemoteVmsAnswer = (GetRemoteVmsAnswer) answer; - return getRemoteVmsAnswer.getUnmanagedInstances(); - } - - @Override - public String getConfigComponentName() { - return UnmanagedVMsManagerImpl.class.getSimpleName(); - } - - @Override - public ConfigKey[] getConfigKeys() { - return new ConfigKey[]{ - UnmanageVMPreserveNic, - RemoteKvmInstanceDisksCopyTimeout, - ConvertVmwareInstanceToKvmTimeout, - ThreadsOnMSToImportVMwareVMFiles, - ThreadsOnKVMHostToImportVMwareVMFiles, - ConvertVmwareInstanceToKvmExtraParamsAllowed, - ConvertVmwareInstanceToKvmExtraParamsAllowedList - }; - } -} +// 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 com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CheckConvertInstanceAnswer; +import com.cloud.agent.api.CheckConvertInstanceCommand; +import com.cloud.agent.api.CheckVolumeAnswer; +import com.cloud.agent.api.CheckVolumeCommand; +import com.cloud.agent.api.ConvertInstanceAnswer; +import com.cloud.agent.api.ConvertInstanceCommand; +import com.cloud.agent.api.CopyRemoteVolumeAnswer; +import com.cloud.agent.api.CopyRemoteVolumeCommand; +import com.cloud.agent.api.GetRemoteVmsAnswer; +import com.cloud.agent.api.GetRemoteVmsCommand; +import com.cloud.agent.api.GetUnmanagedInstancesAnswer; +import com.cloud.agent.api.GetUnmanagedInstancesCommand; +import com.cloud.agent.api.ImportConvertedInstanceAnswer; +import com.cloud.agent.api.ImportConvertedInstanceCommand; +import com.cloud.agent.api.PrepareUnmanageVMInstanceAnswer; +import com.cloud.agent.api.PrepareUnmanageVMInstanceCommand; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.RemoteInstanceTO; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.configuration.Config; +import com.cloud.configuration.Resource; +import com.cloud.dc.DataCenter; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.VmwareDatacenterVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.VmwareDatacenterDao; +import com.cloud.deploy.DataCenterDeployment; +import com.cloud.deploy.DeployDestination; +import com.cloud.deploy.DeploymentPlanner; +import com.cloud.deploy.DeploymentPlanningManager; +import com.cloud.event.ActionEvent; +import com.cloud.event.ActionEventUtils; +import com.cloud.event.EventTypes; +import com.cloud.event.EventVO; +import com.cloud.event.UsageEventUtils; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.InsufficientAddressCapacityException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InsufficientVirtualNetworkCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.OperationTimedoutException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.UnsupportedServiceException; +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.hypervisor.HypervisorGuru; +import com.cloud.hypervisor.HypervisorGuruManager; +import com.cloud.network.Network; +import com.cloud.network.NetworkModel; +import com.cloud.network.Networks; +import com.cloud.network.PhysicalNetwork; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkVO; +import com.cloud.network.dao.PhysicalNetworkDao; +import com.cloud.offering.DiskOffering; +import com.cloud.offering.NetworkOffering; +import com.cloud.offering.ServiceOffering; +import com.cloud.offerings.NetworkOfferingVO; +import com.cloud.offerings.dao.NetworkOfferingDao; +import com.cloud.org.Cluster; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceState; +import com.cloud.resourcelimit.CheckedReservation; +import com.cloud.resourcelimit.ReservationHelper; +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.DataStoreRole; +import com.cloud.storage.DiskOfferingVO; +import com.cloud.storage.GuestOS; +import com.cloud.storage.GuestOSHypervisor; +import com.cloud.storage.ScopeType; +import com.cloud.storage.Snapshot; +import com.cloud.storage.SnapshotVO; +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.SnapshotDao; +import com.cloud.storage.dao.StoragePoolHostDao; +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.LogUtils; +import com.cloud.utils.Pair; +import com.cloud.utils.UuidUtils; +import com.cloud.utils.db.EntityManager; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.net.NetUtils; +import com.cloud.vm.DiskProfile; +import com.cloud.vm.NicProfile; +import com.cloud.vm.NicVO; +import com.cloud.vm.UserVmManager; +import com.cloud.vm.UserVmVO; +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.UserVmDao; +import com.cloud.vm.dao.VMInstanceDetailsDao; +import com.cloud.vm.dao.VMInstanceDao; +import com.google.gson.Gson; +import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.ApiCommandResourceType; +import org.apache.cloudstack.api.ApiConstants; +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.ImportVmCmd; +import org.apache.cloudstack.api.command.admin.vm.ListImportVMTasksCmd; +import org.apache.cloudstack.api.command.admin.vm.ListUnmanagedInstancesCmd; +import org.apache.cloudstack.api.command.admin.vm.ListVmsForImportCmd; +import org.apache.cloudstack.api.command.admin.vm.UnmanageVMInstanceCmd; +import org.apache.cloudstack.api.response.ListResponse; +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.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.framework.config.ConfigKey; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.reservation.dao.ReservationDao; +import org.apache.cloudstack.resourcelimit.Reserver; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.storage.volume.VolumeOnStorageTO; +import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import javax.inject.Inject; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.stream.Collectors; + +import static org.apache.cloudstack.api.ApiConstants.MAX_IOPS; +import static org.apache.cloudstack.api.ApiConstants.MIN_IOPS; +import static org.apache.cloudstack.storage.volume.VolumeImportUnmanageService.AllowImportVolumeWithBackingFile; +import static org.apache.cloudstack.vm.ImportVmTask.Step.CloningInstance; +import static org.apache.cloudstack.vm.ImportVmTask.Step.Completed; +import static org.apache.cloudstack.vm.ImportVmTask.Step.ConvertingInstance; +import static org.apache.cloudstack.vm.ImportVmTask.Step.Importing; + +public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { + protected Logger logger = LogManager.getLogger(UnmanagedVMsManagerImpl.class); + private static final long OTHER_LINUX_64_GUEST_OS_ID = 99; + private static final List importUnmanagedInstancesSupportedHypervisors = + Arrays.asList(Hypervisor.HypervisorType.VMware, Hypervisor.HypervisorType.KVM); + + private static final List forceConvertToPoolAllowedTypes = + Arrays.asList(Storage.StoragePoolType.NetworkFilesystem, Storage.StoragePoolType.Filesystem, + Storage.StoragePoolType.SharedMountPoint); + private static final String DETAIL_VDDK_TRANSPORTS = "vddk.transports"; + private static final String DETAIL_VDDK_THUMBPRINT = "vddk.thumbprint"; + + ConfigKey ConvertVmwareInstanceToKvmExtraParamsAllowed = new ConfigKey<>(Boolean.class, + "convert.vmware.instance.to.kvm.extra.params.allowed", + "Advanced", + "false", + "Disabled by default. If enabled, allows extra parameters to be passed to the virt-v2v binary on KVM conversion hosts", + true, + ConfigKey.Scope.Global, + null); + + ConfigKey ConvertVmwareInstanceToKvmExtraParamsAllowedList = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED, + String.class, + "convert.vmware.instance.to.kvm.extra.params.allowed.list", + "", + "Comma separated list of allowed extra parameters to be passed to the virt-v2v binary on KVM conversion hosts", + true, + ConfigKey.Kind.CSV, + null); + + @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 ReservationDao reservationDao; + @Inject + private VMInstanceDetailsDao vmInstanceDetailsDao; + @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 VolumeApiService volumeApiService; + @Inject + private DeploymentPlanningManager deploymentPlanningManager; + @Inject + private VirtualMachineManager virtualMachineManager; + @Inject + private ManagementService managementService; + @Inject + private NicDao nicDao; + @Inject + private NetworkModel networkModel; + @Inject + private ConfigurationDao configurationDao; + @Inject + private GuestOSDao guestOSDao; + @Inject + private GuestOSHypervisorDao guestOSHypervisorDao; + @Inject + private SnapshotDao snapshotDao; + @Inject + private UserVmDao userVmDao; + @Inject + private NetworkOfferingDao networkOfferingDao; + @Inject + EntityManager entityMgr; + @Inject + private NetworkOrchestrationService networkMgr; + @Inject + private PhysicalNetworkDao physicalNetworkDao; + @Inject + private StoragePoolHostDao storagePoolHostDao; + @Inject + private HypervisorGuruManager hypervisorGuruManager; + @Inject + private VmwareDatacenterDao vmwareDatacenterDao; + @Inject + private ImageStoreDao imageStoreDao; + @Inject + private DataStoreManager dataStoreManager; + @Inject + private ImportVmTasksManager importVmTasksManager; + + protected Gson gson; + + public UnmanagedVMsManagerImpl() { + gson = GsonHelper.getGsonLogger(); + } + + private VMTemplateVO createDefaultDummyVmImportTemplate(boolean isKVM) { + String templateName = (isKVM) ? KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME : VM_IMPORT_DEFAULT_TEMPLATE_NAME; + VMTemplateVO template = null; + try { + template = VMTemplateVO.createSystemIso(templateDao.getNextInSequence(Long.class, "id"), templateName, templateName, true, + "", true, 64, Account.ACCOUNT_ID_SYSTEM, "", + "VM Import Default Template", false, OTHER_LINUX_64_GUEST_OS_ID); + template.setState(VirtualMachineTemplate.State.Inactive); + template = templateDao.persist(template); + if (template == null) { + return null; + } + templateDao.remove(template.getId()); + template = templateDao.findByName(templateName); + } catch (Exception e) { + logger.error("Unable to create default dummy template for VM import", e); + } + return template; + } + + private List getAdditionalNameFilters(Cluster cluster) { + List additionalNameFilter = new ArrayList<>(); + if (cluster == null) { + return additionalNameFilter; + } + 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 (StringUtils.isEmpty(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 (StringUtils.isNotEmpty(path)) { + if (!additionalNameFilter.contains(path)) { + volumeFileNames.add(path); + } + if (path.contains("-")) { + split = path.split("-"); + path = split[0]; + if (StringUtils.isNotEmpty(path) && !path.equals("ROOT") && !additionalNameFilter.contains(path)) { + volumeFileNames.add(path); + } + } + } + } + } catch (Exception e) { + logger.warn("Unable to find volume file name for volume: {} while adding filters unmanaged VMs", volumeVO, e); + } + if (!volumeFileNames.isEmpty()) { + additionalNameFilter.addAll(volumeFileNames); + } + } + } + return additionalNameFilter; + } + + private List getHostsManagedVms(List hosts) { + if (CollectionUtils.isEmpty(hosts)) { + return new ArrayList<>(); + } + List instances = vmDao.listByHostOrLastHostOrHostPod(hosts.stream().map(HostVO::getId).collect(Collectors.toList()), hosts.get(0).getPodId()); + List managedVms = instances.stream().map(VMInstanceVO::getInstanceName).collect(Collectors.toList()); + return managedVms; + } + + private boolean hostSupportsServiceOfferingAndTemplate(HostVO host, ServiceOffering serviceOffering, VirtualMachineTemplate template) { + if (StringUtils.isAllEmpty(serviceOffering.getHostTag(), template.getTemplateTag())) { + return true; + } + hostDao.loadHostTags(host); + return host.checkHostServiceOfferingAndTemplateTags(serviceOffering, template, UserVmManager.getStrictHostTags()); + } + + private boolean storagePoolSupportsDiskOffering(StoragePool pool, DiskOffering diskOffering) { + if (pool == null) { + return false; + } + if (diskOffering == null) { + return false; + } + return volumeApiService.doesStoragePoolSupportDiskOffering(pool, diskOffering); + } + + private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedInstanceTO instance, ServiceOfferingVO serviceOffering, final Account owner, final DataCenter zone, final Map details, Hypervisor.HypervisorType hypervisorType) + throws ServerApiException, PermissionDeniedException, ResourceAllocationException { + if (instance == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Cannot find VM to import."); + } + if (serviceOffering == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Cannot find service offering used to import VM [%s].", instance.getName())); + } + 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 [%s] is not valid for importing VM [%s].", cpu, instance.getName())); + } + if (memory == null || memory == 0) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Memory [%s] is not valid for importing VM [%s].", memory, instance.getName())); + } + + if (serviceOffering.isDynamic()) { + if (details.containsKey(VmDetailConstants.CPU_SPEED)) { + try { + cpuSpeed = Integer.parseInt(details.get(VmDetailConstants.CPU_SPEED)); + } catch (Exception e) { + logger.error("Failed to get CPU speed for importing VM [{}] due to [{}].", instance, e.getMessage(), e); + } + } + 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(UnmanagedInstanceTO.PowerState.PowerOff)) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %d CPU cores do not match 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(UnmanagedInstanceTO.PowerState.PowerOff)) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %dMB memory does not match VM memory %dMB and VM is not in powered off state (Power state: %s)", serviceOffering.getUuid(), serviceOffering.getRamSize(), memory, instance.getPowerState())); + } + if (hypervisorType == Hypervisor.HypervisorType.VMware && 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 match VM CPU speed %dMHz and VM is not in powered off state (Power state: %s)", serviceOffering.getUuid(), serviceOffering.getSpeed(), cpuSpeed, instance.getPowerState())); + } + } + return serviceOffering; + } + + /** + * Merges caller-supplied MAC addresses into the NIC IP address map. + * For each NIC entry in {@code nicMacAddressMap}, the MAC address is set on the corresponding + * {@link Network.IpAddresses} object. If no IP address entry exists for a given NIC, a new + * {@link Network.IpAddresses} object is created to carry the MAC. + * + * @param nicIpAddressMap map of NIC ID to IP addresses (may be empty, never null after cmd getter) + * @param nicMacAddressMap map of NIC ID to validated/standardized MAC address strings + * @return merged map with MAC addresses populated where supplied by the caller + */ + protected Map mergeNicMacAddresses( + final Map nicIpAddressMap, + final Map nicMacAddressMap) { + if (MapUtils.isEmpty(nicMacAddressMap)) { + return nicIpAddressMap; + } + Map merged = new HashMap<>(nicIpAddressMap); + for (Map.Entry entry : nicMacAddressMap.entrySet()) { + String nicId = entry.getKey(); + String mac = entry.getValue(); + Network.IpAddresses existing = merged.get(nicId); + if (existing != null) { + existing.setMacAddress(mac); + } else { + merged.put(nicId, new Network.IpAddresses(null, null, mac)); + } + } + return merged; + } + + private Map getNicIpAddresses(final List nics, final Map callerNicIpAddressMap) { + Map nicIpAddresses = new HashMap<>(); + for (UnmanagedInstanceTO.Nic nic : nics) { + Network.IpAddresses ipAddresses = null; + if (MapUtils.isNotEmpty(callerNicIpAddressMap) && callerNicIpAddressMap.containsKey(nic.getNicId())) { + ipAddresses = callerNicIpAddressMap.get(nic.getNicId()); + } + // If IP is set to auto-assign, check NIC doesn't have more that one IP from SDK + if (ipAddresses != null && ipAddresses.getIp4Address() != null && ipAddresses.getIp4Address().equals("auto") && !CollectionUtils.isEmpty(nic.getIpAddress())) { + if (nic.getIpAddress().size() > 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())); + } + String address = nic.getIpAddress().get(0); + if (NetUtils.isValidIp4(address)) { + ipAddresses.setIp4Address(address); + } + } + if (ipAddresses != null) { + nicIpAddresses.put(nic.getNicId(), ipAddresses); + } + } + return nicIpAddresses; + } + + private StoragePool getStoragePool(final UnmanagedInstanceTO.Disk disk, final DataCenter zone, final Cluster cluster, DiskOffering diskOffering) { + StoragePool storagePool = null; + final String dsHost = disk.getDatastoreHost(); + final String dsPath = disk.getDatastorePath(); + final String dsType = disk.getDatastoreType(); + final String dsName = disk.getDatastoreName(); + if (dsType != null) { + List pools = primaryDataStoreDao.listPoolByHostPath(dsHost, dsPath); + for (StoragePool pool : pools) { + if (pool.getDataCenterId() == zone.getId() && + (pool.getClusterId() == null || pool.getClusterId().equals(cluster.getId())) && + volumeApiService.doesStoragePoolSupportDiskOffering(pool, diskOffering)) { + storagePool = pool; + break; + } + } + } + + if (storagePool == null) { + Set pools = new HashSet<>(primaryDataStoreDao.listPoolsByCluster(cluster.getId())); + pools.addAll(primaryDataStoreDao.listByDataCenterId(zone.getId())); + boolean isNameUuid = StringUtils.isNotBlank(dsName) && UuidUtils.isUuid(dsName); + for (StoragePool pool : pools) { + String searchPoolParam = StringUtils.isNotBlank(dsPath) ? dsPath : dsName; + if ((StringUtils.contains(pool.getPath(), searchPoolParam) || isNameUuid && pool.getUuid().equals(dsName)) && + volumeApiService.doesStoragePoolSupportDiskOffering(pool, diskOffering)) { + 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; + } + + private Pair> getRootAndDataDisks( + List disks, + final Map dataDiskOfferingMap) { + UnmanagedInstanceTO.Disk rootDisk = null; + List dataDisks = new ArrayList<>(); + + Set callerDiskIds = dataDiskOfferingMap.keySet(); + if (callerDiskIds.size() != disks.size() - 1) { + String msg = String.format("VM has total %d disks for which %d disk offering mappings provided. %d disks need a disk offering for import", disks.size(), callerDiskIds.size(), disks.size() - 1); + logger.error(String.format("%s. %s parameter can be used to provide disk offerings for the disks", msg, ApiConstants.DATADISK_OFFERING_LIST)); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, msg); + } + List diskIdsWithoutOffering = new ArrayList<>(); + for (UnmanagedInstanceTO.Disk disk : disks) { + String diskId = disk.getDiskId(); + if (!callerDiskIds.contains(diskId)) { + diskIdsWithoutOffering.add(diskId); + rootDisk = disk; + } else { + dataDisks.add(disk); + DiskOffering diskOffering = diskOfferingDao.findById(dataDiskOfferingMap.getOrDefault(disk.getDiskId(), null)); + if ((disk.getCapacity() == null || disk.getCapacity() <= 0) && diskOffering != null) { + disk.setCapacity(diskOffering.getDiskSize()); + } + } + } + if (diskIdsWithoutOffering.size() > 1 || rootDisk == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM has total %d disks, disk offering mapping not provided for %d disks. Disk IDs that may need a disk offering - %s", disks.size(), diskIdsWithoutOffering.size() - 1, String.join(", ", diskIdsWithoutOffering))); + } + + return new Pair<>(rootDisk, dataDisks); + } + + private void checkUnmanagedDiskAndOfferingForImport(String instanceName, UnmanagedInstanceTO.Disk disk, DiskOffering diskOffering, ServiceOffering serviceOffering, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed, List reservations) + throws ServerApiException, PermissionDeniedException, ResourceAllocationException { + if (serviceOffering == null && diskOffering == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID [%s] not found during VM [%s] import.", disk.getDiskId(), instanceName)); + } + if (diskOffering != null) { + accountService.checkAccess(owner, diskOffering, zone); + } + 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 != 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 != 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)))); + } + diskOffering = diskOffering != null ? diskOffering : diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); + StoragePool storagePool = getStoragePool(disk, zone, cluster, 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())); + } + resourceLimitService.checkVolumeResourceLimit(owner, true, disk.getCapacity(), diskOffering, reservations); + } + + private void checkUnmanagedDiskAndOfferingForImport(String intanceName, List disks, final Map diskOfferingMap, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed, List reservations) + throws ServerApiException, PermissionDeniedException, ResourceAllocationException { + String diskController = null; + for (UnmanagedInstanceTO.Disk disk : disks) { + if (disk == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve disk details for VM [%s].", intanceName)); + } + 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 (StringUtils.isEmpty(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 data disk controllers are of the same type", diskController, disk.getController())); + } + } + checkUnmanagedDiskAndOfferingForImport(intanceName, disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), null, owner, zone, cluster, migrateAllowed, reservations); + } + } + + private void checkUnmanagedNicAndNetworkForImport(String instanceName, UnmanagedInstanceTO.Nic nic, Network network, final DataCenter zone, final Account owner, final boolean autoAssign, Hypervisor.HypervisorType hypervisorType) throws ServerApiException { + basicNetworkChecks(instanceName, nic, network); + 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 (!autoAssign && network.getGuestType().equals(Network.GuestType.Isolated)) { + return; + } + checksOnlyNeededForVmware(nic, network, hypervisorType); + } + + private void checksOnlyNeededForVmware(UnmanagedInstanceTO.Nic nic, Network network, final Hypervisor.HypervisorType hypervisorType) { + if (hypervisorType == Hypervisor.HypervisorType.VMware) { + String networkBroadcastUri = network.getBroadcastUri() == null ? null : network.getBroadcastUri().toString(); + if (nic.getVlan() != null && nic.getVlan() != 0 && nic.getPvlan() == null && + (StringUtils.isEmpty(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())); + } + String pvLanType = nic.getPvlanType() == null ? "" : nic.getPvlanType().toLowerCase().substring(0, 1); + if (nic.getVlan() != null && nic.getVlan() != 0 && nic.getPvlan() != null && nic.getPvlan() != 0 && + (StringUtils.isEmpty(networkBroadcastUri) || !String.format("pvlan://%d-%s%d", nic.getVlan(), pvLanType, nic.getPvlan()).equals(networkBroadcastUri))) { + 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-%s%d during VM import", network.getUuid(), networkBroadcastUri, nic.getNicId(), nic.getVlan(), pvLanType, nic.getPvlan())); + } + } + } + + private void basicNetworkChecks(String instanceName, UnmanagedInstanceTO.Nic nic, Network network) { + if (nic == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve the NIC details used by VM [%s] from VMware. Please check if this VM have NICs in VMWare.", instanceName)); + } + if (network == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import.", nic.getNicId())); + } + } + + private void checkUnmanagedNicAndNetworkHostnameForImport(String instanceName, UnmanagedInstanceTO.Nic nic, Network network, final String hostName) throws ServerApiException { + basicNetworkChecks(instanceName, nic, network); + // 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(String.format("VM with Name [%s] already exists in the network [%s] domain [%s]. Cannot import another VM with the same name. Please try again with a different name.", hostName, network, network.getNetworkDomain())); + } + } + + private void checkUnmanagedNicIpAndNetworkForImport(String instanceName, UnmanagedInstanceTO.Nic nic, Network network, final Network.IpAddresses ipAddresses) throws ServerApiException { + basicNetworkChecks(instanceName, nic, network); + // Check IP is assigned for non L2 networks + if (!network.getGuestType().equals(Network.GuestType.L2) && (ipAddresses == null || StringUtils.isEmpty(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 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 && StringUtils.isNotEmpty(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())); + } + } + } + + private Map getUnmanagedNicNetworkMap(String instanceName, List nics, final Map callerNicNetworkMap, + final Map callerNicIpAddressMap, final DataCenter zone, final String hostName, + final Account owner, Hypervisor.HypervisorType hypervisorType) throws ServerApiException { + Map nicNetworkMap = new HashMap<>(); + String nicAdapter = null; + for (int i = 0; i < nics.size(); i++) { + UnmanagedInstanceTO.Nic nic = nics.get(i); + if (StringUtils.isEmpty(nicAdapter)) { + 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())); + } + } + 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 && nic.getVlan() != 0) { + // 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(instanceName, nic, networkVO, zone, owner, true, hypervisorType); + network = networkVO; + } catch (Exception e) { + logger.error(String.format("Error when checking NIC [%s] of unmanaged instance to import due to [%s].", nic.getNicId(), e.getMessage()), e); + } + if (network != null) { + checkUnmanagedNicAndNetworkHostnameForImport(instanceName, nic, network, hostName); + checkUnmanagedNicIpAndNetworkForImport(instanceName, nic, network, ipAddresses); + break; + } + } + } + } else { + network = networkDao.findById(callerNicNetworkMap.get(nic.getNicId())); + boolean autoImport = false; + if (hypervisorType == Hypervisor.HypervisorType.KVM) { + autoImport = ipAddresses != null && ipAddresses.getIp4Address() != null && ipAddresses.getIp4Address().equalsIgnoreCase("auto"); + } + checkUnmanagedNicAndNetworkForImport(instanceName, nic, network, zone, owner, autoImport, hypervisorType); + checkUnmanagedNicAndNetworkHostnameForImport(instanceName, nic, network, hostName); + checkUnmanagedNicIpAndNetworkForImport(instanceName, 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())); + } + nicNetworkMap.put(nic.getNicId(), network.getId()); + } + return nicNetworkMap; + } + + private Pair importExternalDisk(UnmanagedInstanceTO.Disk disk, VirtualMachine vm, DeployDestination dest, DiskOffering diskOffering, + Volume.Type type, VirtualMachineTemplate template,Long deviceId, String remoteUrl, String username, String password, + String tmpPath, DiskProfile diskProfile) { + final String path = StringUtils.isEmpty(disk.getDatastorePath()) ? disk.getImagePath() : disk.getDatastorePath(); + String chainInfo = disk.getChainInfo(); + if (StringUtils.isEmpty(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); + } + Map storage = dest.getStorageForDisks(); + Volume volume = volumeDao.findById(diskProfile.getVolumeId()); + StoragePool storagePool = storage.get(volume); + CopyRemoteVolumeCommand copyRemoteVolumeCommand = new CopyRemoteVolumeCommand(); + copyRemoteVolumeCommand.setRemoteIp(remoteUrl); + copyRemoteVolumeCommand.setUsername(username); + copyRemoteVolumeCommand.setPassword(password); + copyRemoteVolumeCommand.setSrcFile(path); + StorageFilerTO storageTO = new StorageFilerTO(storagePool); + copyRemoteVolumeCommand.setStorageFilerTO(storageTO); + if(tmpPath == null || tmpPath.length() < 1) { + tmpPath = "/tmp/"; + } else { + // Add / if path doesn't end with / + if(tmpPath.charAt(tmpPath.length() - 1) != '/') { + tmpPath += "/"; + } + } + copyRemoteVolumeCommand.setTempPath(tmpPath); + int copyTimeout = UnmanagedVMsManager.RemoteKvmInstanceDisksCopyTimeout.value(); + if (copyTimeout <= 0) { + copyTimeout = Integer.valueOf(UnmanagedVMsManager.RemoteKvmInstanceDisksCopyTimeout.defaultValue()); + } + int copyTimeoutInSecs = copyTimeout * 60; + copyRemoteVolumeCommand.setWait(copyTimeoutInSecs); + logger.error(String.format("Initiating copy remote volume %s from %s, timeout %d secs", path, remoteUrl, copyTimeoutInSecs)); + Answer answer = agentManager.easySend(dest.getHost().getId(), copyRemoteVolumeCommand); + if (!(answer instanceof CopyRemoteVolumeAnswer)) { + throw new CloudRuntimeException("Error while copying volume of remote instance: " + answer.getDetails()); + } + CopyRemoteVolumeAnswer copyRemoteVolumeAnswer = (CopyRemoteVolumeAnswer) answer; + checkVolume(copyRemoteVolumeAnswer.getVolumeDetails()); + if (!copyRemoteVolumeAnswer.getResult()) { + throw new CloudRuntimeException("Unable to copy volume of remote instance"); + } + diskProfile.setSize(copyRemoteVolumeAnswer.getSize()); + DiskProfile profile = volumeManager.updateImportedVolume(type, diskOffering, vm, template, deviceId, + storagePool.getId(), storagePool.getPoolType(), copyRemoteVolumeAnswer.getFilename(), chainInfo, diskProfile); + + return new Pair<>(profile, storagePool); + } + + private Pair importKVMLocalDisk(VirtualMachine vm, DiskOffering diskOffering, + Volume.Type type, VirtualMachineTemplate template, + Long deviceId, Long hostId, String diskPath, DiskProfile diskProfile) { + List storagePools = primaryDataStoreDao.findLocalStoragePoolsByHostAndTags(hostId, null); + if(storagePools.size() < 1) { + throw new CloudRuntimeException("Local Storage not found for host"); + } + + StoragePool storagePool = storagePools.get(0); + + DiskProfile profile = volumeManager.updateImportedVolume(type, diskOffering, vm, template, deviceId, + storagePool.getId(), storagePool.getPoolType(), diskPath, null, diskProfile); + + return new Pair<>(profile, storagePool); + } + + private Pair importKVMSharedDisk(VirtualMachine vm, DiskOffering diskOffering, + Volume.Type type, VirtualMachineTemplate template, + Long deviceId, Long poolId, String diskPath, DiskProfile diskProfile) { + StoragePool storagePool = primaryDataStoreDao.findById(poolId); + + DiskProfile profile = volumeManager.updateImportedVolume(type, diskOffering, vm, template, deviceId, + poolId, storagePool.getPoolType(), diskPath, null, diskProfile); + + return new Pair<>(profile, storagePool); + } + + private Pair importDisk(UnmanagedInstanceTO.Disk disk, VirtualMachine vm, Cluster cluster, DiskOffering diskOffering, + 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 = StringUtils.isEmpty(disk.getFileBaseName()) ? disk.getImagePath() : disk.getFileBaseName(); + String chainInfo = disk.getChainInfo(); + if (vm.getHypervisorType() == Hypervisor.HypervisorType.VMware && StringUtils.isEmpty(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, diskOffering); + DiskProfile profile = volumeManager.importVolume(type, name, diskOffering, diskSize, + minIops, maxIops, vm.getDataCenterId(), vm.getHypervisorType(), vm, template, owner, deviceId, storagePool.getId(), storagePool.getPoolType(), path, chainInfo); + + return new Pair(profile, storagePool); + } + + protected NicProfile importNic(UnmanagedInstanceTO.Nic nic, VirtualMachine vm, Network network, Network.IpAddresses ipAddresses, int deviceId, boolean isDefaultNic, boolean forced) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException { + // Prefer caller-supplied MAC (from nicmacaddresslist); fall back to hypervisor-reported MAC + String macAddress = (ipAddresses != null && StringUtils.isNotEmpty(ipAddresses.getMacAddress())) + ? ipAddresses.getMacAddress() + : nic.getMacAddress(); + DataCenterVO dataCenterVO = dataCenterDao.findById(network.getDataCenterId()); + Pair result = networkOrchestrationService.importNic(macAddress, deviceId, network, isDefaultNic, vm, ipAddresses, dataCenterVO, forced); + if (result == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC ID: %s import failed", nic.getNicId())); + } + return result.first(); + } + + 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 + try { + networkOrchestrationService.release(profile, true); + } catch (Exception e) { + logger.error("Unable to release NICs for unsuccessful import unmanaged VM: {}", userVm, e); + nicDao.removeNicsForInstance(userVm.getId()); + } + // Remove vm + vmDao.remove(userVm.getId()); + } + + 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")); + } + if (sourceHost == null || serviceOffering == null || diskProfileStoragePoolList == null) { + logger.error(String.format("Failed to check migrations need during import, VM: %s", userVm)); + cleanupFailedImportVM(vm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to check migrations need during import, VM: %s", userVm.getInstanceName())); + } + if (!hostSupportsServiceOfferingAndTemplate(sourceHost, serviceOffering, template)) { + logger.debug("VM {} needs to be migrated", vm); + final VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm, template, serviceOffering, owner, null); + profile.setServiceOffering(serviceOfferingDao.findById(vm.getId(), serviceOffering.getId())); + 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) { + String errorMsg = String.format("VM import failed for Unmanaged VM [%s] during VM migration, cannot find deployment destination due to [%s].", vm, e.getMessage()); + logger.warn(errorMsg, e); + cleanupFailedImportVM(vm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg); + } + 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())); + } + try { + 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) { + String errorMsg = String.format("VM import failed for Unmanaged VM [%s] during VM migration due to [%s].", vm, e.getMessage()); + logger.error(errorMsg, e); + cleanupFailedImportVM(vm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg); + } + } + 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; + } + boolean poolSupportsOfferings = storagePoolSupportsDiskOffering(diskProfileStoragePool.second(), dOffering); + if (poolSupportsOfferings) { + continue; + } + logger.debug("Volume {} needs to be migrated", volumeVO); + Pair, List> poolsPair = managementService.listStoragePoolsForSystemMigrationOfVolume(profile.getVolumeId(), null, null, null, null, false, true); + 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(s) found", userVm.getInstanceName(), volumeVO.getUuid())); + } + List storagePools = poolsPair.second(); + StoragePool storagePool = null; + if (CollectionUtils.isNotEmpty(storagePools)) { + for (StoragePool pool : storagePools) { + if (diskProfileStoragePool.second().getId() != pool.getId() && + storagePoolSupportsDiskOffering(pool, dOffering) + ) { + 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) + ) { + storagePool = pool; + break; + } + } + } + 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("Found storage pool {} for migrating the volume {} to", storagePool, volumeVO); + } + try { + Volume volume = null; + if (vm.getState().equals(VirtualMachine.State.Running)) { + volume = volumeManager.liveMigrateVolume(volumeVO, storagePool); + } else { + volume = volumeManager.migrateVolume(volumeVO, storagePool); + } + if (volume == null) { + String msg = ""; + if (vm.getState().equals(VirtualMachine.State.Running)) { + msg = String.format("Live migration for volume: %s to destination pool: %s failed", volumeVO, storagePool); + } else { + msg = String.format("Migration for volume: %s to destination pool: %s failed", volumeVO, storagePool); + } + logger.error(msg); + throw new CloudRuntimeException(msg); + } + } catch (Exception e) { + logger.error("VM import failed for unmanaged vm: {} during volume migration", vm, e); + cleanupFailedImportVM(vm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume migration. %s", userVm.getInstanceName(), StringUtils.defaultString(e.getMessage()))); + } + } + return userVm; + } + + private void publishVMUsageUpdateResourceCount(final UserVm userVm, ServiceOfferingVO serviceOfferingVO, VirtualMachineTemplate templateVO) { + if (userVm == null || serviceOfferingVO == null) { + logger.error("Failed to publish usage records during VM import because VM [{}] or ServiceOffering [{}] is null.", userVm, serviceOfferingVO); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "VM import failed for Unmanaged VM during publishing Usage Records."); + } + try { + if (!serviceOfferingVO.isDynamic()) { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, 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_CREATE, userVm.getAccountId(), userVm.getAccountId(), userVm.getDataCenterId(), userVm.getHostName(), serviceOfferingVO.getId(), userVm.getTemplateId(), + userVm.getHypervisorType().toString(), VirtualMachine.class.getName(), userVm.getUuid(), userVm.getDetails(), userVm.isDisplayVm()); + } + if (userVm.getState() == VirtualMachine.State.Running) { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_START, userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), userVm.getHostName(), serviceOfferingVO.getId(), userVm.getTemplateId(), + userVm.getHypervisorType().toString(), VirtualMachine.class.getName(), userVm.getUuid(), userVm.isDisplayVm()); + } + } catch (Exception e) { + logger.error("Failed to publish usage records during VM import for unmanaged VM [{}] due to [{}].", userVm, e.getMessage(), e); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm %s during publishing usage records", userVm.getInstanceName())); + } + resourceLimitService.incrementVmResourceCount(userVm.getAccountId(), userVm.isDisplayVm(), serviceOfferingVO, templateVO); + // Save usage event and update resource count for user vm volumes + List volumes = volumeDao.findByInstance(userVm.getId()); + for (VolumeVO volume : volumes) { + 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("Failed to publish volume ID: {} usage records during VM import", volume, e); + } + resourceLimitService.incrementVolumeResourceCount(userVm.getAccountId(), volume.isDisplayVolume(), + volume.getSize(), diskOfferingDao.findById(volume.getDiskOfferingId())); + } + + List nics = nicDao.listByVmId(userVm.getId()); + for (NicVO nic : nics) { + try { + NetworkVO network = networkDao.findById(nic.getNetworkId()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), + Long.toString(nic.getId()), network.getNetworkOfferingId(), null, 1L, VirtualMachine.class.getName(), userVm.getUuid(), userVm.isDisplay()); + } catch (Exception e) { + logger.error(String.format("Failed to publish network usage records during VM import. %s", StringUtils.defaultString(e.getMessage()))); + } + } + } + + private UserVm importVirtualMachineInternal(final UnmanagedInstanceTO unmanagedInstance, final String instanceNameInternal, 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 Map dataDiskOfferingMap, + final Map nicNetworkMap, final Map callerNicIpAddressMap, final Long guestOsId, + final Map details, final boolean migrateAllowed, final boolean forced, final boolean isImportUnmanagedFromSameHypervisor) { + logger.debug(LogUtils.logGsonWithoutException("Trying to import VM [%s] with name [%s], in zone [%s], cluster [%s], and host [%s], using template [%s], service offering [%s], disks map [%s], NICs map [%s] and details [%s].", + unmanagedInstance, displayName, zone, cluster, host, template, serviceOffering, dataDiskOfferingMap, nicNetworkMap, details)); + UserVm userVm = null; + ServiceOfferingVO validatedServiceOffering = null; + try { + validatedServiceOffering = getUnmanagedInstanceServiceOffering(unmanagedInstance, serviceOffering, owner, zone, details, cluster.getHypervisorType()); + } catch (Exception e) { + String errorMsg = String.format("Failed to import Unmanaged VM [%s] because the service offering [%s] is not compatible due to [%s].", unmanagedInstance, serviceOffering, StringUtils.defaultIfEmpty(e.getMessage(), "")); + logger.error(errorMsg, e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg); + } + + String internalCSName = unmanagedInstance.getInternalCSName(); + if (StringUtils.isEmpty(internalCSName)) { + internalCSName = instanceNameInternal; + } + 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 && host != null && !hostSupportsServiceOfferingAndTemplate(host, validatedServiceOffering, template)) { + throw new InvalidParameterValueException(String.format("Service offering: %s or template: %s is not compatible with host: %s of unmanaged VM: %s", serviceOffering.getUuid(), template.getUuid(), host.getUuid(), displayName)); + } + // 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", displayName)); + } + Pair> rootAndDataDisksPair = getRootAndDataDisks(unmanagedInstanceDisks, dataDiskOfferingMap); + final UnmanagedInstanceTO.Disk rootDisk = rootAndDataDisksPair.first(); + final List dataDisks = rootAndDataDisksPair.second(); + if (rootDisk == null || StringUtils.isEmpty(rootDisk.getController())) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed. Unable to retrieve root disk details for VM: %s ", displayName)); + } + if (cluster.getHypervisorType() == Hypervisor.HypervisorType.KVM) { + Long rootDiskOfferingId = validatedServiceOffering.getDiskOfferingId(); + DiskOffering rootDiskOffering = diskOfferingDao.findById(rootDiskOfferingId); + if ((rootDisk.getCapacity() == null || rootDisk.getCapacity() <= 0) && rootDiskOffering != null) { + rootDisk.setCapacity(rootDiskOffering.getDiskSize()); + } + } + allDetails.put(VmDetailConstants.ROOT_DISK_CONTROLLER, rootDisk.getController()); + if (cluster.getHypervisorType() == Hypervisor.HypervisorType.KVM && isImportUnmanagedFromSameHypervisor) { + long size = Double.valueOf(Math.ceil((double)rootDisk.getCapacity() / Resource.ResourceType.bytesToGiB)).longValue(); + allDetails.put(VmDetailConstants.ROOT_DISK_SIZE, String.valueOf(size)); + } + + List reservations = new ArrayList<>(); + try { + checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), rootDisk, null, validatedServiceOffering, owner, zone, cluster, migrateAllowed, reservations); + if (CollectionUtils.isNotEmpty(dataDisks)) { // Data disk(s) present + checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), dataDisks, dataDiskOfferingMap, owner, zone, cluster, migrateAllowed, reservations); + allDetails.put(VmDetailConstants.DATA_DISK_CONTROLLER, dataDisks.get(0).getController()); + } + + // Check NICs and supplied networks + Map nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap); + Map allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getName(), unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner, cluster.getHypervisorType()); + if (!CollectionUtils.isEmpty(unmanagedInstance.getNics())) { + allDetails.put(VmDetailConstants.NIC_ADAPTER, unmanagedInstance.getNics().get(0).getAdapterType()); + } + + if (StringUtils.isNotEmpty(unmanagedInstance.getVncPassword())) { + allDetails.put(VmDetailConstants.KVM_VNC_PASSWORD, unmanagedInstance.getVncPassword()); + } + + addImportingVMBootTypeAndModeDetails(unmanagedInstance.getBootType(), unmanagedInstance.getBootMode(), allDetails); + + VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff; + if (unmanagedInstance.getPowerState().equals(UnmanagedInstanceTO.PowerState.PowerOn)) { + powerState = VirtualMachine.PowerState.PowerOn; + } + + try { + userVm = userVmManager.importVM(zone, host, template, internalCSName, displayName, owner, + null, caller, true, null, owner.getAccountId(), userId, + validatedServiceOffering, null, guestOsId, hostName, + cluster.getHypervisorType(), allDetails, powerState, null); + } catch (InsufficientCapacityException ice) { + String errorMsg = String.format("Failed to import VM [%s] due to [%s].", displayName, ice.getMessage()); + logger.error(errorMsg, ice); + throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, errorMsg); + } + + if (userVm == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import vm name: %s", displayName)); + } + List> diskProfileStoragePoolList = new ArrayList<>(); + try { + if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) { + throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId())); + } + Long minIops = null; + if (details.containsKey(MIN_IOPS)) { + minIops = Long.parseLong(details.get(MIN_IOPS)); + } + Long maxIops = null; + if (details.containsKey(MAX_IOPS)) { + maxIops = Long.parseLong(details.get(MAX_IOPS)); + } + DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); + diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, cluster, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()), + rootDisk.getCapacity(), minIops, maxIops, template, owner, null)); + long deviceId = 1L; + 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(), offering.getMinIops(), offering.getMaxIops(), + template, owner, deviceId)); + deviceId++; + } + } catch (Exception e) { + logger.error(String.format("Failed to import volumes while importing vm: %s", displayName), e); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", displayName, StringUtils.defaultString(e.getMessage()))); + } + try { + int nicIndex = 0; + 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, nicIndex, nicIndex == 0, forced); + nicIndex++; + } + } catch (Exception e) { + logger.error(String.format("Failed to import NICs while importing vm: %s", displayName), e); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import NICs while importing vm: %s. %s", displayName, StringUtils.defaultString(e.getMessage()))); + } + if (migrateAllowed) { + userVm = migrateImportedVM(host, template, validatedServiceOffering, userVm, owner, diskProfileStoragePoolList); + } + publishVMUsageUpdateResourceCount(userVm, validatedServiceOffering, template); + return userVm; + + } catch (ResourceAllocationException e) { // This will be thrown by checkUnmanagedDiskAndOfferingForImport, so the VM was not imported yet + logger.error("Volume resource allocation error for owner: {}", owner, e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resource allocation error for owner: %s. %s", owner.getUuid(), StringUtils.defaultString(e.getMessage()))); + } finally { + ReservationHelper.closeAll(reservations); + } + } + + private void addImportingVMBootTypeAndModeDetails(String bootType, String bootMode, Map allDetails) { + if (StringUtils.isNotBlank(bootType) && bootType.equalsIgnoreCase("uefi") && StringUtils.isNotBlank(bootMode)) { + allDetails.put("UEFI", bootMode); + } + } + + private HashMap getUnmanagedInstancesForHost(HostVO host, String instanceName, List managedVms) { + HashMap unmanagedInstances = new HashMap<>(); + if (host.isInMaintenanceStates()) { + return unmanagedInstances; + } + + GetUnmanagedInstancesCommand command = new GetUnmanagedInstancesCommand(); + command.setInstanceName(instanceName); + command.setManagedInstancesNames(managedVms); + Answer answer = agentManager.easySend(host.getId(), command); + if (!(answer instanceof GetUnmanagedInstancesAnswer) || !answer.getResult()) { + return unmanagedInstances; + } + GetUnmanagedInstancesAnswer unmanagedInstancesAnswer = (GetUnmanagedInstancesAnswer) answer; + unmanagedInstances = unmanagedInstancesAnswer.getUnmanagedInstances(); + return unmanagedInstances; + } + + protected Cluster basicAccessChecks(Long clusterId) { + final Account caller = CallContext.current().getCallingAccount(); + if (caller.getType() != Account.Type.ADMIN) { + throw new PermissionDeniedException(String.format("Cannot perform this operation, caller account [%s] is not ROOT Admin.", caller.getUuid())); + } + if (clusterId == null) { + throw new InvalidParameterValueException("Cluster ID cannot be null."); + } + final Cluster cluster = clusterDao.findById(clusterId); + if (cluster == null) { + throw new InvalidParameterValueException(String.format("Cluster with ID [%d] cannot be found.", clusterId)); + } + + if (!importUnmanagedInstancesSupportedHypervisors.contains(cluster.getHypervisorType())) { + throw new InvalidParameterValueException(String.format("VM import is currently not supported for hypervisor [%s].", cluster.getHypervisorType().toString())); + } + return cluster; + } + + @Override + public ListResponse listUnmanagedInstances(ListUnmanagedInstancesCmd cmd) { + Long clusterId = cmd.getClusterId(); + Cluster cluster = basicAccessChecks(clusterId); + String keyword = cmd.getKeyword(); + if (StringUtils.isNotEmpty(keyword)) { + keyword = keyword.toLowerCase(); + } + List hosts = resourceManager.listHostsInClusterByStatus(clusterId, Status.Up); + List additionalNameFilters = getAdditionalNameFilters(cluster); + List managedVms = new ArrayList<>(additionalNameFilters); + managedVms.addAll(getHostsManagedVms(hosts)); + List responses = new ArrayList<>(); + for (HostVO host : hosts) { + HashMap unmanagedInstances = getUnmanagedInstancesForHost(host, cmd.getName(), managedVms); + Set keys = unmanagedInstances.keySet(); + for (String key : keys) { + UnmanagedInstanceTO instance = unmanagedInstances.get(key); + if (StringUtils.isNotEmpty(keyword) && + !instance.getName().toLowerCase().contains(keyword)) { + continue; + } + responses.add(responseGenerator.createUnmanagedInstanceResponse(instance, cluster, host)); + } + } + ListResponse listResponses = new ListResponse<>(); + listResponses.setResponses(responses, responses.size()); + return listResponses; + } + + @Override + public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { + return baseImportInstance(cmd); + } + + /** + * Base logic for import virtual machines (unmanaged, external) into CloudStack + * @param cmd importVM or importUnmanagedInstance command + * @return imported user vm + */ + private UserVmResponse baseImportInstance(ImportUnmanagedInstanceCmd cmd) { + basicParametersCheckForImportInstance(cmd.getName(), cmd.getDomainId(), cmd.getAccountName()); + + final String instanceName = cmd.getName(); + Long clusterId = cmd.getClusterId(); + Cluster cluster = basicAccessChecks(clusterId); + + if (!cluster.getAllocationState().equals(Cluster.AllocationState.Enabled)) { + throw new InvalidParameterValueException(String.format("Cluster [%s] is not enabled.", cluster)); + } + + final Account caller = CallContext.current().getCallingAccount(); + final DataCenter zone = dataCenterDao.findById(cluster.getDataCenterId()); + final Account owner = accountService.getActiveAccountById(cmd.getEntityOwnerId()); + long userId = getUserIdForImportInstance(owner); + + VMTemplateVO template = getTemplateForImportInstance(cmd.getTemplateId(), cluster.getHypervisorType()); + ServiceOfferingVO serviceOffering = getServiceOfferingForImportInstance(cmd.getServiceOfferingId(), owner, zone); + + String displayName = getDisplayNameForImportInstance(cmd.getDisplayName(), instanceName); + String hostName = getHostNameForImportInstance(cmd.getHostName(), cluster.getHypervisorType(), instanceName, displayName); + + checkVmwareInstanceNameForImportInstance(cluster.getHypervisorType(), instanceName, hostName, zone); + final Map nicNetworkMap = cmd.getNicNetworkList(); + final Map nicIpAddressMap = mergeNicMacAddresses(cmd.getNicIpAddressList(), cmd.getNicMacAddressList()); + final Map dataDiskOfferingMap = cmd.getDataDiskToDiskOfferingList(); + final Map details = cmd.getDetails(); + final boolean forced = cmd.isForced(); + List hosts = resourceManager.listHostsInClusterByStatus(clusterId, Status.Up); + UserVm userVm = null; + List additionalNameFilters = getAdditionalNameFilters(cluster); + List managedVms = new ArrayList<>(additionalNameFilters); + managedVms.addAll(getHostsManagedVms(hosts)); + + try { + + ActionEventUtils.onStartedActionEvent(userId, owner.getId(), EventTypes.EVENT_VM_IMPORT, + cmd.getEventDescription(), null, null, true, 0); + + if (cmd instanceof ImportVmCmd) { + ImportVmCmd importVmCmd = (ImportVmCmd) cmd; + if (StringUtils.isBlank(importVmCmd.getImportSource())) { + throw new CloudRuntimeException("Please provide an import source for importing the VM"); + } + String source = importVmCmd.getImportSource().toUpperCase(); + ImportSource importSource = Enum.valueOf(ImportSource.class, source); + if (ImportSource.VMWARE == importSource) { + userVm = importUnmanagedInstanceFromVmwareToKvm(zone, cluster, + template, instanceName, displayName, hostName, caller, owner, userId, + serviceOffering, dataDiskOfferingMap, + nicNetworkMap, nicIpAddressMap, + details, importVmCmd, forced); + } + } else { + if (List.of(Hypervisor.HypervisorType.VMware, Hypervisor.HypervisorType.KVM).contains(cluster.getHypervisorType())) { + userVm = importUnmanagedInstanceFromHypervisor(zone, cluster, hosts, additionalNameFilters, + template, instanceName, displayName, hostName, caller, owner, userId, + serviceOffering, dataDiskOfferingMap, + nicNetworkMap, nicIpAddressMap, + details, cmd.getMigrateAllowed(), managedVms, forced); + } + } + + } 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(), StringUtils.defaultString(e.getMessage()))); + } + + if (userVm == null) { + ActionEventUtils.onCompletedActionEvent(userId, owner.getId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_IMPORT, + cmd.getEventDescription(), null, null, 0); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to find unmanaged vm with name: %s in cluster: %s", instanceName, cluster.getUuid())); + } + ActionEventUtils.onCompletedActionEvent(userId, owner.getId(), EventVO.LEVEL_INFO, EventTypes.EVENT_VM_IMPORT, + cmd.getEventDescription(), userVm.getId(), ApiCommandResourceType.VirtualMachine.toString(), 0); + return responseGenerator.createUserVmResponse(ResponseObject.ResponseView.Full, "virtualmachine", userVm).get(0); + } + + protected void checkExtraParamsAllowed(String extraParams) { + if (StringUtils.isBlank(extraParams)) { + return; + } + if (BooleanUtils.isFalse(ConvertVmwareInstanceToKvmExtraParamsAllowed.value())) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, + "Extra parameters for Vmware to KVM conversion are disabled by the administrator"); + } + String allowedParamsStr = ConvertVmwareInstanceToKvmExtraParamsAllowedList.value(); + if (StringUtils.isBlank(allowedParamsStr)) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, + "Extra parameters for Vmware to KVM conversion are enabled but the allowed list of parameters is empty"); + } + List allowedParams = Arrays.asList(allowedParamsStr.split(",")); + List sanitizedParams = Arrays.asList(extraParams.split(" ")) + .stream() + .filter(x -> x.startsWith("-")) + .map(s -> s.replaceFirst("^-+", "").trim()) //Remove the starting hyphens as in --X or -x + .collect(Collectors.toList()); + for (String param : sanitizedParams) { + if (!allowedParams.contains(param)) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, + String.format("The parameter %s is not allowed by the administrator", param)); + } + } + } + + private long getUserIdForImportInstance(Account owner) { + long userId = CallContext.current().getCallingUserId(); + List userVOs = userDao.listByAccount(owner.getAccountId()); + if (CollectionUtils.isNotEmpty(userVOs)) { + userId = userVOs.get(0).getId(); + } + return userId; + } + + protected void basicParametersCheckForImportInstance(String name, Long domainId, String accountName) { + if (StringUtils.isEmpty(name)) { + throw new InvalidParameterValueException("Instance name cannot be empty"); + } + if (domainId != null && StringUtils.isEmpty(accountName)) { + throw new InvalidParameterValueException(String.format("%s parameter must be specified with %s parameter", ApiConstants.DOMAIN_ID, ApiConstants.ACCOUNT)); + } + } + + private void checkVmwareInstanceNameForImportInstance(Hypervisor.HypervisorType hypervisorType, String instanceName, String hostName, DataCenter zone) { + if (hypervisorType.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())); + } + } + } + + private String getHostNameForImportInstance(String hostName, Hypervisor.HypervisorType hypervisorType, + String instanceName, String displayName) { + if (StringUtils.isEmpty(hostName)) { + hostName = hypervisorType == Hypervisor.HypervisorType.VMware ? instanceName : displayName; + if (!NetUtils.verifyDomainNameLabel(hostName, true)) { + throw new InvalidParameterValueException("Please provide a valid hostname for the VM. VM name contains unsupported characters that cannot be used as hostname."); + } + } + 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"); + } + return hostName; + } + + private String getDisplayNameForImportInstance(String displayName, String instanceName) { + return StringUtils.isEmpty(displayName) ? instanceName : displayName; + } + + private ServiceOfferingVO getServiceOfferingForImportInstance(Long serviceOfferingId, Account owner, DataCenter zone) { + if (serviceOfferingId == null) { + throw new InvalidParameterValueException("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); + return serviceOffering; + } + + protected VMTemplateVO getTemplateForImportInstance(Long templateId, Hypervisor.HypervisorType hypervisorType) { + VMTemplateVO template; + if (templateId == null) { + boolean isKVMHypervisor = Hypervisor.HypervisorType.KVM.equals(hypervisorType); + String templateName = (isKVMHypervisor) ? KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME : VM_IMPORT_DEFAULT_TEMPLATE_NAME; + template = templateDao.findByName(templateName); + if (template == null) { + template = createDefaultDummyVmImportTemplate(isKVMHypervisor); + 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 parameter for import", templateName, hypervisorType.toString())); + } + } + } else { + template = templateDao.findById(templateId); + } + if (template == null) { + throw new InvalidParameterValueException(String.format("Template ID: %d cannot be found", templateId)); + } + return template; + } + + @Override + @ActionEvent(eventType = EventTypes.EVENT_VM_IMPORT, eventDescription = "importing VM", async = true) + public UserVmResponse importVm(ImportVmCmd cmd) { + String source = cmd.getImportSource().toUpperCase(); + ImportSource importSource = Enum.valueOf(ImportSource.class, source); + if (ImportSource.VMWARE == importSource || ImportSource.UNMANAGED == importSource) { + checkExtraParamsAllowed(cmd.getExtraParams()); + return baseImportInstance(cmd); + } else { + return importKvmInstance(cmd); + } + } + + private UserVm importUnmanagedInstanceFromHypervisor(DataCenter zone, Cluster cluster, + List hosts, List additionalNameFilters, + VMTemplateVO template, String instanceName, String displayName, + String hostName, Account caller, Account owner, long userId, + ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap, + Map nicNetworkMap, Map nicIpAddressMap, + Map details, Boolean migrateAllowed, List managedVms, boolean forced) throws ResourceAllocationException { + UserVm userVm = null; + for (HostVO host : hosts) { + HashMap unmanagedInstances = getUnmanagedInstancesForHost(host, instanceName, managedVms); + if (MapUtils.isEmpty(unmanagedInstances)) { + continue; + } + Set names = unmanagedInstances.keySet(); + for (String name : names) { + if (!instanceName.equals(name)) { + continue; + } + 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)); + } + + if (template.getName().equals(VM_IMPORT_DEFAULT_TEMPLATE_NAME) && cluster.getHypervisorType().equals(Hypervisor.HypervisorType.KVM)) { + throw new InvalidParameterValueException("Template is needed and unable to use default template for hypervisor " + host.getHypervisorType().toString()); + } + + if (template.getName().equals(VM_IMPORT_DEFAULT_TEMPLATE_NAME)) { + String osName = unmanagedInstance.getOperatingSystem(); + GuestOS guestOS = null; + if (StringUtils.isNotEmpty(osName)) { + guestOS = guestOSDao.findOneByDisplayName(osName); + } + + GuestOSHypervisor guestOSHypervisor = null; + if (guestOS != null) { + guestOSHypervisor = guestOSHypervisorDao.findByOsIdAndHypervisor(guestOS.getId(), host.getHypervisorType().toString(), host.getHypervisorVersion()); + } + if (guestOSHypervisor == null && StringUtils.isNotEmpty(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())); + } + 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(guestOSHypervisor.getGuestOsId()); + } + + List reservations = new ArrayList<>(); + try { + checkVmResourceLimitsForUnmanagedInstanceImport(owner, unmanagedInstance, serviceOffering, template, reservations); + userVm = importVirtualMachineInternal(unmanagedInstance, instanceName, zone, cluster, host, + template, displayName, hostName, CallContext.current().getCallingAccount(), owner, userId, + serviceOffering, dataDiskOfferingMap, + nicNetworkMap, nicIpAddressMap, null, + details, migrateAllowed, forced, true); + } finally { + ReservationHelper.closeAll(reservations); + } + break; + } + if (userVm != null) { + break; + } + } + return userVm; + } + + protected void checkVmResourceLimitsForUnmanagedInstanceImport(Account owner, UnmanagedInstanceTO unmanagedInstance, ServiceOfferingVO serviceOffering, VMTemplateVO template, List reservations) throws ResourceAllocationException { + // When importing an unmanaged instance, the amount of CPUs and memory is obtained from the hypervisor unless powered off + // and not using a dynamic offering, unlike the external VM import that always obtains it from the compute offering + Integer cpu = serviceOffering.getCpu(); + Integer memory = serviceOffering.getRamSize(); + + if (serviceOffering.isDynamic() || !UnmanagedInstanceTO.PowerState.PowerOff.equals(unmanagedInstance.getPowerState())) { + cpu = unmanagedInstance.getCpuCores(); + memory = unmanagedInstance.getMemory(); + } + + if (cpu == null || cpu == 0) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("CPU cores [%s] is not valid for importing VM [%s].", cpu, unmanagedInstance.getName())); + } + if (memory == null || memory == 0) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Memory [%s] is not valid for importing VM [%s].", memory, unmanagedInstance.getName())); + } + + List resourceLimitHostTags = resourceLimitService.getResourceLimitHostTags(serviceOffering, template); + + CheckedReservation vmReservation = new CheckedReservation(owner, Resource.ResourceType.user_vm, resourceLimitHostTags, 1L, reservationDao, resourceLimitService); + reservations.add(vmReservation); + + CheckedReservation cpuReservation = new CheckedReservation(owner, Resource.ResourceType.cpu, resourceLimitHostTags, cpu.longValue(), reservationDao, resourceLimitService); + reservations.add(cpuReservation); + + CheckedReservation memReservation = new CheckedReservation(owner, Resource.ResourceType.memory, resourceLimitHostTags, memory.longValue(), reservationDao, resourceLimitService); + reservations.add(memReservation); + } + + private Pair getSourceVmwareUnmanagedInstance(String vcenter, String datacenterName, String username, + String password, String clusterName, String sourceHostName, + String sourceVM, ServiceOfferingVO serviceOffering) { + HypervisorGuru vmwareGuru = hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware); + + Map params = createParamsForTemplateFromVmwareVmMigration(vcenter, datacenterName, + username, password, clusterName, sourceHostName, sourceVM); + addServiceOfferingDetailsToParams(params, serviceOffering); + + return vmwareGuru.getHypervisorVMOutOfBandAndCloneIfRequired(sourceHostName, sourceVM, params); + } + + /** + * Add the minimum resources to check on the hypervisor source VM before converting the instance against the selected offering resources + * @param params sets the minimum CPU number, CPU speed and memory to be checked against the source VM + * @param serviceOffering service offering for the converted VM + */ + protected void addServiceOfferingDetailsToParams(Map params, ServiceOfferingVO serviceOffering) { + if (serviceOffering != null) { + serviceOfferingDao.loadDetails(serviceOffering); + Map serviceOfferingDetails = serviceOffering.getDetails(); + + if (serviceOffering.getCpu() != null) { + params.put(VmDetailConstants.CPU_NUMBER, String.valueOf(serviceOffering.getCpu())); + } else if (MapUtils.isNotEmpty(serviceOfferingDetails) && serviceOfferingDetails.containsKey(ApiConstants.MIN_CPU_NUMBER)) { + params.put(VmDetailConstants.CPU_NUMBER, serviceOfferingDetails.get(ApiConstants.MIN_CPU_NUMBER)); + } + + if (serviceOffering.getSpeed() != null) { + params.put(VmDetailConstants.CPU_SPEED, String.valueOf(serviceOffering.getSpeed())); + } + + if (serviceOffering.getRamSize() != null) { + params.put(VmDetailConstants.MEMORY, String.valueOf(serviceOffering.getRamSize())); + } else if (MapUtils.isNotEmpty(serviceOfferingDetails) && serviceOfferingDetails.containsKey(ApiConstants.MIN_MEMORY)) { + params.put(VmDetailConstants.MEMORY, serviceOfferingDetails.get(ApiConstants.MIN_MEMORY)); + } + } + } + + private String createOvfTemplateOfSourceVmwareUnmanagedInstance(String vcenter, String datacenterName, String username, + String password, String clusterName, String sourceHostName, + String sourceVMwareInstanceName, DataStoreTO convertLocation, int threadsCountToExportOvf) { + HypervisorGuru vmwareGuru = hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware); + + Map params = createParamsForTemplateFromVmwareVmMigration(vcenter, datacenterName, + username, password, clusterName, sourceHostName, sourceVMwareInstanceName); + + return vmwareGuru.createVMTemplateOutOfBand(sourceHostName, sourceVMwareInstanceName, params, convertLocation, threadsCountToExportOvf); + } + + protected UserVm importUnmanagedInstanceFromVmwareToKvm(DataCenter zone, Cluster destinationCluster, VMTemplateVO template, + String sourceVMName, String displayName, String hostName, + Account caller, Account owner, long userId, + ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap, + Map nicNetworkMap, Map nicIpAddressMap, + Map details, ImportVmCmd cmd, boolean forced) throws ResourceAllocationException { + Long existingVcenterId = cmd.getExistingVcenterId(); + String vcenter = cmd.getVcenter(); + String datacenterName = cmd.getDatacenterName(); + String username = cmd.getUsername(); + String password = cmd.getPassword(); + String clusterName = cmd.getClusterName(); + String sourceHostName = cmd.getHostIp(); + Long convertInstanceHostId = cmd.getConvertInstanceHostId(); + Long importInstanceHostId = cmd.getImportInstanceHostId(); + Long convertStoragePoolId = cmd.getConvertStoragePoolId(); + String extraParams = cmd.getExtraParams(); + boolean forceConvertToPool = cmd.getForceConvertToPool(); + Long guestOsId = cmd.getGuestOsId(); + boolean forceMsToImportVmFiles = Boolean.TRUE.equals(cmd.getForceMsToImportVmFiles()); + boolean useVddk = cmd.getUseVddk(); + + if ((existingVcenterId == null && vcenter == null) || (existingVcenterId != null && vcenter != null)) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, + "Please provide an existing vCenter ID or a vCenter IP/Name, parameters are mutually exclusive"); + } + if (existingVcenterId == null && StringUtils.isAnyBlank(vcenter, datacenterName, username, password)) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, + "Please set all the information for a vCenter IP/Name, datacenter, username and password"); + } + if (forceMsToImportVmFiles && useVddk) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, + String.format("Parameters %s and %s are mutually exclusive", + ApiConstants.FORCE_MS_TO_IMPORT_VM_FILES, ApiConstants.USE_VDDK)); + } + + checkConversionStoragePool(convertStoragePoolId, forceConvertToPool); + validateSelectedConversionStoragePoolForVddk(useVddk, convertStoragePoolId, serviceOffering, dataDiskOfferingMap); + + checkExtraParamsAllowed(extraParams); + + if (existingVcenterId != null) { + VmwareDatacenterVO existingDC = vmwareDatacenterDao.findById(existingVcenterId); + if (existingDC == null) { + String err = String.format("Cannot find any existing VMware DC with ID %s", existingVcenterId); + logger.error(err); + throw new CloudRuntimeException(err); + } + vcenter = existingDC.getVcenterHost(); + datacenterName = existingDC.getVmwareDatacenterName(); + username = existingDC.getUser(); + password = existingDC.getPassword(); + } + + boolean isClonedInstance = false; + UnmanagedInstanceTO sourceVMwareInstance = null; + DataStoreTO temporaryConvertLocation = null; + String ovfTemplateOnConvertLocation = null; + ImportVmTask importVMTask = null; + List reservations = new ArrayList<>(); + try { + HostVO convertHost = selectKVMHostForConversionInCluster(destinationCluster, convertInstanceHostId, useVddk); + HostVO importHost = (useVddk && importInstanceHostId == null) + ? convertHost + : selectKVMHostForImportingInCluster(destinationCluster, importInstanceHostId); + + boolean isOvfExportSupported = false; + CheckConvertInstanceAnswer conversionSupportAnswer = checkConversionSupportOnHost(convertHost, sourceVMName, false, useVddk, details); + if (!useVddk) { + isOvfExportSupported = conversionSupportAnswer.isOvfExportSupported(); + } + logger.debug("The host {} is selected to execute the conversion of the " + + "instance {} from VMware to KVM ", convertHost, sourceVMName); + + temporaryConvertLocation = selectInstanceConversionTemporaryLocation( + destinationCluster, convertHost, importHost, convertStoragePoolId, forceConvertToPool); + List convertStoragePools = findInstanceConversionDestinationStoragePoolsInCluster(destinationCluster, serviceOffering, dataDiskOfferingMap, temporaryConvertLocation, forceConvertToPool); + + long importStartTime = System.currentTimeMillis(); + importVMTask = importVmTasksManager.createImportVMTaskRecord(zone, owner, userId, displayName, vcenter, datacenterName, sourceVMName, + convertHost, importHost); + importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, null, CloningInstance); + + // sourceVMwareInstance could be a cloned instance from sourceVMName, of the sourceVMName itself if its powered off. + // isClonedInstance indicates if the VM is a clone of sourceVMName + + Pair sourceInstanceDetails = getSourceVmwareUnmanagedInstance(vcenter, datacenterName, username, password, clusterName, sourceHostName, sourceVMName, serviceOffering); + sourceVMwareInstance = sourceInstanceDetails.first(); + isClonedInstance = sourceInstanceDetails.second(); + + // Ensure that the configured resource limits will not be exceeded before beginning the conversion process + checkVmResourceLimitsForUnmanagedInstanceImport(owner, sourceVMwareInstance, serviceOffering, template, reservations); + + boolean isWindowsVm = sourceVMwareInstance.getOperatingSystem().toLowerCase().contains("windows"); + if (isWindowsVm) { + checkConversionSupportOnHost(convertHost, sourceVMName, true, useVddk, details); + } + + checkNetworkingBeforeConvertingVmwareInstance(zone, owner, displayName, hostName, sourceVMwareInstance, nicNetworkMap, nicIpAddressMap, forced); + UnmanagedInstanceTO convertedInstance; + if (!useVddk && (forceMsToImportVmFiles || !isOvfExportSupported)) { + // Uses MS for OVF export to temporary conversion location + int noOfThreads = UnmanagedVMsManager.ThreadsOnMSToImportVMwareVMFiles.value(); + importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, null, ConvertingInstance); + ovfTemplateOnConvertLocation = createOvfTemplateOfSourceVmwareUnmanagedInstance( + vcenter, datacenterName, username, password, clusterName, sourceHostName, + sourceVMwareInstance.getName(), temporaryConvertLocation, noOfThreads); + convertedInstance = convertVmwareInstanceToKVMWithOVFOnConvertLocation(sourceVMName, + sourceVMwareInstance, convertHost, importHost, convertStoragePools, + serviceOffering, dataDiskOfferingMap, temporaryConvertLocation, + ovfTemplateOnConvertLocation, forceConvertToPool, extraParams); + } else { + // Uses KVM Host for direct conversion using VDDK, or for OVF export to temporary conversion location through ovftool + importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, null, ConvertingInstance); + convertedInstance = convertVmwareInstanceToKVMUsingVDDKOrAfterExportingOVFToConvertLocation( + sourceVMName, sourceVMwareInstance, convertHost, importHost, + convertStoragePools, serviceOffering, dataDiskOfferingMap, + temporaryConvertLocation, vcenter, username, password, datacenterName, forceConvertToPool, extraParams, useVddk, details); + } + + sanitizeConvertedInstance(convertedInstance, sourceVMwareInstance); + importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, null, Importing); + UserVm userVm = importVirtualMachineInternal(convertedInstance, null, zone, destinationCluster, null, + template, displayName, hostName, caller, owner, userId, + serviceOffering, dataDiskOfferingMap, + nicNetworkMap, nicIpAddressMap, guestOsId, + details, false, forced, false); + long timeElapsedInSecs = (System.currentTimeMillis() - importStartTime) / 1000; + logger.debug(String.format("VMware VM %s imported successfully to CloudStack instance %s (%s), Time taken: %d secs, OVF files imported from %s, Source VMware VM details - OS: %s, PowerState: %s, Disks: %s, NICs: %s", + sourceVMName, displayName, displayName, timeElapsedInSecs, (ovfTemplateOnConvertLocation != null)? "MS" : "KVM Host", sourceVMwareInstance.getOperatingSystem(), sourceVMwareInstance.getPowerState(), sourceVMwareInstance.getDisks(), sourceVMwareInstance.getNics())); + importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, userVm.getId(), Completed); + return userVm; + } catch (CloudRuntimeException e) { + logger.error(String.format("Error importing VM: %s", e.getMessage()), e); + importVmTasksManager.updateImportVMTaskErrorState(importVMTask, ImportVmTask.TaskState.Failed, e.getMessage()); + ActionEventUtils.onCompletedActionEvent(userId, owner.getId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_IMPORT, + cmd.getEventDescription(), null, null, 0); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); + } finally { + if (isClonedInstance && sourceVMwareInstance != null) { + removeClonedInstance(vcenter, datacenterName, username, password, sourceHostName, sourceVMwareInstance.getName(), sourceVMName); + } + if (temporaryConvertLocation != null && StringUtils.isNotBlank(ovfTemplateOnConvertLocation)) { + removeTemplate(temporaryConvertLocation, ovfTemplateOnConvertLocation); + } + ReservationHelper.closeAll(reservations); + } + } + + /** + * Check whether the conversion storage pool exists and is suitable for the conversion or not. + * Secondary storage is only allowed when forceConvertToPool is false. + * @param convertStoragePoolId the ID of the storage pool (primary or secondary) + * @param forceConvertToPool when true, only primary storage pool must be allowed + * @throws CloudRuntimeException in case these requirements are not met + */ + protected void checkConversionStoragePool(Long convertStoragePoolId, boolean forceConvertToPool) { + if (forceConvertToPool && convertStoragePoolId == null) { + String msg = "The parameter forceconverttopool is set to true, but a primary storage pool has not been provided for conversion"; + logFailureAndThrowException(msg); + } + if (convertStoragePoolId != null) { + StoragePoolVO selectedStoragePool = primaryDataStoreDao.findById(convertStoragePoolId); + if (selectedStoragePool == null) { + logFailureAndThrowException(String.format("Cannot find a storage pool with ID %s", convertStoragePoolId)); + } + if (forceConvertToPool && !forceConvertToPoolAllowedTypes.contains(selectedStoragePool.getPoolType())) { + logFailureAndThrowException(String.format("The selected storage pool %s does not support direct conversion " + + "as its type %s", selectedStoragePool.getName(), selectedStoragePool.getPoolType().name())); + } + } + } + + protected void validateSelectedConversionStoragePoolForVddk(boolean useVddk, Long convertStoragePoolId, + ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap) { + if (!useVddk || convertStoragePoolId == null) { + return; + } + + StoragePoolVO selectedStoragePool = primaryDataStoreDao.findById(convertStoragePoolId); + if (selectedStoragePool == null) { + return; + } + + if (serviceOffering.getDiskOfferingId() != null) { + DiskOfferingVO rootDiskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); + if (rootDiskOffering == null) { + throw new InvalidParameterValueException(String.format("Cannot find disk offering with ID %s that belongs to the service offering %s", + serviceOffering.getDiskOfferingId(), serviceOffering.getName())); + } + if (!volumeApiService.doesStoragePoolSupportDiskOffering(selectedStoragePool, rootDiskOffering)) { + throw new InvalidParameterValueException(String.format("The root disk offering '%s' is not supported by the selected conversion storage pool '%s'. " + + "When using VDDK, all selected disk offerings must be compatible with the conversion storage pool, as it will become the primary storage for the imported volumes.", + rootDiskOffering.getName(), selectedStoragePool.getName())); + } + } + + if (MapUtils.isNotEmpty(dataDiskOfferingMap)) { + for (Long diskOfferingId : dataDiskOfferingMap.values()) { + DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId); + if (diskOffering == null) { + throw new InvalidParameterValueException(String.format("Cannot find disk offering with ID %s", diskOfferingId)); + } + if (!volumeApiService.doesStoragePoolSupportDiskOffering(selectedStoragePool, diskOffering)) { + throw new InvalidParameterValueException(String.format("The data disk offering '%s' is not supported by the selected conversion storage pool '%s'. " + + "When using VDDK, all selected disk offerings must be compatible with the conversion storage pool, as it will become the primary storage for the imported volumes.", + diskOffering.getName(), selectedStoragePool.getName())); + } + } + } + } + + private void checkNetworkingBeforeConvertingVmwareInstance(DataCenter zone, Account owner, String displayName, + String hostName, UnmanagedInstanceTO sourceVMwareInstance, + Map nicNetworkMap, + Map nicIpAddressMap, + boolean forced) { + List nics = sourceVMwareInstance.getNics(); + List networkIds = new ArrayList<>(nicNetworkMap.values()); + if (nics.size() != networkIds.size()) { + String msg = String.format("Different number of nics found on instance %s: %s vs %s nics provided", + sourceVMwareInstance.getName(), nics.size(), networkIds.size()); + logger.error(msg); + throw new CloudRuntimeException(msg); + } + + for (UnmanagedInstanceTO.Nic nic : nics) { + Long networkId = nicNetworkMap.get(nic.getNicId()); + NetworkVO network = networkDao.findById(networkId); + if (network == null) { + String err = String.format("Cannot find a network with id = %s", networkId); + logger.error(err); + throw new CloudRuntimeException(err); + } + Network.IpAddresses ipAddresses = null; + if (MapUtils.isNotEmpty(nicIpAddressMap) && nicIpAddressMap.containsKey(nic.getNicId())) { + ipAddresses = nicIpAddressMap.get(nic.getNicId()); + } + boolean autoImport = ipAddresses != null && ipAddresses.getIp4Address() != null && ipAddresses.getIp4Address().equalsIgnoreCase("auto"); + checkUnmanagedNicAndNetworkMacAddressForImport(network, nic, forced); + checkUnmanagedNicAndNetworkForImport(displayName, nic, network, zone, owner, autoImport, Hypervisor.HypervisorType.KVM); + checkUnmanagedNicAndNetworkHostnameForImport(displayName, nic, network, hostName); + checkUnmanagedNicIpAndNetworkForImport(displayName, nic, network, ipAddresses); + } + } + + private void checkUnmanagedNicAndNetworkMacAddressForImport(NetworkVO network, UnmanagedInstanceTO.Nic nic, boolean forced) { + NicVO existingNic = nicDao.findByNetworkIdAndMacAddress(network.getId(), nic.getMacAddress()); + if (existingNic != null && !forced) { + String err = String.format("NIC %s with MAC address %s already exists on network %s and forced flag is disabled. " + + "Retry with forced flag enabled if a new MAC address to be generated.", nic, nic.getMacAddress(), network); + logger.error(err); + throw new CloudRuntimeException(err); + } + } + + private void sanitizeConvertedInstance(UnmanagedInstanceTO convertedInstance, UnmanagedInstanceTO sourceVMwareInstance) { + convertedInstance.setCpuCores(sourceVMwareInstance.getCpuCores()); + convertedInstance.setCpuSpeed(sourceVMwareInstance.getCpuSpeed()); + convertedInstance.setCpuCoresPerSocket(sourceVMwareInstance.getCpuCoresPerSocket()); + convertedInstance.setMemory(sourceVMwareInstance.getMemory()); + convertedInstance.setPowerState(UnmanagedInstanceTO.PowerState.PowerOff); + List convertedInstanceDisks = convertedInstance.getDisks(); + List sourceVMwareInstanceDisks = sourceVMwareInstance.getDisks(); + for (int i = 0; i < convertedInstanceDisks.size(); i++) { + UnmanagedInstanceTO.Disk disk = convertedInstanceDisks.get(i); + disk.setDiskId(sourceVMwareInstanceDisks.get(i).getDiskId()); + } + List convertedInstanceNics = convertedInstance.getNics(); + List sourceVMwareInstanceNics = sourceVMwareInstance.getNics(); + if (CollectionUtils.isEmpty(convertedInstanceNics) && CollectionUtils.isNotEmpty(sourceVMwareInstanceNics)) { + for (UnmanagedInstanceTO.Nic nic : sourceVMwareInstanceNics) { + // In case the NICs information is not parsed from the converted XML domain, use the cloned instance NICs with virtio adapter + nic.setAdapterType("virtio"); + } + convertedInstance.setNics(sourceVMwareInstanceNics); + for (int i = 0; i < convertedInstanceNics.size(); i++) { + UnmanagedInstanceTO.Nic nic = convertedInstanceNics.get(i); + nic.setNicId(sourceVMwareInstanceNics.get(i).getNicId()); + } + } else if (CollectionUtils.isNotEmpty(convertedInstanceNics) && CollectionUtils.isNotEmpty(sourceVMwareInstanceNics) + && convertedInstanceNics.size() == sourceVMwareInstanceNics.size()) { + for (int i = 0; i < convertedInstanceNics.size(); i++) { + UnmanagedInstanceTO.Nic nic = convertedInstanceNics.get(i); + nic.setNicId(sourceVMwareInstanceNics.get(i).getNicId()); + if (nic.getMacAddress() == null) { + nic.setMacAddress(sourceVMwareInstanceNics.get(i).getMacAddress()); + } + } + } + } + + private void removeClonedInstance(String vcenter, String datacenterName, String username, String password, + String sourceHostName, String clonedInstanceName, String sourceVM) { + HypervisorGuru vmwareGuru = hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware); + Map params = createParamsForRemoveClonedInstance(vcenter, datacenterName, username, password, sourceVM); + boolean result = vmwareGuru.removeClonedHypervisorVMOutOfBand(sourceHostName, clonedInstanceName, params); + if (!result) { + String msg = String.format("Could not properly remove the cloned instance %s from VMware datacenter %s:%s", + clonedInstanceName, vcenter, datacenterName); + logger.warn(msg); + return; + } + logger.debug(String.format("Removed the cloned instance %s from VMWare datacenter %s/%s", + clonedInstanceName, vcenter, datacenterName)); + } + + private void removeTemplate(DataStoreTO convertLocation, String ovfTemplateOnConvertLocation) { + HypervisorGuru vmwareGuru = hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware); + boolean result = vmwareGuru.removeVMTemplateOutOfBand(convertLocation, ovfTemplateOnConvertLocation); + if (!result) { + String msg = String.format("Could not remove the template file %s on datastore %s", + ovfTemplateOnConvertLocation, convertLocation.getUrl()); + logger.warn(msg); + return; + } + logger.debug(String.format("Removed the template file %s on datastore %s", + ovfTemplateOnConvertLocation, convertLocation.getUrl())); + } + + private Map createParamsForRemoveClonedInstance(String vcenter, String datacenterName, String username, + String password, String sourceVM) { + Map params = new HashMap<>(); + params.put(VmDetailConstants.VMWARE_VCENTER_HOST, vcenter); + params.put(VmDetailConstants.VMWARE_DATACENTER_NAME, datacenterName); + params.put(VmDetailConstants.VMWARE_VCENTER_USERNAME, username); + params.put(VmDetailConstants.VMWARE_VCENTER_PASSWORD, password); + return params; + } + + HostVO selectKVMHostForImportingInCluster(Cluster destinationCluster, Long importInstanceHostId) { + if (importInstanceHostId != null) { + String err = null; + HostVO selectedHost = hostDao.findById(importInstanceHostId); + if (selectedHost == null) { + err = String.format("Cannot find host with ID %s to import the instance", + importInstanceHostId); + } else if (selectedHost.getResourceState() != ResourceState.Enabled) { + err = String.format( + "Cannot import the converted instance on the host %s as it is not in Enabled state", + selectedHost); + } else if (selectedHost.getStatus() != Status.Up) { + err = String.format( + "Cannot import the converted instance on the host %s as it is not running", + selectedHost); + } else if (selectedHost.getType() != Host.Type.Routing) { + err = String.format( + "Cannot import the converted instance on the host %s as it is not a routing host", + selectedHost); + } else if (destinationCluster.getId() != selectedHost.getClusterId()) { + err = String.format( + "Cannot import the converted instance on the host %s as it is not in the same cluster as the destination cluster", + selectedHost); + } + + if (err != null) { + logger.error(err); + throw new CloudRuntimeException(err); + } + return selectedHost; + } + + List hosts = hostDao.listByClusterAndHypervisorType(destinationCluster.getId(), destinationCluster.getHypervisorType()); + if (CollectionUtils.isNotEmpty(hosts)) { + return hosts.get(new Random().nextInt(hosts.size())); + } + + String err = String.format( + "Could not find any suitable %s host in cluster %s to import the converted instance", + destinationCluster.getHypervisorType(), destinationCluster); + logger.error(err); + throw new CloudRuntimeException(err); + } + + HostVO selectKVMHostForConversionInCluster(Cluster destinationCluster, Long convertInstanceHostId, boolean useVddk) { + if (convertInstanceHostId != null) { + HostVO selectedHost = hostDao.findById(convertInstanceHostId); + String err = null; + if (selectedHost == null) { + err = String.format("Cannot find host with ID %s for conversion", + convertInstanceHostId); + } else if (!List.of(ResourceState.Enabled, ResourceState.Disabled).contains(selectedHost.getResourceState())) { + err = String.format( + "Cannot perform the conversion on the host %s as the host is in %s state", + selectedHost, selectedHost.getResourceState()); + } else if (selectedHost.getStatus() != Status.Up) { + err = String.format( + "Cannot perform the conversion on the host %s as it is not running", + selectedHost); + } else if (selectedHost.getType() != Host.Type.Routing) { + err = String.format( + "Cannot perform the conversion on the host %s as it is not a routing host", + selectedHost); + } else if (destinationCluster.getDataCenterId() != selectedHost.getDataCenterId()) { + err = String.format( + "Cannot perform the conversion on the host %s as it is not in the same zone as the destination cluster", + selectedHost); + } + if (err != null) { + logger.error(err); + throw new CloudRuntimeException(err); + } + return selectedHost; + } + + // Auto select host with conversion capability + List hosts = hostDao.listByClusterHypervisorTypeAndHostCapability(destinationCluster.getId(), destinationCluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION); + if (CollectionUtils.isNotEmpty(hosts)) { + if (useVddk) { + List vddkHosts = filterHostsWithVddkSupport(hosts); + if (CollectionUtils.isNotEmpty(vddkHosts)) { + hosts = vddkHosts; + } + } + if (CollectionUtils.isNotEmpty(hosts)) { + return hosts.get(new Random().nextInt(hosts.size())); + } + } + + // Try without host capability check + hosts = hostDao.listByClusterAndHypervisorType(destinationCluster.getId(), destinationCluster.getHypervisorType()); + if (CollectionUtils.isNotEmpty(hosts)) { + if (useVddk) { + List vddkHosts = filterHostsWithVddkSupport(hosts); + if (CollectionUtils.isNotEmpty(vddkHosts)) { + hosts = vddkHosts; + } + } + if (CollectionUtils.isNotEmpty(hosts)) { + return hosts.get(new Random().nextInt(hosts.size())); + } + } + + String err = useVddk + ? String.format("Could not find any suitable %s host in cluster %s with '%s' configured to perform the VDDK-based instance conversion", + destinationCluster.getHypervisorType(), destinationCluster, Host.HOST_VDDK_SUPPORT) + : String.format("Could not find any suitable %s host in cluster %s to perform the instance conversion", + destinationCluster.getHypervisorType(), destinationCluster); + logger.error(err); + throw new CloudRuntimeException(err); + } + + private List filterHostsWithVddkSupport(List hosts) { + return hosts.stream().filter(h -> { + hostDao.loadDetails(h); + return Boolean.parseBoolean(h.getDetail(Host.HOST_VDDK_SUPPORT)); + }).collect(Collectors.toList()); + } + + private CheckConvertInstanceAnswer checkConversionSupportOnHost(HostVO convertHost, String sourceVM, + boolean checkWindowsGuestConversionSupport, + boolean useVddk, Map details) { + logger.debug(String.format("Checking the %s%s conversion support on the host %s", + useVddk ? "VDDK " : "", + checkWindowsGuestConversionSupport ? "windows guest " : "", + convertHost)); + CheckConvertInstanceCommand cmd = new CheckConvertInstanceCommand(checkWindowsGuestConversionSupport, useVddk); + if (MapUtils.isNotEmpty(details)) { + cmd.setVddkLibDir(StringUtils.trimToNull(details.get(Host.HOST_VDDK_LIB_DIR))); + } + int timeoutSeconds = 60; + cmd.setWait(timeoutSeconds); + + CheckConvertInstanceAnswer checkConvertInstanceAnswer; + try { + checkConvertInstanceAnswer = (CheckConvertInstanceAnswer) agentManager.send(convertHost.getId(), cmd); + } catch (AgentUnavailableException | OperationTimedoutException e) { + String err = String.format("Failed to check %s conversion support on the host %s for converting instance %s from VMware to KVM due to: %s", + checkWindowsGuestConversionSupport? "windows guest" : "", convertHost, sourceVM, e.getMessage()); + logger.error(err); + throw new CloudRuntimeException(err); + } + + if (!checkConvertInstanceAnswer.getResult()) { + String err = String.format("The host %s doesn't support conversion of instance %s from VMware to KVM due to: %s", + convertHost, sourceVM, checkConvertInstanceAnswer.getDetails()); + logger.error(err); + throw new CloudRuntimeException(err); + } + + return checkConvertInstanceAnswer; + } + + private UnmanagedInstanceTO convertVmwareInstanceToKVMWithOVFOnConvertLocation( + String sourceVM, UnmanagedInstanceTO sourceVMwareInstance, HostVO convertHost, + HostVO importHost, List convertStoragePools, + ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap, + DataStoreTO temporaryConvertLocation, String ovfTemplateDirConvertLocation, + boolean forceConvertToPool, String extraParams) { + + logger.debug("Delegating the conversion of instance {} from VMware to KVM to the host {} using OVF {} on conversion datastore", + sourceVM, convertHost, ovfTemplateDirConvertLocation); + + RemoteInstanceTO remoteInstanceTO = new RemoteInstanceTO(sourceVM, sourceVMwareInstance.getClusterName(), sourceVMwareInstance.getHostName()); + List destinationStoragePools = selectInstanceConversionStoragePools(convertStoragePools, sourceVMwareInstance.getDisks(), serviceOffering, dataDiskOfferingMap); + ConvertInstanceCommand cmd = new ConvertInstanceCommand(remoteInstanceTO, + Hypervisor.HypervisorType.KVM, temporaryConvertLocation, + ovfTemplateDirConvertLocation, false, false, sourceVM); + if (StringUtils.isNotBlank(extraParams)) { + cmd.setExtraParams(extraParams); + } + int timeoutSeconds = UnmanagedVMsManager.ConvertVmwareInstanceToKvmTimeout.value() * 60 * 60; + cmd.setWait(timeoutSeconds); + + return convertAndImportToKVM(cmd, convertHost, importHost, sourceVM, + remoteInstanceTO, destinationStoragePools, temporaryConvertLocation, forceConvertToPool); + } + + private UnmanagedInstanceTO convertVmwareInstanceToKVMUsingVDDKOrAfterExportingOVFToConvertLocation( + String sourceVM, UnmanagedInstanceTO sourceVMwareInstance, HostVO convertHost, + HostVO importHost, List convertStoragePools, + ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap, + DataStoreTO temporaryConvertLocation, String vcenterHost, String vcenterUsername, + String vcenterPassword, String datacenterName, boolean forceConvertToPool, String extraParams, + boolean useVddk, Map details) { + logger.debug("Delegating the conversion of instance {} from VMware to KVM to the host {} after OVF export through ovftool", sourceVM, convertHost); + + RemoteInstanceTO remoteInstanceTO = new RemoteInstanceTO(sourceVMwareInstance.getName(), sourceVMwareInstance.getPath(), vcenterHost, vcenterUsername, vcenterPassword, datacenterName, sourceVMwareInstance.getClusterName(), sourceVMwareInstance.getHostName()); + List destinationStoragePools = selectInstanceConversionStoragePools(convertStoragePools, sourceVMwareInstance.getDisks(), serviceOffering, dataDiskOfferingMap); + ConvertInstanceCommand cmd = new ConvertInstanceCommand(remoteInstanceTO, + Hypervisor.HypervisorType.KVM, temporaryConvertLocation, null, false, true, sourceVM); + int timeoutSeconds = UnmanagedVMsManager.ConvertVmwareInstanceToKvmTimeout.value() * 60 * 60; + cmd.setWait(timeoutSeconds); + int noOfThreads = UnmanagedVMsManager.ThreadsOnKVMHostToImportVMwareVMFiles.value(); + if (noOfThreads == 0) { + // Use no. of threads as the disks count + noOfThreads = sourceVMwareInstance.getDisks().size(); + } + cmd.setThreadsCountToExportOvf(noOfThreads); + if (StringUtils.isNotBlank(extraParams)) { + cmd.setExtraParams(extraParams); + } + cmd.setUseVddk(useVddk); + applyVddkOverridesFromDetails(cmd, details); + return convertAndImportToKVM(cmd, convertHost, importHost, sourceVM, + remoteInstanceTO, destinationStoragePools, temporaryConvertLocation, forceConvertToPool); + } + + private void applyVddkOverridesFromDetails(ConvertInstanceCommand cmd, Map details) { + if (MapUtils.isEmpty(details)) { + return; + } + + cmd.setVddkLibDir(StringUtils.trimToNull(details.get(Host.HOST_VDDK_LIB_DIR))); + cmd.setVddkTransports(StringUtils.trimToNull(details.get(DETAIL_VDDK_TRANSPORTS))); + cmd.setVddkThumbprint(StringUtils.trimToNull(details.get(DETAIL_VDDK_THUMBPRINT))); + } + + private UnmanagedInstanceTO convertAndImportToKVM(ConvertInstanceCommand convertInstanceCommand, HostVO convertHost, HostVO importHost, + String sourceVM, + RemoteInstanceTO remoteInstanceTO, + List destinationStoragePools, + DataStoreTO temporaryConvertLocation, + boolean forceConvertToPool) { + Answer convertAnswer; + try { + convertAnswer = agentManager.send(convertHost.getId(), convertInstanceCommand); + } catch (AgentUnavailableException | OperationTimedoutException e) { + String err = String.format("Could not send the convert instance command to host %s due to: %s", + convertHost, e.getMessage()); + logger.error(err, e); + throw new CloudRuntimeException(err); + } + + if (!convertAnswer.getResult()) { + String err = String.format("The convert process failed for instance %s from VMware to KVM on host %s: %s", + sourceVM, convertHost, convertAnswer.getDetails()); + logger.error(err); + throw new CloudRuntimeException(err); + } + + Answer importAnswer; + try { + ImportConvertedInstanceCommand importCmd = new ImportConvertedInstanceCommand( + remoteInstanceTO, destinationStoragePools, temporaryConvertLocation, + ((ConvertInstanceAnswer)convertAnswer).getTemporaryConvertUuid(), forceConvertToPool); + importAnswer = agentManager.send(importHost.getId(), importCmd); + } catch (AgentUnavailableException | OperationTimedoutException e) { + String err = String.format( + "Could not send the import converted instance command to host %s due to: %s", + importHost, e.getMessage()); + logger.error(err, e); + throw new CloudRuntimeException(err); + } + + if (!importAnswer.getResult()) { + String err = String.format( + "The import process failed for instance %s from VMware to KVM on host %s: %s", + sourceVM, importHost, importAnswer.getDetails()); + logger.error(err); + throw new CloudRuntimeException(err); + } + + return ((ImportConvertedInstanceAnswer) importAnswer).getConvertedInstance(); + } + + private List findInstanceConversionDestinationStoragePoolsInCluster( + Cluster destinationCluster, ServiceOfferingVO serviceOffering, + Map dataDiskOfferingMap, + DataStoreTO temporaryConvertLocation, boolean forceConvertToPool) { + List poolsList; + if (!forceConvertToPool) { + Set pools = new HashSet<>(primaryDataStoreDao.findClusterWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)); + pools.addAll(primaryDataStoreDao.findZoneWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getDataCenterId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)); + if (pools.isEmpty()) { + String msg = String.format("Cannot find suitable storage pools in the cluster %s for the conversion", destinationCluster.getName()); + logger.error(msg); + throw new CloudRuntimeException(msg); + } + poolsList = new ArrayList<>(pools); + } else { + DataStore dataStore = dataStoreManager.getDataStore(temporaryConvertLocation.getUuid(), temporaryConvertLocation.getRole()); + poolsList = Collections.singletonList(primaryDataStoreDao.findById(dataStore.getId())); + } + + if (serviceOffering.getDiskOfferingId() != null) { + DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); + if (diskOffering == null) { + String msg = String.format("Cannot find disk offering with ID %s that belongs to the service offering %s", serviceOffering.getDiskOfferingId(), serviceOffering.getName()); + logger.error(msg); + throw new CloudRuntimeException(msg); + } + if (getStoragePoolWithTags(poolsList, diskOffering.getTags()) == null) { + String msg = String.format("Cannot find suitable storage pool for disk offering %s that belongs to the service offering %s", diskOffering.getName(), serviceOffering.getName()); + logger.error(msg); + throw new CloudRuntimeException(msg); + } + } + for (Long diskOfferingId : dataDiskOfferingMap.values()) { + DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId); + if (diskOffering == null) { + String msg = String.format("Cannot find disk offering with ID %s", diskOfferingId); + logger.error(msg); + throw new CloudRuntimeException(msg); + } + if (getStoragePoolWithTags(poolsList, diskOffering.getTags()) == null) { + String msg = String.format("Cannot find suitable storage pool for disk offering %s", diskOffering.getName()); + logger.error(msg); + throw new CloudRuntimeException(msg); + } + } + + return poolsList; + } + + private StoragePoolVO getStoragePoolWithTags(List pools, String tags) { + if (StringUtils.isEmpty(tags)) { + return pools.get(0); + } + for (StoragePoolVO pool : pools) { + if (volumeApiService.doesStoragePoolSupportDiskOfferingTags(pool, tags)) { + return pool; + } + } + return null; + } + + private List selectInstanceConversionStoragePools( + List pools, List disks, + ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap + ) { + List storagePools = new ArrayList<>(disks.size()); + Set dataDiskIds = dataDiskOfferingMap.keySet(); + for (UnmanagedInstanceTO.Disk disk : disks) { + Long diskOfferingId = null; + if (dataDiskIds.contains(disk.getDiskId())) { + diskOfferingId = dataDiskOfferingMap.get(disk.getDiskId()); + } else { + diskOfferingId = serviceOffering.getDiskOfferingId(); + } + + //TODO: Choose pools by capacity + if (diskOfferingId == null) { + storagePools.add(pools.get(0).getUuid()); + } else { + DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId); + StoragePoolVO pool = getStoragePoolWithTags(pools, diskOffering.getTags()); + storagePools.add(pool.getUuid()); + } + } + return storagePools; + } + + private void logFailureAndThrowException(String msg) { + logger.error(msg); + throw new CloudRuntimeException(msg); + } + + private void checkBeforeSelectingTemporaryConversionStoragePool(StoragePoolVO selectedStoragePool, Long convertStoragePoolId, Cluster destinationCluster, HostVO convertHost) { + if (selectedStoragePool == null) { + logFailureAndThrowException(String.format("Cannot find a storage pool with ID %s", convertStoragePoolId)); + } + if ((selectedStoragePool.getScope() == ScopeType.CLUSTER && selectedStoragePool.getClusterId() != destinationCluster.getId()) || + (selectedStoragePool.getScope() == ScopeType.ZONE && selectedStoragePool.getDataCenterId() != destinationCluster.getDataCenterId())) { + logFailureAndThrowException(String.format("Cannot use the storage pool %s for the instance conversion as " + + "it is not in the scope of the cluster %s", selectedStoragePool.getName(), destinationCluster.getName())); + } + if (convertHost != null && selectedStoragePool.getScope() == ScopeType.CLUSTER && !selectedStoragePool.getClusterId().equals(convertHost.getClusterId())) { + logFailureAndThrowException(String.format("Cannot use the storage pool %s for the instance conversion as " + + "the host %s for conversion is in a different cluster", selectedStoragePool.getName(), convertHost.getName())); + } + } + + private DataStoreTO getImageStoreOnDestinationZoneForTemporaryConversion(Cluster destinationCluster, boolean forceConvertToPool) { + if (forceConvertToPool) { + logFailureAndThrowException("Please select a primary storage pool when the parameter forceconverttopool is set to true"); + } + long zoneId = destinationCluster.getDataCenterId(); + ImageStoreVO imageStore = imageStoreDao.findOneByZoneAndProtocol(zoneId, "nfs"); + if (imageStore == null) { + logFailureAndThrowException(String.format("Could not find an NFS secondary storage pool on zone %s to use as a temporary location " + + "for instance conversion", zoneId)); + } + DataStore dataStore = dataStoreManager.getDataStore(imageStore.getId(), DataStoreRole.Image); + return dataStore.getTO(); + } + + private void checkDestinationOrTemporaryStoragePoolForConversion(StoragePoolVO selectedStoragePool, boolean forceConvertToPool, HostVO convertHost, HostVO importHost) { + if (selectedStoragePool.getScope() == ScopeType.HOST && (ObjectUtils.anyNull(convertHost, importHost) || + ObjectUtils.allNotNull(convertHost, importHost) && convertHost.getId() != importHost.getId() || + !forceConvertToPool) ) { + logFailureAndThrowException("Please select the same host as convert and importing host and " + + "set forceconvertopool to true to use a local storage pool for conversion"); + } + if (!forceConvertToPool && selectedStoragePool.getPoolType() != Storage.StoragePoolType.NetworkFilesystem) { + logFailureAndThrowException(String.format("The storage pool %s is not supported for temporary conversion location," + + "only NFS storage pools are supported when forceconverttopool is set to false", selectedStoragePool.getName())); + } + } + + protected DataStoreTO selectInstanceConversionTemporaryLocation(Cluster destinationCluster, + HostVO convertHost, HostVO importHost, + Long convertStoragePoolId, boolean forceConvertToPool) { + if (convertStoragePoolId == null) { + String msg = String.format("No convert storage pool has been provided, " + + "selecting an NFS secondary storage pool from the destination cluster (%s) zone", destinationCluster.getName()); + logger.debug(msg); + return getImageStoreOnDestinationZoneForTemporaryConversion(destinationCluster, forceConvertToPool); + } + + StoragePoolVO selectedStoragePool = primaryDataStoreDao.findById(convertStoragePoolId); + checkBeforeSelectingTemporaryConversionStoragePool(selectedStoragePool, convertStoragePoolId, destinationCluster, convertHost); + checkDestinationOrTemporaryStoragePoolForConversion(selectedStoragePool, forceConvertToPool, convertHost, importHost); + + return dataStoreManager.getPrimaryDataStore(convertStoragePoolId).getTO(); + } + + protected Map createParamsForTemplateFromVmwareVmMigration(String vcenterHost, String datacenterName, + String username, String password, + String clusterName, String sourceHostName, + String sourceVMName) { + Map params = new HashMap<>(); + params.put(VmDetailConstants.VMWARE_VCENTER_HOST, vcenterHost); + params.put(VmDetailConstants.VMWARE_DATACENTER_NAME, datacenterName); + params.put(VmDetailConstants.VMWARE_VCENTER_USERNAME, username); + params.put(VmDetailConstants.VMWARE_VCENTER_PASSWORD, password); + params.put(VmDetailConstants.VMWARE_CLUSTER_NAME, clusterName); + params.put(VmDetailConstants.VMWARE_HOST_NAME, sourceHostName); + params.put(VmDetailConstants.VMWARE_VM_NAME, sourceVMName); + return params; + } + + @Override + public List> getCommands() { + final List> cmdList = new ArrayList>(); + cmdList.add(ListUnmanagedInstancesCmd.class); + cmdList.add(ImportUnmanagedInstanceCmd.class); + cmdList.add(UnmanageVMInstanceCmd.class); + cmdList.add(ListVmsForImportCmd.class); + cmdList.add(ImportVmCmd.class); + cmdList.add(ListImportVMTasksCmd.class); + return cmdList; + } + + /** + * Perform validations before attempting to unmanage a VM from CloudStack: + * - VM must not have any associated volume snapshot + * - VM must not have an attached ISO + * - VM must not belong to any CKS cluster + * @throws UnsupportedServiceException in case any of the validations above fail + */ + void performUnmanageVMInstancePrechecks(VMInstanceVO vmVO) { + if (hasVolumeSnapshotsPriorToUnmanageVM(vmVO)) { + throw new UnsupportedServiceException("Cannot unmanage VM with id = " + vmVO.getUuid() + + " as there are volume snapshots for its volume(s). Please remove snapshots before unmanaging."); + } + + if (hasISOAttached(vmVO)) { + throw new UnsupportedServiceException("Cannot unmanage VM with id = " + vmVO.getUuid() + + " as there is an ISO attached. Please detach ISO before unmanaging."); + } + + if (userVmManager.isVMPartOfAnyCKSCluster(vmVO)) { + throw new UnsupportedServiceException("Cannot unmanage VM with id = " + vmVO.getUuid() + + " as it belongs to a CKS cluster. Please remove the VM from the CKS cluster before unmanaging."); + } + } + + private boolean hasVolumeSnapshotsPriorToUnmanageVM(VMInstanceVO vmVO) { + List volumes = volumeDao.findByInstance(vmVO.getId()); + for (VolumeVO volume : volumes) { + List snaps = snapshotDao.listByVolumeId(volume.getId()); + if (CollectionUtils.isNotEmpty(snaps)) { + for (SnapshotVO snap : snaps) { + if (snap.getState() != Snapshot.State.Destroyed && snap.getRemoved() == null) { + return true; + } + } + } + } + return false; + } + + private boolean hasISOAttached(VMInstanceVO vmVO) { + UserVmVO userVM = userVmDao.findById(vmVO.getId()); + if (userVM == null) { + throw new InvalidParameterValueException("Could not find user VM with ID = " + vmVO.getUuid()); + } + return userVM.getIsoId() != null; + } + + /** + * Find a suitable host within the scope of the VM to unmanage to verify the VM exists + */ + private Long findSuitableHostId(VMInstanceVO vmVO) { + Long hostId = vmVO.getHostId(); + if (hostId == null) { + long zoneId = vmVO.getDataCenterId(); + List hosts = hostDao.listAllHostsUpByZoneAndHypervisor(zoneId, vmVO.getHypervisorType()); + for (HostVO host : hosts) { + if (host.isInMaintenanceStates() || host.getState() != Status.Up || host.getStatus() != Status.Up) { + continue; + } + hostId = host.getId(); + break; + } + } + + if (hostId == null) { + throw new CloudRuntimeException(String.format("Cannot find a host to verify if the VM [%s] exists. Thus we are unable to unmanage it.", vmVO.getUuid())); + } + return hostId; + } + + @Override + @ActionEvent(eventType = EventTypes.EVENT_VM_UNMANAGE, eventDescription = "unmanaging VM", async = true) + public Pair unmanageVMInstance(long vmId, Long paramHostId, boolean isForced) { + VMInstanceVO vmVO = vmDao.findById(vmId); + if (vmVO == null || vmVO.getRemoved() != null) { + throw new InvalidParameterValueException("Could not find VM to unmanage, it is either removed or not existing VM"); + } else if (vmVO.getState() != VirtualMachine.State.Running && vmVO.getState() != VirtualMachine.State.Stopped) { + throw new InvalidParameterValueException("VM with id = " + vmVO.getUuid() + " must be running or stopped to be unmanaged"); + } else if (!UnmanagedVMsManager.isSupported(vmVO.getHypervisorType())) { + throw new UnsupportedServiceException("Unmanage VM is currently not allowed for hypervisor " + + vmVO.getHypervisorType().toString()); + } else if (vmVO.getType() != VirtualMachine.Type.User) { + throw new UnsupportedServiceException("Unmanage VM is currently allowed for guest VMs only"); + } else if (paramHostId != null && + (vmVO.getHypervisorType() != Hypervisor.HypervisorType.KVM || vmVO.getState() != VirtualMachine.State.Stopped)) { + throw new UnsupportedServiceException("Param hostid is only supported for KVM hypervisor for stopped Instances."); + } else if (!isForced && vmVO.getHypervisorType() == Hypervisor.HypervisorType.KVM + && vmInstanceDetailsDao.findDetail(vmId, VmDetailConstants.CONFIG_DRIVE_LOCATION) != null) { + throw new UnsupportedServiceException("Config drive is attached to Instance, use forced param true from API to unmanage it."); + } + + if (vmVO.getType().equals(VirtualMachine.Type.User)) { + UserVmVO userVm = userVmDao.findById(vmId); + if (UserVmManager.SHAREDFSVM.equals(userVm.getUserVmType())) { + throw new InvalidParameterValueException("Operation not supported on Shared FileSystem Instance"); + } + } + + performUnmanageVMInstancePrechecks(vmVO); + + boolean isKvmVmStopped = VirtualMachine.State.Stopped.equals(vmVO.getState()) && vmVO.getHypervisorType() == Hypervisor.HypervisorType.KVM; + Long hostId = isKvmVmStopped ? vmVO.getLastHostId() : findSuitableHostId(vmVO); + String instanceName = vmVO.getInstanceName(); + + if (!isKvmVmStopped && !existsVMToUnmanage(instanceName, hostId)) { + throw new CloudRuntimeException(String.format("VM %s is not found in the hypervisor", vmVO)); + } + + return userVmManager.unmanageUserVM(vmId, paramHostId); + } + + /** + * Verify the VM to unmanage exists on the hypervisor + */ + private boolean existsVMToUnmanage(String instanceName, Long hostId) { + PrepareUnmanageVMInstanceCommand command = new PrepareUnmanageVMInstanceCommand(); + command.setInstanceName(instanceName); + Answer ans = agentManager.easySend(hostId, command); + if (!(ans instanceof PrepareUnmanageVMInstanceAnswer)) { + throw new CloudRuntimeException(String.format("Error communicating with host %s", hostDao.findById(hostId))); + } + PrepareUnmanageVMInstanceAnswer answer = (PrepareUnmanageVMInstanceAnswer) ans; + if (!answer.getResult()) { + logger.error("Error verifying VM {} exists on host {}: {}", instanceName::toString, () -> hostDao.findById(hostId), answer::getDetails); + } + return answer.getResult(); + } + + private UserVmResponse importKvmInstance(ImportVmCmd cmd) { + final Account caller = CallContext.current().getCallingAccount(); + if (caller.getType() != Account.Type.ADMIN) { + throw new PermissionDeniedException(String.format("Cannot perform this operation, Calling account is not root admin: %s", caller.getUuid())); + } + final Long zoneId = cmd.getZoneId(); + final DataCenterVO zone = dataCenterDao.findById(zoneId); + if (zone == null) { + throw new InvalidParameterValueException("Please specify a valid zone."); + } + final String hypervisorType = cmd.getHypervisor(); + if (!Hypervisor.HypervisorType.KVM.toString().equalsIgnoreCase(hypervisorType)) { + throw new InvalidParameterValueException(String.format("VM import is currently not supported for hypervisor: %s", hypervisorType)); + } + + final String instanceName = cmd.getName(); + if (StringUtils.isEmpty(instanceName)) { + throw new InvalidParameterValueException(String.format("Instance name cannot be empty")); + } + if (cmd.getDomainId() != null && StringUtils.isEmpty(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()); + if (CollectionUtils.isNotEmpty(userVOs)) { + userId = userVOs.get(0).getId(); + } + VMTemplateVO template = getTemplateForImportInstance(cmd.getTemplateId(), Hypervisor.HypervisorType.KVM); + 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); + String displayName = cmd.getDisplayName(); + if (StringUtils.isEmpty(displayName)) { + displayName = instanceName; + } + String hostName = cmd.getHostName(); + if (StringUtils.isEmpty(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 = mergeNicMacAddresses(cmd.getNicIpAddressList(), cmd.getNicMacAddressList()); + final Map dataDiskOfferingMap = cmd.getDataDiskToDiskOfferingList(); + final Map details = cmd.getDetails(); + + String remoteUrl = cmd.getHost(); + String source = cmd.getImportSource().toUpperCase(); + String diskPath = cmd.getDiskPath(); + ImportSource importSource = Enum.valueOf(ImportSource.class, source); + Long hostId = cmd.getHostId(); + Long poolId = cmd.getStoragePoolId(); + Long networkId = cmd.getNetworkId(); + + UnmanagedInstanceTO unmanagedInstanceTO = null; + if (ImportSource.EXTERNAL == importSource) { + if (StringUtils.isBlank(cmd.getUsername())) { + throw new InvalidParameterValueException("Username need to be provided."); + } + + HashMap instancesMap = getRemoteVmsOnKVMHost(zoneId, remoteUrl, cmd.getUsername(), cmd.getPassword()); + unmanagedInstanceTO = instancesMap.get(cmd.getName()); + if (unmanagedInstanceTO == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM with name: %s not found on remote host %s", instanceName, remoteUrl)); + } + } + + if (ImportSource.SHARED == importSource || ImportSource.LOCAL == importSource) { + if (diskPath == null) { + throw new InvalidParameterValueException("Disk Path is required for Import from shared/local storage"); + } + + if (networkId == null) { + throw new InvalidParameterValueException("Network is required for Import from shared/local storage"); + } + + if (poolId == null) { + throw new InvalidParameterValueException("Storage Pool is required for Import from shared/local storage"); + } + + StoragePool storagePool = primaryDataStoreDao.findById(poolId); + if (storagePool == null) { + throw new InvalidParameterValueException("Storage Pool not found"); + } + + if (volumeDao.findByPoolIdAndPath(poolId, diskPath) != null) { + throw new InvalidParameterValueException("Disk image is already in use"); + } + + DiskOffering diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); + + if (diskOffering != null && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) { + throw new InvalidParameterValueException(String.format("Service offering: %s storage tags are not compatible with selected storage pool: %s", serviceOffering.getUuid(), storagePool.getUuid())); + } + } + + if (ImportSource.LOCAL == importSource) { + if (hostId == null) { + throw new InvalidParameterValueException("Host is required for Import from local storage"); + } + + if (hostDao.findById(hostId) == null) { + throw new InvalidParameterValueException("Host not found"); + } + + if(storagePoolHostDao.findByPoolHost(poolId, hostId) == null) { + throw new InvalidParameterValueException("Specified Local Storage Pool not found on Host"); + } + } + + UserVm userVm = null; + + try { + + if (ImportSource.EXTERNAL == importSource) { + String username = cmd.getUsername(); + String password = cmd.getPassword(); + String tmpPath = cmd.getTmpPath(); + userVm = importExternalKvmVirtualMachine(unmanagedInstanceTO, instanceName, zone, + template, displayName, hostName, caller, owner, userId, + serviceOffering, dataDiskOfferingMap, + nicNetworkMap, nicIpAddressMap, remoteUrl, username, password, tmpPath, details); + } else if (ImportSource.SHARED == importSource || ImportSource.LOCAL == importSource) { + try { + userVm = importKvmVirtualMachineFromDisk(importSource, instanceName, zone, + template, displayName, hostName, caller, owner, userId, + serviceOffering, dataDiskOfferingMap, networkId, hostId, poolId, diskPath, + details); + } catch (InsufficientCapacityException e) { + throw new RuntimeException(e); + } catch (ResourceAllocationException e) { + throw new RuntimeException(e); + } + } + + } 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(), StringUtils.defaultString(e.getMessage()))); + } + + if (userVm == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import Vm with name: %s ", instanceName)); + } + + CallContext.current().setEventResourceId(userVm.getId()); + CallContext.current().setEventResourceType(ApiCommandResourceType.VirtualMachine); + return responseGenerator.createUserVmResponse(ResponseObject.ResponseView.Full, "virtualmachine", userVm).get(0); + } + + private UserVm importExternalKvmVirtualMachine(final UnmanagedInstanceTO unmanagedInstance, final String instanceName, final DataCenter zone, + final VirtualMachineTemplate template, final String displayName, final String hostName, final Account caller, final Account owner, final Long userId, + final ServiceOfferingVO serviceOffering, final Map dataDiskOfferingMap, + final Map nicNetworkMap, final Map callerNicIpAddressMap, + final String remoteUrl, String username, String password, String tmpPath, final Map details) throws ResourceAllocationException { + UserVm userVm = null; + + Map allDetails = new HashMap<>(details); + // 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)); + } + + DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); + Pair> rootAndDataDisksPair = getRootAndDataDisks(unmanagedInstanceDisks, dataDiskOfferingMap); + final UnmanagedInstanceTO.Disk rootDisk = rootAndDataDisksPair.first(); + final List dataDisks = rootAndDataDisksPair.second(); + if (rootDisk == null || StringUtils.isEmpty(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 reservations = new ArrayList<>(); + try { + checkVmResourceLimitsForExternalKvmVmImport(owner, serviceOffering, (VMTemplateVO) template, details, reservations); + checkVolumeResourceLimitsForExternalKvmVmImport(owner, rootDisk, dataDisks, diskOffering, dataDiskOfferingMap, reservations); + + // Check NICs and supplied networks + Map nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap); + Map allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getName(), unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner, Hypervisor.HypervisorType.KVM); + if (!CollectionUtils.isEmpty(unmanagedInstance.getNics())) { + allDetails.put(VmDetailConstants.NIC_ADAPTER, unmanagedInstance.getNics().get(0).getAdapterType()); + } + VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff; + + try { + userVm = userVmManager.importVM(zone, null, template, null, displayName, owner, + null, caller, true, null, owner.getAccountId(), userId, + serviceOffering, null, null, hostName, + Hypervisor.HypervisorType.KVM, allDetails, powerState, null); + } 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)); + } + String rootVolumeName = String.format("ROOT-%s", userVm.getId()); + DiskProfile diskProfile = volumeManager.allocateRawVolume(Volume.Type.ROOT, rootVolumeName, diskOffering, null, null, null, userVm, template, owner, null, false); + + DiskProfile[] dataDiskProfiles = new DiskProfile[dataDisks.size()]; + int diskSeq = 0; + for (UnmanagedInstanceTO.Disk disk : dataDisks) { + DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId())); + DiskProfile dataDiskProfile = volumeManager.allocateRawVolume(Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()), offering, null, null, null, userVm, template, owner, null, false); + dataDiskProfiles[diskSeq++] = dataDiskProfile; + } + + final VirtualMachineProfile profile = new VirtualMachineProfileImpl(userVm, template, serviceOffering, owner, null); + ServiceOfferingVO dummyOffering = serviceOfferingDao.findById(userVm.getId(), serviceOffering.getId()); + profile.setServiceOffering(dummyOffering); + DeploymentPlanner.ExcludeList excludeList = new DeploymentPlanner.ExcludeList(); + final DataCenterDeployment plan = new DataCenterDeployment(zone.getId(), null, null, null, null, null); + DeployDestination dest = null; + try { + dest = deploymentPlanningManager.planDeployment(profile, plan, excludeList, null); + } catch (Exception e) { + logger.warn("Import failed for Vm: {} while finding deployment destination", userVm, e); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s while finding deployment destination", userVm.getInstanceName())); + } + if(dest == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s. Suitable deployment destination not found", userVm.getInstanceName())); + } + + List> diskProfileStoragePoolList = new ArrayList<>(); + try { + diskProfileStoragePoolList.add(importExternalDisk(rootDisk, userVm, dest, diskOffering, Volume.Type.ROOT, + template, null, remoteUrl, username, password, tmpPath, diskProfile)); + + long deviceId = 1L; + diskSeq = 0; + for (UnmanagedInstanceTO.Disk disk : dataDisks) { + DiskProfile dataDiskProfile = dataDiskProfiles[diskSeq++]; + DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId())); + + diskProfileStoragePoolList.add(importExternalDisk(disk, userVm, dest, offering, Volume.Type.DATADISK, + template, deviceId, remoteUrl, username, password, tmpPath, dataDiskProfile)); + deviceId++; + } + } catch (Exception e) { + logger.error(String.format("Failed to import volumes while importing vm: %s", instanceName), e); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", instanceName, StringUtils.defaultString(e.getMessage()))); + } + try { + int nicIndex = 0; + 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, nicIndex, nicIndex==0, true); + nicIndex++; + } + } catch (Exception e) { + logger.error(String.format("Failed to import NICs while importing vm: %s", instanceName), e); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import NICs while importing vm: %s. %s", instanceName, StringUtils.defaultString(e.getMessage()))); + } + publishVMUsageUpdateResourceCount(userVm, dummyOffering, template); + return userVm; + + } finally { + ReservationHelper.closeAll(reservations); + } + } + + protected void checkVolumeResourceLimitsForExternalKvmVmImport(Account owner, UnmanagedInstanceTO.Disk rootDisk, + List dataDisks, DiskOfferingVO rootDiskOffering, + Map dataDiskOfferingMap, List reservations) throws ResourceAllocationException { + if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) { + throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId())); + } + resourceLimitService.checkVolumeResourceLimit(owner, true, rootDisk.getCapacity(), rootDiskOffering, reservations); + + if (CollectionUtils.isEmpty(dataDisks)) { + return; + } + for (UnmanagedInstanceTO.Disk disk : dataDisks) { + if (disk.getCapacity() == null || disk.getCapacity() == 0) { + throw new InvalidParameterValueException(String.format("Data disk ID: %s size is invalid", disk.getDiskId())); + } + DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId())); + resourceLimitService.checkVolumeResourceLimit(owner, true, disk.getCapacity(), offering, reservations); + } + } + + private UserVm importKvmVirtualMachineFromDisk(final ImportSource importSource, final String instanceName, final DataCenter zone, + final VirtualMachineTemplate template, final String displayName, final String hostName, final Account caller, final Account owner, final Long userId, + final ServiceOfferingVO serviceOffering, final Map dataDiskOfferingMap, final Long networkId, + final Long hostId, final Long poolId, final String diskPath, final Map details) throws InsufficientCapacityException, ResourceAllocationException { + + UserVm userVm = null; + + Map allDetails = new HashMap<>(details); + + VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff; + + NetworkVO network = networkDao.findById(networkId); + if (network == null) { + throw new InvalidParameterValueException("Unable to find network by id " + networkId); + } + + networkModel.checkNetworkPermissions(owner, network); + + // don't allow to use system networks + NetworkOffering networkOffering = entityMgr.findById(NetworkOffering.class, network.getNetworkOfferingId()); + if (networkOffering.isSystemOnly()) { + throw new InvalidParameterValueException("Network id=" + networkId + " is system only and can't be used for vm deployment"); + } + + LinkedHashMap> networkNicMap = new LinkedHashMap<>(); + + if ((network.getDataCenterId() != zone.getId())) { + if (!network.isStrechedL2Network()) { + throw new InvalidParameterValueException("Network id=" + network.getId() + + " doesn't belong to zone " + zone.getId()); + } + } + + String macAddress = networkModel.getNextAvailableMacAddressInNetwork(networkId); + + String ipAddress = network.getGuestType() != Network.GuestType.L2 ? "auto" : null; + + Network.IpAddresses requestedIpPair = new Network.IpAddresses(ipAddress, null, macAddress); + + NicProfile nicProfile = new NicProfile(requestedIpPair.getIp4Address(), requestedIpPair.getIp6Address(), requestedIpPair.getMacAddress()); + nicProfile.setOrderIndex(0); + + boolean securityGroupEnabled = false; + if (networkModel.isSecurityGroupSupportedInNetwork(network)) { + securityGroupEnabled = true; + } + List profiles = networkNicMap.get(network.getUuid()); + if (CollectionUtils.isEmpty(profiles)) { + profiles = new ArrayList<>(); + } + profiles.add(nicProfile); + networkNicMap.put(network.getUuid(), profiles); + + List reservations = new ArrayList<>(); + try { + checkVmResourceLimitsForExternalKvmVmImport(owner, serviceOffering, (VMTemplateVO) template, details, reservations); + userVm = userVmManager.importVM(zone, null, template, null, displayName, owner, + null, caller, true, null, owner.getAccountId(), userId, + serviceOffering, null, null, hostName, + Hypervisor.HypervisorType.KVM, allDetails, powerState, networkNicMap); + + if (userVm == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import vm name: %s", instanceName)); + } + + DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); + List resourceLimitStorageTags = resourceLimitService.getResourceLimitStorageTagsForResourceCountOperation(true, diskOffering); + CheckedReservation volumeReservation = new CheckedReservation(owner, Resource.ResourceType.volume, resourceLimitStorageTags, + CollectionUtils.isNotEmpty(resourceLimitStorageTags) ? 1L : 0L, reservationDao, resourceLimitService); + reservations.add(volumeReservation); + + String rootVolumeName = String.format("ROOT-%s", userVm.getId()); + DiskProfile diskProfile = volumeManager.allocateRawVolume(Volume.Type.ROOT, rootVolumeName, diskOffering, null, null, null, userVm, template, owner, null, false); + + final VirtualMachineProfile profile = new VirtualMachineProfileImpl(userVm, template, serviceOffering, owner, null); + ServiceOfferingVO dummyOffering = serviceOfferingDao.findById(userVm.getId(), serviceOffering.getId()); + profile.setServiceOffering(dummyOffering); + DeploymentPlanner.ExcludeList excludeList = new DeploymentPlanner.ExcludeList(); + final DataCenterDeployment plan = new DataCenterDeployment(zone.getId(), null, null, hostId, poolId, null); + DeployDestination dest = null; + try { + dest = deploymentPlanningManager.planDeployment(profile, plan, excludeList, null); + } catch (Exception e) { + logger.warn("Import failed for Vm: {} while finding deployment destination", userVm, e); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s while finding deployment destination", userVm.getInstanceName())); + } + if(dest == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s. Suitable deployment destination not found", userVm.getInstanceName())); + } + + Map storage = dest.getStorageForDisks(); + Volume volume = volumeDao.findById(diskProfile.getVolumeId()); + StoragePool storagePool = storage.get(volume); + CheckVolumeCommand checkVolumeCommand = new CheckVolumeCommand(); + checkVolumeCommand.setSrcFile(diskPath); + StorageFilerTO storageTO = new StorageFilerTO(storagePool); + checkVolumeCommand.setStorageFilerTO(storageTO); + Answer answer = agentManager.easySend(dest.getHost().getId(), checkVolumeCommand); + if (!(answer instanceof CheckVolumeAnswer)) { + cleanupFailedImportVM(userVm); + throw new CloudRuntimeException("Disk not found or is invalid"); + } + CheckVolumeAnswer checkVolumeAnswer = (CheckVolumeAnswer) answer; + try { + checkVolume(checkVolumeAnswer.getVolumeDetails()); + } catch (CloudRuntimeException e) { + cleanupFailedImportVM(userVm); + throw e; + } + if (!checkVolumeAnswer.getResult()) { + cleanupFailedImportVM(userVm); + throw new CloudRuntimeException("Disk not found or is invalid"); + } + diskProfile.setSize(checkVolumeAnswer.getSize()); + + CheckedReservation primaryStorageReservation = new CheckedReservation(owner, Resource.ResourceType.primary_storage, resourceLimitStorageTags, + CollectionUtils.isNotEmpty(resourceLimitStorageTags) ? diskProfile.getSize() : 0L, reservationDao, resourceLimitService); + reservations.add(primaryStorageReservation); + + List> diskProfileStoragePoolList = new ArrayList<>(); + try { + long deviceId = 1L; + if(ImportSource.SHARED == importSource) { + diskProfileStoragePoolList.add(importKVMSharedDisk(userVm, diskOffering, Volume.Type.ROOT, + template, deviceId, poolId, diskPath, diskProfile)); + } else if(ImportSource.LOCAL == importSource) { + diskProfileStoragePoolList.add(importKVMLocalDisk(userVm, diskOffering, Volume.Type.ROOT, + template, deviceId, hostId, diskPath, diskProfile)); + } + } catch (Exception e) { + logger.error(String.format("Failed to import volumes while importing vm: %s", instanceName), e); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", instanceName, StringUtils.defaultString(e.getMessage()))); + } + networkOrchestrationService.importNic(macAddress, 0, network, true, userVm, requestedIpPair, zone, true); + publishVMUsageUpdateResourceCount(userVm, dummyOffering, template); + return userVm; + + } catch (InsufficientCapacityException ice) { // This will be thrown by com.cloud.vm.UserVmService.importVM + logger.error(String.format("Failed to import vm name: %s", instanceName), ice); + throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ice.getMessage()); + } catch (ResourceAllocationException e) { + cleanupFailedImportVM(userVm); + throw e; + } finally { + ReservationHelper.closeAll(reservations); + } + } + + protected void checkVmResourceLimitsForExternalKvmVmImport(Account owner, ServiceOfferingVO serviceOffering, VMTemplateVO template, Map details, List reservations) throws ResourceAllocationException { + // When importing an external VM, the amount of CPUs and memory is always obtained from the compute offering, + // unlike the unmanaged instance import that obtains it from the hypervisor unless the VM is powered off and the offering is fixed + Integer cpu = serviceOffering.getCpu(); + Integer memory = serviceOffering.getRamSize(); + + if (serviceOffering.isDynamic()) { + cpu = getDetailAsInteger(VmDetailConstants.CPU_NUMBER, details); + memory = getDetailAsInteger(VmDetailConstants.MEMORY, details); + } + + List resourceLimitHostTags = resourceLimitService.getResourceLimitHostTags(serviceOffering, template); + + CheckedReservation vmReservation = new CheckedReservation(owner, Resource.ResourceType.user_vm, resourceLimitHostTags, 1L, reservationDao, resourceLimitService); + reservations.add(vmReservation); + + CheckedReservation cpuReservation = new CheckedReservation(owner, Resource.ResourceType.cpu, resourceLimitHostTags, cpu.longValue(), reservationDao, resourceLimitService); + reservations.add(cpuReservation); + + CheckedReservation memReservation = new CheckedReservation(owner, Resource.ResourceType.memory, resourceLimitHostTags, memory.longValue(), reservationDao, resourceLimitService); + reservations.add(memReservation); + } + + protected Integer getDetailAsInteger(String key, Map details) { + String detail = details.get(key); + if (detail == null) { + throw new InvalidParameterValueException(String.format("Detail '%s' must be provided.", key)); + } + try { + return Integer.valueOf(detail); + } catch (NumberFormatException e) { + throw new InvalidParameterValueException(String.format("Please provide a valid integer value for detail '%s'.", key)); + } + } + + private void checkVolume(Map volumeDetails) { + if (MapUtils.isEmpty(volumeDetails)) { + return; + } + + if (volumeDetails.containsKey(VolumeOnStorageTO.Detail.IS_LOCKED)) { + String isLocked = volumeDetails.get(VolumeOnStorageTO.Detail.IS_LOCKED); + if (Boolean.parseBoolean(isLocked)) { + logFailureAndThrowException("Locked volume cannot be imported or unmanaged."); + } + } + if (volumeDetails.containsKey(VolumeOnStorageTO.Detail.IS_ENCRYPTED)) { + String isEncrypted = volumeDetails.get(VolumeOnStorageTO.Detail.IS_ENCRYPTED); + if (Boolean.parseBoolean(isEncrypted)) { + logFailureAndThrowException("Encrypted volume cannot be imported or unmanaged."); + } + } + if (volumeDetails.containsKey(VolumeOnStorageTO.Detail.BACKING_FILE)) { + String backingFile = volumeDetails.get(VolumeOnStorageTO.Detail.BACKING_FILE); + if (StringUtils.isNotBlank(backingFile) && !AllowImportVolumeWithBackingFile.value()) { + logFailureAndThrowException("Volume with backing file cannot be imported or unmanaged."); + } + } + } + + private NetworkVO getDefaultNetwork(DataCenter zone, Account owner, boolean selectAny) throws InsufficientCapacityException, ResourceAllocationException { + NetworkVO defaultNetwork = null; + + // if no network is passed in + // Check if default virtual network offering has + // Availability=Required. If it's true, search for corresponding + // network + // * if network is found, use it. If more than 1 virtual network is + // found, throw an error + // * if network is not found, create a new one and use it + + List requiredOfferings = networkOfferingDao.listByAvailability(NetworkOffering.Availability.Required, false); + if (requiredOfferings.size() < 1) { + throw new InvalidParameterValueException("Unable to find network offering with availability=" + NetworkOffering.Availability.Required + + " to automatically create the network as a part of vm creation"); + } + + if (requiredOfferings.get(0).getState() == NetworkOffering.State.Enabled) { + // get Virtual networks + List virtualNetworks = networkModel.listNetworksForAccount(owner.getId(), zone.getId(), Network.GuestType.Isolated); + if (virtualNetworks == null) { + throw new InvalidParameterValueException("No (virtual) networks are found for account " + owner); + } + if (virtualNetworks.isEmpty()) { + defaultNetwork = createDefaultNetworkForAccount(zone, owner, requiredOfferings); + } else if (virtualNetworks.size() > 1 && !selectAny) { + throw new InvalidParameterValueException("More than 1 default Isolated networks are found for account " + owner + "; please specify networkIds"); + } else { + defaultNetwork = networkDao.findById(virtualNetworks.get(0).getId()); + } + } else { + throw new InvalidParameterValueException("Required network offering id=" + requiredOfferings.get(0).getId() + " is not in " + NetworkOffering.State.Enabled); + } + + return defaultNetwork; + } + + private NetworkVO createDefaultNetworkForAccount(DataCenter zone, Account owner, List requiredOfferings) + throws InsufficientCapacityException, ResourceAllocationException { + NetworkVO defaultNetwork = null; + long physicalNetworkId = networkModel.findPhysicalNetworkId(zone.getId(), requiredOfferings.get(0).getTags(), requiredOfferings.get(0).getTrafficType()); + // Validate physical network + PhysicalNetwork physicalNetwork = physicalNetworkDao.findById(physicalNetworkId); + if (physicalNetwork == null) { + throw new InvalidParameterValueException("Unable to find physical network with id: " + physicalNetworkId + " and tag: " + + requiredOfferings.get(0).getTags()); + } + logger.debug("Creating network for account {} from the network offering {} as a part of deployVM process", owner, requiredOfferings.get(0)); + Network newNetwork = networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName() + "-network", + null, null, null, false, null, owner, null, physicalNetwork, zone.getId(), ControlledEntity.ACLType.Account, null, null, null, null, true, null, null, + null, null, null, null, null, null, null, null, null); + if (newNetwork != null) { + defaultNetwork = networkDao.findById(newNetwork.getId()); + } + return defaultNetwork; + } + + public ListResponse listVmsForImport(ListVmsForImportCmd cmd) { + final Account caller = CallContext.current().getCallingAccount(); + if (caller.getType() != Account.Type.ADMIN) { + throw new PermissionDeniedException(String.format("Cannot perform this operation, Calling account is not root admin: %s", caller.getUuid())); + } + final Long zoneId = cmd.getZoneId(); + final DataCenterVO zone = dataCenterDao.findById(zoneId); + if (zone == null) { + throw new InvalidParameterValueException("Please specify a valid zone."); + } + final String hypervisorType = cmd.getHypervisor(); + if (!Hypervisor.HypervisorType.KVM.toString().equalsIgnoreCase(hypervisorType)) { + throw new InvalidParameterValueException(String.format("VM Import is currently not supported for hypervisor: %s", hypervisorType)); + } + + String keyword = cmd.getKeyword(); + if (StringUtils.isNotEmpty(keyword)) { + keyword = keyword.toLowerCase(); + } + + List responses = new ArrayList<>(); + HashMap vmMap = getRemoteVmsOnKVMHost(zoneId, cmd.getHost(), cmd.getUsername(), cmd.getPassword()); + for (String key : vmMap.keySet()) { + UnmanagedInstanceTO instance = vmMap.get(key); + if (StringUtils.isNotEmpty(keyword) && + !instance.getName().toLowerCase().contains(keyword)) { + continue; + } + responses.add(responseGenerator.createUnmanagedInstanceResp \ No newline at end of file diff --git a/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java index bee6c4ad257f..829d72e5366e 100644 --- a/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java @@ -1,1612 +1,1778 @@ -// 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.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyMap; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.net.URI; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.apache.cloudstack.api.ApiConstants; -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.ImportVmCmd; -import org.apache.cloudstack.api.command.admin.vm.ListUnmanagedInstancesCmd; -import org.apache.cloudstack.api.command.admin.vm.ListVmsForImportCmd; -import org.apache.cloudstack.api.response.ListResponse; -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.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; -import org.apache.cloudstack.framework.config.ConfigKey; -import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.cloudstack.resourcelimit.Reserver; -import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; -import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.jetbrains.annotations.NotNull; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.BDDMockito; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockedConstruction; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; -import org.mockito.junit.MockitoJUnitRunner; - -import com.cloud.agent.AgentManager; -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.CheckConvertInstanceAnswer; -import com.cloud.agent.api.CheckConvertInstanceCommand; -import com.cloud.agent.api.CheckVolumeAnswer; -import com.cloud.agent.api.CheckVolumeCommand; -import com.cloud.agent.api.ConvertInstanceAnswer; -import com.cloud.agent.api.ConvertInstanceCommand; -import com.cloud.agent.api.CopyRemoteVolumeAnswer; -import com.cloud.agent.api.CopyRemoteVolumeCommand; -import com.cloud.agent.api.GetRemoteVmsAnswer; -import com.cloud.agent.api.GetRemoteVmsCommand; -import com.cloud.agent.api.GetUnmanagedInstancesAnswer; -import com.cloud.agent.api.GetUnmanagedInstancesCommand; -import com.cloud.agent.api.ImportConvertedInstanceAnswer; -import com.cloud.agent.api.ImportConvertedInstanceCommand; -import com.cloud.agent.api.to.DataStoreTO; -import com.cloud.dc.ClusterVO; -import com.cloud.dc.DataCenter; -import com.cloud.dc.DataCenterVO; -import com.cloud.dc.VmwareDatacenterVO; -import com.cloud.dc.dao.ClusterDao; -import com.cloud.dc.dao.DataCenterDao; -import com.cloud.dc.dao.VmwareDatacenterDao; -import com.cloud.deploy.DeployDestination; -import com.cloud.deploy.DeploymentPlanningManager; -import com.cloud.event.ActionEventUtils; -import com.cloud.event.UsageEventUtils; -import com.cloud.exception.AgentUnavailableException; -import com.cloud.exception.InsufficientServerCapacityException; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.OperationTimedoutException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.PermissionDeniedException; -import com.cloud.exception.UnsupportedServiceException; -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.hypervisor.HypervisorGuru; -import com.cloud.hypervisor.HypervisorGuruManager; -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; -import com.cloud.offering.NetworkOffering; -import com.cloud.offering.ServiceOffering; -import com.cloud.org.Grouping; -import com.cloud.resource.ResourceManager; -import com.cloud.resource.ResourceState; -import com.cloud.resourcelimit.CheckedReservation; -import com.cloud.service.ServiceOfferingVO; -import com.cloud.service.dao.ServiceOfferingDao; -import com.cloud.storage.DataStoreRole; -import com.cloud.storage.DiskOfferingVO; -import com.cloud.storage.ScopeType; -import com.cloud.storage.Snapshot; -import com.cloud.storage.SnapshotVO; -import com.cloud.storage.Storage; -import com.cloud.storage.StoragePool; -import com.cloud.storage.StoragePoolHostVO; -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.SnapshotDao; -import com.cloud.storage.dao.StoragePoolHostDao; -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.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.utils.db.EntityManager; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.vm.DiskProfile; -import com.cloud.vm.ImportVMTaskVO; -import com.cloud.vm.NicProfile; -import com.cloud.vm.UserVmManager; -import com.cloud.vm.UserVmVO; -import com.cloud.vm.VmDetailConstants; -import com.cloud.vm.VMInstanceDetailVO; -import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.VirtualMachine; -import com.cloud.vm.dao.NicDao; -import com.cloud.vm.dao.UserVmDao; -import com.cloud.vm.dao.VMInstanceDao; -import com.cloud.vm.dao.VMInstanceDetailsDao; - -@RunWith(MockitoJUnitRunner.class) -public class UnmanagedVMsManagerImplTest { - - @Spy - @InjectMocks - private UnmanagedVMsManagerImpl unmanagedVMsManager; - - @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 VolumeDao volumeDao; - @Mock - private ResourceLimitService resourceLimitService; - @Mock - private PrimaryDataStoreDao primaryDataStoreDao; - @Mock - private VolumeApiService volumeApiService; - @Mock - private NetworkModel networkModel; - @Mock - private ConfigurationDao configurationDao; - @Mock - private UserVmDao userVmDao; - @Mock - private NicDao nicDao; - @Mock - private HostDao hostDao; - @Mock - private VmwareDatacenterDao vmwareDatacenterDao; - @Mock - private HypervisorGuruManager hypervisorGuruManager; - @Mock - private ImageStoreDao imageStoreDao; - @Mock - private DataStoreManager dataStoreManager; - @Mock - private StoragePoolHostDao storagePoolHostDao; - @Mock - private ImportVmTasksManager importVmTasksManager; - @Mock - private SnapshotDao snapshotDao; - - @Mock - private VMInstanceVO virtualMachine; - @Mock - EntityManager entityMgr; - @Mock - DeploymentPlanningManager deploymentPlanningManager; - @Mock - ImportVMTaskVO importVMTaskVO; - @Mock - private VMInstanceDetailsDao vmInstanceDetailsDao; - @Mock - private ConfigKey configKeyMockParamsAllowed; - @Mock - private ConfigKey configKeyMockParamsAllowedList; - @Mock - private Account accountMock; - @Mock - private ServiceOfferingVO serviceOfferingMock; - @Mock - private VMTemplateVO templateMock; - @Mock - private UnmanagedInstanceTO unmanagedInstanceMock; - - private static final long virtualMachineId = 1L; - - private AutoCloseable closeable; - - private MockedStatic actionEventUtilsMocked; - - private UnmanagedInstanceTO instance; - - @Before - public void setUp() throws Exception { - closeable = MockitoAnnotations.openMocks(this); - actionEventUtilsMocked = Mockito.mockStatic(ActionEventUtils.class); - BDDMockito.given(ActionEventUtils.onStartedActionEvent(anyLong(), anyLong(), anyString(), anyString(), anyLong(), anyString(), anyBoolean(), anyLong())) - .willReturn(1L); - BDDMockito.given(ActionEventUtils.onCompletedActionEvent(anyLong(), anyLong(), anyString(), anyString(), anyString(), anyLong(), anyString(), anyLong())) - .willReturn(1L); - - AccountVO account = new AccountVO("admin", 1L, "", 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); - - instance = new UnmanagedInstanceTO(); - instance.setName("TestInstance"); - instance.setCpuCores(2); - instance.setCpuCoresPerSocket(1); - instance.setCpuSpeed(1000); - instance.setMemory(1024); - instance.setOperatingSystem("CentOS 7"); - List instanceDisks = getDisks(); - instance.setDisks(instanceDisks); - 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(UnmanagedInstanceTO.PowerState.PowerOn); - - ClusterVO clusterVO = new ClusterVO(1L, 1L, "Cluster"); - clusterVO.setHypervisorType(Hypervisor.HypervisorType.VMware.toString()); - when(clusterDao.findById(anyLong())).thenReturn(clusterVO); - when(configurationDao.getValue(Mockito.anyString())).thenReturn(null); - List hosts = new ArrayList<>(); - HostVO hostVO = Mockito.mock(HostVO.class); - when(hostVO.isInMaintenanceStates()).thenReturn(false); - hosts.add(hostVO); - when(resourceManager.listHostsInClusterByStatus(anyLong(), any(Status.class))).thenReturn(hosts); - when(resourceManager.listAllUpAndEnabledHostsInOneZoneByHypervisor(any(Hypervisor.HypervisorType.class), anyLong())).thenReturn(hosts); - List templates = new ArrayList<>(); - when(templatePoolDao.listAll()).thenReturn(templates); - List volumes = new ArrayList<>(); - when(volumeDao.findIncludingRemovedByZone(anyLong())).thenReturn(volumes); - GetUnmanagedInstancesCommand cmd = Mockito.mock(GetUnmanagedInstancesCommand.class); - HashMap map = new HashMap<>(); - map.put(instance.getName(), instance); - Answer answer = new GetUnmanagedInstancesAnswer(cmd, "", map); - when(agentManager.easySend(anyLong(), any(GetUnmanagedInstancesCommand.class))).thenReturn(answer); - GetRemoteVmsCommand remoteVmListcmd = Mockito.mock(GetRemoteVmsCommand.class); - Answer remoteVmListAnswer = new GetRemoteVmsAnswer(remoteVmListcmd, "", map); - when(agentManager.easySend(anyLong(), any(GetRemoteVmsCommand.class))).thenReturn(remoteVmListAnswer); - DataCenterVO zone = Mockito.mock(DataCenterVO.class); - when(zone.getId()).thenReturn(1L); - when(dataCenterDao.findById(anyLong())).thenReturn(zone); - when(accountService.getActiveAccountById(anyLong())).thenReturn(Mockito.mock(Account.class)); - List users = new ArrayList<>(); - users.add(Mockito.mock(UserVO.class)); - when(userDao.listByAccount(anyLong())).thenReturn(users); - VMTemplateVO template = Mockito.mock(VMTemplateVO.class); - when(template.getName()).thenReturn("Template"); - when(templateDao.findById(anyLong())).thenReturn(template); - ServiceOfferingVO serviceOffering = Mockito.mock(ServiceOfferingVO.class); - when(serviceOffering.getId()).thenReturn(1L); - 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(anyLong())).thenReturn(serviceOffering); - when(serviceOfferingDao.findById(anyLong(), anyLong())).thenReturn(Mockito.mock(ServiceOfferingVO.class)); - DiskOfferingVO diskOfferingVO = Mockito.mock(DiskOfferingVO.class); - when(diskOfferingDao.findById(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 - userVm.setInstanceName(instance.getName()); - userVm.setHostName(instance.getName()); - StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); - when(poolVO.getDataCenterId()).thenReturn(1L); - when(poolVO.getClusterId()).thenReturn(clusterVO.getId()); - List pools = new ArrayList<>(); - pools.add(poolVO); - when(primaryDataStoreDao.listPoolByHostPath(Mockito.anyString(), Mockito.anyString())).thenReturn(pools); - when(userVmManager.importVM(nullable(DataCenter.class), nullable(Host.class), nullable(VirtualMachineTemplate.class), nullable(String.class), nullable(String.class), - nullable(Account.class), nullable(String.class), nullable(Account.class), nullable(Boolean.class), nullable(String.class), - nullable(Long.class), nullable(Long.class), nullable(ServiceOffering.class), nullable(String.class), nullable(Long.class), - nullable(String.class), nullable(Hypervisor.HypervisorType.class), nullable(Map.class), nullable(VirtualMachine.PowerState.class), nullable(LinkedHashMap.class))).thenReturn(userVm); - 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(anyLong())).thenReturn(networkVO); - List networks = new ArrayList<>(); - networks.add(networkVO); - when(networkDao.listByZone(anyLong())).thenReturn(networks); - doNothing().when(networkModel).checkNetworkPermissions(any(Account.class), any(Network.class)); - NicProfile profile = Mockito.mock(NicProfile.class); - Integer deviceId = 100; - Pair pair = new Pair<>(profile, deviceId); - when(networkOrchestrationService.importNic(nullable(String.class), nullable(Integer.class), nullable(Network.class), nullable(Boolean.class), nullable(VirtualMachine.class), nullable(Network.IpAddresses.class), nullable(DataCenter.class), Mockito.anyBoolean())).thenReturn(pair); - when(volumeDao.findByInstance(Mockito.anyLong())).thenReturn(volumes); - List userVmResponses = new ArrayList<>(); - UserVmResponse userVmResponse = new UserVmResponse(); - userVmResponse.setInstanceName(instance.getName()); - userVmResponses.add(userVmResponse); - when(responseGenerator.createUserVmResponse(any(ResponseObject.ResponseView.class), Mockito.anyString(), any(UserVm.class))).thenReturn(userVmResponses); - - when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Running); - - when(unmanagedInstanceMock.getCpuCores()).thenReturn(8); - when(unmanagedInstanceMock.getMemory()).thenReturn(4096); - when(serviceOfferingMock.getCpu()).thenReturn(4); - when(serviceOfferingMock.getRamSize()).thenReturn(2048); - } - - @NotNull - private static List getDisks() { - List instanceDisks = new ArrayList<>(); - UnmanagedInstanceTO.Disk instanceDisk = new UnmanagedInstanceTO.Disk(); - instanceDisk.setDiskId("1000-1"); - instanceDisk.setPosition(0); - instanceDisk.setLabel("DiskLabel"); - instanceDisk.setController("scsi"); - instanceDisk.setImagePath("[b6ccf44a1fa13e29b3667b4954fa10ee] TestInstance/ROOT-1.vmdk"); - instanceDisk.setCapacity(5242880L); - instanceDisk.setDatastoreName("Test"); - instanceDisk.setDatastoreHost("Test"); - instanceDisk.setDatastorePath("Test"); - instanceDisk.setDatastoreType("NFS"); - instanceDisks.add(instanceDisk); - return instanceDisks; - } - - @After - public void tearDown() throws Exception { - closeable.close(); - actionEventUtilsMocked.close(); - CallContext.unregister(); - } - - @Test - public void listUnmanagedInstancesTest() { - ListUnmanagedInstancesCmd cmd = Mockito.mock(ListUnmanagedInstancesCmd.class); - unmanagedVMsManager.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.XenServer.toString()); - when(clusterDao.findById(anyLong())).thenReturn(cluster); - unmanagedVMsManager.listUnmanagedInstances(cmd); - } - - @Test(expected = PermissionDeniedException.class) - public void listUnmanagedInstancesInvalidCallerTest() { - CallContext.unregister(); - AccountVO account = new AccountVO("user", 1L, "", 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); - unmanagedVMsManager.listUnmanagedInstances(cmd); - } - - @Test - public void importUnmanagedInstanceTest() { - ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class); - when(importUnmanageInstanceCmd.getName()).thenReturn("TestInstance"); - when(importUnmanageInstanceCmd.getDomainId()).thenReturn(null); - when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true); - try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class); - MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.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"); - unmanagedVMsManager.importUnmanagedInstance(importUnmanageInstanceCmd); - } - - @Test(expected = ServerApiException.class) - public void importUnmanagedInstanceMissingInstanceTest() { - ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class); - when(importUnmanageInstanceCmd.getName()).thenReturn("SomeInstance"); - when(importUnmanageInstanceCmd.getDomainId()).thenReturn(null); - try (MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.importUnmanagedInstance(importUnmanageInstanceCmd); - } - } - - @Test(expected = InvalidParameterValueException.class) - public void unmanageVMInstanceMissingInstanceTest() { - when(vmDao.findById(anyLong())).thenReturn(null); - unmanagedVMsManager.unmanageVMInstance(1L, null, false); - } - - @Test(expected = InvalidParameterValueException.class) - public void unmanageVMInstanceRemovedInstanceTest() { - VMInstanceVO userVmVO = mock(VMInstanceVO.class); - when(vmDao.findById(anyLong())).thenReturn(userVmVO); - when(userVmVO.getRemoved()).thenReturn(new Date()); - unmanagedVMsManager.unmanageVMInstance(1L, null, false); - } - - @Test(expected = InvalidParameterValueException.class) - public void unmanageVMInstanceDestroyedInstanceTest() { - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Destroyed); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = InvalidParameterValueException.class) - public void unmanageVMInstanceExpungedInstanceTest() { - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Expunging); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void unmanageVMInstanceExistingVMSnapshotsTest() { - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.None); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void unmanageVMInstanceInvalidHyperVisor() { - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.None); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void unmanageVMInstanceInvalidVmType() { - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.VMware); - when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.ConsoleProxy); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void unmanageVMInstanceExistingVolumeSnapshotsTest() { - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.None); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void unmanageVMInstanceExistingISOAttachedTest() { - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.None); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void unmanageVMInstanceVmwareHostIdParamTest() { - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.VMware); - when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, 1L, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void unmanageVMInstanceRunningHostIdParamTest() { - when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Running); - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, 1L, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void unmanageVMInstanceRunningForceParamTest() { - when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Running); - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); - VMInstanceDetailVO vmInstanceDetailVO = mock(VMInstanceDetailVO.class); - when(vmInstanceDetailsDao.findDetail(virtualMachineId, VmDetailConstants.CONFIG_DRIVE_LOCATION)).thenReturn(vmInstanceDetailVO); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test - public void unmanageVMInstanceVMwareHostId() { - when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); - UserVmVO userVmVO = mock(UserVmVO.class); - when(userVmVO.getIsoId()).thenReturn(null); - when(userVmDao.findById(anyLong())).thenReturn(userVmVO); - when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, 1L, false); - } - - @Test - public void unmanageVMInstanceStoppedInstanceTest() { - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); - when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); - UserVmVO userVmVO = mock(UserVmVO.class); - when(userVmDao.findById(anyLong())).thenReturn(userVmVO); - Mockito.doNothing().when(unmanagedVMsManager).performUnmanageVMInstancePrechecks(any()); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void testUnmanageVMInstanceWithVolumeSnapshotsFail() { - when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); - when(virtualMachine.getId()).thenReturn(virtualMachineId); - UserVmVO userVmVO = mock(UserVmVO.class); - when(userVmDao.findById(anyLong())).thenReturn(userVmVO); - when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); - VolumeVO volumeVO = mock(VolumeVO.class); - long volumeId = 20L; - when(volumeVO.getId()).thenReturn(volumeId); - SnapshotVO snapshotVO = mock(SnapshotVO.class); - when(snapshotVO.getState()).thenReturn(Snapshot.State.BackedUp); - when(snapshotDao.listByVolumeId(volumeId)).thenReturn(Collections.singletonList(snapshotVO)); - when(volumeDao.findByInstance(virtualMachineId)).thenReturn(Collections.singletonList(volumeVO)); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void testUnmanageVMInstanceWithAssociatedIsoFail() { - when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); - when(virtualMachine.getId()).thenReturn(virtualMachineId); - UserVmVO userVmVO = mock(UserVmVO.class); - when(userVmVO.getIsoId()).thenReturn(null); - when(userVmDao.findById(anyLong())).thenReturn(userVmVO); - when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); - when(userVmVO.getIsoId()).thenReturn(1L); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void testUnmanageVMInstanceBelongingToCksClusterFail() { - when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); - when(virtualMachine.getId()).thenReturn(virtualMachineId); - UserVmVO userVmVO = mock(UserVmVO.class); - when(userVmVO.getIsoId()).thenReturn(null); - when(userVmDao.findById(anyLong())).thenReturn(userVmVO); - when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); - when(userVmManager.isVMPartOfAnyCKSCluster(virtualMachine)).thenReturn(true); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test - public void testListRemoteInstancesTest() { - ListVmsForImportCmd cmd = Mockito.mock(ListVmsForImportCmd.class); - when(cmd.getHypervisor()).thenReturn(Hypervisor.HypervisorType.KVM.toString()); - when(cmd.getUsername()).thenReturn("user"); - when(cmd.getPassword()).thenReturn("pass"); - ListResponse response = unmanagedVMsManager.listVmsForImport(cmd); - Assert.assertEquals(1, response.getCount().intValue()); - } - - @Test(expected = InvalidParameterValueException.class) - public void testListRemoteInstancesTestNonKVM() { - ListVmsForImportCmd cmd = Mockito.mock(ListVmsForImportCmd.class); - unmanagedVMsManager.listVmsForImport(cmd); - } - @Test - public void testImportFromExternalTest() throws InsufficientServerCapacityException { - String vmname = "TestInstance"; - ImportVmCmd cmd = Mockito.mock(ImportVmCmd.class); - when(cmd.getHypervisor()).thenReturn(Hypervisor.HypervisorType.KVM.toString()); - when(cmd.getName()).thenReturn(vmname); - when(cmd.getUsername()).thenReturn("user"); - when(cmd.getPassword()).thenReturn("pass"); - when(cmd.getImportSource()).thenReturn("external"); - when(cmd.getDomainId()).thenReturn(null); - HostVO host = Mockito.mock(HostVO.class); - DeployDestination mockDest = Mockito.mock(DeployDestination.class); - when(deploymentPlanningManager.planDeployment(any(), any(), any(), any())).thenReturn(mockDest); - DiskProfile diskProfile = Mockito.mock(DiskProfile.class); - when(volumeManager.allocateRawVolume(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), anyBoolean())) - .thenReturn(diskProfile); - Map storage = new HashMap<>(); - VolumeVO volume = Mockito.mock(VolumeVO.class); - StoragePoolVO storagePool = Mockito.mock(StoragePoolVO.class); - storage.put(volume, storagePool); - when(mockDest.getStorageForDisks()).thenReturn(storage); - when(mockDest.getHost()).thenReturn(host); - when(volumeDao.findById(anyLong())).thenReturn(volume); - CopyRemoteVolumeAnswer copyAnswer = Mockito.mock(CopyRemoteVolumeAnswer.class); - when(copyAnswer.getResult()).thenReturn(true); - when(agentManager.easySend(anyLong(), any(CopyRemoteVolumeCommand.class))).thenReturn(copyAnswer); - try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class); - MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.importVm(cmd); - } - } - - private void baseBasicParametersCheckForImportInstance(String name, Long domainId, String accountName) { - unmanagedVMsManager.basicParametersCheckForImportInstance(name, domainId, accountName); - } - - @Test(expected = InvalidParameterValueException.class) - public void testBasicParametersCheckForImportInstanceMissingName() { - baseBasicParametersCheckForImportInstance(null, 1L, "test"); - } - - @Test(expected = InvalidParameterValueException.class) - public void testBasicParametersCheckForImportInstanceMissingDomainAndAccount() { - baseBasicParametersCheckForImportInstance("vm", 1L, ""); - } - - @Test(expected = InvalidParameterValueException.class) - public void testBasicAccessChecksMissingClusterId() { - unmanagedVMsManager.basicAccessChecks(null); - } - - @Test(expected = PermissionDeniedException.class) - public void testBasicAccessChecksNotAdminCaller() { - CallContext.unregister(); - AccountVO account = new AccountVO("user", 1L, "", 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); - unmanagedVMsManager.basicAccessChecks(1L); - } - - @Test(expected = InvalidParameterValueException.class) - public void testBasicAccessChecksUnsupportedHypervisorType() { - ClusterVO clusterVO = new ClusterVO(1L, 1L, "Cluster"); - clusterVO.setHypervisorType(Hypervisor.HypervisorType.XenServer.toString()); - when(clusterDao.findById(anyLong())).thenReturn(clusterVO); - unmanagedVMsManager.basicAccessChecks(1L); - } - - @Test - public void testGetTemplateForImportInstanceDefaultTemplate() { - String defaultTemplateName = "DefaultTemplate"; - VMTemplateVO template = Mockito.mock(VMTemplateVO.class); - when(template.getName()).thenReturn(defaultTemplateName); - when(templateDao.findByName(anyString())).thenReturn(template); - VMTemplateVO templateForImportInstance = unmanagedVMsManager.getTemplateForImportInstance(null, Hypervisor.HypervisorType.KVM); - Assert.assertEquals(defaultTemplateName, templateForImportInstance.getName()); - } - - private enum VcenterParameter { - EXISTING, - EXTERNAL, - BOTH, - NONE, - EXISTING_INVALID, - AGENT_UNAVAILABLE, - CONVERT_FAILURE, - FORCE_MS_AND_USE_VDDK, - USE_VDDK_OVF_UNSUPPORTED, - USE_VDDK_OVF_SUPPORTED, - USE_VDDK_DETAILS_OVERRIDES - } - - private void baseTestImportVmFromVmwareToKvm(VcenterParameter vcenterParameter, boolean selectConvertHost, - boolean selectTemporaryStorage) throws OperationTimedoutException, AgentUnavailableException { - long clusterId = 1L; - long zoneId = 1L; - long existingDatacenterId = 1L; - String vcenterHost = "192.168.1.2"; - String datacenter = "Datacenter"; - String username = "administrator@vsphere.local"; - String password = "password"; - String host = "192.168.1.10"; - String vmName = "TestInstanceFromVmware"; - instance.setName(vmName); - String tmplFileName = "5b8d689a-e61a-4ac3-9b76-e121ff90fbd3"; - long newVmId = 2L; - long networkId = 1L; - - ClusterVO cluster = mock(ClusterVO.class); - when(cluster.getId()).thenReturn(clusterId); - when(cluster.getAllocationState()).thenReturn(Grouping.AllocationState.Enabled); - when(cluster.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); - when(cluster.getDataCenterId()).thenReturn(zoneId); - when(clusterDao.findById(clusterId)).thenReturn(cluster); - - ImportVmCmd importVmCmd = Mockito.mock(ImportVmCmd.class); - - when(importVmCmd.getName()).thenReturn(vmName); - when(importVmCmd.getClusterId()).thenReturn(clusterId); - when(importVmCmd.getDomainId()).thenReturn(null); - when(importVmCmd.getImportSource()).thenReturn(VmImportService.ImportSource.VMWARE.toString()); - when(importVmCmd.getHostIp()).thenReturn(host); - when(importVmCmd.getNicNetworkList()).thenReturn(Map.of("NIC 1", networkId)); - when(importVmCmd.getConvertInstanceHostId()).thenReturn(null); - when(importVmCmd.getImportInstanceHostId()).thenReturn(null); - when(importVmCmd.getConvertStoragePoolId()).thenReturn(null); - when(importVmCmd.getExistingVcenterId()).thenReturn(null); - when(importVmCmd.getVcenter()).thenReturn(null); - when(importVmCmd.getDatacenterName()).thenReturn(null); - when(importVmCmd.getUsername()).thenReturn(null); - when(importVmCmd.getPassword()).thenReturn(null); - when(importVmCmd.getDetails()).thenReturn(new HashMap<>()); - - boolean forceMsToImportVmFiles = false; - boolean useVddk = false; - boolean ovfExportSupported = false; - if (VcenterParameter.FORCE_MS_AND_USE_VDDK == vcenterParameter) { - forceMsToImportVmFiles = true; - useVddk = true; - } else if (VcenterParameter.USE_VDDK_OVF_UNSUPPORTED == vcenterParameter) { - useVddk = true; - } else if (VcenterParameter.USE_VDDK_OVF_SUPPORTED == vcenterParameter) { - useVddk = true; - ovfExportSupported = true; - } else if (VcenterParameter.USE_VDDK_DETAILS_OVERRIDES == vcenterParameter) { - useVddk = true; - ovfExportSupported = true; - when(importVmCmd.getDetails()).thenReturn(Map.of( - "vddk.lib.dir", "/opt/vmware-vddk/override", - "vddk.transports", "nbd:nbdssl", - "vddk.thumbprint", "AA:BB:CC:DD:EE")); - } - when(importVmCmd.getForceMsToImportVmFiles()).thenReturn(forceMsToImportVmFiles); - when(importVmCmd.getUseVddk()).thenReturn(useVddk); - - NetworkVO networkVO = Mockito.mock(NetworkVO.class); - when(networkVO.getGuestType()).thenReturn(Network.GuestType.L2); - when(networkVO.getDataCenterId()).thenReturn(zoneId); - when(networkDao.findById(networkId)).thenReturn(networkVO); - - HypervisorGuru vmwareGuru = mock(HypervisorGuru.class); - when(hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware)).thenReturn(vmwareGuru); - when(vmwareGuru.getHypervisorVMOutOfBandAndCloneIfRequired(anyString(), anyString(), anyMap())).thenReturn(new Pair<>(instance, true)); - when(vmwareGuru.removeClonedHypervisorVMOutOfBand(anyString(), anyString(), anyMap())).thenReturn(true); - when(vmwareGuru.createVMTemplateOutOfBand(anyString(), anyString(), anyMap(), any(DataStoreTO.class), anyInt())).thenReturn(tmplFileName); - when(vmwareGuru.removeVMTemplateOutOfBand(any(DataStoreTO.class), anyString())).thenReturn(true); - - HostVO convertHost = mock(HostVO.class); - long convertHostId = 1L; - when(convertHost.getStatus()).thenReturn(Status.Up); - when(convertHost.getResourceState()).thenReturn(ResourceState.Enabled); - when(convertHost.getId()).thenReturn(convertHostId); - when(convertHost.getType()).thenReturn(Host.Type.Routing); - when(convertHost.getDataCenterId()).thenReturn(zoneId); - when(convertHost.getClusterId()).thenReturn(clusterId); - if (selectConvertHost) { - when(importVmCmd.getConvertInstanceHostId()).thenReturn(convertHostId); - when(importVmCmd.getImportInstanceHostId()).thenReturn(convertHostId); - when(hostDao.findById(convertHostId)).thenReturn(convertHost); - } else { - when(hostDao.listByClusterAndHypervisorType(clusterId, Hypervisor.HypervisorType.KVM)).thenReturn(List.of(convertHost)); - } - - DataStoreTO dataStoreTO = mock(DataStoreTO.class); - DataStore dataStore = mock(DataStore.class); - when(dataStore.getTO()).thenReturn(dataStoreTO); - - StoragePoolVO destPool = mock(StoragePoolVO.class); - when(destPool.getDataCenterId()).thenReturn(zoneId); - when(destPool.getClusterId()).thenReturn(null); - when(destPool.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem); - StoragePoolVO zoneDestPool = mock(StoragePoolVO.class); - if (selectTemporaryStorage) { - long temporaryStoragePoolId = 1L; - when(importVmCmd.getConvertStoragePoolId()).thenReturn(temporaryStoragePoolId); - when(primaryDataStoreDao.findById(temporaryStoragePoolId)).thenReturn(destPool); - when(dataStoreManager.getPrimaryDataStore(temporaryStoragePoolId)).thenReturn(dataStore); - } else { - ImageStoreVO imageStoreVO = mock(ImageStoreVO.class); - when(imageStoreVO.getId()).thenReturn(1L); - when(imageStoreDao.findOneByZoneAndProtocol(zoneId, "nfs")).thenReturn(imageStoreVO); - when(dataStoreManager.getDataStore(1L, DataStoreRole.Image)).thenReturn(dataStore); - } - when(primaryDataStoreDao.listPoolByHostPath(Mockito.anyString(), Mockito.anyString())).thenReturn(List.of(destPool)); - when(primaryDataStoreDao.findClusterWideStoragePoolsByHypervisorAndPoolType(clusterId, Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)).thenReturn(List.of(destPool)); - when(primaryDataStoreDao.findZoneWideStoragePoolsByHypervisorAndPoolType(zoneId, Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)).thenReturn(List.of(zoneDestPool)); - - if (VcenterParameter.EXISTING == vcenterParameter) { - VmwareDatacenterVO datacenterVO = mock(VmwareDatacenterVO.class); - when(datacenterVO.getVcenterHost()).thenReturn(vcenterHost); - when(datacenterVO.getVmwareDatacenterName()).thenReturn(datacenter); - when(datacenterVO.getUser()).thenReturn(username); - when(datacenterVO.getPassword()).thenReturn(password); - when(importVmCmd.getExistingVcenterId()).thenReturn(existingDatacenterId); - when(vmwareDatacenterDao.findById(existingDatacenterId)).thenReturn(datacenterVO); - } - - if (VcenterParameter.BOTH == vcenterParameter) { - when(importVmCmd.getExistingVcenterId()).thenReturn(existingDatacenterId); - when(importVmCmd.getVcenter()).thenReturn(vcenterHost); - } else if (VcenterParameter.NONE == vcenterParameter) { - when(importVmCmd.getExistingVcenterId()).thenReturn(null); - when(importVmCmd.getVcenter()).thenReturn(null); - } else if (VcenterParameter.EXISTING_INVALID == vcenterParameter) { - when(importVmCmd.getExistingVcenterId()).thenReturn(existingDatacenterId); - when(vmwareDatacenterDao.findById(existingDatacenterId)).thenReturn(null); - } - - if (VcenterParameter.FORCE_MS_AND_USE_VDDK == vcenterParameter - || VcenterParameter.USE_VDDK_OVF_UNSUPPORTED == vcenterParameter - || VcenterParameter.USE_VDDK_OVF_SUPPORTED == vcenterParameter - || VcenterParameter.USE_VDDK_DETAILS_OVERRIDES == vcenterParameter) { - Mockito.doReturn((Long) null).when(importVmCmd).getExistingVcenterId(); - Mockito.doReturn(vcenterHost).when(importVmCmd).getVcenter(); - Mockito.doReturn(datacenter).when(importVmCmd).getDatacenterName(); - Mockito.doReturn(username).when(importVmCmd).getUsername(); - Mockito.doReturn(password).when(importVmCmd).getPassword(); - } - - CheckConvertInstanceAnswer checkConvertInstanceAnswer = mock(CheckConvertInstanceAnswer.class); - when(checkConvertInstanceAnswer.getResult()).thenReturn(vcenterParameter != VcenterParameter.CONVERT_FAILURE); - when(checkConvertInstanceAnswer.isOvfExportSupported()).thenReturn(ovfExportSupported); - if (VcenterParameter.AGENT_UNAVAILABLE != vcenterParameter) { - when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(CheckConvertInstanceCommand.class))).thenReturn(checkConvertInstanceAnswer); - } - - when(importVmTasksManager.createImportVMTaskRecord(any(DataCenter.class), any(Account.class), anyLong(), anyString(), - anyString(), anyString(), anyString(), any(Host.class), any(Host.class))).thenReturn(importVMTaskVO); - when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any(DiskOffering.class))).thenReturn(true); - - ConvertInstanceAnswer convertInstanceAnswer = mock(ConvertInstanceAnswer.class); - ImportConvertedInstanceAnswer convertImportedInstanceAnswer = mock(ImportConvertedInstanceAnswer.class); - when(convertInstanceAnswer.getResult()).thenReturn(vcenterParameter != VcenterParameter.CONVERT_FAILURE); - Mockito.lenient().when(convertImportedInstanceAnswer.getConvertedInstance()).thenReturn(instance); - Mockito.lenient().when(convertImportedInstanceAnswer.getResult()).thenReturn(vcenterParameter != VcenterParameter.CONVERT_FAILURE); - if (VcenterParameter.AGENT_UNAVAILABLE != vcenterParameter) { - when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(ConvertInstanceCommand.class))).thenReturn(convertInstanceAnswer); - Mockito.lenient().when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(ImportConvertedInstanceCommand.class))).thenReturn(convertImportedInstanceAnswer); - } - - try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class); - MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.importVm(importVmCmd); - verify(vmwareGuru).getHypervisorVMOutOfBandAndCloneIfRequired(Mockito.eq(host), Mockito.eq(vmName), anyMap()); - if (VcenterParameter.USE_VDDK_OVF_SUPPORTED == vcenterParameter) { - verify(vmwareGuru, Mockito.never()).createVMTemplateOutOfBand(anyString(), anyString(), anyMap(), any(DataStoreTO.class), anyInt()); - verify(agentManager).send(Mockito.eq(convertHostId), Mockito.argThat(command -> - command instanceof ConvertInstanceCommand && ((ConvertInstanceCommand) command).isUseVddk())); - verify(vmwareGuru, Mockito.never()).removeVMTemplateOutOfBand(any(DataStoreTO.class), anyString()); - } else if (VcenterParameter.USE_VDDK_DETAILS_OVERRIDES == vcenterParameter) { - verify(vmwareGuru, Mockito.never()).createVMTemplateOutOfBand(anyString(), anyString(), anyMap(), any(DataStoreTO.class), anyInt()); - verify(agentManager).send(Mockito.eq(convertHostId), Mockito.argThat(command -> { - if (!(command instanceof ConvertInstanceCommand)) { - return false; - } - ConvertInstanceCommand convertCmd = (ConvertInstanceCommand) command; - return convertCmd.isUseVddk() - && "/opt/vmware-vddk/override".equals(convertCmd.getVddkLibDir()) - && "nbd:nbdssl".equals(convertCmd.getVddkTransports()) - && "AA:BB:CC:DD:EE".equals(convertCmd.getVddkThumbprint()); - })); - verify(vmwareGuru, Mockito.never()).removeVMTemplateOutOfBand(any(DataStoreTO.class), anyString()); - } else { - verify(vmwareGuru).createVMTemplateOutOfBand(Mockito.eq(host), Mockito.eq(vmName), anyMap(), any(DataStoreTO.class), anyInt()); - verify(vmwareGuru).removeVMTemplateOutOfBand(any(DataStoreTO.class), anyString()); - } - verify(vmwareGuru).removeClonedHypervisorVMOutOfBand(Mockito.eq(host), Mockito.eq(vmName), anyMap()); - } - } - - @Test - public void importFromLocalDisk() throws InsufficientServerCapacityException { - importFromDisk("local"); - } - - @Test - public void importFromsharedStorage() throws InsufficientServerCapacityException { - importFromDisk("shared"); - } - - private void importFromDisk(String source) throws InsufficientServerCapacityException { - String vmname = "testVm"; - ImportVmCmd cmd = Mockito.mock(ImportVmCmd.class); - when(cmd.getHypervisor()).thenReturn(Hypervisor.HypervisorType.KVM.toString()); - when(cmd.getName()).thenReturn(vmname); - when(cmd.getImportSource()).thenReturn(source); - when(cmd.getDiskPath()).thenReturn("/var/lib/libvirt/images/test.qcow2"); - when(cmd.getDomainId()).thenReturn(null); - HostVO host = Mockito.mock(HostVO.class); - when(hostDao.findById(anyLong())).thenReturn(host); - NetworkOffering netOffering = Mockito.mock(NetworkOffering.class); - when(entityMgr.findById(NetworkOffering.class, 0L)).thenReturn(netOffering); - DeployDestination mockDest = Mockito.mock(DeployDestination.class); - when(deploymentPlanningManager.planDeployment(any(), any(), any(), any())).thenReturn(mockDest); - DiskProfile diskProfile = Mockito.mock(DiskProfile.class); - when(volumeManager.allocateRawVolume(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), anyBoolean())) - .thenReturn(diskProfile); - Map storage = new HashMap<>(); - VolumeVO volume = Mockito.mock(VolumeVO.class); - StoragePoolVO storagePool = Mockito.mock(StoragePoolVO.class); - storage.put(volume, storagePool); - when(mockDest.getStorageForDisks()).thenReturn(storage); - when(mockDest.getHost()).thenReturn(host); - when(volumeDao.findById(anyLong())).thenReturn(volume); - CheckVolumeAnswer answer = Mockito.mock(CheckVolumeAnswer.class); - when(answer.getResult()).thenReturn(true); - when(agentManager.easySend(anyLong(), any(CheckVolumeCommand.class))).thenReturn(answer); - List storagePools = new ArrayList<>(); - storagePools.add(storagePool); - when(primaryDataStoreDao.findLocalStoragePoolsByHostAndTags(anyLong(), any())).thenReturn(storagePools); - when(primaryDataStoreDao.findById(anyLong())).thenReturn(storagePool); - when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true); - StoragePoolHostVO storagePoolHost = Mockito.mock(StoragePoolHostVO.class); - when(storagePoolHostDao.findByPoolHost(anyLong(), anyLong())).thenReturn(storagePoolHost); - try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class); - MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.importVm(cmd); - } - } - - @Test - public void testImportVmFromVmwareToKvmExistingVcenter() throws OperationTimedoutException, AgentUnavailableException { - baseTestImportVmFromVmwareToKvm(VcenterParameter.EXISTING, false, false); - } - - @Test - public void testImportVmFromVmwareToKvmExistingVcenterSetConvertHost() throws OperationTimedoutException, AgentUnavailableException { - baseTestImportVmFromVmwareToKvm(VcenterParameter.EXISTING, true, false); - } - - @Test - public void testImportVmFromVmwareToKvmExistingVcenterSetConvertHostAndTemporaryStorage() throws OperationTimedoutException, AgentUnavailableException { - baseTestImportVmFromVmwareToKvm(VcenterParameter.EXISTING, true, true); - } - - @Test(expected = ServerApiException.class) - public void testImportVmFromVmwareToKvmExistingVcenterExclusiveParameters() throws OperationTimedoutException, AgentUnavailableException { - baseTestImportVmFromVmwareToKvm(VcenterParameter.BOTH, false, false); - } - - @Test(expected = ServerApiException.class) - public void testImportVmFromVmwareToKvmExistingVcenterMissingParameters() throws OperationTimedoutException, AgentUnavailableException { - baseTestImportVmFromVmwareToKvm(VcenterParameter.NONE, false, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testImportVmFromVmwareToKvmExistingVcenterInvalid() throws OperationTimedoutException, AgentUnavailableException { - baseTestImportVmFromVmwareToKvm(VcenterParameter.EXISTING_INVALID, false, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testImportVmFromVmwareToKvmExistingVcenterAgentUnavailable() throws OperationTimedoutException, AgentUnavailableException { - baseTestImportVmFromVmwareToKvm(VcenterParameter.AGENT_UNAVAILABLE, false, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testImportVmFromVmwareToKvmExistingVcenterConvertFailure() throws OperationTimedoutException, AgentUnavailableException { - baseTestImportVmFromVmwareToKvm(VcenterParameter.CONVERT_FAILURE, false, false); - } - - @Test(expected = ServerApiException.class) - public void testImportVmFromVmwareToKvmForceMsMutuallyExclusiveWithUseVddk() throws OperationTimedoutException, AgentUnavailableException { - baseTestImportVmFromVmwareToKvm(VcenterParameter.FORCE_MS_AND_USE_VDDK, false, false); - } - - @Test(expected = InvalidParameterValueException.class) - public void testValidateSelectedConversionStoragePoolForVddkFailsWhenPoolDoesNotSupportDiskOfferings() { - long poolId = 11L; - StoragePoolVO selectedPool = mock(StoragePoolVO.class); - ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class); - DiskOfferingVO rootDiskOffering = mock(DiskOfferingVO.class); - DiskOfferingVO dataDiskOffering = mock(DiskOfferingVO.class); - - when(serviceOffering.getDiskOfferingId()).thenReturn(21L); - when(primaryDataStoreDao.findById(poolId)).thenReturn(selectedPool); - when(diskOfferingDao.findById(21L)).thenReturn(rootDiskOffering); - when(diskOfferingDao.findById(22L)).thenReturn(dataDiskOffering); - when(volumeApiService.doesStoragePoolSupportDiskOffering(selectedPool, rootDiskOffering)).thenReturn(true); - when(volumeApiService.doesStoragePoolSupportDiskOffering(selectedPool, dataDiskOffering)).thenReturn(false); - - unmanagedVMsManager.validateSelectedConversionStoragePoolForVddk(true, poolId, - serviceOffering, Map.of("1000-2", 22L)); - } - - @Test - public void testValidateSelectedConversionStoragePoolForVddkPassesWhenPoolSupportsAllDiskOfferings() { - long poolId = 12L; - StoragePoolVO selectedPool = mock(StoragePoolVO.class); - ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class); - DiskOfferingVO rootDiskOffering = mock(DiskOfferingVO.class); - DiskOfferingVO dataDiskOffering = mock(DiskOfferingVO.class); - - when(serviceOffering.getDiskOfferingId()).thenReturn(31L); - when(primaryDataStoreDao.findById(poolId)).thenReturn(selectedPool); - when(diskOfferingDao.findById(31L)).thenReturn(rootDiskOffering); - when(diskOfferingDao.findById(32L)).thenReturn(dataDiskOffering); - when(volumeApiService.doesStoragePoolSupportDiskOffering(selectedPool, rootDiskOffering)).thenReturn(true); - when(volumeApiService.doesStoragePoolSupportDiskOffering(selectedPool, dataDiskOffering)).thenReturn(true); - - unmanagedVMsManager.validateSelectedConversionStoragePoolForVddk(true, poolId, - serviceOffering, Map.of("1000-2", 32L)); - } - - private ClusterVO getClusterForTests() { - ClusterVO cluster = mock(ClusterVO.class); - when(cluster.getId()).thenReturn(1L); - when(cluster.getDataCenterId()).thenReturn(1L); - return cluster; - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectInstanceConversionTemporaryLocationInvalidStorage() { - ClusterVO cluster = getClusterForTests(); - - long poolId = 1L; - when(primaryDataStoreDao.findById(poolId)).thenReturn(null); - unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, poolId, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectInstanceConversionTemporaryLocationPoolInvalidScope() { - ClusterVO cluster = getClusterForTests(); - long poolId = 1L; - StoragePoolVO pool = mock(StoragePoolVO.class); - when(pool.getScope()).thenReturn(ScopeType.CLUSTER); - when(pool.getClusterId()).thenReturn(100L); - when(primaryDataStoreDao.findById(poolId)).thenReturn(pool); - unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, poolId, false); - } - - - @Test(expected = CloudRuntimeException.class) - public void testSelectInstanceConversionTemporaryLocationPoolConvertHostDifferentCluster() { - ClusterVO cluster = getClusterForTests(); - long poolId = 1L; - StoragePoolVO pool = mock(StoragePoolVO.class); - when(pool.getScope()).thenReturn(ScopeType.CLUSTER); - when(pool.getClusterId()).thenReturn(1L); - HostVO host = mock(HostVO.class); - when(primaryDataStoreDao.findById(poolId)).thenReturn(pool); - when(host.getClusterId()).thenReturn(2L); - unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, host, null, poolId, false); - } - - - @Test(expected = CloudRuntimeException.class) - public void testSelectInstanceConversionTemporaryLocationLocalStoragePoolInvalid() { - ClusterVO cluster = getClusterForTests(); - long poolId = 1L; - StoragePoolVO pool = mock(StoragePoolVO.class); - when(pool.getScope()).thenReturn(ScopeType.HOST); - when(primaryDataStoreDao.findById(poolId)).thenReturn(pool); - unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, poolId, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectInstanceConversionTemporaryLocationStoragePoolInvalidType() { - ClusterVO cluster = getClusterForTests(); - long poolId = 1L; - StoragePoolVO pool = mock(StoragePoolVO.class); - when(pool.getScope()).thenReturn(ScopeType.CLUSTER); - when(pool.getClusterId()).thenReturn(1L); - when(primaryDataStoreDao.findById(poolId)).thenReturn(pool); - when(pool.getPoolType()).thenReturn(Storage.StoragePoolType.RBD); - unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, poolId, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectInstanceConversionTemporaryLocationNoPoolAvailable() { - ClusterVO cluster = getClusterForTests(); - when(imageStoreDao.findOneByZoneAndProtocol(anyLong(), anyString())).thenReturn(null); - unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, null, false); - } - - @Test - public void testSelectKVMHostForImportingInClusterWithImportInstanceIdSuccess() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Enabled); - when(host.getStatus()).thenReturn(Status.Up); - when(host.getType()).thenReturn(Host.Type.Routing); - when(host.getClusterId()).thenReturn(1L); - - when(hostDao.findById(hostId)).thenReturn(host); - - HostVO returnedHost = unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); - Assert.assertEquals(host, returnedHost); - } - - @Test - public void testSelectKVMHostForImportingInClusterWithNullImportInstanceIdSuccess() { - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(hostDao.listByClusterAndHypervisorType(cluster.getId(), cluster.getHypervisorType())).thenReturn(List.of(host)); - - HostVO returnedHost = unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, null); - Assert.assertEquals(host, returnedHost); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForImportingInClusterFailure() { - ClusterVO cluster = getClusterForTests(); - when(hostDao.listByClusterAndHypervisorType(cluster.getId(), cluster.getHypervisorType())).thenReturn(List.of()); - - unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, null); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidCluster() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Enabled); - when(host.getStatus()).thenReturn(Status.Up); - when(host.getType()).thenReturn(Host.Type.Routing); - when(host.getClusterId()).thenReturn(2L); - - when(hostDao.findById(hostId)).thenReturn(host); - - unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidType() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Enabled); - when(host.getStatus()).thenReturn(Status.Up); - when(host.getType()).thenReturn(Host.Type.Storage); - - when(hostDao.findById(hostId)).thenReturn(host); - - unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidStatus() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Enabled); - when(host.getStatus()).thenReturn(Status.Alert); - - when(hostDao.findById(hostId)).thenReturn(host); - - unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidResourceState() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Disabled); - - when(hostDao.findById(hostId)).thenReturn(host); - - unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidHostId() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - - when(hostDao.findById(hostId)).thenReturn(null); - - unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); - } - - @Test - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdEnabledHost() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Enabled); - when(host.getStatus()).thenReturn(Status.Up); - when(host.getType()).thenReturn(Host.Type.Routing); - when(host.getDataCenterId()).thenReturn(1L); - - when(hostDao.findById(hostId)).thenReturn(host); - - HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); - Assert.assertEquals(host, returnedHost); - } +// 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.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.apache.cloudstack.api.ApiConstants; +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.ImportVmCmd; +import org.apache.cloudstack.api.command.admin.vm.ListUnmanagedInstancesCmd; +import org.apache.cloudstack.api.command.admin.vm.ListVmsForImportCmd; +import org.apache.cloudstack.api.response.ListResponse; +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.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.framework.config.ConfigKey; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.resourcelimit.Reserver; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.jetbrains.annotations.NotNull; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.BDDMockito; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedConstruction; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CheckConvertInstanceAnswer; +import com.cloud.agent.api.CheckConvertInstanceCommand; +import com.cloud.agent.api.CheckVolumeAnswer; +import com.cloud.agent.api.CheckVolumeCommand; +import com.cloud.agent.api.ConvertInstanceAnswer; +import com.cloud.agent.api.ConvertInstanceCommand; +import com.cloud.agent.api.CopyRemoteVolumeAnswer; +import com.cloud.agent.api.CopyRemoteVolumeCommand; +import com.cloud.agent.api.GetRemoteVmsAnswer; +import com.cloud.agent.api.GetRemoteVmsCommand; +import com.cloud.agent.api.GetUnmanagedInstancesAnswer; +import com.cloud.agent.api.GetUnmanagedInstancesCommand; +import com.cloud.agent.api.ImportConvertedInstanceAnswer; +import com.cloud.agent.api.ImportConvertedInstanceCommand; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.dc.ClusterVO; +import com.cloud.dc.DataCenter; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.VmwareDatacenterVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.VmwareDatacenterDao; +import com.cloud.deploy.DeployDestination; +import com.cloud.deploy.DeploymentPlanningManager; +import com.cloud.event.ActionEventUtils; +import com.cloud.event.UsageEventUtils; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.InsufficientServerCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.OperationTimedoutException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.exception.UnsupportedServiceException; +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.hypervisor.HypervisorGuru; +import com.cloud.hypervisor.HypervisorGuruManager; +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; +import com.cloud.offering.NetworkOffering; +import com.cloud.offering.ServiceOffering; +import com.cloud.org.Grouping; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceState; +import com.cloud.resourcelimit.CheckedReservation; +import com.cloud.service.ServiceOfferingVO; +import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.DiskOfferingVO; +import com.cloud.storage.ScopeType; +import com.cloud.storage.Snapshot; +import com.cloud.storage.SnapshotVO; +import com.cloud.storage.Storage; +import com.cloud.storage.StoragePool; +import com.cloud.storage.StoragePoolHostVO; +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.SnapshotDao; +import com.cloud.storage.dao.StoragePoolHostDao; +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.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.utils.db.EntityManager; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.DiskProfile; +import com.cloud.vm.ImportVMTaskVO; +import com.cloud.vm.NicProfile; +import com.cloud.vm.UserVmManager; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.VmDetailConstants; +import com.cloud.vm.VMInstanceDetailVO; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.dao.NicDao; +import com.cloud.vm.dao.UserVmDao; +import com.cloud.vm.dao.VMInstanceDao; +import com.cloud.vm.dao.VMInstanceDetailsDao; + +@RunWith(MockitoJUnitRunner.class) +public class UnmanagedVMsManagerImplTest { + + @Spy + @InjectMocks + private UnmanagedVMsManagerImpl unmanagedVMsManager; + + @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 VolumeDao volumeDao; + @Mock + private ResourceLimitService resourceLimitService; + @Mock + private PrimaryDataStoreDao primaryDataStoreDao; + @Mock + private VolumeApiService volumeApiService; + @Mock + private NetworkModel networkModel; + @Mock + private ConfigurationDao configurationDao; + @Mock + private UserVmDao userVmDao; + @Mock + private NicDao nicDao; + @Mock + private HostDao hostDao; + @Mock + private VmwareDatacenterDao vmwareDatacenterDao; + @Mock + private HypervisorGuruManager hypervisorGuruManager; + @Mock + private ImageStoreDao imageStoreDao; + @Mock + private DataStoreManager dataStoreManager; + @Mock + private StoragePoolHostDao storagePoolHostDao; + @Mock + private ImportVmTasksManager importVmTasksManager; + @Mock + private SnapshotDao snapshotDao; + + @Mock + private VMInstanceVO virtualMachine; + @Mock + EntityManager entityMgr; + @Mock + DeploymentPlanningManager deploymentPlanningManager; + @Mock + ImportVMTaskVO importVMTaskVO; + @Mock + private VMInstanceDetailsDao vmInstanceDetailsDao; + @Mock + private ConfigKey configKeyMockParamsAllowed; + @Mock + private ConfigKey configKeyMockParamsAllowedList; + @Mock + private Account accountMock; + @Mock + private ServiceOfferingVO serviceOfferingMock; + @Mock + private VMTemplateVO templateMock; + @Mock + private UnmanagedInstanceTO unmanagedInstanceMock; + + private static final long virtualMachineId = 1L; + + private AutoCloseable closeable; + + private MockedStatic actionEventUtilsMocked; + + private UnmanagedInstanceTO instance; + + @Before + public void setUp() throws Exception { + closeable = MockitoAnnotations.openMocks(this); + actionEventUtilsMocked = Mockito.mockStatic(ActionEventUtils.class); + BDDMockito.given(ActionEventUtils.onStartedActionEvent(anyLong(), anyLong(), anyString(), anyString(), anyLong(), anyString(), anyBoolean(), anyLong())) + .willReturn(1L); + BDDMockito.given(ActionEventUtils.onCompletedActionEvent(anyLong(), anyLong(), anyString(), anyString(), anyString(), anyLong(), anyString(), anyLong())) + .willReturn(1L); + + AccountVO account = new AccountVO("admin", 1L, "", 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); + + instance = new UnmanagedInstanceTO(); + instance.setName("TestInstance"); + instance.setCpuCores(2); + instance.setCpuCoresPerSocket(1); + instance.setCpuSpeed(1000); + instance.setMemory(1024); + instance.setOperatingSystem("CentOS 7"); + List instanceDisks = getDisks(); + instance.setDisks(instanceDisks); + 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(UnmanagedInstanceTO.PowerState.PowerOn); + + ClusterVO clusterVO = new ClusterVO(1L, 1L, "Cluster"); + clusterVO.setHypervisorType(Hypervisor.HypervisorType.VMware.toString()); + when(clusterDao.findById(anyLong())).thenReturn(clusterVO); + when(configurationDao.getValue(Mockito.anyString())).thenReturn(null); + List hosts = new ArrayList<>(); + HostVO hostVO = Mockito.mock(HostVO.class); + when(hostVO.isInMaintenanceStates()).thenReturn(false); + hosts.add(hostVO); + when(resourceManager.listHostsInClusterByStatus(anyLong(), any(Status.class))).thenReturn(hosts); + when(resourceManager.listAllUpAndEnabledHostsInOneZoneByHypervisor(any(Hypervisor.HypervisorType.class), anyLong())).thenReturn(hosts); + List templates = new ArrayList<>(); + when(templatePoolDao.listAll()).thenReturn(templates); + List volumes = new ArrayList<>(); + when(volumeDao.findIncludingRemovedByZone(anyLong())).thenReturn(volumes); + GetUnmanagedInstancesCommand cmd = Mockito.mock(GetUnmanagedInstancesCommand.class); + HashMap map = new HashMap<>(); + map.put(instance.getName(), instance); + Answer answer = new GetUnmanagedInstancesAnswer(cmd, "", map); + when(agentManager.easySend(anyLong(), any(GetUnmanagedInstancesCommand.class))).thenReturn(answer); + GetRemoteVmsCommand remoteVmListcmd = Mockito.mock(GetRemoteVmsCommand.class); + Answer remoteVmListAnswer = new GetRemoteVmsAnswer(remoteVmListcmd, "", map); + when(agentManager.easySend(anyLong(), any(GetRemoteVmsCommand.class))).thenReturn(remoteVmListAnswer); + DataCenterVO zone = Mockito.mock(DataCenterVO.class); + when(zone.getId()).thenReturn(1L); + when(dataCenterDao.findById(anyLong())).thenReturn(zone); + when(accountService.getActiveAccountById(anyLong())).thenReturn(Mockito.mock(Account.class)); + List users = new ArrayList<>(); + users.add(Mockito.mock(UserVO.class)); + when(userDao.listByAccount(anyLong())).thenReturn(users); + VMTemplateVO template = Mockito.mock(VMTemplateVO.class); + when(template.getName()).thenReturn("Template"); + when(templateDao.findById(anyLong())).thenReturn(template); + ServiceOfferingVO serviceOffering = Mockito.mock(ServiceOfferingVO.class); + when(serviceOffering.getId()).thenReturn(1L); + 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(anyLong())).thenReturn(serviceOffering); + when(serviceOfferingDao.findById(anyLong(), anyLong())).thenReturn(Mockito.mock(ServiceOfferingVO.class)); + DiskOfferingVO diskOfferingVO = Mockito.mock(DiskOfferingVO.class); + when(diskOfferingDao.findById(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 + userVm.setInstanceName(instance.getName()); + userVm.setHostName(instance.getName()); + StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); + when(poolVO.getDataCenterId()).thenReturn(1L); + when(poolVO.getClusterId()).thenReturn(clusterVO.getId()); + List pools = new ArrayList<>(); + pools.add(poolVO); + when(primaryDataStoreDao.listPoolByHostPath(Mockito.anyString(), Mockito.anyString())).thenReturn(pools); + when(userVmManager.importVM(nullable(DataCenter.class), nullable(Host.class), nullable(VirtualMachineTemplate.class), nullable(String.class), nullable(String.class), + nullable(Account.class), nullable(String.class), nullable(Account.class), nullable(Boolean.class), nullable(String.class), + nullable(Long.class), nullable(Long.class), nullable(ServiceOffering.class), nullable(String.class), nullable(Long.class), + nullable(String.class), nullable(Hypervisor.HypervisorType.class), nullable(Map.class), nullable(VirtualMachine.PowerState.class), nullable(LinkedHashMap.class))).thenReturn(userVm); + 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(anyLong())).thenReturn(networkVO); + List networks = new ArrayList<>(); + networks.add(networkVO); + when(networkDao.listByZone(anyLong())).thenReturn(networks); + doNothing().when(networkModel).checkNetworkPermissions(any(Account.class), any(Network.class)); + NicProfile profile = Mockito.mock(NicProfile.class); + Integer deviceId = 100; + Pair pair = new Pair<>(profile, deviceId); + when(networkOrchestrationService.importNic(nullable(String.class), nullable(Integer.class), nullable(Network.class), nullable(Boolean.class), nullable(VirtualMachine.class), nullable(Network.IpAddresses.class), nullable(DataCenter.class), Mockito.anyBoolean())).thenReturn(pair); + when(volumeDao.findByInstance(Mockito.anyLong())).thenReturn(volumes); + List userVmResponses = new ArrayList<>(); + UserVmResponse userVmResponse = new UserVmResponse(); + userVmResponse.setInstanceName(instance.getName()); + userVmResponses.add(userVmResponse); + when(responseGenerator.createUserVmResponse(any(ResponseObject.ResponseView.class), Mockito.anyString(), any(UserVm.class))).thenReturn(userVmResponses); + + when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Running); + + when(unmanagedInstanceMock.getCpuCores()).thenReturn(8); + when(unmanagedInstanceMock.getMemory()).thenReturn(4096); + when(serviceOfferingMock.getCpu()).thenReturn(4); + when(serviceOfferingMock.getRamSize()).thenReturn(2048); + } + + @NotNull + private static List getDisks() { + List instanceDisks = new ArrayList<>(); + UnmanagedInstanceTO.Disk instanceDisk = new UnmanagedInstanceTO.Disk(); + instanceDisk.setDiskId("1000-1"); + instanceDisk.setPosition(0); + instanceDisk.setLabel("DiskLabel"); + instanceDisk.setController("scsi"); + instanceDisk.setImagePath("[b6ccf44a1fa13e29b3667b4954fa10ee] TestInstance/ROOT-1.vmdk"); + instanceDisk.setCapacity(5242880L); + instanceDisk.setDatastoreName("Test"); + instanceDisk.setDatastoreHost("Test"); + instanceDisk.setDatastorePath("Test"); + instanceDisk.setDatastoreType("NFS"); + instanceDisks.add(instanceDisk); + return instanceDisks; + } + + @After + public void tearDown() throws Exception { + closeable.close(); + actionEventUtilsMocked.close(); + CallContext.unregister(); + } + + @Test + public void listUnmanagedInstancesTest() { + ListUnmanagedInstancesCmd cmd = Mockito.mock(ListUnmanagedInstancesCmd.class); + unmanagedVMsManager.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.XenServer.toString()); + when(clusterDao.findById(anyLong())).thenReturn(cluster); + unmanagedVMsManager.listUnmanagedInstances(cmd); + } + + @Test(expected = PermissionDeniedException.class) + public void listUnmanagedInstancesInvalidCallerTest() { + CallContext.unregister(); + AccountVO account = new AccountVO("user", 1L, "", 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); + unmanagedVMsManager.listUnmanagedInstances(cmd); + } + + @Test + public void importUnmanagedInstanceTest() { + ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class); + when(importUnmanageInstanceCmd.getName()).thenReturn("TestInstance"); + when(importUnmanageInstanceCmd.getDomainId()).thenReturn(null); + when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true); + try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class); + MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.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"); + unmanagedVMsManager.importUnmanagedInstance(importUnmanageInstanceCmd); + } + + @Test(expected = ServerApiException.class) + public void importUnmanagedInstanceMissingInstanceTest() { + ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class); + when(importUnmanageInstanceCmd.getName()).thenReturn("SomeInstance"); + when(importUnmanageInstanceCmd.getDomainId()).thenReturn(null); + try (MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.importUnmanagedInstance(importUnmanageInstanceCmd); + } + } + + @Test(expected = InvalidParameterValueException.class) + public void unmanageVMInstanceMissingInstanceTest() { + when(vmDao.findById(anyLong())).thenReturn(null); + unmanagedVMsManager.unmanageVMInstance(1L, null, false); + } + + @Test(expected = InvalidParameterValueException.class) + public void unmanageVMInstanceRemovedInstanceTest() { + VMInstanceVO userVmVO = mock(VMInstanceVO.class); + when(vmDao.findById(anyLong())).thenReturn(userVmVO); + when(userVmVO.getRemoved()).thenReturn(new Date()); + unmanagedVMsManager.unmanageVMInstance(1L, null, false); + } + + @Test(expected = InvalidParameterValueException.class) + public void unmanageVMInstanceDestroyedInstanceTest() { + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Destroyed); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = InvalidParameterValueException.class) + public void unmanageVMInstanceExpungedInstanceTest() { + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Expunging); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void unmanageVMInstanceExistingVMSnapshotsTest() { + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.None); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void unmanageVMInstanceInvalidHyperVisor() { + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.None); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void unmanageVMInstanceInvalidVmType() { + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.VMware); + when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.ConsoleProxy); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void unmanageVMInstanceExistingVolumeSnapshotsTest() { + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.None); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void unmanageVMInstanceExistingISOAttachedTest() { + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.None); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void unmanageVMInstanceVmwareHostIdParamTest() { + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.VMware); + when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, 1L, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void unmanageVMInstanceRunningHostIdParamTest() { + when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Running); + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, 1L, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void unmanageVMInstanceRunningForceParamTest() { + when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Running); + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + VMInstanceDetailVO vmInstanceDetailVO = mock(VMInstanceDetailVO.class); + when(vmInstanceDetailsDao.findDetail(virtualMachineId, VmDetailConstants.CONFIG_DRIVE_LOCATION)).thenReturn(vmInstanceDetailVO); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test + public void unmanageVMInstanceVMwareHostId() { + when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); + UserVmVO userVmVO = mock(UserVmVO.class); + when(userVmVO.getIsoId()).thenReturn(null); + when(userVmDao.findById(anyLong())).thenReturn(userVmVO); + when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, 1L, false); + } + + @Test + public void unmanageVMInstanceStoppedInstanceTest() { + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); + UserVmVO userVmVO = mock(UserVmVO.class); + when(userVmDao.findById(anyLong())).thenReturn(userVmVO); + Mockito.doNothing().when(unmanagedVMsManager).performUnmanageVMInstancePrechecks(any()); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void testUnmanageVMInstanceWithVolumeSnapshotsFail() { + when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); + when(virtualMachine.getId()).thenReturn(virtualMachineId); + UserVmVO userVmVO = mock(UserVmVO.class); + when(userVmDao.findById(anyLong())).thenReturn(userVmVO); + when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); + VolumeVO volumeVO = mock(VolumeVO.class); + long volumeId = 20L; + when(volumeVO.getId()).thenReturn(volumeId); + SnapshotVO snapshotVO = mock(SnapshotVO.class); + when(snapshotVO.getState()).thenReturn(Snapshot.State.BackedUp); + when(snapshotDao.listByVolumeId(volumeId)).thenReturn(Collections.singletonList(snapshotVO)); + when(volumeDao.findByInstance(virtualMachineId)).thenReturn(Collections.singletonList(volumeVO)); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void testUnmanageVMInstanceWithAssociatedIsoFail() { + when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); + when(virtualMachine.getId()).thenReturn(virtualMachineId); + UserVmVO userVmVO = mock(UserVmVO.class); + when(userVmVO.getIsoId()).thenReturn(null); + when(userVmDao.findById(anyLong())).thenReturn(userVmVO); + when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); + when(userVmVO.getIsoId()).thenReturn(1L); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void testUnmanageVMInstanceBelongingToCksClusterFail() { + when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); + when(virtualMachine.getId()).thenReturn(virtualMachineId); + UserVmVO userVmVO = mock(UserVmVO.class); + when(userVmVO.getIsoId()).thenReturn(null); + when(userVmDao.findById(anyLong())).thenReturn(userVmVO); + when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); + when(userVmManager.isVMPartOfAnyCKSCluster(virtualMachine)).thenReturn(true); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test + public void testListRemoteInstancesTest() { + ListVmsForImportCmd cmd = Mockito.mock(ListVmsForImportCmd.class); + when(cmd.getHypervisor()).thenReturn(Hypervisor.HypervisorType.KVM.toString()); + when(cmd.getUsername()).thenReturn("user"); + when(cmd.getPassword()).thenReturn("pass"); + ListResponse response = unmanagedVMsManager.listVmsForImport(cmd); + Assert.assertEquals(1, response.getCount().intValue()); + } + + @Test(expected = InvalidParameterValueException.class) + public void testListRemoteInstancesTestNonKVM() { + ListVmsForImportCmd cmd = Mockito.mock(ListVmsForImportCmd.class); + unmanagedVMsManager.listVmsForImport(cmd); + } + @Test + public void testImportFromExternalTest() throws InsufficientServerCapacityException { + String vmname = "TestInstance"; + ImportVmCmd cmd = Mockito.mock(ImportVmCmd.class); + when(cmd.getHypervisor()).thenReturn(Hypervisor.HypervisorType.KVM.toString()); + when(cmd.getName()).thenReturn(vmname); + when(cmd.getUsername()).thenReturn("user"); + when(cmd.getPassword()).thenReturn("pass"); + when(cmd.getImportSource()).thenReturn("external"); + when(cmd.getDomainId()).thenReturn(null); + HostVO host = Mockito.mock(HostVO.class); + DeployDestination mockDest = Mockito.mock(DeployDestination.class); + when(deploymentPlanningManager.planDeployment(any(), any(), any(), any())).thenReturn(mockDest); + DiskProfile diskProfile = Mockito.mock(DiskProfile.class); + when(volumeManager.allocateRawVolume(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), anyBoolean())) + .thenReturn(diskProfile); + Map storage = new HashMap<>(); + VolumeVO volume = Mockito.mock(VolumeVO.class); + StoragePoolVO storagePool = Mockito.mock(StoragePoolVO.class); + storage.put(volume, storagePool); + when(mockDest.getStorageForDisks()).thenReturn(storage); + when(mockDest.getHost()).thenReturn(host); + when(volumeDao.findById(anyLong())).thenReturn(volume); + CopyRemoteVolumeAnswer copyAnswer = Mockito.mock(CopyRemoteVolumeAnswer.class); + when(copyAnswer.getResult()).thenReturn(true); + when(agentManager.easySend(anyLong(), any(CopyRemoteVolumeCommand.class))).thenReturn(copyAnswer); + try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class); + MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.importVm(cmd); + } + } + + private void baseBasicParametersCheckForImportInstance(String name, Long domainId, String accountName) { + unmanagedVMsManager.basicParametersCheckForImportInstance(name, domainId, accountName); + } + + @Test(expected = InvalidParameterValueException.class) + public void testBasicParametersCheckForImportInstanceMissingName() { + baseBasicParametersCheckForImportInstance(null, 1L, "test"); + } + + @Test(expected = InvalidParameterValueException.class) + public void testBasicParametersCheckForImportInstanceMissingDomainAndAccount() { + baseBasicParametersCheckForImportInstance("vm", 1L, ""); + } + + @Test(expected = InvalidParameterValueException.class) + public void testBasicAccessChecksMissingClusterId() { + unmanagedVMsManager.basicAccessChecks(null); + } + + @Test(expected = PermissionDeniedException.class) + public void testBasicAccessChecksNotAdminCaller() { + CallContext.unregister(); + AccountVO account = new AccountVO("user", 1L, "", 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); + unmanagedVMsManager.basicAccessChecks(1L); + } + + @Test(expected = InvalidParameterValueException.class) + public void testBasicAccessChecksUnsupportedHypervisorType() { + ClusterVO clusterVO = new ClusterVO(1L, 1L, "Cluster"); + clusterVO.setHypervisorType(Hypervisor.HypervisorType.XenServer.toString()); + when(clusterDao.findById(anyLong())).thenReturn(clusterVO); + unmanagedVMsManager.basicAccessChecks(1L); + } + + @Test + public void testGetTemplateForImportInstanceDefaultTemplate() { + String defaultTemplateName = "DefaultTemplate"; + VMTemplateVO template = Mockito.mock(VMTemplateVO.class); + when(template.getName()).thenReturn(defaultTemplateName); + when(templateDao.findByName(anyString())).thenReturn(template); + VMTemplateVO templateForImportInstance = unmanagedVMsManager.getTemplateForImportInstance(null, Hypervisor.HypervisorType.KVM); + Assert.assertEquals(defaultTemplateName, templateForImportInstance.getName()); + } + + private enum VcenterParameter { + EXISTING, + EXTERNAL, + BOTH, + NONE, + EXISTING_INVALID, + AGENT_UNAVAILABLE, + CONVERT_FAILURE, + FORCE_MS_AND_USE_VDDK, + USE_VDDK_OVF_UNSUPPORTED, + USE_VDDK_OVF_SUPPORTED, + USE_VDDK_DETAILS_OVERRIDES + } + + private void baseTestImportVmFromVmwareToKvm(VcenterParameter vcenterParameter, boolean selectConvertHost, + boolean selectTemporaryStorage) throws OperationTimedoutException, AgentUnavailableException { + long clusterId = 1L; + long zoneId = 1L; + long existingDatacenterId = 1L; + String vcenterHost = "192.168.1.2"; + String datacenter = "Datacenter"; + String username = "administrator@vsphere.local"; + String password = "password"; + String host = "192.168.1.10"; + String vmName = "TestInstanceFromVmware"; + instance.setName(vmName); + String tmplFileName = "5b8d689a-e61a-4ac3-9b76-e121ff90fbd3"; + long newVmId = 2L; + long networkId = 1L; + + ClusterVO cluster = mock(ClusterVO.class); + when(cluster.getId()).thenReturn(clusterId); + when(cluster.getAllocationState()).thenReturn(Grouping.AllocationState.Enabled); + when(cluster.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + when(cluster.getDataCenterId()).thenReturn(zoneId); + when(clusterDao.findById(clusterId)).thenReturn(cluster); + + ImportVmCmd importVmCmd = Mockito.mock(ImportVmCmd.class); + + when(importVmCmd.getName()).thenReturn(vmName); + when(importVmCmd.getClusterId()).thenReturn(clusterId); + when(importVmCmd.getDomainId()).thenReturn(null); + when(importVmCmd.getImportSource()).thenReturn(VmImportService.ImportSource.VMWARE.toString()); + when(importVmCmd.getHostIp()).thenReturn(host); + when(importVmCmd.getNicNetworkList()).thenReturn(Map.of("NIC 1", networkId)); + when(importVmCmd.getConvertInstanceHostId()).thenReturn(null); + when(importVmCmd.getImportInstanceHostId()).thenReturn(null); + when(importVmCmd.getConvertStoragePoolId()).thenReturn(null); + when(importVmCmd.getExistingVcenterId()).thenReturn(null); + when(importVmCmd.getVcenter()).thenReturn(null); + when(importVmCmd.getDatacenterName()).thenReturn(null); + when(importVmCmd.getUsername()).thenReturn(null); + when(importVmCmd.getPassword()).thenReturn(null); + when(importVmCmd.getDetails()).thenReturn(new HashMap<>()); + + boolean forceMsToImportVmFiles = false; + boolean useVddk = false; + boolean ovfExportSupported = false; + if (VcenterParameter.FORCE_MS_AND_USE_VDDK == vcenterParameter) { + forceMsToImportVmFiles = true; + useVddk = true; + } else if (VcenterParameter.USE_VDDK_OVF_UNSUPPORTED == vcenterParameter) { + useVddk = true; + } else if (VcenterParameter.USE_VDDK_OVF_SUPPORTED == vcenterParameter) { + useVddk = true; + ovfExportSupported = true; + } else if (VcenterParameter.USE_VDDK_DETAILS_OVERRIDES == vcenterParameter) { + useVddk = true; + ovfExportSupported = true; + when(importVmCmd.getDetails()).thenReturn(Map.of( + "vddk.lib.dir", "/opt/vmware-vddk/override", + "vddk.transports", "nbd:nbdssl", + "vddk.thumbprint", "AA:BB:CC:DD:EE")); + } + when(importVmCmd.getForceMsToImportVmFiles()).thenReturn(forceMsToImportVmFiles); + when(importVmCmd.getUseVddk()).thenReturn(useVddk); + + NetworkVO networkVO = Mockito.mock(NetworkVO.class); + when(networkVO.getGuestType()).thenReturn(Network.GuestType.L2); + when(networkVO.getDataCenterId()).thenReturn(zoneId); + when(networkDao.findById(networkId)).thenReturn(networkVO); + + HypervisorGuru vmwareGuru = mock(HypervisorGuru.class); + when(hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware)).thenReturn(vmwareGuru); + when(vmwareGuru.getHypervisorVMOutOfBandAndCloneIfRequired(anyString(), anyString(), anyMap())).thenReturn(new Pair<>(instance, true)); + when(vmwareGuru.removeClonedHypervisorVMOutOfBand(anyString(), anyString(), anyMap())).thenReturn(true); + when(vmwareGuru.createVMTemplateOutOfBand(anyString(), anyString(), anyMap(), any(DataStoreTO.class), anyInt())).thenReturn(tmplFileName); + when(vmwareGuru.removeVMTemplateOutOfBand(any(DataStoreTO.class), anyString())).thenReturn(true); + + HostVO convertHost = mock(HostVO.class); + long convertHostId = 1L; + when(convertHost.getStatus()).thenReturn(Status.Up); + when(convertHost.getResourceState()).thenReturn(ResourceState.Enabled); + when(convertHost.getId()).thenReturn(convertHostId); + when(convertHost.getType()).thenReturn(Host.Type.Routing); + when(convertHost.getDataCenterId()).thenReturn(zoneId); + when(convertHost.getClusterId()).thenReturn(clusterId); + if (selectConvertHost) { + when(importVmCmd.getConvertInstanceHostId()).thenReturn(convertHostId); + when(importVmCmd.getImportInstanceHostId()).thenReturn(convertHostId); + when(hostDao.findById(convertHostId)).thenReturn(convertHost); + } else { + when(hostDao.listByClusterAndHypervisorType(clusterId, Hypervisor.HypervisorType.KVM)).thenReturn(List.of(convertHost)); + } + + DataStoreTO dataStoreTO = mock(DataStoreTO.class); + DataStore dataStore = mock(DataStore.class); + when(dataStore.getTO()).thenReturn(dataStoreTO); + + StoragePoolVO destPool = mock(StoragePoolVO.class); + when(destPool.getDataCenterId()).thenReturn(zoneId); + when(destPool.getClusterId()).thenReturn(null); + when(destPool.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem); + StoragePoolVO zoneDestPool = mock(StoragePoolVO.class); + if (selectTemporaryStorage) { + long temporaryStoragePoolId = 1L; + when(importVmCmd.getConvertStoragePoolId()).thenReturn(temporaryStoragePoolId); + when(primaryDataStoreDao.findById(temporaryStoragePoolId)).thenReturn(destPool); + when(dataStoreManager.getPrimaryDataStore(temporaryStoragePoolId)).thenReturn(dataStore); + } else { + ImageStoreVO imageStoreVO = mock(ImageStoreVO.class); + when(imageStoreVO.getId()).thenReturn(1L); + when(imageStoreDao.findOneByZoneAndProtocol(zoneId, "nfs")).thenReturn(imageStoreVO); + when(dataStoreManager.getDataStore(1L, DataStoreRole.Image)).thenReturn(dataStore); + } + when(primaryDataStoreDao.listPoolByHostPath(Mockito.anyString(), Mockito.anyString())).thenReturn(List.of(destPool)); + when(primaryDataStoreDao.findClusterWideStoragePoolsByHypervisorAndPoolType(clusterId, Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)).thenReturn(List.of(destPool)); + when(primaryDataStoreDao.findZoneWideStoragePoolsByHypervisorAndPoolType(zoneId, Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)).thenReturn(List.of(zoneDestPool)); + + if (VcenterParameter.EXISTING == vcenterParameter) { + VmwareDatacenterVO datacenterVO = mock(VmwareDatacenterVO.class); + when(datacenterVO.getVcenterHost()).thenReturn(vcenterHost); + when(datacenterVO.getVmwareDatacenterName()).thenReturn(datacenter); + when(datacenterVO.getUser()).thenReturn(username); + when(datacenterVO.getPassword()).thenReturn(password); + when(importVmCmd.getExistingVcenterId()).thenReturn(existingDatacenterId); + when(vmwareDatacenterDao.findById(existingDatacenterId)).thenReturn(datacenterVO); + } + + if (VcenterParameter.BOTH == vcenterParameter) { + when(importVmCmd.getExistingVcenterId()).thenReturn(existingDatacenterId); + when(importVmCmd.getVcenter()).thenReturn(vcenterHost); + } else if (VcenterParameter.NONE == vcenterParameter) { + when(importVmCmd.getExistingVcenterId()).thenReturn(null); + when(importVmCmd.getVcenter()).thenReturn(null); + } else if (VcenterParameter.EXISTING_INVALID == vcenterParameter) { + when(importVmCmd.getExistingVcenterId()).thenReturn(existingDatacenterId); + when(vmwareDatacenterDao.findById(existingDatacenterId)).thenReturn(null); + } + + if (VcenterParameter.FORCE_MS_AND_USE_VDDK == vcenterParameter + || VcenterParameter.USE_VDDK_OVF_UNSUPPORTED == vcenterParameter + || VcenterParameter.USE_VDDK_OVF_SUPPORTED == vcenterParameter + || VcenterParameter.USE_VDDK_DETAILS_OVERRIDES == vcenterParameter) { + Mockito.doReturn((Long) null).when(importVmCmd).getExistingVcenterId(); + Mockito.doReturn(vcenterHost).when(importVmCmd).getVcenter(); + Mockito.doReturn(datacenter).when(importVmCmd).getDatacenterName(); + Mockito.doReturn(username).when(importVmCmd).getUsername(); + Mockito.doReturn(password).when(importVmCmd).getPassword(); + } + + CheckConvertInstanceAnswer checkConvertInstanceAnswer = mock(CheckConvertInstanceAnswer.class); + when(checkConvertInstanceAnswer.getResult()).thenReturn(vcenterParameter != VcenterParameter.CONVERT_FAILURE); + when(checkConvertInstanceAnswer.isOvfExportSupported()).thenReturn(ovfExportSupported); + if (VcenterParameter.AGENT_UNAVAILABLE != vcenterParameter) { + when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(CheckConvertInstanceCommand.class))).thenReturn(checkConvertInstanceAnswer); + } + + when(importVmTasksManager.createImportVMTaskRecord(any(DataCenter.class), any(Account.class), anyLong(), anyString(), + anyString(), anyString(), anyString(), any(Host.class), any(Host.class))).thenReturn(importVMTaskVO); + when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any(DiskOffering.class))).thenReturn(true); + + ConvertInstanceAnswer convertInstanceAnswer = mock(ConvertInstanceAnswer.class); + ImportConvertedInstanceAnswer convertImportedInstanceAnswer = mock(ImportConvertedInstanceAnswer.class); + when(convertInstanceAnswer.getResult()).thenReturn(vcenterParameter != VcenterParameter.CONVERT_FAILURE); + Mockito.lenient().when(convertImportedInstanceAnswer.getConvertedInstance()).thenReturn(instance); + Mockito.lenient().when(convertImportedInstanceAnswer.getResult()).thenReturn(vcenterParameter != VcenterParameter.CONVERT_FAILURE); + if (VcenterParameter.AGENT_UNAVAILABLE != vcenterParameter) { + when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(ConvertInstanceCommand.class))).thenReturn(convertInstanceAnswer); + Mockito.lenient().when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(ImportConvertedInstanceCommand.class))).thenReturn(convertImportedInstanceAnswer); + } + + try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class); + MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.importVm(importVmCmd); + verify(vmwareGuru).getHypervisorVMOutOfBandAndCloneIfRequired(Mockito.eq(host), Mockito.eq(vmName), anyMap()); + if (VcenterParameter.USE_VDDK_OVF_SUPPORTED == vcenterParameter) { + verify(vmwareGuru, Mockito.never()).createVMTemplateOutOfBand(anyString(), anyString(), anyMap(), any(DataStoreTO.class), anyInt()); + verify(agentManager).send(Mockito.eq(convertHostId), Mockito.argThat(command -> + command instanceof ConvertInstanceCommand && ((ConvertInstanceCommand) command).isUseVddk())); + verify(vmwareGuru, Mockito.never()).removeVMTemplateOutOfBand(any(DataStoreTO.class), anyString()); + } else if (VcenterParameter.USE_VDDK_DETAILS_OVERRIDES == vcenterParameter) { + verify(vmwareGuru, Mockito.never()).createVMTemplateOutOfBand(anyString(), anyString(), anyMap(), any(DataStoreTO.class), anyInt()); + verify(agentManager).send(Mockito.eq(convertHostId), Mockito.argThat(command -> { + if (!(command instanceof ConvertInstanceCommand)) { + return false; + } + ConvertInstanceCommand convertCmd = (ConvertInstanceCommand) command; + return convertCmd.isUseVddk() + && "/opt/vmware-vddk/override".equals(convertCmd.getVddkLibDir()) + && "nbd:nbdssl".equals(convertCmd.getVddkTransports()) + && "AA:BB:CC:DD:EE".equals(convertCmd.getVddkThumbprint()); + })); + verify(vmwareGuru, Mockito.never()).removeVMTemplateOutOfBand(any(DataStoreTO.class), anyString()); + } else { + verify(vmwareGuru).createVMTemplateOutOfBand(Mockito.eq(host), Mockito.eq(vmName), anyMap(), any(DataStoreTO.class), anyInt()); + verify(vmwareGuru).removeVMTemplateOutOfBand(any(DataStoreTO.class), anyString()); + } + verify(vmwareGuru).removeClonedHypervisorVMOutOfBand(Mockito.eq(host), Mockito.eq(vmName), anyMap()); + } + } + + @Test + public void importFromLocalDisk() throws InsufficientServerCapacityException { + importFromDisk("local"); + } + + @Test + public void importFromsharedStorage() throws InsufficientServerCapacityException { + importFromDisk("shared"); + } + + private void importFromDisk(String source) throws InsufficientServerCapacityException { + String vmname = "testVm"; + ImportVmCmd cmd = Mockito.mock(ImportVmCmd.class); + when(cmd.getHypervisor()).thenReturn(Hypervisor.HypervisorType.KVM.toString()); + when(cmd.getName()).thenReturn(vmname); + when(cmd.getImportSource()).thenReturn(source); + when(cmd.getDiskPath()).thenReturn("/var/lib/libvirt/images/test.qcow2"); + when(cmd.getDomainId()).thenReturn(null); + HostVO host = Mockito.mock(HostVO.class); + when(hostDao.findById(anyLong())).thenReturn(host); + NetworkOffering netOffering = Mockito.mock(NetworkOffering.class); + when(entityMgr.findById(NetworkOffering.class, 0L)).thenReturn(netOffering); + DeployDestination mockDest = Mockito.mock(DeployDestination.class); + when(deploymentPlanningManager.planDeployment(any(), any(), any(), any())).thenReturn(mockDest); + DiskProfile diskProfile = Mockito.mock(DiskProfile.class); + when(volumeManager.allocateRawVolume(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), anyBoolean())) + .thenReturn(diskProfile); + Map storage = new HashMap<>(); + VolumeVO volume = Mockito.mock(VolumeVO.class); + StoragePoolVO storagePool = Mockito.mock(StoragePoolVO.class); + storage.put(volume, storagePool); + when(mockDest.getStorageForDisks()).thenReturn(storage); + when(mockDest.getHost()).thenReturn(host); + when(volumeDao.findById(anyLong())).thenReturn(volume); + CheckVolumeAnswer answer = Mockito.mock(CheckVolumeAnswer.class); + when(answer.getResult()).thenReturn(true); + when(agentManager.easySend(anyLong(), any(CheckVolumeCommand.class))).thenReturn(answer); + List storagePools = new ArrayList<>(); + storagePools.add(storagePool); + when(primaryDataStoreDao.findLocalStoragePoolsByHostAndTags(anyLong(), any())).thenReturn(storagePools); + when(primaryDataStoreDao.findById(anyLong())).thenReturn(storagePool); + when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true); + StoragePoolHostVO storagePoolHost = Mockito.mock(StoragePoolHostVO.class); + when(storagePoolHostDao.findByPoolHost(anyLong(), anyLong())).thenReturn(storagePoolHost); + try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class); + MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.importVm(cmd); + } + } + + @Test + public void testImportVmFromVmwareToKvmExistingVcenter() throws OperationTimedoutException, AgentUnavailableException { + baseTestImportVmFromVmwareToKvm(VcenterParameter.EXISTING, false, false); + } + + @Test + public void testImportVmFromVmwareToKvmExistingVcenterSetConvertHost() throws OperationTimedoutException, AgentUnavailableException { + baseTestImportVmFromVmwareToKvm(VcenterParameter.EXISTING, true, false); + } + + @Test + public void testImportVmFromVmwareToKvmExistingVcenterSetConvertHostAndTemporaryStorage() throws OperationTimedoutException, AgentUnavailableException { + baseTestImportVmFromVmwareToKvm(VcenterParameter.EXISTING, true, true); + } + + @Test(expected = ServerApiException.class) + public void testImportVmFromVmwareToKvmExistingVcenterExclusiveParameters() throws OperationTimedoutException, AgentUnavailableException { + baseTestImportVmFromVmwareToKvm(VcenterParameter.BOTH, false, false); + } + + @Test(expected = ServerApiException.class) + public void testImportVmFromVmwareToKvmExistingVcenterMissingParameters() throws OperationTimedoutException, AgentUnavailableException { + baseTestImportVmFromVmwareToKvm(VcenterParameter.NONE, false, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testImportVmFromVmwareToKvmExistingVcenterInvalid() throws OperationTimedoutException, AgentUnavailableException { + baseTestImportVmFromVmwareToKvm(VcenterParameter.EXISTING_INVALID, false, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testImportVmFromVmwareToKvmExistingVcenterAgentUnavailable() throws OperationTimedoutException, AgentUnavailableException { + baseTestImportVmFromVmwareToKvm(VcenterParameter.AGENT_UNAVAILABLE, false, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testImportVmFromVmwareToKvmExistingVcenterConvertFailure() throws OperationTimedoutException, AgentUnavailableException { + baseTestImportVmFromVmwareToKvm(VcenterParameter.CONVERT_FAILURE, false, false); + } + + @Test(expected = ServerApiException.class) + public void testImportVmFromVmwareToKvmForceMsMutuallyExclusiveWithUseVddk() throws OperationTimedoutException, AgentUnavailableException { + baseTestImportVmFromVmwareToKvm(VcenterParameter.FORCE_MS_AND_USE_VDDK, false, false); + } + + @Test(expected = InvalidParameterValueException.class) + public void testValidateSelectedConversionStoragePoolForVddkFailsWhenPoolDoesNotSupportDiskOfferings() { + long poolId = 11L; + StoragePoolVO selectedPool = mock(StoragePoolVO.class); + ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class); + DiskOfferingVO rootDiskOffering = mock(DiskOfferingVO.class); + DiskOfferingVO dataDiskOffering = mock(DiskOfferingVO.class); + + when(serviceOffering.getDiskOfferingId()).thenReturn(21L); + when(primaryDataStoreDao.findById(poolId)).thenReturn(selectedPool); + when(diskOfferingDao.findById(21L)).thenReturn(rootDiskOffering); + when(diskOfferingDao.findById(22L)).thenReturn(dataDiskOffering); + when(volumeApiService.doesStoragePoolSupportDiskOffering(selectedPool, rootDiskOffering)).thenReturn(true); + when(volumeApiService.doesStoragePoolSupportDiskOffering(selectedPool, dataDiskOffering)).thenReturn(false); + + unmanagedVMsManager.validateSelectedConversionStoragePoolForVddk(true, poolId, + serviceOffering, Map.of("1000-2", 22L)); + } + + @Test + public void testValidateSelectedConversionStoragePoolForVddkPassesWhenPoolSupportsAllDiskOfferings() { + long poolId = 12L; + StoragePoolVO selectedPool = mock(StoragePoolVO.class); + ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class); + DiskOfferingVO rootDiskOffering = mock(DiskOfferingVO.class); + DiskOfferingVO dataDiskOffering = mock(DiskOfferingVO.class); + + when(serviceOffering.getDiskOfferingId()).thenReturn(31L); + when(primaryDataStoreDao.findById(poolId)).thenReturn(selectedPool); + when(diskOfferingDao.findById(31L)).thenReturn(rootDiskOffering); + when(diskOfferingDao.findById(32L)).thenReturn(dataDiskOffering); + when(volumeApiService.doesStoragePoolSupportDiskOffering(selectedPool, rootDiskOffering)).thenReturn(true); + when(volumeApiService.doesStoragePoolSupportDiskOffering(selectedPool, dataDiskOffering)).thenReturn(true); + + unmanagedVMsManager.validateSelectedConversionStoragePoolForVddk(true, poolId, + serviceOffering, Map.of("1000-2", 32L)); + } + + private ClusterVO getClusterForTests() { + ClusterVO cluster = mock(ClusterVO.class); + when(cluster.getId()).thenReturn(1L); + when(cluster.getDataCenterId()).thenReturn(1L); + return cluster; + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectInstanceConversionTemporaryLocationInvalidStorage() { + ClusterVO cluster = getClusterForTests(); + + long poolId = 1L; + when(primaryDataStoreDao.findById(poolId)).thenReturn(null); + unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, poolId, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectInstanceConversionTemporaryLocationPoolInvalidScope() { + ClusterVO cluster = getClusterForTests(); + long poolId = 1L; + StoragePoolVO pool = mock(StoragePoolVO.class); + when(pool.getScope()).thenReturn(ScopeType.CLUSTER); + when(pool.getClusterId()).thenReturn(100L); + when(primaryDataStoreDao.findById(poolId)).thenReturn(pool); + unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, poolId, false); + } + + + @Test(expected = CloudRuntimeException.class) + public void testSelectInstanceConversionTemporaryLocationPoolConvertHostDifferentCluster() { + ClusterVO cluster = getClusterForTests(); + long poolId = 1L; + StoragePoolVO pool = mock(StoragePoolVO.class); + when(pool.getScope()).thenReturn(ScopeType.CLUSTER); + when(pool.getClusterId()).thenReturn(1L); + HostVO host = mock(HostVO.class); + when(primaryDataStoreDao.findById(poolId)).thenReturn(pool); + when(host.getClusterId()).thenReturn(2L); + unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, host, null, poolId, false); + } + + + @Test(expected = CloudRuntimeException.class) + public void testSelectInstanceConversionTemporaryLocationLocalStoragePoolInvalid() { + ClusterVO cluster = getClusterForTests(); + long poolId = 1L; + StoragePoolVO pool = mock(StoragePoolVO.class); + when(pool.getScope()).thenReturn(ScopeType.HOST); + when(primaryDataStoreDao.findById(poolId)).thenReturn(pool); + unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, poolId, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectInstanceConversionTemporaryLocationStoragePoolInvalidType() { + ClusterVO cluster = getClusterForTests(); + long poolId = 1L; + StoragePoolVO pool = mock(StoragePoolVO.class); + when(pool.getScope()).thenReturn(ScopeType.CLUSTER); + when(pool.getClusterId()).thenReturn(1L); + when(primaryDataStoreDao.findById(poolId)).thenReturn(pool); + when(pool.getPoolType()).thenReturn(Storage.StoragePoolType.RBD); + unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, poolId, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectInstanceConversionTemporaryLocationNoPoolAvailable() { + ClusterVO cluster = getClusterForTests(); + when(imageStoreDao.findOneByZoneAndProtocol(anyLong(), anyString())).thenReturn(null); + unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, null, false); + } + + @Test + public void testSelectKVMHostForImportingInClusterWithImportInstanceIdSuccess() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Enabled); + when(host.getStatus()).thenReturn(Status.Up); + when(host.getType()).thenReturn(Host.Type.Routing); + when(host.getClusterId()).thenReturn(1L); + + when(hostDao.findById(hostId)).thenReturn(host); + + HostVO returnedHost = unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); + Assert.assertEquals(host, returnedHost); + } + + @Test + public void testSelectKVMHostForImportingInClusterWithNullImportInstanceIdSuccess() { + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(hostDao.listByClusterAndHypervisorType(cluster.getId(), cluster.getHypervisorType())).thenReturn(List.of(host)); + + HostVO returnedHost = unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, null); + Assert.assertEquals(host, returnedHost); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForImportingInClusterFailure() { + ClusterVO cluster = getClusterForTests(); + when(hostDao.listByClusterAndHypervisorType(cluster.getId(), cluster.getHypervisorType())).thenReturn(List.of()); + + unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, null); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidCluster() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Enabled); + when(host.getStatus()).thenReturn(Status.Up); + when(host.getType()).thenReturn(Host.Type.Routing); + when(host.getClusterId()).thenReturn(2L); + + when(hostDao.findById(hostId)).thenReturn(host); + + unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidType() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Enabled); + when(host.getStatus()).thenReturn(Status.Up); + when(host.getType()).thenReturn(Host.Type.Storage); + + when(hostDao.findById(hostId)).thenReturn(host); + + unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidStatus() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Enabled); + when(host.getStatus()).thenReturn(Status.Alert); + + when(hostDao.findById(hostId)).thenReturn(host); + + unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidResourceState() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Disabled); + + when(hostDao.findById(hostId)).thenReturn(host); + + unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidHostId() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + + when(hostDao.findById(hostId)).thenReturn(null); + + unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); + } + + @Test + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdEnabledHost() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Enabled); + when(host.getStatus()).thenReturn(Status.Up); + when(host.getType()).thenReturn(Host.Type.Routing); + when(host.getDataCenterId()).thenReturn(1L); + + when(hostDao.findById(hostId)).thenReturn(host); + + HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); + Assert.assertEquals(host, returnedHost); + } + + @Test + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdDisabledHost() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Disabled); + when(host.getStatus()).thenReturn(Status.Up); + when(host.getType()).thenReturn(Host.Type.Routing); + when(host.getDataCenterId()).thenReturn(1L); + + when(hostDao.findById(hostId)).thenReturn(host); + + HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); + Assert.assertEquals(host, returnedHost); + } + + @Test + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdSuccessCompatible() { + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + + when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(), + cluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION)).thenReturn(List.of(host)); + + HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, null, false); + Assert.assertEquals(host, returnedHost); + } + + @Test + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdSuccessNonCompatible() { + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + + when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(), + cluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION)).thenReturn(List.of()); + + when(hostDao.listByClusterAndHypervisorType(cluster.getId(), cluster.getHypervisorType())).thenReturn(List.of(host)); + + HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, null, false); + Assert.assertEquals(host, returnedHost); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdFailure() { + ClusterVO cluster = getClusterForTests(); + + when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(), + cluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION)).thenReturn(List.of()); + + when(hostDao.listByClusterAndHypervisorType(cluster.getId(), cluster.getHypervisorType())).thenReturn(List.of()); + + unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, null, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidZone() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Enabled); + when(host.getStatus()).thenReturn(Status.Up); + when(host.getType()).thenReturn(Host.Type.Routing); + when(host.getDataCenterId()).thenReturn(2L); + + when(hostDao.findById(hostId)).thenReturn(host); + + unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidType() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Enabled); + when(host.getStatus()).thenReturn(Status.Up); + when(host.getType()).thenReturn(Host.Type.SecondaryStorage); + + when(hostDao.findById(hostId)).thenReturn(host); + + unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidStatus() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Enabled); + when(host.getStatus()).thenReturn(Status.Down); + + when(hostDao.findById(hostId)).thenReturn(host); + + unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidResourceState() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Maintenance); + + when(hostDao.findById(hostId)).thenReturn(host); + + unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidHostId() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + + when(hostDao.findById(hostId)).thenReturn(null); + + unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); + } + + @Test + public void testSelectKVMHostForConversionInClusterVddkAutoSelectsHostWithVddkSupport() { + ClusterVO cluster = getClusterForTests(); + HostVO hostWithVddk = Mockito.mock(HostVO.class); + HostVO hostWithoutVddk = Mockito.mock(HostVO.class); + when(hostWithVddk.getDetail(Host.HOST_VDDK_SUPPORT)).thenReturn("true"); + when(hostWithoutVddk.getDetail(Host.HOST_VDDK_SUPPORT)).thenReturn(null); + + when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(), + cluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION)) + .thenReturn(List.of(hostWithoutVddk, hostWithVddk)); + + HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, null, true); + Assert.assertEquals(hostWithVddk, returnedHost); + } + + @Test + public void testCheckConversionStoragePoolSecondaryStorageStaging() { + unmanagedVMsManager.checkConversionStoragePool(null, false); + Mockito.verifyNoInteractions(primaryDataStoreDao); + } + + @Test(expected = CloudRuntimeException.class) + public void testCheckConversionStoragePoolTemporarySecondaryStorageForceConvertToPool() { + unmanagedVMsManager.checkConversionStoragePool(null, true); + } + + @Test + public void testCheckConversionStoragePoolPrimaryStagingPool() { + StoragePoolVO destPool = mock(StoragePoolVO.class); + long destPoolId = 1L; + Mockito.when(primaryDataStoreDao.findById(destPoolId)).thenReturn(destPool); + unmanagedVMsManager.checkConversionStoragePool(destPoolId, false); + } + + @Test + public void testCheckConversionStoragePoolPrimaryStagingPoolTypeAllowedForce() { + StoragePoolVO destPool = mock(StoragePoolVO.class); + Mockito.when(destPool.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem); + long destPoolId = 1L; + Mockito.when(primaryDataStoreDao.findById(destPoolId)).thenReturn(destPool); + unmanagedVMsManager.checkConversionStoragePool(destPoolId, true); + } + + @Test(expected = CloudRuntimeException.class) + public void testCheckConversionStoragePoolPrimaryStagingPoolTypeNotAllowedForce() { + StoragePoolVO destPool = mock(StoragePoolVO.class); + Mockito.when(destPool.getPoolType()).thenReturn(Storage.StoragePoolType.RBD); + long destPoolId = 1L; + Mockito.when(primaryDataStoreDao.findById(destPoolId)).thenReturn(destPool); + unmanagedVMsManager.checkConversionStoragePool(destPoolId, true); + } + + @Test + public void testCheckExtraParamsAllowedEmptyParams() { + unmanagedVMsManager.checkExtraParamsAllowed(null); + Mockito.verifyNoInteractions(configKeyMockParamsAllowed); + } + + @Test(expected = ServerApiException.class) + public void testCheckExtraParamsAllowedDisabledByAdministrator() { + unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowed = configKeyMockParamsAllowed; + Mockito.when(configKeyMockParamsAllowed.value()).thenReturn(false); + unmanagedVMsManager.checkExtraParamsAllowed("--mac 00:0c:29:e6:3d:9d:ip:192.168.0.89,192.168.0.1,24,192.168.0.254 -x"); + } + + @Test(expected = ServerApiException.class) + public void testCheckExtraParamsAllowedEnabledButEmptyAllowedList() { + unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowed = configKeyMockParamsAllowed; + unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowedList = configKeyMockParamsAllowedList; + Mockito.when(configKeyMockParamsAllowed.value()).thenReturn(true); + Mockito.when(configKeyMockParamsAllowedList.value()).thenReturn(null); + unmanagedVMsManager.checkExtraParamsAllowed("--mac 00:0c:29:e6:3d:9d:ip:192.168.0.89,192.168.0.1,24,192.168.0.254 -x"); + } + + @Test + public void testCheckExtraParamsAllowedEnabledAndAllowedList() { + unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowed = configKeyMockParamsAllowed; + unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowedList = configKeyMockParamsAllowedList; + Mockito.when(configKeyMockParamsAllowed.value()).thenReturn(true); + Mockito.when(configKeyMockParamsAllowedList.value()).thenReturn("mac,network,x"); + unmanagedVMsManager.checkExtraParamsAllowed("--mac 00:0c:29:e6:3d:9d:ip:192.168.0.89,192.168.0.1,24,192.168.0.254 -x"); + } + + @Test(expected = ServerApiException.class) + public void testCheckExtraParamsAllowedEnabledParamNotInTheAllowedList() { + unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowed = configKeyMockParamsAllowed; + unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowedList = configKeyMockParamsAllowedList; + Mockito.when(configKeyMockParamsAllowed.value()).thenReturn(true); + Mockito.when(configKeyMockParamsAllowedList.value()).thenReturn("network,x"); + unmanagedVMsManager.checkExtraParamsAllowed("--mac 00:0c:29:e6:3d:9d:ip:192.168.0.89,192.168.0.1,24,192.168.0.254 -x"); + } + + @Test + public void testAddServiceOfferingDetailsToParamsFixedOffering() { + Map params = new HashMap<>(); + ServiceOfferingVO serviceOfferingVO = mock(ServiceOfferingVO.class); + Mockito.when(serviceOfferingVO.getCpu()).thenReturn(2); + Mockito.when(serviceOfferingVO.getRamSize()).thenReturn(2048); + unmanagedVMsManager.addServiceOfferingDetailsToParams(params, serviceOfferingVO); + Assert.assertEquals("2", params.get(VmDetailConstants.CPU_NUMBER)); + Assert.assertEquals("2048", params.get(VmDetailConstants.MEMORY)); + } + + @Test + public void testAddServiceOfferingDetailsToParamsCustomConstrainedOffering() { + Map params = new HashMap<>(); + ServiceOfferingVO serviceOfferingVO = mock(ServiceOfferingVO.class); + Map details = new HashMap<>(); + details.put(ApiConstants.MIN_CPU_NUMBER, "1"); + details.put(ApiConstants.MIN_MEMORY, "1024"); + Mockito.when(serviceOfferingVO.getDetails()).thenReturn(details); + Mockito.when(serviceOfferingVO.getCpu()).thenReturn(null); + Mockito.when(serviceOfferingVO.getSpeed()).thenReturn(1500); + Mockito.when(serviceOfferingVO.getRamSize()).thenReturn(null); + unmanagedVMsManager.addServiceOfferingDetailsToParams(params, serviceOfferingVO); + Assert.assertEquals("1", params.get(VmDetailConstants.CPU_NUMBER)); + Assert.assertEquals("1500", params.get(VmDetailConstants.CPU_SPEED)); + Assert.assertEquals("1024", params.get(VmDetailConstants.MEMORY)); + } + + @Test + public void testAddServiceOfferingDetailsToParamsCustomUnconstrainedOffering() { + Map params = new HashMap<>(); + ServiceOfferingVO serviceOfferingVO = mock(ServiceOfferingVO.class); + Mockito.when(serviceOfferingVO.getCpu()).thenReturn(null); + Mockito.when(serviceOfferingVO.getSpeed()).thenReturn(null); + Mockito.when(serviceOfferingVO.getRamSize()).thenReturn(null); + unmanagedVMsManager.addServiceOfferingDetailsToParams(params, serviceOfferingVO); + Assert.assertFalse(params.containsKey(VmDetailConstants.CPU_NUMBER)); + Assert.assertFalse(params.containsKey(VmDetailConstants.CPU_SPEED)); + Assert.assertFalse(params.containsKey(VmDetailConstants.MEMORY)); + } + + @Test + public void checkVmResourceLimitsForUnmanagedInstanceImportTestUsesInformationFromHypervisorWhenOfferingIsDynamic() throws Exception { + when(serviceOfferingMock.isDynamic()).thenReturn(true); + List reservations = new ArrayList<>(); + + try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.checkVmResourceLimitsForUnmanagedInstanceImport(accountMock, unmanagedInstanceMock, serviceOfferingMock, templateMock, reservations); + + Assert.assertEquals(3, mockedConstruction.constructed().size()); + Assert.assertEquals(3, reservations.size()); + verify(unmanagedInstanceMock).getCpuCores(); + verify(unmanagedInstanceMock).getMemory(); + } + } + + @Test + public void checkVmResourceLimitsForUnmanagedInstanceImportTestUsesInformationFromHypervisorWhenVmIsPoweredOn() throws Exception { + when(unmanagedInstanceMock.getPowerState()).thenReturn(UnmanagedInstanceTO.PowerState.PowerOn); + when(serviceOfferingMock.isDynamic()).thenReturn(false); + List reservations = new ArrayList<>(); + + try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.checkVmResourceLimitsForUnmanagedInstanceImport(accountMock, unmanagedInstanceMock, serviceOfferingMock, templateMock, reservations); + + Assert.assertEquals(3, mockedConstruction.constructed().size()); + Assert.assertEquals(3, reservations.size()); + verify(unmanagedInstanceMock).getCpuCores(); + verify(unmanagedInstanceMock).getMemory(); + } + } + + @Test + public void checkVmResourceLimitsForUnmanagedInstanceImportTestUsesInformationFromOfferingWhenOfferingIsNotDynamicAndVmIsPoweredOff() throws Exception { + when(unmanagedInstanceMock.getPowerState()).thenReturn(UnmanagedInstanceTO.PowerState.PowerOff); + when(serviceOfferingMock.isDynamic()).thenReturn(false); + List reservations = new ArrayList<>(); + + try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.checkVmResourceLimitsForUnmanagedInstanceImport(accountMock, unmanagedInstanceMock, serviceOfferingMock, templateMock, reservations); + + Assert.assertEquals(3, mockedConstruction.constructed().size()); + Assert.assertEquals(3, reservations.size()); + verify(serviceOfferingMock).getCpu(); + verify(serviceOfferingMock).getRamSize(); + verify(unmanagedInstanceMock, Mockito.never()).getCpuCores(); + verify(unmanagedInstanceMock, Mockito.never()).getMemory(); + } + } + + @Test + public void checkVmResourceLimitsForExternalKvmVmImportTestUsesInformationFromOfferingWhenOfferingIsNotDynamic() throws ResourceAllocationException { + when(serviceOfferingMock.isDynamic()).thenReturn(false); + Map details = new HashMap<>(); + List reservations = new ArrayList<>(); + + try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.checkVmResourceLimitsForExternalKvmVmImport(accountMock, serviceOfferingMock, templateMock, details, reservations); + + Assert.assertEquals(3, mockedConstruction.constructed().size()); + Assert.assertEquals(3, reservations.size()); + verify(serviceOfferingMock).getCpu(); + verify(serviceOfferingMock).getRamSize(); + verify(unmanagedVMsManager, Mockito.never()).getDetailAsInteger(VmDetailConstants.CPU_NUMBER, details); + verify(unmanagedVMsManager, Mockito.never()).getDetailAsInteger(VmDetailConstants.MEMORY, details); + } + } + + @Test + public void checkVmResourceLimitsForExternalKvmVmImportTestUsesInformationFromDetailsWhenOfferingIsDynamic() throws ResourceAllocationException { + when(serviceOfferingMock.isDynamic()).thenReturn(true); + Map details = new HashMap<>(); + details.put(VmDetailConstants.CPU_NUMBER, "8"); + details.put(VmDetailConstants.MEMORY, "4096"); + List reservations = new ArrayList<>(); + + try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.checkVmResourceLimitsForExternalKvmVmImport(accountMock, serviceOfferingMock, templateMock, details, reservations); + + Assert.assertEquals(3, mockedConstruction.constructed().size()); + Assert.assertEquals(3, reservations.size()); + verify(unmanagedVMsManager).getDetailAsInteger(VmDetailConstants.CPU_NUMBER, details); + verify(unmanagedVMsManager).getDetailAsInteger(VmDetailConstants.MEMORY, details); + } + } + + @Test(expected = InvalidParameterValueException.class) + public void getDetailAsIntegerTestThrowsInvalidParameterValueExceptionWhenDetailIsNull() { + Map details = new HashMap<>(); + unmanagedVMsManager.getDetailAsInteger("non-existent", details); + } + + @Test(expected = InvalidParameterValueException.class) + public void getDetailAsIntegerTestThrowsInvalidParameterValueExceptionWhenValueIsInvalid() { + Map details = new HashMap<>(); + details.put("key", "not-a-number"); + unmanagedVMsManager.getDetailAsInteger("key", details); + } + + // ------------------------------------------------------------------------- + // mergeNicMacAddresses tests + // ------------------------------------------------------------------------- @Test - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdDisabledHost() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Disabled); - when(host.getStatus()).thenReturn(Status.Up); - when(host.getType()).thenReturn(Host.Type.Routing); - when(host.getDataCenterId()).thenReturn(1L); + public void mergeNicMacAddressesEmptyMacMapReturnsOriginal() { + Map ipMap = new HashMap<>(); + ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); - when(hostDao.findById(hostId)).thenReturn(host); + Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, new HashMap<>()); - HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); - Assert.assertEquals(host, returnedHost); + Assert.assertSame(ipMap, result); + Assert.assertNull(result.get("nic1").getMacAddress()); } @Test - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdSuccessCompatible() { - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); + public void mergeNicMacAddressesNullMacMapReturnsOriginal() { + Map ipMap = new HashMap<>(); + ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); - when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(), - cluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION)).thenReturn(List.of(host)); + Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, null); - HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, null, false); - Assert.assertEquals(host, returnedHost); + Assert.assertSame(ipMap, result); } @Test - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdSuccessNonCompatible() { - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - - when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(), - cluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION)).thenReturn(List.of()); - - when(hostDao.listByClusterAndHypervisorType(cluster.getId(), cluster.getHypervisorType())).thenReturn(List.of(host)); - - HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, null, false); - Assert.assertEquals(host, returnedHost); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdFailure() { - ClusterVO cluster = getClusterForTests(); - - when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(), - cluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION)).thenReturn(List.of()); - - when(hostDao.listByClusterAndHypervisorType(cluster.getId(), cluster.getHypervisorType())).thenReturn(List.of()); - - unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, null, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidZone() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Enabled); - when(host.getStatus()).thenReturn(Status.Up); - when(host.getType()).thenReturn(Host.Type.Routing); - when(host.getDataCenterId()).thenReturn(2L); - - when(hostDao.findById(hostId)).thenReturn(host); - - unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidType() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Enabled); - when(host.getStatus()).thenReturn(Status.Up); - when(host.getType()).thenReturn(Host.Type.SecondaryStorage); - - when(hostDao.findById(hostId)).thenReturn(host); - - unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidStatus() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Enabled); - when(host.getStatus()).thenReturn(Status.Down); - - when(hostDao.findById(hostId)).thenReturn(host); - - unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidResourceState() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Maintenance); - - when(hostDao.findById(hostId)).thenReturn(host); - - unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidHostId() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - - when(hostDao.findById(hostId)).thenReturn(null); - - unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); - } - - @Test - public void testSelectKVMHostForConversionInClusterVddkAutoSelectsHostWithVddkSupport() { - ClusterVO cluster = getClusterForTests(); - HostVO hostWithVddk = Mockito.mock(HostVO.class); - HostVO hostWithoutVddk = Mockito.mock(HostVO.class); - when(hostWithVddk.getDetail(Host.HOST_VDDK_SUPPORT)).thenReturn("true"); - when(hostWithoutVddk.getDetail(Host.HOST_VDDK_SUPPORT)).thenReturn(null); - - when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(), - cluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION)) - .thenReturn(List.of(hostWithoutVddk, hostWithVddk)); - - HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, null, true); - Assert.assertEquals(hostWithVddk, returnedHost); - } + public void mergeNicMacAddressesMacMergedIntoExistingEntry() { + Map ipMap = new HashMap<>(); + ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); - @Test - public void testCheckConversionStoragePoolSecondaryStorageStaging() { - unmanagedVMsManager.checkConversionStoragePool(null, false); - Mockito.verifyNoInteractions(primaryDataStoreDao); - } + Map macMap = new HashMap<>(); + macMap.put("nic1", "aa:bb:cc:dd:ee:ff"); - @Test(expected = CloudRuntimeException.class) - public void testCheckConversionStoragePoolTemporarySecondaryStorageForceConvertToPool() { - unmanagedVMsManager.checkConversionStoragePool(null, true); - } + Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, macMap); - @Test - public void testCheckConversionStoragePoolPrimaryStagingPool() { - StoragePoolVO destPool = mock(StoragePoolVO.class); - long destPoolId = 1L; - Mockito.when(primaryDataStoreDao.findById(destPoolId)).thenReturn(destPool); - unmanagedVMsManager.checkConversionStoragePool(destPoolId, false); + Assert.assertEquals("aa:bb:cc:dd:ee:ff", result.get("nic1").getMacAddress()); + Assert.assertEquals("10.0.0.1", result.get("nic1").getIp4Address()); } @Test - public void testCheckConversionStoragePoolPrimaryStagingPoolTypeAllowedForce() { - StoragePoolVO destPool = mock(StoragePoolVO.class); - Mockito.when(destPool.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem); - long destPoolId = 1L; - Mockito.when(primaryDataStoreDao.findById(destPoolId)).thenReturn(destPool); - unmanagedVMsManager.checkConversionStoragePool(destPoolId, true); - } - - @Test(expected = CloudRuntimeException.class) - public void testCheckConversionStoragePoolPrimaryStagingPoolTypeNotAllowedForce() { - StoragePoolVO destPool = mock(StoragePoolVO.class); - Mockito.when(destPool.getPoolType()).thenReturn(Storage.StoragePoolType.RBD); - long destPoolId = 1L; - Mockito.when(primaryDataStoreDao.findById(destPoolId)).thenReturn(destPool); - unmanagedVMsManager.checkConversionStoragePool(destPoolId, true); - } + public void mergeNicMacAddressesNewEntryCreatedWhenNicNotInIpMap() { + Map ipMap = new HashMap<>(); - @Test - public void testCheckExtraParamsAllowedEmptyParams() { - unmanagedVMsManager.checkExtraParamsAllowed(null); - Mockito.verifyNoInteractions(configKeyMockParamsAllowed); - } + Map macMap = new HashMap<>(); + macMap.put("nic1", "aa:bb:cc:dd:ee:ff"); - @Test(expected = ServerApiException.class) - public void testCheckExtraParamsAllowedDisabledByAdministrator() { - unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowed = configKeyMockParamsAllowed; - Mockito.when(configKeyMockParamsAllowed.value()).thenReturn(false); - unmanagedVMsManager.checkExtraParamsAllowed("--mac 00:0c:29:e6:3d:9d:ip:192.168.0.89,192.168.0.1,24,192.168.0.254 -x"); - } + Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, macMap); - @Test(expected = ServerApiException.class) - public void testCheckExtraParamsAllowedEnabledButEmptyAllowedList() { - unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowed = configKeyMockParamsAllowed; - unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowedList = configKeyMockParamsAllowedList; - Mockito.when(configKeyMockParamsAllowed.value()).thenReturn(true); - Mockito.when(configKeyMockParamsAllowedList.value()).thenReturn(null); - unmanagedVMsManager.checkExtraParamsAllowed("--mac 00:0c:29:e6:3d:9d:ip:192.168.0.89,192.168.0.1,24,192.168.0.254 -x"); + Assert.assertNotNull(result.get("nic1")); + Assert.assertEquals("aa:bb:cc:dd:ee:ff", result.get("nic1").getMacAddress()); + Assert.assertNull(result.get("nic1").getIp4Address()); } @Test - public void testCheckExtraParamsAllowedEnabledAndAllowedList() { - unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowed = configKeyMockParamsAllowed; - unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowedList = configKeyMockParamsAllowedList; - Mockito.when(configKeyMockParamsAllowed.value()).thenReturn(true); - Mockito.when(configKeyMockParamsAllowedList.value()).thenReturn("mac,network,x"); - unmanagedVMsManager.checkExtraParamsAllowed("--mac 00:0c:29:e6:3d:9d:ip:192.168.0.89,192.168.0.1,24,192.168.0.254 -x"); - } + public void mergeNicMacAddressesMultipleNicsMergedCorrectly() { + Map ipMap = new HashMap<>(); + ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); + ipMap.put("nic2", new Network.IpAddresses("10.0.0.2", null)); - @Test(expected = ServerApiException.class) - public void testCheckExtraParamsAllowedEnabledParamNotInTheAllowedList() { - unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowed = configKeyMockParamsAllowed; - unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowedList = configKeyMockParamsAllowedList; - Mockito.when(configKeyMockParamsAllowed.value()).thenReturn(true); - Mockito.when(configKeyMockParamsAllowedList.value()).thenReturn("network,x"); - unmanagedVMsManager.checkExtraParamsAllowed("--mac 00:0c:29:e6:3d:9d:ip:192.168.0.89,192.168.0.1,24,192.168.0.254 -x"); - } + Map macMap = new HashMap<>(); + macMap.put("nic1", "aa:bb:cc:dd:ee:01"); + macMap.put("nic2", "aa:bb:cc:dd:ee:02"); - @Test - public void testAddServiceOfferingDetailsToParamsFixedOffering() { - Map params = new HashMap<>(); - ServiceOfferingVO serviceOfferingVO = mock(ServiceOfferingVO.class); - Mockito.when(serviceOfferingVO.getCpu()).thenReturn(2); - Mockito.when(serviceOfferingVO.getRamSize()).thenReturn(2048); - unmanagedVMsManager.addServiceOfferingDetailsToParams(params, serviceOfferingVO); - Assert.assertEquals("2", params.get(VmDetailConstants.CPU_NUMBER)); - Assert.assertEquals("2048", params.get(VmDetailConstants.MEMORY)); - } + Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, macMap); - @Test - public void testAddServiceOfferingDetailsToParamsCustomConstrainedOffering() { - Map params = new HashMap<>(); - ServiceOfferingVO serviceOfferingVO = mock(ServiceOfferingVO.class); - Map details = new HashMap<>(); - details.put(ApiConstants.MIN_CPU_NUMBER, "1"); - details.put(ApiConstants.MIN_MEMORY, "1024"); - Mockito.when(serviceOfferingVO.getDetails()).thenReturn(details); - Mockito.when(serviceOfferingVO.getCpu()).thenReturn(null); - Mockito.when(serviceOfferingVO.getSpeed()).thenReturn(1500); - Mockito.when(serviceOfferingVO.getRamSize()).thenReturn(null); - unmanagedVMsManager.addServiceOfferingDetailsToParams(params, serviceOfferingVO); - Assert.assertEquals("1", params.get(VmDetailConstants.CPU_NUMBER)); - Assert.assertEquals("1500", params.get(VmDetailConstants.CPU_SPEED)); - Assert.assertEquals("1024", params.get(VmDetailConstants.MEMORY)); + Assert.assertEquals("aa:bb:cc:dd:ee:01", result.get("nic1").getMacAddress()); + Assert.assertEquals("10.0.0.1", result.get("nic1").getIp4Address()); + Assert.assertEquals("aa:bb:cc:dd:ee:02", result.get("nic2").getMacAddress()); + Assert.assertEquals("10.0.0.2", result.get("nic2").getIp4Address()); } - @Test - public void testAddServiceOfferingDetailsToParamsCustomUnconstrainedOffering() { - Map params = new HashMap<>(); - ServiceOfferingVO serviceOfferingVO = mock(ServiceOfferingVO.class); - Mockito.when(serviceOfferingVO.getCpu()).thenReturn(null); - Mockito.when(serviceOfferingVO.getSpeed()).thenReturn(null); - Mockito.when(serviceOfferingVO.getRamSize()).thenReturn(null); - unmanagedVMsManager.addServiceOfferingDetailsToParams(params, serviceOfferingVO); - Assert.assertFalse(params.containsKey(VmDetailConstants.CPU_NUMBER)); - Assert.assertFalse(params.containsKey(VmDetailConstants.CPU_SPEED)); - Assert.assertFalse(params.containsKey(VmDetailConstants.MEMORY)); - } + // ------------------------------------------------------------------------- + // importNic: caller MAC vs hypervisor MAC selection + // ------------------------------------------------------------------------- @Test - public void checkVmResourceLimitsForUnmanagedInstanceImportTestUsesInformationFromHypervisorWhenOfferingIsDynamic() throws Exception { - when(serviceOfferingMock.isDynamic()).thenReturn(true); - List reservations = new ArrayList<>(); + public void importNicUsesCallerSuppliedMacWhenPresent() throws Exception { + UnmanagedInstanceTO.Nic nic = new UnmanagedInstanceTO.Nic(); + nic.setNicId("nic1"); + nic.setMacAddress("11:22:33:44:55:66"); - try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.checkVmResourceLimitsForUnmanagedInstanceImport(accountMock, unmanagedInstanceMock, serviceOfferingMock, templateMock, reservations); + Network.IpAddresses ipAddresses = new Network.IpAddresses(null, null, "aa:bb:cc:dd:ee:ff"); - Assert.assertEquals(3, mockedConstruction.constructed().size()); - Assert.assertEquals(3, reservations.size()); - verify(unmanagedInstanceMock).getCpuCores(); - verify(unmanagedInstanceMock).getMemory(); - } - } + NetworkVO networkVO = Mockito.mock(NetworkVO.class); + when(networkVO.getDataCenterId()).thenReturn(1L); + DataCenterVO dcVO = Mockito.mock(DataCenterVO.class); + when(dataCenterDao.findById(1L)).thenReturn(dcVO); - @Test - public void checkVmResourceLimitsForUnmanagedInstanceImportTestUsesInformationFromHypervisorWhenVmIsPoweredOn() throws Exception { - when(unmanagedInstanceMock.getPowerState()).thenReturn(UnmanagedInstanceTO.PowerState.PowerOn); - when(serviceOfferingMock.isDynamic()).thenReturn(false); - List reservations = new ArrayList<>(); + NicProfile profile = Mockito.mock(NicProfile.class); + Pair pair = new Pair<>(profile, 0); + when(networkOrchestrationService.importNic( + Mockito.eq("aa:bb:cc:dd:ee:ff"), + Mockito.anyInt(), Mockito.eq(networkVO), Mockito.anyBoolean(), + Mockito.any(), Mockito.eq(ipAddresses), Mockito.eq(dcVO), Mockito.anyBoolean())) + .thenReturn(pair); - try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.checkVmResourceLimitsForUnmanagedInstanceImport(accountMock, unmanagedInstanceMock, serviceOfferingMock, templateMock, reservations); + UserVmVO vm = Mockito.mock(UserVmVO.class); + NicProfile result = unmanagedVMsManager.importNic(nic, vm, networkVO, ipAddresses, 0, true, false); - Assert.assertEquals(3, mockedConstruction.constructed().size()); - Assert.assertEquals(3, reservations.size()); - verify(unmanagedInstanceMock).getCpuCores(); - verify(unmanagedInstanceMock).getMemory(); - } + Assert.assertNotNull(result); + Mockito.verify(networkOrchestrationService).importNic( + Mockito.eq("aa:bb:cc:dd:ee:ff"), + Mockito.anyInt(), Mockito.any(), Mockito.anyBoolean(), + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyBoolean()); } @Test - public void checkVmResourceLimitsForUnmanagedInstanceImportTestUsesInformationFromOfferingWhenOfferingIsNotDynamicAndVmIsPoweredOff() throws Exception { - when(unmanagedInstanceMock.getPowerState()).thenReturn(UnmanagedInstanceTO.PowerState.PowerOff); - when(serviceOfferingMock.isDynamic()).thenReturn(false); - List reservations = new ArrayList<>(); + public void importNicFallsBackToHypervisorMacWhenIpAddressesHasNoMac() throws Exception { + UnmanagedInstanceTO.Nic nic = new UnmanagedInstanceTO.Nic(); + nic.setNicId("nic1"); + nic.setMacAddress("11:22:33:44:55:66"); - try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.checkVmResourceLimitsForUnmanagedInstanceImport(accountMock, unmanagedInstanceMock, serviceOfferingMock, templateMock, reservations); + Network.IpAddresses ipAddresses = new Network.IpAddresses("10.0.0.1", null); // no MAC - Assert.assertEquals(3, mockedConstruction.constructed().size()); - Assert.assertEquals(3, reservations.size()); - verify(serviceOfferingMock).getCpu(); - verify(serviceOfferingMock).getRamSize(); - verify(unmanagedInstanceMock, Mockito.never()).getCpuCores(); - verify(unmanagedInstanceMock, Mockito.never()).getMemory(); - } - } + NetworkVO networkVO = Mockito.mock(NetworkVO.class); + when(networkVO.getDataCenterId()).thenReturn(1L); + DataCenterVO dcVO = Mockito.mock(DataCenterVO.class); + when(dataCenterDao.findById(1L)).thenReturn(dcVO); - @Test - public void checkVmResourceLimitsForExternalKvmVmImportTestUsesInformationFromOfferingWhenOfferingIsNotDynamic() throws ResourceAllocationException { - when(serviceOfferingMock.isDynamic()).thenReturn(false); - Map details = new HashMap<>(); - List reservations = new ArrayList<>(); + NicProfile profile = Mockito.mock(NicProfile.class); + Pair pair = new Pair<>(profile, 0); + when(networkOrchestrationService.importNic( + Mockito.eq("11:22:33:44:55:66"), + Mockito.anyInt(), Mockito.eq(networkVO), Mockito.anyBoolean(), + Mockito.any(), Mockito.eq(ipAddresses), Mockito.eq(dcVO), Mockito.anyBoolean())) + .thenReturn(pair); - try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.checkVmResourceLimitsForExternalKvmVmImport(accountMock, serviceOfferingMock, templateMock, details, reservations); + UserVmVO vm = Mockito.mock(UserVmVO.class); + NicProfile result = unmanagedVMsManager.importNic(nic, vm, networkVO, ipAddresses, 0, true, false); - Assert.assertEquals(3, mockedConstruction.constructed().size()); - Assert.assertEquals(3, reservations.size()); - verify(serviceOfferingMock).getCpu(); - verify(serviceOfferingMock).getRamSize(); - verify(unmanagedVMsManager, Mockito.never()).getDetailAsInteger(VmDetailConstants.CPU_NUMBER, details); - verify(unmanagedVMsManager, Mockito.never()).getDetailAsInteger(VmDetailConstants.MEMORY, details); - } + Assert.assertNotNull(result); + Mockito.verify(networkOrchestrationService).importNic( + Mockito.eq("11:22:33:44:55:66"), + Mockito.anyInt(), Mockito.any(), Mockito.anyBoolean(), + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyBoolean()); } @Test - public void checkVmResourceLimitsForExternalKvmVmImportTestUsesInformationFromDetailsWhenOfferingIsDynamic() throws ResourceAllocationException { - when(serviceOfferingMock.isDynamic()).thenReturn(true); - Map details = new HashMap<>(); - details.put(VmDetailConstants.CPU_NUMBER, "8"); - details.put(VmDetailConstants.MEMORY, "4096"); - List reservations = new ArrayList<>(); - - try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.checkVmResourceLimitsForExternalKvmVmImport(accountMock, serviceOfferingMock, templateMock, details, reservations); - - Assert.assertEquals(3, mockedConstruction.constructed().size()); - Assert.assertEquals(3, reservations.size()); - verify(unmanagedVMsManager).getDetailAsInteger(VmDetailConstants.CPU_NUMBER, details); - verify(unmanagedVMsManager).getDetailAsInteger(VmDetailConstants.MEMORY, details); - } - } + public void importNicFallsBackToHypervisorMacWhenIpAddressesIsNull() throws Exception { + UnmanagedInstanceTO.Nic nic = new UnmanagedInstanceTO.Nic(); + nic.setNicId("nic1"); + nic.setMacAddress("11:22:33:44:55:66"); - @Test(expected = InvalidParameterValueException.class) - public void getDetailAsIntegerTestThrowsInvalidParameterValueExceptionWhenDetailIsNull() { - Map details = new HashMap<>(); - unmanagedVMsManager.getDetailAsInteger("non-existent", details); - } + NetworkVO networkVO = Mockito.mock(NetworkVO.class); + when(networkVO.getDataCenterId()).thenReturn(1L); + DataCenterVO dcVO = Mockito.mock(DataCenterVO.class); + when(dataCenterDao.findById(1L)).thenReturn(dcVO); - @Test(expected = InvalidParameterValueException.class) - public void getDetailAsIntegerTestThrowsInvalidParameterValueExceptionWhenValueIsInvalid() { - Map details = new HashMap<>(); - details.put("key", "not-a-number"); - unmanagedVMsManager.getDetailAsInteger("key", details); + NicProfile profile = Mockito.mock(NicProfile.class); + Pair pair = new Pair<>(profile, 0); + when(networkOrchestrationService.importNic( + Mockito.eq("11:22:33:44:55:66"), + Mockito.anyInt(), Mockito.eq(networkVO), Mockito.anyBoolean(), + Mockito.any(), Mockito.isNull(), Mockito.eq(dcVO), Mockito.anyBoolean())) + .thenReturn(pair); + + UserVmVO vm = Mockito.mock(UserVmVO.class); + NicProfile result = unmanagedVMsManager.importNic(nic, vm, networkVO, null, 0, true, false); + + Assert.assertNotNull(result); + Mockito.verify(networkOrchestrationService).importNic( + Mockito.eq("11:22:33:44:55:66"), + Mockito.anyInt(), Mockito.any(), Mockito.anyBoolean(), + Mockito.any(), Mockito.isNull(), Mockito.any(), Mockito.anyBoolean()); } } From 620599813db626c95c3ea8b350e52556f5fda8e2 Mon Sep 17 00:00:00 2001 From: Prashanth Reddy Date: Thu, 11 Jun 2026 21:11:53 +0000 Subject: [PATCH 02/10] fix: simplify importNic tests to avoid Mockito 5 UnnecessaryStubbingException Remove test-specific stubs for dataCenterDao and networkOrchestrationService.importNic that duplicate the setUp() stubs. With Mockito 5 strict stubs, test-method stubs that don't get invoked (because setUp's broader nullable() stubs match first) trigger UnnecessaryStubbingException. Rely on setUp's stubs and only verify the MAC argument. --- .../vm/UnmanagedVMsManagerImplTest.java | 307 ++++++++---------- 1 file changed, 139 insertions(+), 168 deletions(-) diff --git a/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java index 829d72e5366e..4cb665449346 100644 --- a/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java @@ -1608,171 +1608,142 @@ public void getDetailAsIntegerTestThrowsInvalidParameterValueExceptionWhenValueI Map details = new HashMap<>(); details.put("key", "not-a-number"); unmanagedVMsManager.getDetailAsInteger("key", details); - } - - // ------------------------------------------------------------------------- - // mergeNicMacAddresses tests - // ------------------------------------------------------------------------- - - @Test - public void mergeNicMacAddressesEmptyMacMapReturnsOriginal() { - Map ipMap = new HashMap<>(); - ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); - - Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, new HashMap<>()); - - Assert.assertSame(ipMap, result); - Assert.assertNull(result.get("nic1").getMacAddress()); - } - - @Test - public void mergeNicMacAddressesNullMacMapReturnsOriginal() { - Map ipMap = new HashMap<>(); - ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); - - Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, null); - - Assert.assertSame(ipMap, result); - } - - @Test - public void mergeNicMacAddressesMacMergedIntoExistingEntry() { - Map ipMap = new HashMap<>(); - ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); - - Map macMap = new HashMap<>(); - macMap.put("nic1", "aa:bb:cc:dd:ee:ff"); - - Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, macMap); - - Assert.assertEquals("aa:bb:cc:dd:ee:ff", result.get("nic1").getMacAddress()); - Assert.assertEquals("10.0.0.1", result.get("nic1").getIp4Address()); - } - - @Test - public void mergeNicMacAddressesNewEntryCreatedWhenNicNotInIpMap() { - Map ipMap = new HashMap<>(); - - Map macMap = new HashMap<>(); - macMap.put("nic1", "aa:bb:cc:dd:ee:ff"); - - Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, macMap); - - Assert.assertNotNull(result.get("nic1")); - Assert.assertEquals("aa:bb:cc:dd:ee:ff", result.get("nic1").getMacAddress()); - Assert.assertNull(result.get("nic1").getIp4Address()); - } - - @Test - public void mergeNicMacAddressesMultipleNicsMergedCorrectly() { - Map ipMap = new HashMap<>(); - ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); - ipMap.put("nic2", new Network.IpAddresses("10.0.0.2", null)); - - Map macMap = new HashMap<>(); - macMap.put("nic1", "aa:bb:cc:dd:ee:01"); - macMap.put("nic2", "aa:bb:cc:dd:ee:02"); - - Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, macMap); - - Assert.assertEquals("aa:bb:cc:dd:ee:01", result.get("nic1").getMacAddress()); - Assert.assertEquals("10.0.0.1", result.get("nic1").getIp4Address()); - Assert.assertEquals("aa:bb:cc:dd:ee:02", result.get("nic2").getMacAddress()); - Assert.assertEquals("10.0.0.2", result.get("nic2").getIp4Address()); - } - - // ------------------------------------------------------------------------- - // importNic: caller MAC vs hypervisor MAC selection - // ------------------------------------------------------------------------- - - @Test - public void importNicUsesCallerSuppliedMacWhenPresent() throws Exception { - UnmanagedInstanceTO.Nic nic = new UnmanagedInstanceTO.Nic(); - nic.setNicId("nic1"); - nic.setMacAddress("11:22:33:44:55:66"); - - Network.IpAddresses ipAddresses = new Network.IpAddresses(null, null, "aa:bb:cc:dd:ee:ff"); - - NetworkVO networkVO = Mockito.mock(NetworkVO.class); - when(networkVO.getDataCenterId()).thenReturn(1L); - DataCenterVO dcVO = Mockito.mock(DataCenterVO.class); - when(dataCenterDao.findById(1L)).thenReturn(dcVO); - - NicProfile profile = Mockito.mock(NicProfile.class); - Pair pair = new Pair<>(profile, 0); - when(networkOrchestrationService.importNic( - Mockito.eq("aa:bb:cc:dd:ee:ff"), - Mockito.anyInt(), Mockito.eq(networkVO), Mockito.anyBoolean(), - Mockito.any(), Mockito.eq(ipAddresses), Mockito.eq(dcVO), Mockito.anyBoolean())) - .thenReturn(pair); - - UserVmVO vm = Mockito.mock(UserVmVO.class); - NicProfile result = unmanagedVMsManager.importNic(nic, vm, networkVO, ipAddresses, 0, true, false); - - Assert.assertNotNull(result); - Mockito.verify(networkOrchestrationService).importNic( - Mockito.eq("aa:bb:cc:dd:ee:ff"), - Mockito.anyInt(), Mockito.any(), Mockito.anyBoolean(), - Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyBoolean()); - } - - @Test - public void importNicFallsBackToHypervisorMacWhenIpAddressesHasNoMac() throws Exception { - UnmanagedInstanceTO.Nic nic = new UnmanagedInstanceTO.Nic(); - nic.setNicId("nic1"); - nic.setMacAddress("11:22:33:44:55:66"); - - Network.IpAddresses ipAddresses = new Network.IpAddresses("10.0.0.1", null); // no MAC - - NetworkVO networkVO = Mockito.mock(NetworkVO.class); - when(networkVO.getDataCenterId()).thenReturn(1L); - DataCenterVO dcVO = Mockito.mock(DataCenterVO.class); - when(dataCenterDao.findById(1L)).thenReturn(dcVO); - - NicProfile profile = Mockito.mock(NicProfile.class); - Pair pair = new Pair<>(profile, 0); - when(networkOrchestrationService.importNic( - Mockito.eq("11:22:33:44:55:66"), - Mockito.anyInt(), Mockito.eq(networkVO), Mockito.anyBoolean(), - Mockito.any(), Mockito.eq(ipAddresses), Mockito.eq(dcVO), Mockito.anyBoolean())) - .thenReturn(pair); - - UserVmVO vm = Mockito.mock(UserVmVO.class); - NicProfile result = unmanagedVMsManager.importNic(nic, vm, networkVO, ipAddresses, 0, true, false); - - Assert.assertNotNull(result); - Mockito.verify(networkOrchestrationService).importNic( - Mockito.eq("11:22:33:44:55:66"), - Mockito.anyInt(), Mockito.any(), Mockito.anyBoolean(), - Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyBoolean()); - } - - @Test - public void importNicFallsBackToHypervisorMacWhenIpAddressesIsNull() throws Exception { - UnmanagedInstanceTO.Nic nic = new UnmanagedInstanceTO.Nic(); - nic.setNicId("nic1"); - nic.setMacAddress("11:22:33:44:55:66"); - - NetworkVO networkVO = Mockito.mock(NetworkVO.class); - when(networkVO.getDataCenterId()).thenReturn(1L); - DataCenterVO dcVO = Mockito.mock(DataCenterVO.class); - when(dataCenterDao.findById(1L)).thenReturn(dcVO); - - NicProfile profile = Mockito.mock(NicProfile.class); - Pair pair = new Pair<>(profile, 0); - when(networkOrchestrationService.importNic( - Mockito.eq("11:22:33:44:55:66"), - Mockito.anyInt(), Mockito.eq(networkVO), Mockito.anyBoolean(), - Mockito.any(), Mockito.isNull(), Mockito.eq(dcVO), Mockito.anyBoolean())) - .thenReturn(pair); - - UserVmVO vm = Mockito.mock(UserVmVO.class); - NicProfile result = unmanagedVMsManager.importNic(nic, vm, networkVO, null, 0, true, false); - - Assert.assertNotNull(result); - Mockito.verify(networkOrchestrationService).importNic( - Mockito.eq("11:22:33:44:55:66"), - Mockito.anyInt(), Mockito.any(), Mockito.anyBoolean(), - Mockito.any(), Mockito.isNull(), Mockito.any(), Mockito.anyBoolean()); - } -} + } + + // ------------------------------------------------------------------------- + // mergeNicMacAddresses tests + // ------------------------------------------------------------------------- + + @Test + public void mergeNicMacAddressesEmptyMacMapReturnsOriginal() { + Map ipMap = new HashMap<>(); + ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); + + Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, new HashMap<>()); + + Assert.assertSame(ipMap, result); + Assert.assertNull(result.get("nic1").getMacAddress()); + } + + @Test + public void mergeNicMacAddressesNullMacMapReturnsOriginal() { + Map ipMap = new HashMap<>(); + ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); + + Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, null); + + Assert.assertSame(ipMap, result); + } + + @Test + public void mergeNicMacAddressesMacMergedIntoExistingEntry() { + Map ipMap = new HashMap<>(); + ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); + + Map macMap = new HashMap<>(); + macMap.put("nic1", "aa:bb:cc:dd:ee:ff"); + + Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, macMap); + + Assert.assertEquals("aa:bb:cc:dd:ee:ff", result.get("nic1").getMacAddress()); + Assert.assertEquals("10.0.0.1", result.get("nic1").getIp4Address()); + } + + @Test + public void mergeNicMacAddressesNewEntryCreatedWhenNicNotInIpMap() { + Map ipMap = new HashMap<>(); + + Map macMap = new HashMap<>(); + macMap.put("nic1", "aa:bb:cc:dd:ee:ff"); + + Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, macMap); + + Assert.assertNotNull(result.get("nic1")); + Assert.assertEquals("aa:bb:cc:dd:ee:ff", result.get("nic1").getMacAddress()); + Assert.assertNull(result.get("nic1").getIp4Address()); + } + + @Test + public void mergeNicMacAddressesMultipleNicsMergedCorrectly() { + Map ipMap = new HashMap<>(); + ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); + ipMap.put("nic2", new Network.IpAddresses("10.0.0.2", null)); + + Map macMap = new HashMap<>(); + macMap.put("nic1", "aa:bb:cc:dd:ee:01"); + macMap.put("nic2", "aa:bb:cc:dd:ee:02"); + + Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, macMap); + + Assert.assertEquals("aa:bb:cc:dd:ee:01", result.get("nic1").getMacAddress()); + Assert.assertEquals("10.0.0.1", result.get("nic1").getIp4Address()); + Assert.assertEquals("aa:bb:cc:dd:ee:02", result.get("nic2").getMacAddress()); + Assert.assertEquals("10.0.0.2", result.get("nic2").getIp4Address()); + } + + // ------------------------------------------------------------------------- + // importNic: caller MAC vs hypervisor MAC selection + // ------------------------------------------------------------------------- + + @Test + public void importNicUsesCallerSuppliedMacWhenPresent() throws Exception { + UnmanagedInstanceTO.Nic nic = new UnmanagedInstanceTO.Nic(); + nic.setNicId("nic1"); + nic.setMacAddress("11:22:33:44:55:66"); + + Network.IpAddresses ipAddresses = new Network.IpAddresses(null, null, "aa:bb:cc:dd:ee:ff"); + + NetworkVO networkVO = Mockito.mock(NetworkVO.class); + when(networkVO.getDataCenterId()).thenReturn(1L); + + UserVmVO vm = Mockito.mock(UserVmVO.class); + NicProfile result = unmanagedVMsManager.importNic(nic, vm, networkVO, ipAddresses, 0, true, false); + + Assert.assertNotNull(result); + Mockito.verify(networkOrchestrationService).importNic( + Mockito.eq("aa:bb:cc:dd:ee:ff"), + Mockito.anyInt(), Mockito.any(), Mockito.anyBoolean(), + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyBoolean()); + } + + @Test + public void importNicFallsBackToHypervisorMacWhenIpAddressesHasNoMac() throws Exception { + UnmanagedInstanceTO.Nic nic = new UnmanagedInstanceTO.Nic(); + nic.setNicId("nic1"); + nic.setMacAddress("11:22:33:44:55:66"); + + Network.IpAddresses ipAddresses = new Network.IpAddresses("10.0.0.1", null); // no MAC + + NetworkVO networkVO = Mockito.mock(NetworkVO.class); + when(networkVO.getDataCenterId()).thenReturn(1L); + + UserVmVO vm = Mockito.mock(UserVmVO.class); + NicProfile result = unmanagedVMsManager.importNic(nic, vm, networkVO, ipAddresses, 0, true, false); + + Assert.assertNotNull(result); + Mockito.verify(networkOrchestrationService).importNic( + Mockito.eq("11:22:33:44:55:66"), + Mockito.anyInt(), Mockito.any(), Mockito.anyBoolean(), + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyBoolean()); + } + + @Test + public void importNicFallsBackToHypervisorMacWhenIpAddressesIsNull() throws Exception { + UnmanagedInstanceTO.Nic nic = new UnmanagedInstanceTO.Nic(); + nic.setNicId("nic1"); + nic.setMacAddress("11:22:33:44:55:66"); + + NetworkVO networkVO = Mockito.mock(NetworkVO.class); + when(networkVO.getDataCenterId()).thenReturn(1L); + + UserVmVO vm = Mockito.mock(UserVmVO.class); + NicProfile result = unmanagedVMsManager.importNic(nic, vm, networkVO, null, 0, true, false); + + Assert.assertNotNull(result); + Mockito.verify(networkOrchestrationService).importNic( + Mockito.eq("11:22:33:44:55:66"), + Mockito.anyInt(), Mockito.any(), Mockito.anyBoolean(), + Mockito.any(), Mockito.isNull(), Mockito.any(), Mockito.anyBoolean()); + } +} + \ No newline at end of file From 8a77bbc0dc45ee10769ad1753a0bad24f6c36ded Mon Sep 17 00:00:00 2001 From: Prashanth Reddy Date: Thu, 11 Jun 2026 21:21:53 +0000 Subject: [PATCH 03/10] style: fix line endings, trailing whitespace, missing EOF newline Normalize all changed files to LF line endings, strip trailing whitespace, and ensure a single newline at end of file to pass pre-commit hooks: end-of-file-fixer, mixed-line-ending, trailing-whitespace. --- .../java/com/cloud/vm/VmDetailConstants.java | 278 +- .../apache/cloudstack/api/ApiConstants.java | 2988 ++++---- .../admin/vm/ImportUnmanagedInstanceCmd.java | 563 +- .../vm/UnmanagedVMsManagerImpl.java | 6354 ++++++++--------- .../vm/UnmanagedVMsManagerImplTest.java | 3498 ++++----- 5 files changed, 6840 insertions(+), 6841 deletions(-) diff --git a/api/src/main/java/com/cloud/vm/VmDetailConstants.java b/api/src/main/java/com/cloud/vm/VmDetailConstants.java index bcee784512ba..c3754ab7c424 100644 --- a/api/src/main/java/com/cloud/vm/VmDetailConstants.java +++ b/api/src/main/java/com/cloud/vm/VmDetailConstants.java @@ -1,140 +1,140 @@ -// 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.vm; - -public interface VmDetailConstants { - String KEYBOARD = "keyboard"; - String CPU_CORE_PER_SOCKET = "cpu.corespersocket"; - String CPU_THREAD_PER_CORE = "cpu.threadspercore"; - String ROOT_DISK_SIZE = "rootdisksize"; - String BOOT_MODE = "boot.mode"; - String NAME_ON_HYPERVISOR= "nameonhypervisor"; - - // VMware specific - String NIC_ADAPTER = "nicAdapter"; - String ROOT_DISK_CONTROLLER = "rootDiskController"; - String DATA_DISK_CONTROLLER = "dataDiskController"; - String SVGA_VRAM_SIZE = "svga.vramSize"; - String NESTED_VIRTUALIZATION_FLAG = "nestedVirtualizationFlag"; - String RAM_RESERVATION = "ramReservation"; - - // XenServer specific (internal) - String HYPERVISOR_TOOLS_VERSION = "hypervisortoolsversion"; - String PLATFORM = "platform"; - String TIME_OFFSET = "timeoffset"; - - // KVM specific (internal) - String KVM_VNC_PORT = "kvm.vnc.port"; - String KVM_VNC_ADDRESS = "kvm.vnc.address"; - String KVM_VNC_PASSWORD = "kvm.vnc.password"; - String KVM_GUEST_OS_MACHINE_TYPE = "kvm.guest.os.machine.type"; - - // KVM specific, custom virtual GPU hardware - String VIDEO_HARDWARE = "video.hardware"; - String VIDEO_RAM = "video.ram"; - - //KVM specific, loop threads for block IO requests - String IOTHREADS = "iothreads"; - String IO_POLICY = "io.policy"; - - // KVM specific, the number of queues for multiqueue NICs - String NIC_MULTIQUEUE_NUMBER = "nic.multiqueue.number"; - String NIC_PACKED_VIRTQUEUES_ENABLED = "nic.packed.virtqueues.enabled"; - - // KVM specific, disk controllers - String KVM_SKIP_FORCE_DISK_CONTROLLER = "skip.force.disk.controller"; - - // Mac OSX guest specific (internal) - String SMC_PRESENT = "smc.present"; - String FIRMWARE = "firmware"; - - // VM deployment with custom compute offering params - String CPU_NUMBER = "cpuNumber"; - String CPU_SPEED = "cpuSpeed"; - String MEMORY = "memory"; - - // Misc details for internal usage (not to be set/changed by user or admin) - String CPU_OVER_COMMIT_RATIO = "cpuOvercommitRatio"; - String MEMORY_OVER_COMMIT_RATIO = "memoryOvercommitRatio"; - String MESSAGE_RESERVED_CAPACITY_FREED_FLAG = "Message.ReservedCapacityFreed.Flag"; - String DEPLOY_VM = "deployvm"; - String SSH_PUBLIC_KEY = "SSH.PublicKey"; - String SSH_KEY_PAIR_NAMES = "SSH.KeyPairNames"; - String PASSWORD = "password"; - String ENCRYPTED_PASSWORD = "Encrypted.Password"; - - String CONFIG_DRIVE_LOCATION = "configDriveLocation"; - String LAST_CONFIG_DRIVE_LOCATION = "lastConfigDriveLocation"; - - String SKIP_DRS = "skipFromDRS"; - - // VM import with nic, disk and custom params for custom compute offering - String NIC = "nic"; - String NETWORK = "network"; - String IP4_ADDRESS = "ip4Address"; +// 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.vm; + +public interface VmDetailConstants { + String KEYBOARD = "keyboard"; + String CPU_CORE_PER_SOCKET = "cpu.corespersocket"; + String CPU_THREAD_PER_CORE = "cpu.threadspercore"; + String ROOT_DISK_SIZE = "rootdisksize"; + String BOOT_MODE = "boot.mode"; + String NAME_ON_HYPERVISOR= "nameonhypervisor"; + + // VMware specific + String NIC_ADAPTER = "nicAdapter"; + String ROOT_DISK_CONTROLLER = "rootDiskController"; + String DATA_DISK_CONTROLLER = "dataDiskController"; + String SVGA_VRAM_SIZE = "svga.vramSize"; + String NESTED_VIRTUALIZATION_FLAG = "nestedVirtualizationFlag"; + String RAM_RESERVATION = "ramReservation"; + + // XenServer specific (internal) + String HYPERVISOR_TOOLS_VERSION = "hypervisortoolsversion"; + String PLATFORM = "platform"; + String TIME_OFFSET = "timeoffset"; + + // KVM specific (internal) + String KVM_VNC_PORT = "kvm.vnc.port"; + String KVM_VNC_ADDRESS = "kvm.vnc.address"; + String KVM_VNC_PASSWORD = "kvm.vnc.password"; + String KVM_GUEST_OS_MACHINE_TYPE = "kvm.guest.os.machine.type"; + + // KVM specific, custom virtual GPU hardware + String VIDEO_HARDWARE = "video.hardware"; + String VIDEO_RAM = "video.ram"; + + //KVM specific, loop threads for block IO requests + String IOTHREADS = "iothreads"; + String IO_POLICY = "io.policy"; + + // KVM specific, the number of queues for multiqueue NICs + String NIC_MULTIQUEUE_NUMBER = "nic.multiqueue.number"; + String NIC_PACKED_VIRTQUEUES_ENABLED = "nic.packed.virtqueues.enabled"; + + // KVM specific, disk controllers + String KVM_SKIP_FORCE_DISK_CONTROLLER = "skip.force.disk.controller"; + + // Mac OSX guest specific (internal) + String SMC_PRESENT = "smc.present"; + String FIRMWARE = "firmware"; + + // VM deployment with custom compute offering params + String CPU_NUMBER = "cpuNumber"; + String CPU_SPEED = "cpuSpeed"; + String MEMORY = "memory"; + + // Misc details for internal usage (not to be set/changed by user or admin) + String CPU_OVER_COMMIT_RATIO = "cpuOvercommitRatio"; + String MEMORY_OVER_COMMIT_RATIO = "memoryOvercommitRatio"; + String MESSAGE_RESERVED_CAPACITY_FREED_FLAG = "Message.ReservedCapacityFreed.Flag"; + String DEPLOY_VM = "deployvm"; + String SSH_PUBLIC_KEY = "SSH.PublicKey"; + String SSH_KEY_PAIR_NAMES = "SSH.KeyPairNames"; + String PASSWORD = "password"; + String ENCRYPTED_PASSWORD = "Encrypted.Password"; + + String CONFIG_DRIVE_LOCATION = "configDriveLocation"; + String LAST_CONFIG_DRIVE_LOCATION = "lastConfigDriveLocation"; + + String SKIP_DRS = "skipFromDRS"; + + // VM import with nic, disk and custom params for custom compute offering + String NIC = "nic"; + String NETWORK = "network"; + String IP4_ADDRESS = "ip4Address"; String IP6_ADDRESS = "ip6Address"; - String NIC_MAC_ADDRESS = "mac"; - String DISK = "disk"; - String DISK_OFFERING = "diskOffering"; - - String DEPLOY_AS_IS_CONFIGURATION = "configurationId"; - String KEY_PAIR_NAMES = "keypairnames"; - String CKS_CONTROL_NODE_LOGIN_USER = "controlNodeLoginUser"; - String CKS_NODE_TYPE = "node"; - String OFFERING = "offering"; - String TEMPLATE = "template"; - String AFFINITY_GROUP = "affinitygroup"; - - // VMware to KVM VM migrations specific - String VMWARE_TO_KVM_PREFIX = "vmware-to-kvm"; - String VMWARE_VCENTER_HOST = String.format("%s-vcenter", VMWARE_TO_KVM_PREFIX); - String VMWARE_DATACENTER_NAME = String.format("%s-datacenter", VMWARE_TO_KVM_PREFIX); - String VMWARE_CLUSTER_NAME = String.format("%s-cluster", VMWARE_TO_KVM_PREFIX); - String VMWARE_VCENTER_USERNAME = String.format("%s-username", VMWARE_TO_KVM_PREFIX); - String VMWARE_VCENTER_PASSWORD = String.format("%s-password", VMWARE_TO_KVM_PREFIX); - String VMWARE_VM_NAME = String.format("%s-vmname", VMWARE_TO_KVM_PREFIX); - String VMWARE_HOST_NAME = String.format("%s-host", VMWARE_TO_KVM_PREFIX); - String VMWARE_DISK = String.format("%s-disk", VMWARE_TO_KVM_PREFIX); - String VMWARE_MAC_ADDRESSES = String.format("%s-mac-addresses", VMWARE_TO_KVM_PREFIX); - - // TPM - String VIRTUAL_TPM_ENABLED = "virtual.tpm.enabled"; - String VIRTUAL_TPM_MODEL = "virtual.tpm.model"; - String VIRTUAL_TPM_VERSION = "virtual.tpm.version"; - - // CPU mode and model, ADMIN only - String GUEST_CPU_MODE = "guest.cpu.mode"; - String GUEST_CPU_MODEL = "guest.cpu.model"; - - // Lease related - String INSTANCE_LEASE_EXPIRY_DATE = "leaseexpirydate"; - String INSTANCE_LEASE_EXPIRY_ACTION = "leaseexpiryaction"; - String INSTANCE_LEASE_EXECUTION = "leaseactionexecution"; - - // External orchestrator related - String MAC_ADDRESS = "mac_address"; - String EXPUNGE_EXTERNAL_VM = "expunge.external.vm"; - String EXTERNAL_DETAIL_PREFIX = "External:"; - String CLOUDSTACK_VM_DETAILS = "cloudstack.vm.details"; - String CLOUDSTACK_VLAN = "cloudstack.vlan"; - - // KVM Checkpoints related - String ACTIVE_CHECKPOINT_ID = "active.checkpoint.id"; - String ACTIVE_CHECKPOINT_CREATE_TIME = "active.checkpoint.create.time"; - String LAST_CHECKPOINT_ID = "last.checkpoint.id"; - String LAST_CHECKPOINT_CREATE_TIME = "last.checkpoint.create.time"; -} + String NIC_MAC_ADDRESS = "mac"; + String DISK = "disk"; + String DISK_OFFERING = "diskOffering"; + + String DEPLOY_AS_IS_CONFIGURATION = "configurationId"; + String KEY_PAIR_NAMES = "keypairnames"; + String CKS_CONTROL_NODE_LOGIN_USER = "controlNodeLoginUser"; + String CKS_NODE_TYPE = "node"; + String OFFERING = "offering"; + String TEMPLATE = "template"; + String AFFINITY_GROUP = "affinitygroup"; + + // VMware to KVM VM migrations specific + String VMWARE_TO_KVM_PREFIX = "vmware-to-kvm"; + String VMWARE_VCENTER_HOST = String.format("%s-vcenter", VMWARE_TO_KVM_PREFIX); + String VMWARE_DATACENTER_NAME = String.format("%s-datacenter", VMWARE_TO_KVM_PREFIX); + String VMWARE_CLUSTER_NAME = String.format("%s-cluster", VMWARE_TO_KVM_PREFIX); + String VMWARE_VCENTER_USERNAME = String.format("%s-username", VMWARE_TO_KVM_PREFIX); + String VMWARE_VCENTER_PASSWORD = String.format("%s-password", VMWARE_TO_KVM_PREFIX); + String VMWARE_VM_NAME = String.format("%s-vmname", VMWARE_TO_KVM_PREFIX); + String VMWARE_HOST_NAME = String.format("%s-host", VMWARE_TO_KVM_PREFIX); + String VMWARE_DISK = String.format("%s-disk", VMWARE_TO_KVM_PREFIX); + String VMWARE_MAC_ADDRESSES = String.format("%s-mac-addresses", VMWARE_TO_KVM_PREFIX); + + // TPM + String VIRTUAL_TPM_ENABLED = "virtual.tpm.enabled"; + String VIRTUAL_TPM_MODEL = "virtual.tpm.model"; + String VIRTUAL_TPM_VERSION = "virtual.tpm.version"; + + // CPU mode and model, ADMIN only + String GUEST_CPU_MODE = "guest.cpu.mode"; + String GUEST_CPU_MODEL = "guest.cpu.model"; + + // Lease related + String INSTANCE_LEASE_EXPIRY_DATE = "leaseexpirydate"; + String INSTANCE_LEASE_EXPIRY_ACTION = "leaseexpiryaction"; + String INSTANCE_LEASE_EXECUTION = "leaseactionexecution"; + + // External orchestrator related + String MAC_ADDRESS = "mac_address"; + String EXPUNGE_EXTERNAL_VM = "expunge.external.vm"; + String EXTERNAL_DETAIL_PREFIX = "External:"; + String CLOUDSTACK_VM_DETAILS = "cloudstack.vm.details"; + String CLOUDSTACK_VLAN = "cloudstack.vlan"; + + // KVM Checkpoints related + String ACTIVE_CHECKPOINT_ID = "active.checkpoint.id"; + String ACTIVE_CHECKPOINT_CREATE_TIME = "active.checkpoint.create.time"; + String LAST_CHECKPOINT_ID = "last.checkpoint.id"; + String LAST_CHECKPOINT_CREATE_TIME = "last.checkpoint.create.time"; +} 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 a8820698e1a2..f923d305a09a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -1,1495 +1,1495 @@ -// 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; - -public class ApiConstants { - public static final String ACCOUNT = "account"; - public static final String ACCOUNTS = "accounts"; - public static final String ACCOUNT_NAME = "accountname"; - public static final String ACCOUNT_STATE_TO_SHOW = "accountstatetoshow"; - public static final String ACCOUNT_TYPE = "accounttype"; - public static final String ACCOUNT_ID = "accountid"; - public static final String ACCOUNT_IDS = "accountids"; - public static final String ACCUMULATE = "accumulate"; - public static final String ACQUIRED = "acquired"; - public static final String ACTIVATION_RULE = "activationrule"; - public static final String ACTIVITY = "activity"; - public static final String ADAPTER_TYPE = "adaptertype"; - public static final String ADDITONAL_CONFIG_ENABLED = "additionalconfigenabled"; - public static final String ADDRESS = "address"; - public static final String ALGORITHM = "algorithm"; - public static final String ALIAS = "alias"; - public static final String ALLOCATED = "allocated"; - public static final String ALLOCATED_DATE = "allocateddate"; - public static final String ALLOCATED_ONLY = "allocatedonly"; - public static final String ALLOCATED_TIME = "allocated"; - public static final String ALLOWED_ROLE_TYPES = "allowedroletypes"; - public static final String ALLOW_USER_FORCE_STOP_VM = "allowuserforcestopvm"; - public static final String ANNOTATION = "annotation"; - public static final String API_KEY = "apikey"; - public static final String API_KEY_ACCESS = "apikeyaccess"; - public static final String ARCHIVED = "archived"; - public static final String ARCH = "arch"; - public static final String AS_NUMBER = "asnumber"; - public static final String AS_NUMBER_ID = "asnumberid"; - public static final String ASN_RANGE = "asnrange"; - public static final String ASN_RANGE_ID = "asnrangeid"; - public static final String API_KEY_FILTER = "apikeyfilter"; - public static final String ASYNC_BACKUP = "asyncbackup"; - public static final String AUTO_SELECT = "autoselect"; - public static final String USER_API_KEY = "userapikey"; - public static final String APPLIED = "applied"; - public static final String LIST_LB_VMIPS = "lbvmips"; - public static final String LIVE_PATCH = "livepatch"; - public static final String AVAILABLE = "available"; - public static final String AVAILABLE_SUBNETS = "availablesubnets"; - public static final String AVAILABLE_VIRTUAL_MACHINE_COUNT = "availablevirtualmachinecount"; - public static final String BACKUP_AVAILABLE = "backupavailable"; - public static final String BACKUP_ID = "backupid"; - public static final String BACKUP_LIMIT = "backuplimit"; - public static final String BACKUP_OFFERING_NAME = "backupofferingname"; - public static final String BACKUP_OFFERING_ID = "backupofferingid"; - public static final String BACKUP_STORAGE_AVAILABLE = "backupstorageavailable"; - public static final String BACKUP_STORAGE_LIMIT = "backupstoragelimit"; - public static final String BACKUP_STORAGE_TOTAL = "backupstoragetotal"; - public static final String BACKUP_VM_OFFERING_REMOVED = "vmbackupofferingremoved"; - public static final String IS_BACKUP_VM_EXPUNGED = "isbackupvmexpunged"; - public static final String BACKUP_TOTAL = "backuptotal"; - public static final String BALANCE = "balance"; - public static final String BALANCES = "balances"; - public static final String BASE64_IMAGE = "base64image"; - public static final String BGP_PEERS = "bgppeers"; - public static final String BGP_PEER_IDS = "bgppeerids"; - public static final String BATCH_SIZE = "batchsize"; - public static final String BITS = "bits"; - public static final String BOOTABLE = "bootable"; - public static final String BIND_DN = "binddn"; - public static final String BIND_PASSWORD = "bindpass"; - public static final String BLANK_INSTANCE = "blankinstance"; - public static final String BUS_ADDRESS = "busaddress"; - public static final String BYTES_READ_RATE = "bytesreadrate"; - public static final String BYTES_READ_RATE_MAX = "bytesreadratemax"; - public static final String BYTES_READ_RATE_MAX_LENGTH = "bytesreadratemaxlength"; - public static final String BYTES_WRITE_RATE = "byteswriterate"; - 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 CALLER = "caller"; - 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"; - public static final String CERTIFICATE = "certificate"; - 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 CERTIFICATE_ISSUER = "issuer"; - public static final String CERTIFICATE_SERIALNUM = "serialnum"; - public static final String CERTIFICATE_SUBJECT = "subject"; - public static final String CERTIFICATE_VALIDITY = "validity"; - public static final String CONVERT_INSTANCE_HOST_ID = "convertinstancehostid"; - public static final String CONVERT_INSTANCE_STORAGE_POOL_ID = "convertinstancepoolid"; - public static final String ENABLED_REVOCATION_CHECK = "enabledrevocationcheck"; - public static final String CLIENT_ADDRESS = "clientaddress"; - public static final String COMBINED_CAPACITY_ORDERING = "COMBINED"; - public static final String CONTROLLER = "controller"; - public static final String CONTROLLER_UNIT = "controllerunit"; - public static final String CONSOLE_ENDPOINT_CREATOR_ADDRESS = "consoleendpointcreatoraddress"; - public static final String COPY_IMAGE_TAGS = "copyimagetags"; - public static final String CPU_OVERCOMMIT_RATIO = "cpuOvercommitRatio"; - 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_ID = "datastoreid"; - public static final String DATASTORE_NAME = "datastorename"; - public static final String DATASTORE_PATH = "datastorepath"; - public static final String DATASTORE_STATE = "datastorestate"; - 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"; - public static final String CIDR = "cidr"; - public static final String CIDR_SIZE = "cidrsize"; - - public static final String IP6_CIDR = "ip6cidr"; - public static final String CIDR_LIST = "cidrlist"; - public static final String DEST_CIDR_LIST = "destcidrlist"; - public static final String CLEANUP = "cleanup"; - public static final String MAKEREDUNDANT = "makeredundant"; - public static final String CLUSTER_ID = "clusterid"; - public static final String CLUSTER_IDS = "clusterids"; - public static final String CLUSTER_NAME = "clustername"; - public static final String CLUSTER_TYPE = "clustertype"; - public static final String CN = "cn"; - public static final String COMMAND = "command"; - public static final String CMD_EVENT_TYPE = "cmdeventtype"; - public static final String CNI_CONFIG = "cniconfig"; - public static final String CNI_CONFIG_ID = "cniconfigurationid"; - public static final String CNI_CONFIG_DETAILS = "cniconfigdetails"; - public static final String CNI_CONFIG_NAME = "cniconfigname"; - public static final String CSI_ENABLED = "csienabled"; - public static final String COMPONENT = "component"; - public static final String CPU = "CPU"; - 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 CPU_LOAD_AVERAGE = "cpuloadaverage"; - public static final String CREATED = "created"; - public static final String CROSS_ZONE_INSTANCE_CREATION = "crosszoneinstancecreation"; - public static final String CTX_ACCOUNT_ID = "ctxaccountid"; - public static final String CTX_DETAILS = "ctxDetails"; - public static final String CTX_USER_ID = "ctxuserid"; - public static final String CTXSTARTEVENTID = "ctxstarteventid"; - public static final String CTX_START_EVENT_ID = "ctxStartEventId"; - public static final String CUSTOMIZED = "customized"; - public static final String CUSTOMIZED_IOPS = "customizediops"; - public static final String CUSTOM_ID = "customid"; - public static final String CUSTOM_ACTION_ID = "customactionid"; - public static final String CUSTOM_JOB_ID = "customjobid"; - public static final String CURRENCY = "currency"; - public static final String CURRENT_START_IP = "currentstartip"; - public static final String CURRENT_END_IP = "currentendip"; - public static final String ENCRYPT = "encrypt"; - public static final String ENCRYPT_FORMAT = "encryptformat"; - public static final String ENCRYPT_ROOT = "encryptroot"; - public static final String ENCRYPTION_SUPPORTED = "encryptionsupported"; - public static final String ETCD_IPS = "etcdips"; - public static final String MIN_IOPS = "miniops"; - public static final String MAX_IOPS = "maxiops"; - public static final String HYPERVISOR_SNAPSHOT_RESERVE = "hypervisorsnapshotreserve"; - public static final String DATACENTER_NAME = "datacentername"; - public static final String DATADISKS_DETAILS = "datadisksdetails"; - public static final String DATADISK_OFFERING_LIST = "datadiskofferinglist"; - public static final String DATE = "date"; - public static final String DEFAULT_VALUE = "defaultvalue"; - public static final String DELETE_PROTECTION = "deleteprotection"; - public static final String DESCRIPTION = "description"; - public static final String DESTINATION = "destination"; - public static final String DESTINATION_ZONE_ID = "destzoneid"; - public static final String DETAILS = "details"; - public static final String DEVICE_ID = "deviceid"; - public static final String DEVICE_IDS = "deviceids"; - public static final String DEVICE_NAME = "devicename"; - 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 ORCHESTRATOR_REQUIRES_PREPARE_VM = "orchestratorrequirespreparevm"; - public static final String OVERRIDE_DISK_OFFERING_ID = "overridediskofferingid"; - public static final String DISK_KBS_READ = "diskkbsread"; - public static final String DISK_KBS_WRITE = "diskkbswrite"; - public static final String DISK_IO_READ = "diskioread"; - public static final String DISK_IO_WRITE = "diskiowrite"; - public static final String DISK_IO_PSTOTAL = "diskiopstotal"; - public static final String DISK_SIZE = "disksize"; - public static final String DISK_SIZE_STRICTNESS = "disksizestrictness"; - public static final String DISK_OFFERING_STRICTNESS = "diskofferingstrictness"; - public static final String DOWNLOAD_DETAILS = "downloaddetails"; - public static final String UTILIZATION = "utilization"; - public static final String DRIVER = "driver"; - public static final String ROOT_DISK_SIZE = "rootdisksize"; - public static final String DHCP_OPTIONS_NETWORK_LIST = "dhcpoptionsnetworklist"; - public static final String DHCP_OPTIONS = "dhcpoptions"; - public static final String DHCP_PREFIX = "dhcp:"; - public static final String DISPLAY_NAME = "displayname"; - public static final String DISPLAY_NETWORK = "displaynetwork"; - public static final String DISPLAY_NIC = "displaynic"; - public static final String DISPLAY_TEXT = "displaytext"; - public static final String DISPLAY_VM = "displayvm"; - public static final String DISPLAY_OFFERING = "displayoffering"; - public static final String DISPLAY_VOLUME = "displayvolume"; - public static final String DNS1 = "dns1"; - public static final String DNS2 = "dns2"; - public static final String IP6_DNS1 = "ip6dns1"; - public static final String IP6_DNS2 = "ip6dns2"; - public static final String DOMAIN = "domain"; - public static final String DOMAIN_DETAILS = "domaindetails"; - public static final String DOMAIN_PATH = "domainpath"; - public static final String DOMAIN_ID = "domainid"; - public static final String DOMAIN__ID = "domainId"; - public static final String DUMMY = "dummy"; - public static final String DURATION = "duration"; - public static final String ELIGIBLE = "eligible"; - public static final String EMAIL = "email"; - public static final String ENABLE_CSI = "enablecsi"; - public static final String END_ASN = "endasn"; - public static final String END_DATE = "enddate"; - public static final String END_IP = "endip"; - public static final String END_IPV6 = "endipv6"; - public static final String END_PORT = "endport"; - public static final String ENTRY_TIME = "entrytime"; - public static final String ERROR_MESSAGE = "errormessage"; - public static final String EVENT_ID = "eventid"; - public static final String EVENT_TYPE = "eventtype"; - public static final String EXPIRES = "expires"; - public static final String EXTRA_CONFIG = "extraconfig"; - public static final String EXTRA_PARAMS = "extraparams"; - public static final String EXTRA_DHCP_OPTION = "extradhcpoption"; - public static final String EXTRA_DHCP_OPTION_NAME = "extradhcpoptionname"; - public static final String EXTRA_DHCP_OPTION_CODE = "extradhcpoptioncode"; - public static final String EXTRA_DHCP_OPTION_VALUE = "extradhcpvalue"; - public static final String EXTERNAL = "external"; - public static final String EXTERNAL_UUID = "externaluuid"; - public static final String EXTERNAL_DETAILS = "externaldetails"; - public static final String PARAMETERS = "parameters"; - public static final String EXTENSION = "extension"; - public static final String EXTENSION_ID = "extensionid"; - public static final String EXTENSION_NAME = "extensionname"; - public static final String EXTENSIONS_PATH = "extensionspath"; - public static final String FENCE = "fence"; - public static final String FETCH_LATEST = "fetchlatest"; - public static final String FILESYSTEM = "filesystem"; - public static final String FIRSTNAME = "firstname"; - public static final String FORCED = "forced"; - public static final String FORCED_DESTROY_LOCAL_STORAGE = "forcedestroylocalstorage"; - public static final String FORCE_CONVERT_TO_POOL = "forceconverttopool"; - - public static final String FORCE_DELETE_HOST = "forcedeletehost"; - public static final String FORCE_MS_TO_IMPORT_VM_FILES = "forcemstoimportvmfiles"; - public static final String FORCE_UPDATE_OS_TYPE = "forceupdateostype"; - public static final String FORMAT = "format"; - public static final String FOR_VIRTUAL_NETWORK = "forvirtualnetwork"; - public static final String FOR_SYSTEM_VMS = "forsystemvms"; - public static final String FOR_PROVIDER = "forprovider"; - public static final String FROM_CHECKPOINT_ID = "fromcheckpointid"; - public static final String FULL_PATH = "fullpath"; - public static final String GATEWAY = "gateway"; - public static final String IP6_GATEWAY = "ip6gateway"; - public static final String GROUP = "group"; - public static final String SUBGROUP = "subgroup"; - public static final String GROUP_ID = "groupid"; - public static final String GSLB_LB_METHOD = "gslblbmethod"; - public static final String GSLB_SERVICE_DOMAIN_NAME = "gslbdomainname"; - public static final String GSLB_SERVICE_TYPE = "gslbservicetype"; - public static final String GSLB_STICKY_SESSION_METHOD = "gslbstickysessionmethodname"; - public static final String GSLB_LBRULE_WEIGHT_MAP = "gslblbruleweightsmap"; - public static final String GUEST_CIDR_ADDRESS = "guestcidraddress"; - public static final String GUEST_VLAN_RANGE = "guestvlanrange"; - public static final String HA_ENABLE = "haenable"; - public static final String HA_PROVIDER = "haprovider"; - public static final String HA_STATE = "hastate"; - public static final String HEALTH = "health"; - public static final String HEADERS = "headers"; - public static final String HIDE_IP_ADDRESS_USAGE = "hideipaddressusage"; - public static final String HOST_ID = "hostid"; - public static final String HOST_IDS = "hostids"; - public static final String HOST_IP = "hostip"; - public static final String HOST_NAME = "hostname"; - public static final String HOST = "host"; - public static final String HOST_CONTROL_STATE = "hostcontrolstate"; - public static final String HOSTS_MAP = "hostsmap"; - public static final String HTTP_REQUEST_TYPE = "httprequesttype"; - public static final String HYPERVISOR = "hypervisor"; - public static final String INLINE = "inline"; - public static final String INSTANCE = "instance"; - public static final String ICMP_CODE = "icmpcode"; - public static final String ICMP_TYPE = "icmptype"; - public static final String ID = "id"; - public static final String IDS = "ids"; - public static final String IMPORT_INSTANCE_HOST_ID = "importinstancehostid"; - public static final String INDEX = "index"; - public static final String INSTANCES_DISKS_STATS_RETENTION_ENABLED = "instancesdisksstatsretentionenabled"; - public static final String INSTANCES_DISKS_STATS_RETENTION_TIME = "instancesdisksstatsretentiontime"; - public static final String INSTANCES_STATS_RETENTION_TIME = "instancesstatsretentiontime"; - public static final String INSTANCES_STATS_USER_ONLY = "instancesstatsuseronly"; - public static final String PREFIX = "prefix"; - public static final String PREVIOUS_ACL_RULE_ID = "previousaclruleid"; - public static final String PREVIOUS_OWNER_ID = "previousownerid"; - public static final String PREVIOUS_OWNER_NAME = "previousownername"; - public static final String NEXT_ACL_RULE_ID = "nextaclruleid"; - public static final String NEXT_HOP = "nexthop"; - public static final String MOVE_ACL_CONSISTENCY_HASH = "aclconsistencyhash"; - public static final String IMAGE_PATH = "imagepath"; - public static final String INSTANCE_CONVERSION_SUPPORTED = "instanceconversionsupported"; - public static final String INTERNAL_DNS1 = "internaldns1"; - public static final String INTERNAL_DNS2 = "internaldns2"; - public static final String INTERNET_PROTOCOL = "internetprotocol"; - public static final String INTERVAL_TYPE = "intervaltype"; - public static final String INSTANCE_LEASE_DURATION = "leaseduration"; - public static final String INSTANCE_LEASE_ENABLED = "instanceleaseenabled"; - public static final String INSTANCE_LEASE_EXPIRY_ACTION = "leaseexpiryaction"; - public static final String INSTANCE_LEASE_EXPIRY_DATE= "leaseexpirydate"; - public static final String IOPS_READ_RATE = "iopsreadrate"; - public static final String IOPS_READ_RATE_MAX = "iopsreadratemax"; - public static final String IOPS_READ_RATE_MAX_LENGTH = "iopsreadratemaxlength"; - public static final String IOPS_WRITE_RATE = "iopswriterate"; - 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 IP6_ADDRESSES = "ip6addresses"; - public static final String IP_ADDRESS_ID = "ipaddressid"; - public static final String IS_2FA_ENABLED = "is2faenabled"; - public static final String IS_2FA_VERIFIED = "is2faverified"; - - public static final String IS_2FA_MANDATED = "is2famandated"; - public static final String IS_ACTIVE = "isactive"; - public static final String IS_ASYNC = "isasync"; - public static final String IP_AVAILABLE = "ipavailable"; - public static final String IP_LIMIT = "iplimit"; - public static final String IP_TOTAL = "iptotal"; - public static final String IS_CONTROL_NODE = "iscontrolnode"; - public static final String IS_CLEANUP_REQUIRED = "iscleanuprequired"; - public static final String IS_DYNAMIC = "isdynamic"; - public static final String IS_EDGE = "isedge"; - public static final String IS_ENCRYPTED = "isencrypted"; - public static final String IS_EXTRACTABLE = "isextractable"; - public static final String IS_FEATURED = "isfeatured"; - public static final String IS_IMPLICIT = "isimplicit"; - public static final String IS_ISO = "isiso"; - public static final String IS_PORTABLE = "isportable"; - public static final String IS_PUBLIC = "ispublic"; - public static final String IS_PERSISTENT = "ispersistent"; - public static final String EGRESS_DEFAULT_POLICY = "egressdefaultpolicy"; - public static final String IS_READY = "isready"; - public static final String IS_RECURSIVE = "isrecursive"; - public static final String ISO_FILTER = "isofilter"; - public static final String ISO_ID = "isoid"; - public static final String ISO_GUEST_OS_NONE = "None"; - public static final String JAVA_DISTRIBUTION = "javadistribution"; - public static final String JAVA_VERSION = "javaversion"; - public static final String JOB_ID = "jobid"; - public static final String JOB_STATUS = "jobstatus"; - public static final String KEEPALIVE_ENABLED = "keepaliveenabled"; - public static final String KERNEL_VERSION = "kernelversion"; - public static final String KEYPAIR_ID = "keypairid"; - public static final String KEY = "key"; - public static final String LABEL = "label"; - public static final String LASTNAME = "lastname"; - public static final String LAST_BOOT = "lastboottime"; - public static final String LAST_SERVER_START = "lastserverstart"; - public static final String LAST_SERVER_STOP = "lastserverstop"; - public static final String LEASED = "leased"; - public static final String LEVEL = "level"; - public static final String LENGTH = "length"; - public static final String LIMIT = "limit"; - public static final String LIMIT_CPU_USE = "limitcpuuse"; - public static final String LIST_HOSTS = "listhosts"; - public static final String LOCATION_TYPE = "locationtype"; - public static final String LOCK = "lock"; - public static final String LUN = "lun"; - public static final String LBID = "lbruleid"; - public static final String LB_PROVIDER = "lbprovider"; - public static final String MAC_ADDRESS = "macaddress"; - public static final String MAC_ADDRESSES = "macaddresses"; - public static final String MANUAL_UPGRADE = "manualupgrade"; - public static final String MATCH_TYPE = "matchtype"; - public static final String MAX = "max"; - public static final String MAX_SNAPS = "maxsnaps"; - public static final String MAX_BACKUPS = "maxbackups"; - public static final String MAX_CPU_NUMBER = "maxcpunumber"; - public static final String MAX_MEMORY = "maxmemory"; - public static final String MEMORY_OVERCOMMIT_RATIO = "memoryOvercommitRatio"; - public static final String MESSAGE = "message"; - public static final String MIN_CPU_NUMBER = "mincpunumber"; - public static final String MIN_MEMORY = "minmemory"; - public static final String MIGRATION_TYPE = "migrationtype"; - public static final String MIGRATION_JOB_ID = "migrationjobid"; - public static final String MIGRATION_JOB_STATUS = "migrationjobstatus"; - public static final String MIGRATIONS = "migrations"; - public static final String MEMORY = "memory"; - public static final String MODE = "mode"; - public static final String MOUNT_CKS_ISO_ON_VR = "mountcksisoonvr"; - public static final String MULTI_ARCH = "ismultiarch"; - public static final String NSX_MODE = "nsxmode"; - public static final String NETWORK_MODE = "networkmode"; - public static final String NSX_ENABLED = "isnsxenabled"; - public static final String NAME = "name"; - public static final String METHOD_NAME = "methodname"; - 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 NICS = "nics"; - public static final String NIC_NETWORK_LIST = "nicnetworklist"; +// 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; + +public class ApiConstants { + public static final String ACCOUNT = "account"; + public static final String ACCOUNTS = "accounts"; + public static final String ACCOUNT_NAME = "accountname"; + public static final String ACCOUNT_STATE_TO_SHOW = "accountstatetoshow"; + public static final String ACCOUNT_TYPE = "accounttype"; + public static final String ACCOUNT_ID = "accountid"; + public static final String ACCOUNT_IDS = "accountids"; + public static final String ACCUMULATE = "accumulate"; + public static final String ACQUIRED = "acquired"; + public static final String ACTIVATION_RULE = "activationrule"; + public static final String ACTIVITY = "activity"; + public static final String ADAPTER_TYPE = "adaptertype"; + public static final String ADDITONAL_CONFIG_ENABLED = "additionalconfigenabled"; + public static final String ADDRESS = "address"; + public static final String ALGORITHM = "algorithm"; + public static final String ALIAS = "alias"; + public static final String ALLOCATED = "allocated"; + public static final String ALLOCATED_DATE = "allocateddate"; + public static final String ALLOCATED_ONLY = "allocatedonly"; + public static final String ALLOCATED_TIME = "allocated"; + public static final String ALLOWED_ROLE_TYPES = "allowedroletypes"; + public static final String ALLOW_USER_FORCE_STOP_VM = "allowuserforcestopvm"; + public static final String ANNOTATION = "annotation"; + public static final String API_KEY = "apikey"; + public static final String API_KEY_ACCESS = "apikeyaccess"; + public static final String ARCHIVED = "archived"; + public static final String ARCH = "arch"; + public static final String AS_NUMBER = "asnumber"; + public static final String AS_NUMBER_ID = "asnumberid"; + public static final String ASN_RANGE = "asnrange"; + public static final String ASN_RANGE_ID = "asnrangeid"; + public static final String API_KEY_FILTER = "apikeyfilter"; + public static final String ASYNC_BACKUP = "asyncbackup"; + public static final String AUTO_SELECT = "autoselect"; + public static final String USER_API_KEY = "userapikey"; + public static final String APPLIED = "applied"; + public static final String LIST_LB_VMIPS = "lbvmips"; + public static final String LIVE_PATCH = "livepatch"; + public static final String AVAILABLE = "available"; + public static final String AVAILABLE_SUBNETS = "availablesubnets"; + public static final String AVAILABLE_VIRTUAL_MACHINE_COUNT = "availablevirtualmachinecount"; + public static final String BACKUP_AVAILABLE = "backupavailable"; + public static final String BACKUP_ID = "backupid"; + public static final String BACKUP_LIMIT = "backuplimit"; + public static final String BACKUP_OFFERING_NAME = "backupofferingname"; + public static final String BACKUP_OFFERING_ID = "backupofferingid"; + public static final String BACKUP_STORAGE_AVAILABLE = "backupstorageavailable"; + public static final String BACKUP_STORAGE_LIMIT = "backupstoragelimit"; + public static final String BACKUP_STORAGE_TOTAL = "backupstoragetotal"; + public static final String BACKUP_VM_OFFERING_REMOVED = "vmbackupofferingremoved"; + public static final String IS_BACKUP_VM_EXPUNGED = "isbackupvmexpunged"; + public static final String BACKUP_TOTAL = "backuptotal"; + public static final String BALANCE = "balance"; + public static final String BALANCES = "balances"; + public static final String BASE64_IMAGE = "base64image"; + public static final String BGP_PEERS = "bgppeers"; + public static final String BGP_PEER_IDS = "bgppeerids"; + public static final String BATCH_SIZE = "batchsize"; + public static final String BITS = "bits"; + public static final String BOOTABLE = "bootable"; + public static final String BIND_DN = "binddn"; + public static final String BIND_PASSWORD = "bindpass"; + public static final String BLANK_INSTANCE = "blankinstance"; + public static final String BUS_ADDRESS = "busaddress"; + public static final String BYTES_READ_RATE = "bytesreadrate"; + public static final String BYTES_READ_RATE_MAX = "bytesreadratemax"; + public static final String BYTES_READ_RATE_MAX_LENGTH = "bytesreadratemaxlength"; + public static final String BYTES_WRITE_RATE = "byteswriterate"; + 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 CALLER = "caller"; + 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"; + public static final String CERTIFICATE = "certificate"; + 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 CERTIFICATE_ISSUER = "issuer"; + public static final String CERTIFICATE_SERIALNUM = "serialnum"; + public static final String CERTIFICATE_SUBJECT = "subject"; + public static final String CERTIFICATE_VALIDITY = "validity"; + public static final String CONVERT_INSTANCE_HOST_ID = "convertinstancehostid"; + public static final String CONVERT_INSTANCE_STORAGE_POOL_ID = "convertinstancepoolid"; + public static final String ENABLED_REVOCATION_CHECK = "enabledrevocationcheck"; + public static final String CLIENT_ADDRESS = "clientaddress"; + public static final String COMBINED_CAPACITY_ORDERING = "COMBINED"; + public static final String CONTROLLER = "controller"; + public static final String CONTROLLER_UNIT = "controllerunit"; + public static final String CONSOLE_ENDPOINT_CREATOR_ADDRESS = "consoleendpointcreatoraddress"; + public static final String COPY_IMAGE_TAGS = "copyimagetags"; + public static final String CPU_OVERCOMMIT_RATIO = "cpuOvercommitRatio"; + 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_ID = "datastoreid"; + public static final String DATASTORE_NAME = "datastorename"; + public static final String DATASTORE_PATH = "datastorepath"; + public static final String DATASTORE_STATE = "datastorestate"; + 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"; + public static final String CIDR = "cidr"; + public static final String CIDR_SIZE = "cidrsize"; + + public static final String IP6_CIDR = "ip6cidr"; + public static final String CIDR_LIST = "cidrlist"; + public static final String DEST_CIDR_LIST = "destcidrlist"; + public static final String CLEANUP = "cleanup"; + public static final String MAKEREDUNDANT = "makeredundant"; + public static final String CLUSTER_ID = "clusterid"; + public static final String CLUSTER_IDS = "clusterids"; + public static final String CLUSTER_NAME = "clustername"; + public static final String CLUSTER_TYPE = "clustertype"; + public static final String CN = "cn"; + public static final String COMMAND = "command"; + public static final String CMD_EVENT_TYPE = "cmdeventtype"; + public static final String CNI_CONFIG = "cniconfig"; + public static final String CNI_CONFIG_ID = "cniconfigurationid"; + public static final String CNI_CONFIG_DETAILS = "cniconfigdetails"; + public static final String CNI_CONFIG_NAME = "cniconfigname"; + public static final String CSI_ENABLED = "csienabled"; + public static final String COMPONENT = "component"; + public static final String CPU = "CPU"; + 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 CPU_LOAD_AVERAGE = "cpuloadaverage"; + public static final String CREATED = "created"; + public static final String CROSS_ZONE_INSTANCE_CREATION = "crosszoneinstancecreation"; + public static final String CTX_ACCOUNT_ID = "ctxaccountid"; + public static final String CTX_DETAILS = "ctxDetails"; + public static final String CTX_USER_ID = "ctxuserid"; + public static final String CTXSTARTEVENTID = "ctxstarteventid"; + public static final String CTX_START_EVENT_ID = "ctxStartEventId"; + public static final String CUSTOMIZED = "customized"; + public static final String CUSTOMIZED_IOPS = "customizediops"; + public static final String CUSTOM_ID = "customid"; + public static final String CUSTOM_ACTION_ID = "customactionid"; + public static final String CUSTOM_JOB_ID = "customjobid"; + public static final String CURRENCY = "currency"; + public static final String CURRENT_START_IP = "currentstartip"; + public static final String CURRENT_END_IP = "currentendip"; + public static final String ENCRYPT = "encrypt"; + public static final String ENCRYPT_FORMAT = "encryptformat"; + public static final String ENCRYPT_ROOT = "encryptroot"; + public static final String ENCRYPTION_SUPPORTED = "encryptionsupported"; + public static final String ETCD_IPS = "etcdips"; + public static final String MIN_IOPS = "miniops"; + public static final String MAX_IOPS = "maxiops"; + public static final String HYPERVISOR_SNAPSHOT_RESERVE = "hypervisorsnapshotreserve"; + public static final String DATACENTER_NAME = "datacentername"; + public static final String DATADISKS_DETAILS = "datadisksdetails"; + public static final String DATADISK_OFFERING_LIST = "datadiskofferinglist"; + public static final String DATE = "date"; + public static final String DEFAULT_VALUE = "defaultvalue"; + public static final String DELETE_PROTECTION = "deleteprotection"; + public static final String DESCRIPTION = "description"; + public static final String DESTINATION = "destination"; + public static final String DESTINATION_ZONE_ID = "destzoneid"; + public static final String DETAILS = "details"; + public static final String DEVICE_ID = "deviceid"; + public static final String DEVICE_IDS = "deviceids"; + public static final String DEVICE_NAME = "devicename"; + 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 ORCHESTRATOR_REQUIRES_PREPARE_VM = "orchestratorrequirespreparevm"; + public static final String OVERRIDE_DISK_OFFERING_ID = "overridediskofferingid"; + public static final String DISK_KBS_READ = "diskkbsread"; + public static final String DISK_KBS_WRITE = "diskkbswrite"; + public static final String DISK_IO_READ = "diskioread"; + public static final String DISK_IO_WRITE = "diskiowrite"; + public static final String DISK_IO_PSTOTAL = "diskiopstotal"; + public static final String DISK_SIZE = "disksize"; + public static final String DISK_SIZE_STRICTNESS = "disksizestrictness"; + public static final String DISK_OFFERING_STRICTNESS = "diskofferingstrictness"; + public static final String DOWNLOAD_DETAILS = "downloaddetails"; + public static final String UTILIZATION = "utilization"; + public static final String DRIVER = "driver"; + public static final String ROOT_DISK_SIZE = "rootdisksize"; + public static final String DHCP_OPTIONS_NETWORK_LIST = "dhcpoptionsnetworklist"; + public static final String DHCP_OPTIONS = "dhcpoptions"; + public static final String DHCP_PREFIX = "dhcp:"; + public static final String DISPLAY_NAME = "displayname"; + public static final String DISPLAY_NETWORK = "displaynetwork"; + public static final String DISPLAY_NIC = "displaynic"; + public static final String DISPLAY_TEXT = "displaytext"; + public static final String DISPLAY_VM = "displayvm"; + public static final String DISPLAY_OFFERING = "displayoffering"; + public static final String DISPLAY_VOLUME = "displayvolume"; + public static final String DNS1 = "dns1"; + public static final String DNS2 = "dns2"; + public static final String IP6_DNS1 = "ip6dns1"; + public static final String IP6_DNS2 = "ip6dns2"; + public static final String DOMAIN = "domain"; + public static final String DOMAIN_DETAILS = "domaindetails"; + public static final String DOMAIN_PATH = "domainpath"; + public static final String DOMAIN_ID = "domainid"; + public static final String DOMAIN__ID = "domainId"; + public static final String DUMMY = "dummy"; + public static final String DURATION = "duration"; + public static final String ELIGIBLE = "eligible"; + public static final String EMAIL = "email"; + public static final String ENABLE_CSI = "enablecsi"; + public static final String END_ASN = "endasn"; + public static final String END_DATE = "enddate"; + public static final String END_IP = "endip"; + public static final String END_IPV6 = "endipv6"; + public static final String END_PORT = "endport"; + public static final String ENTRY_TIME = "entrytime"; + public static final String ERROR_MESSAGE = "errormessage"; + public static final String EVENT_ID = "eventid"; + public static final String EVENT_TYPE = "eventtype"; + public static final String EXPIRES = "expires"; + public static final String EXTRA_CONFIG = "extraconfig"; + public static final String EXTRA_PARAMS = "extraparams"; + public static final String EXTRA_DHCP_OPTION = "extradhcpoption"; + public static final String EXTRA_DHCP_OPTION_NAME = "extradhcpoptionname"; + public static final String EXTRA_DHCP_OPTION_CODE = "extradhcpoptioncode"; + public static final String EXTRA_DHCP_OPTION_VALUE = "extradhcpvalue"; + public static final String EXTERNAL = "external"; + public static final String EXTERNAL_UUID = "externaluuid"; + public static final String EXTERNAL_DETAILS = "externaldetails"; + public static final String PARAMETERS = "parameters"; + public static final String EXTENSION = "extension"; + public static final String EXTENSION_ID = "extensionid"; + public static final String EXTENSION_NAME = "extensionname"; + public static final String EXTENSIONS_PATH = "extensionspath"; + public static final String FENCE = "fence"; + public static final String FETCH_LATEST = "fetchlatest"; + public static final String FILESYSTEM = "filesystem"; + public static final String FIRSTNAME = "firstname"; + public static final String FORCED = "forced"; + public static final String FORCED_DESTROY_LOCAL_STORAGE = "forcedestroylocalstorage"; + public static final String FORCE_CONVERT_TO_POOL = "forceconverttopool"; + + public static final String FORCE_DELETE_HOST = "forcedeletehost"; + public static final String FORCE_MS_TO_IMPORT_VM_FILES = "forcemstoimportvmfiles"; + public static final String FORCE_UPDATE_OS_TYPE = "forceupdateostype"; + public static final String FORMAT = "format"; + public static final String FOR_VIRTUAL_NETWORK = "forvirtualnetwork"; + public static final String FOR_SYSTEM_VMS = "forsystemvms"; + public static final String FOR_PROVIDER = "forprovider"; + public static final String FROM_CHECKPOINT_ID = "fromcheckpointid"; + public static final String FULL_PATH = "fullpath"; + public static final String GATEWAY = "gateway"; + public static final String IP6_GATEWAY = "ip6gateway"; + public static final String GROUP = "group"; + public static final String SUBGROUP = "subgroup"; + public static final String GROUP_ID = "groupid"; + public static final String GSLB_LB_METHOD = "gslblbmethod"; + public static final String GSLB_SERVICE_DOMAIN_NAME = "gslbdomainname"; + public static final String GSLB_SERVICE_TYPE = "gslbservicetype"; + public static final String GSLB_STICKY_SESSION_METHOD = "gslbstickysessionmethodname"; + public static final String GSLB_LBRULE_WEIGHT_MAP = "gslblbruleweightsmap"; + public static final String GUEST_CIDR_ADDRESS = "guestcidraddress"; + public static final String GUEST_VLAN_RANGE = "guestvlanrange"; + public static final String HA_ENABLE = "haenable"; + public static final String HA_PROVIDER = "haprovider"; + public static final String HA_STATE = "hastate"; + public static final String HEALTH = "health"; + public static final String HEADERS = "headers"; + public static final String HIDE_IP_ADDRESS_USAGE = "hideipaddressusage"; + public static final String HOST_ID = "hostid"; + public static final String HOST_IDS = "hostids"; + public static final String HOST_IP = "hostip"; + public static final String HOST_NAME = "hostname"; + public static final String HOST = "host"; + public static final String HOST_CONTROL_STATE = "hostcontrolstate"; + public static final String HOSTS_MAP = "hostsmap"; + public static final String HTTP_REQUEST_TYPE = "httprequesttype"; + public static final String HYPERVISOR = "hypervisor"; + public static final String INLINE = "inline"; + public static final String INSTANCE = "instance"; + public static final String ICMP_CODE = "icmpcode"; + public static final String ICMP_TYPE = "icmptype"; + public static final String ID = "id"; + public static final String IDS = "ids"; + public static final String IMPORT_INSTANCE_HOST_ID = "importinstancehostid"; + public static final String INDEX = "index"; + public static final String INSTANCES_DISKS_STATS_RETENTION_ENABLED = "instancesdisksstatsretentionenabled"; + public static final String INSTANCES_DISKS_STATS_RETENTION_TIME = "instancesdisksstatsretentiontime"; + public static final String INSTANCES_STATS_RETENTION_TIME = "instancesstatsretentiontime"; + public static final String INSTANCES_STATS_USER_ONLY = "instancesstatsuseronly"; + public static final String PREFIX = "prefix"; + public static final String PREVIOUS_ACL_RULE_ID = "previousaclruleid"; + public static final String PREVIOUS_OWNER_ID = "previousownerid"; + public static final String PREVIOUS_OWNER_NAME = "previousownername"; + public static final String NEXT_ACL_RULE_ID = "nextaclruleid"; + public static final String NEXT_HOP = "nexthop"; + public static final String MOVE_ACL_CONSISTENCY_HASH = "aclconsistencyhash"; + public static final String IMAGE_PATH = "imagepath"; + public static final String INSTANCE_CONVERSION_SUPPORTED = "instanceconversionsupported"; + public static final String INTERNAL_DNS1 = "internaldns1"; + public static final String INTERNAL_DNS2 = "internaldns2"; + public static final String INTERNET_PROTOCOL = "internetprotocol"; + public static final String INTERVAL_TYPE = "intervaltype"; + public static final String INSTANCE_LEASE_DURATION = "leaseduration"; + public static final String INSTANCE_LEASE_ENABLED = "instanceleaseenabled"; + public static final String INSTANCE_LEASE_EXPIRY_ACTION = "leaseexpiryaction"; + public static final String INSTANCE_LEASE_EXPIRY_DATE= "leaseexpirydate"; + public static final String IOPS_READ_RATE = "iopsreadrate"; + public static final String IOPS_READ_RATE_MAX = "iopsreadratemax"; + public static final String IOPS_READ_RATE_MAX_LENGTH = "iopsreadratemaxlength"; + public static final String IOPS_WRITE_RATE = "iopswriterate"; + 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 IP6_ADDRESSES = "ip6addresses"; + public static final String IP_ADDRESS_ID = "ipaddressid"; + public static final String IS_2FA_ENABLED = "is2faenabled"; + public static final String IS_2FA_VERIFIED = "is2faverified"; + + public static final String IS_2FA_MANDATED = "is2famandated"; + public static final String IS_ACTIVE = "isactive"; + public static final String IS_ASYNC = "isasync"; + public static final String IP_AVAILABLE = "ipavailable"; + public static final String IP_LIMIT = "iplimit"; + public static final String IP_TOTAL = "iptotal"; + public static final String IS_CONTROL_NODE = "iscontrolnode"; + public static final String IS_CLEANUP_REQUIRED = "iscleanuprequired"; + public static final String IS_DYNAMIC = "isdynamic"; + public static final String IS_EDGE = "isedge"; + public static final String IS_ENCRYPTED = "isencrypted"; + public static final String IS_EXTRACTABLE = "isextractable"; + public static final String IS_FEATURED = "isfeatured"; + public static final String IS_IMPLICIT = "isimplicit"; + public static final String IS_ISO = "isiso"; + public static final String IS_PORTABLE = "isportable"; + public static final String IS_PUBLIC = "ispublic"; + public static final String IS_PERSISTENT = "ispersistent"; + public static final String EGRESS_DEFAULT_POLICY = "egressdefaultpolicy"; + public static final String IS_READY = "isready"; + public static final String IS_RECURSIVE = "isrecursive"; + public static final String ISO_FILTER = "isofilter"; + public static final String ISO_ID = "isoid"; + public static final String ISO_GUEST_OS_NONE = "None"; + public static final String JAVA_DISTRIBUTION = "javadistribution"; + public static final String JAVA_VERSION = "javaversion"; + public static final String JOB_ID = "jobid"; + public static final String JOB_STATUS = "jobstatus"; + public static final String KEEPALIVE_ENABLED = "keepaliveenabled"; + public static final String KERNEL_VERSION = "kernelversion"; + public static final String KEYPAIR_ID = "keypairid"; + public static final String KEY = "key"; + public static final String LABEL = "label"; + public static final String LASTNAME = "lastname"; + public static final String LAST_BOOT = "lastboottime"; + public static final String LAST_SERVER_START = "lastserverstart"; + public static final String LAST_SERVER_STOP = "lastserverstop"; + public static final String LEASED = "leased"; + public static final String LEVEL = "level"; + public static final String LENGTH = "length"; + public static final String LIMIT = "limit"; + public static final String LIMIT_CPU_USE = "limitcpuuse"; + public static final String LIST_HOSTS = "listhosts"; + public static final String LOCATION_TYPE = "locationtype"; + public static final String LOCK = "lock"; + public static final String LUN = "lun"; + public static final String LBID = "lbruleid"; + public static final String LB_PROVIDER = "lbprovider"; + public static final String MAC_ADDRESS = "macaddress"; + public static final String MAC_ADDRESSES = "macaddresses"; + public static final String MANUAL_UPGRADE = "manualupgrade"; + public static final String MATCH_TYPE = "matchtype"; + public static final String MAX = "max"; + public static final String MAX_SNAPS = "maxsnaps"; + public static final String MAX_BACKUPS = "maxbackups"; + public static final String MAX_CPU_NUMBER = "maxcpunumber"; + public static final String MAX_MEMORY = "maxmemory"; + public static final String MEMORY_OVERCOMMIT_RATIO = "memoryOvercommitRatio"; + public static final String MESSAGE = "message"; + public static final String MIN_CPU_NUMBER = "mincpunumber"; + public static final String MIN_MEMORY = "minmemory"; + public static final String MIGRATION_TYPE = "migrationtype"; + public static final String MIGRATION_JOB_ID = "migrationjobid"; + public static final String MIGRATION_JOB_STATUS = "migrationjobstatus"; + public static final String MIGRATIONS = "migrations"; + public static final String MEMORY = "memory"; + public static final String MODE = "mode"; + public static final String MOUNT_CKS_ISO_ON_VR = "mountcksisoonvr"; + public static final String MULTI_ARCH = "ismultiarch"; + public static final String NSX_MODE = "nsxmode"; + public static final String NETWORK_MODE = "networkmode"; + public static final String NSX_ENABLED = "isnsxenabled"; + public static final String NAME = "name"; + public static final String METHOD_NAME = "methodname"; + 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 NICS = "nics"; + public static final String NIC_NETWORK_LIST = "nicnetworklist"; public static final String NIC_IP_ADDRESS_LIST = "nicipaddresslist"; - public static final String NIC_MAC_ADDRESS_LIST = "nicmacaddresslist"; - public static final String NIC_MULTIQUEUE_NUMBER = "nicmultiqueuenumber"; - public static final String NIC_PACKED_VIRTQUEUES_ENABLED = "nicpackedvirtqueuesenabled"; - public static final String NEW_START_IP = "newstartip"; - public static final String NEW_END_IP = "newendip"; - public static final String KUBERNETES_NODE_VERSION = "kubernetesnodeversion"; - public static final String NUMA_NODE = "numanode"; - public static final String NUM_RETRIES = "numretries"; - public static final String OFFER_HA = "offerha"; - public static final String OS_DISTRIBUTION = "osdistribution"; - public static final String IS_SYSTEM_OFFERING = "issystem"; - public static final String IS_DEFAULT_USE = "defaultuse"; - public static final String OLD_FORMAT = "oldformat"; - public static final String OP = "op"; - public static final String OPTION = "option"; - public static final String OPTIONS = "options"; - public static final String OS_CATEGORY_ID = "oscategoryid"; - public static final String OS_CATEGORY_NAME = "oscategoryname"; - public static final String OS_NAME = "osname"; - 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"; - public static final String GPU_CARD_ID = "gpucardid"; - public static final String GPU_CARD_NAME = "gpucardname"; - public static final String GPU_COUNT = "gpucount"; - public static final String GPU_DISPLAY = "gpudisplay"; - public static final String GPU_DEVICE_TYPE = "gpudevicetype"; - public static final String GPU_ENABLED = "gpuenabled"; - public static final String MAX_VGPU_PER_PHYSICAL_GPU = "maxvgpuperphysicalgpu"; - public static final String GUEST_OS_LIST = "guestoslist"; - public static final String GUEST_OS_COUNT = "guestoscount"; - public static final String OS_MAPPING_CHECK_ENABLED = "osmappingcheckenabled"; - public static final String OUTOFBANDMANAGEMENT_POWERSTATE = "outofbandmanagementpowerstate"; - public static final String OUTOFBANDMANAGEMENT_ENABLED = "outofbandmanagementenabled"; - public static final String OUTPUT = "output"; - public static final String PROPERTIES = "properties"; - public static final String PARAMS = "params"; - public static final String PARENT = "parent"; - public static final String PARENT_ID = "parentid"; - public static final String PARENT_DOMAIN_ID = "parentdomainid"; - public static final String PARENT_GPU_DEVICE_ID = "parentgpudeviceid"; - public static final String PARENT_SUBNET = "parentsubnet"; - public static final String PARENT_TEMPLATE_ID = "parenttemplateid"; - public static final String PASSWORD = "password"; - public static final String PCI_ROOT = "pciroot"; - public static final String CURRENT_PASSWORD = "currentpassword"; - public static final String SHOULD_UPDATE_PASSWORD = "update_passwd_on_host"; - public static final String PASSWORD_ENABLED = "passwordenabled"; - public static final String SSHKEY_ENABLED = "sshkeyenabled"; - public static final String PATH = "path"; - public static final String PATH_READY = "pathready"; - public static final String PAYLOAD = "payload"; - public static final String PAYLOAD_URL = "payloadurl"; - public static final String PEERS = "peers"; - public static final String PEER_ID = "peerid"; - public static final String PEER_NAME = "peername"; - public static final String PEER_MSID = "peermsid"; - public static final String PEER_RUNID = "peerrunid"; - public static final String PEER_SERVICE_IP = "peerserviceip"; - public static final String PEER_SERVICE_PORT = "peerserviceport"; - public static final String PEER_STATE = "peerstate"; - public static final String POD_ID = "podid"; - public static final String POD_NAME = "podname"; - public static final String POD_IDS = "podids"; - public static final String POLICY_ID = "policyid"; - public static final String PORT = "port"; - 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 PRECEDENCE = "precedence"; - public static final String PREPARE_VM = "preparevm"; - public static final String PRESERVE_IP = "preserveip"; - public static final String PRIVATE_INTERFACE = "privateinterface"; - public static final String PRIVATE_IP = "privateip"; - public static final String PRIVATE_PORT = "privateport"; - public static final String PRIVATE_START_PORT = "privateport"; - public static final String PRIVATE_END_PORT = "privateendport"; - public static final String PRIVATE_ZONE = "privatezone"; - public static final String PROTOCOL = "protocol"; - public static final String PROVISIONINGTYPE = "provisioningtype"; - public static final String PUBLIC_INTERFACE = "publicinterface"; - public static final String PUBLIC_IP_ID = "publicipid"; - public static final String PUBLIC_IP = "publicip"; - public static final String PUBLIC_PORT = "publicport"; - public static final String PUBLIC_START_PORT = "publicport"; - public static final String PUBLIC_END_PORT = "publicendport"; - public static final String PUBLIC_ZONE = "publiczone"; - public static final String PURGE_RESOURCES = "purgeresources"; - public static final String RAM = "RAM"; - public static final String REBALANCE = "rebalance"; - public static final String RECEIVED_BYTES = "receivedbytes"; - public static final String RECONNECT = "reconnect"; - public static final String RECOVER = "recover"; - public static final String REPAIR = "repair"; - public static final String REPETITION_ALLOWED = "repetitionallowed"; - public static final String REQUIRES_HVM = "requireshvm"; - public static final String RESERVED_RESOURCE_DETAILS = "reservedresourcedetails"; - public static final String RESOURCES = "resources"; - public static final String RESOURCE_COUNT = "resourcecount"; - public static final String RESOURCE_NAME = "resourcename"; - public static final String RESOURCE_TYPE = "resourcetype"; - public static final String RESOURCE_TYPE_NAME = "resourcetypename"; - public static final String RESPONSE = "response"; - public static final String RETRIEVE_ONLY_RESOURCE_COUNT = "retrieveonlyresourcecount"; - public static final String REVERTABLE = "revertable"; - public static final String REVOKED = "revoked"; - public static final String REGISTERED = "registered"; - public static final String QUALIFIERS = "qualifiers"; - public static final String QUERY_FILTER = "queryfilter"; - public static final String QUIESCE_VM = "quiescevm"; - public static final String SCHEDULE = "schedule"; - public static final String SCHEDULE_ID = "scheduleid"; - public static final String SCOPE = "scope"; - public static final String SEARCH_BASE = "searchbase"; - public static final String SECONDARY_IP = "secondaryip"; - public static final String SECURITY_GROUP_IDS = "securitygroupids"; - public static final String SECURITY_GROUP_NAMES = "securitygroupnames"; - public static final String SECURITY_GROUP_NAME = "securitygroupname"; - public static final String SECURITY_GROUP_ID = "securitygroupid"; - public static final String SENT = "sent"; - public static final String SENT_BYTES = "sentbytes"; - public static final String SERIAL = "serial"; - public static final String SERVICE_IP = "serviceip"; - public static final String SERVICE_OFFERING_ID = "serviceofferingid"; - public static final String SERVICE_OFFERING_NAME = "serviceofferingname"; - public static final String SESSIONKEY = "sessionkey"; - public static final String SHOW_CAPACITIES = "showcapacities"; - public static final String SHOW_REMOVED = "showremoved"; - public static final String SHOW_RESOURCES = "showresources"; - public static final String SHOW_RESOURCE_ICON = "showicon"; - public static final String SHOW_INACTIVE = "showinactive"; - public static final String SHOW_UNIQUE = "showunique"; - public static final String SHOW_PERMISSIONS = "showpermissions"; - public static final String SIGNATURE = "signature"; - public static final String SIGNATURE_VERSION = "signatureversion"; - public static final String SINCE = "since"; - public static final String SITE_NAME = "sitename"; - public static final String SIZE = "size"; - public static final String SIZEGB = "sizegb"; - public static final String SNAPSHOT = "snapshot"; - public static final String SNAPSHOT_ID = "snapshotid"; - public static final String SNAPSHOT_POLICY_ID = "snapshotpolicyid"; - public static final String SNAPSHOT_TYPE = "snapshottype"; - public static final String SNAPSHOT_QUIESCEVM = "quiescevm"; - - public static final String USE_STORAGE_REPLICATION = "usestoragereplication"; - - public static final String SOURCE_CIDR_LIST = "sourcecidrlist"; - public static final String SOURCE_OFFERING_ID = "sourceofferingid"; - public static final String SOURCE_ZONE_ID = "sourcezoneid"; - public static final String SSL_VERIFICATION = "sslverification"; - public static final String START_ASN = "startasn"; - public static final String START_DATE = "startdate"; - public static final String START_ID = "startid"; - public static final String START_IP = "startip"; - public static final String START_IPV6 = "startipv6"; - public static final String START_PORT = "startport"; - public static final String STATE = "state"; - public static final String STATS = "stats"; - public static final String STATUS = "status"; - public static final String STORAGE_TYPE = "storagetype"; - public static final String STORAGE_POLICY = "storagepolicy"; - public static final String STORAGE_MOTION_ENABLED = "storagemotionenabled"; - public static final String STORAGE_CAPABILITIES = "storagecapabilities"; - public static final String STORAGE_CUSTOM_STATS = "storagecustomstats"; - public static final String SUBNET = "subnet"; - public static final String OWNER = "owner"; - public static final String SWAP_OWNER = "swapowner"; - public static final String SYSTEM_VM_TYPE = "systemvmtype"; - public static final String TAGS = "tags"; - public static final String STORAGE_TAGS = "storagetags"; - public static final String STORAGE_ACCESS_GROUPS = "storageaccessgroups"; - public static final String STORAGE_ACCESS_GROUP = "storageaccessgroup"; - public static final String CLUSTER_STORAGE_ACCESS_GROUPS = "clusterstorageaccessgroups"; - public static final String POD_STORAGE_ACCESS_GROUPS = "podstorageaccessgroups"; - public static final String ZONE_STORAGE_ACCESS_GROUPS = "zonestorageaccessgroups"; - public static final String SUCCESS = "success"; - public static final String SUCCESS_MESSAGE = "successmessage"; - public static final String SUITABLE_FOR_VM = "suitableforvirtualmachine"; - public static final String SUPPORTS_STORAGE_SNAPSHOT = "supportsstoragesnapshot"; - public static final String TARGET_IQN = "targetiqn"; - public static final String TASKS_FILTER = "tasksfilter"; - public static final String TEMPLATE_FILTER = "templatefilter"; - public static final String TEMPLATE_ID = "templateid"; - public static final String TEMPLATE_IDS = "templateids"; - public static final String TEMPLATE_NAME = "templatename"; - public static final String TEMPLATE_TYPE = "templatetype"; - public static final String TEMPLATE_FORMAT = "templateformat"; - public static final String TIMEOUT = "timeout"; - public static final String TIMEZONE = "timezone"; - public static final String TIMEZONEOFFSET = "timezoneoffset"; - public static final String TENANT_NAME = "tenantname"; - public static final String TOTAL = "total"; - public static final String TOTAL_SUBNETS = "totalsubnets"; - public static final String TO_CHECKPOINT_ID = "tocheckpointid"; - public static final String TOTAL_QUOTA = "totalquota"; - public static final String TYPE = "type"; - public static final String TRUST_STORE = "truststore"; - public static final String TRUST_STORE_PASSWORD = "truststorepass"; - public static final String UNIT = "unit"; - public static final String URL = "url"; - public static final String USAGE_INTERFACE = "usageinterface"; - public static final String USED = "used"; - public static final String USED_SUBNETS = "usedsubnets"; - public static final String USED_IOPS = "usediops"; - public static final String USER_DATA = "userdata"; - - public static final String USER_DATA_NAME = "userdataname"; - public static final String USER_DATA_ID = "userdataid"; - public static final String USER_DATA_POLICY = "userdatapolicy"; - public static final String USER_DATA_DETAILS = "userdatadetails"; - public static final String USER_DATA_PARAMS = "userdataparams"; - public static final String USER_FILTER = "userfilter"; - public static final String USER_ID = "userid"; - public static final String USER_SOURCE = "usersource"; - public static final String USER_CONFLICT_SOURCE = "conflictingusersource"; - public static final String USE_SSL = "ssl"; - public static final String USERNAME = "username"; - public static final String USER_CONFIGURABLE = "userconfigurable"; - public static final String USER_SECURITY_GROUP_LIST = "usersecuritygrouplist"; - public static final String USER_SECRET_KEY = "usersecretkey"; - public static final String USE_VDDK = "usevddk"; - public static final String USE_VIRTUAL_NETWORK = "usevirtualnetwork"; - public static final String USE_VIRTUAL_ROUTER_IP_RESOLVER = "userouteripresolver"; - public static final String UPDATE_IN_SEQUENCE = "updateinsequence"; - public static final String VALIDATION_FORMAT = "validationformat"; - public static final String VALUE = "value"; - public static final String VALUE_OPTIONS = "valueoptions"; - public static final String VENDOR_ID = "vendorid"; - public static final String VENDOR_NAME = "vendorname"; - public static final String VGPU_PROFILE_ID = "vgpuprofileid"; - public static final String VGPU_PROFILE_NAME = "vgpuprofilename"; - public static final String VIRTUAL_MACHINE = "virtualmachine"; - public static final String VIRTUAL_MACHINE_ID = "virtualmachineid"; - public static final String VIRTUAL_MACHINE_IDS = "virtualmachineids"; - public static final String VIRTUAL_MACHINE_NAME = "virtualmachinename"; - public static final String VIRTUAL_MACHINE_ID_IP = "vmidipmap"; - public static final String VIRTUAL_MACHINE_COUNT = "virtualmachinecount"; - public static final String VIRTUAL_MACHINE_TYPE = "virtualmachinetype"; - public static final String VIRTUAL_MACHINE_STATE = "vmstate"; - public static final String VIRTUAL_MACHINES = "virtualmachines"; - public static final String USAGE_ID = "usageid"; - public static final String USAGE_TYPE = "usagetype"; - public static final String INCLUDE_TAGS = "includetags"; - - public static final String VLAN = "vlan"; - public static final String VLAN_RANGE = "vlanrange"; - public static final String WORKER_SERVICE_OFFERING_ID = "workerofferingid"; - public static final String WORKER_SERVICE_OFFERING_NAME = "workerofferingname"; - public static final String CONTROL_SERVICE_OFFERING_ID = "controlofferingid"; - public static final String CONTROL_SERVICE_OFFERING_NAME = "controlofferingname"; - public static final String ETCD_SERVICE_OFFERING_ID = "etcdofferingid"; - public static final String ETCD_SERVICE_OFFERING_NAME = "etcdofferingname"; - 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 IS_ALLOCATED = "isallocated"; - public static final String IS_DEDICATED = "isdedicated"; - public static final String TAKEN = "taken"; - public static final String VM_AVAILABLE = "vmavailable"; - public static final String VM_DETAILS = "vmdetails"; - public static final String VM_LIMIT = "vmlimit"; - public static final String VM_TOTAL = "vmtotal"; - public static final String VM_SETTINGS = "vmsettings"; - public static final String VM_TYPE = "vmtype"; - public static final String VNET = "vnet"; - public static final String IS_VOLATILE = "isvolatile"; - public static final String VOLUME_ID = "volumeid"; - public static final String VOLUMES = "volumes"; - public static final String VOLUME_CHECK_RESULT = "volumecheckresult"; - public static final String VOLUME_REPAIR_RESULT = "volumerepairresult"; - - public static final String ZONE = "zone"; - public static final String ZONE_ID = "zoneid"; - public static final String ZONE_NAME = "zonename"; - public static final String ZONE_WISE = "zonewise"; - public static final String NETWORK_TYPE = "networktype"; - public static final String PAGE = "page"; - public static final String PAGE_SIZE = "pagesize"; - public static final String COUNT = "count"; - public static final String TRAFFIC_TYPE = "traffictype"; - public static final String NETWORK_OFFERING_ID = "networkofferingid"; - public static final String TIER_NETWORK_OFFERINGS = "tiernetworkofferings"; - public static final String NETWORK_IDS = "networkids"; - public static final String NETWORK_ID = "networkid"; - public static final String NETWORK_FILTER = "networkfilter"; - public static final String NIC_ID = "nicid"; - public static final String SPECIFY_AS_NUMBER = "specifyasnumber"; - public static final String SPECIFY_VLAN = "specifyvlan"; - public static final String IS_DEFAULT = "isdefault"; - public static final String IS_SYSTEM = "issystem"; - public static final String IS_USER_DEFINED = "isuserdefined"; - public static final String AVAILABILITY = "availability"; - public static final String NETWORKRATE = "networkrate"; - public static final String HOST_TAGS = "hosttags"; - public static final String SSH_KEYPAIR = "keypair"; - public static final String SSH_KEYPAIRS = "keypairs"; - public static final String HTTPMETHOD = "httpmethod"; - public static final String HOST_CPU_CAPACITY = "hostcpucapacity"; - public static final String HOST_CPU_NUM = "hostcpunum"; - public static final String HOST_MEM_CAPACITY = "hostmemcapacity"; - public static final String HOST_MAC = "hostmac"; - public static final String HOST_TAG = "hosttag"; - public static final String PXE_SERVER_TYPE = "pxeservertype"; - public static final String LINMIN_USERNAME = "linminusername"; - public static final String LINMIN_PASSWORD = "linminpassword"; - public static final String LINMIN_APID = "linminapid"; - public static final String DHCP_SERVER_TYPE = "dhcpservertype"; - public static final String LINK_LOCAL_IP = "linklocalip"; - public static final String LINK_LOCAL_MAC_ADDRESS = "linklocalmacaddress"; - public static final String LINK_LOCAL_MAC_NETMASK = "linklocalnetmask"; - public static final String LINK_LOCAL_NETWORK_ID = "linklocalnetworkid"; - public static final String PRIVATE_MAC_ADDRESS = "privatemacaddress"; - public static final String PRIVATE_NETMASK = "privatenetmask"; - public static final String PRIVATE_NETWORK_ID = "privatenetworkid"; - public static final String ALLOCATION_STATE = "allocationstate"; - public static final String MANAGED_STATE = "managedstate"; - public static final String MANAGEMENT_SERVER_ID = "managementserverid"; - public static final String MANAGEMENT_SERVER_NAME = "managementservername"; - public static final String STORAGE = "storage"; - public static final String STORAGE_ID = "storageid"; - public static final String PING_STORAGE_SERVER_IP = "pingstorageserverip"; - public static final String PING_DIR = "pingdir"; - public static final String TFTP_DIR = "tftpdir"; - public static final String PING_CIFS_USERNAME = "pingcifsusername"; - public static final String PING_CIFS_PASSWORD = "pingcifspassword"; - public static final String CHECKSUM = "checksum"; - public static final String NETWORK_DEVICE_TYPE = "networkdevicetype"; - public static final String NETWORK_DEVICE_PARAMETER_LIST = "networkdeviceparameterlist"; - public static final String ZONE_TOKEN = "zonetoken"; - public static final String DHCP_PROVIDER = "dhcpprovider"; - public static final String RESULT = "result"; - public static final String RESUME = "resume"; - public static final String LUN_ID = "lunId"; - public static final String IQN = "iqn"; - public static final String AGGREGATE_NAME = "aggregatename"; - public static final String POOL_NAME = "poolname"; - public static final String VOLUME_NAME = "volumename"; - public static final String VOLUME_STATE = "volumestate"; - public static final String SNAPSHOT_POLICY = "snapshotpolicy"; - public static final String SNAPSHOT_RESERVATION = "snapshotreservation"; - public static final String IP_NETWORK_LIST = "iptonetworklist"; - public static final String PARAM_LIST = "param"; - public static final String FOR_LOAD_BALANCING = "forloadbalancing"; - public static final String KEYBOARD = "keyboard"; - public static final String OPEN_FIREWALL = "openfirewall"; - public static final String TEMPLATE_TAG = "templatetag"; - public static final String HYPERVISOR_VERSION = "hypervisorversion"; - public static final String MAX_GUESTS_LIMIT = "maxguestslimit"; - public static final String MAX_DATA_VOLUMES_LIMIT = "maxdatavolumeslimit"; - public static final String MAX_HOSTS_PER_CLUSTER = "maxhostspercluster"; - public static final String PROJECT_ID = "projectid"; - public static final String PROJECT_IDS = "projectids"; - public static final String PROJECT = "project"; - public static final String ROLE = "role"; - public static final String ROLE_ID = "roleid"; - public static final String PROJECT_ROLE_ID = "projectroleid"; - public static final String PROJECT_ROLE_NAME = "projectrolename"; - public static final String ROLE_TYPE = "roletype"; - public static final String ROLE_NAME = "rolename"; - public static final String PERMISSION = "permission"; - public static final String PERMISSIONS = "permissions"; - public static final String RULE = "rule"; - public static final String RULES = "rules"; - public static final String RULE_ID = "ruleid"; - public static final String PROJECT_ROLE_PERMISSION_ID = "projectrolepermissionid"; - public static final String RULE_ORDER = "ruleorder"; - public static final String USER = "user"; - public static final String ACTIVE_ONLY = "activeonly"; - public static final String TOKEN = "token"; - public static final String ACCEPT = "accept"; - public static final String SORT_KEY = "sortkey"; - public static final String ACCOUNT_DETAILS = "accountdetails"; - public static final String SERVICE_OFFERING_DETAILS = "serviceofferingdetails"; - public static final String SERVICE_PROVIDER_LIST = "serviceproviderlist"; - public static final String SERVICE_CAPABILITY_LIST = "servicecapabilitylist"; - public static final String CAN_CHOOSE_SERVICE_CAPABILITY = "canchooseservicecapability"; - public static final String PROVIDER = "provider"; - public static final String OAUTH_PROVIDER = "oauthprovider"; - public static final String OAUTH_SECRET_KEY = "secretkey"; - public static final String MANAGED = "managed"; - public static final String CAPACITY_BYTES = "capacitybytes"; - public static final String CAPACITY_IOPS = "capacityiops"; - public static final String NETWORK_SPEED = "networkspeed"; - public static final String BROADCAST_DOMAIN_RANGE = "broadcastdomainrange"; - public static final String BROADCAST_URI = "broadcasturi"; - public static final String ISOLATION_METHOD = "isolationmethod"; - public static final String ISOLATION_METHODS = "isolationmethods"; - public static final String PHYSICAL_NETWORK_ID = "physicalnetworkid"; - public static final String PHYSICAL_NETWORK_NAME = "physicalnetworkname"; - public static final String DEST_PHYSICAL_NETWORK_ID = "destinationphysicalnetworkid"; - public static final String ENABLE = "enable"; - public static final String ENABLED = "enabled"; - public static final String SERVICE_NAME = "servicename"; - public static final String DHCP_RANGE = "dhcprange"; - public static final String UUID = "uuid"; - public static final String SECURITY_GROUP_EANBLED = "securitygroupenabled"; - public static final String LOCAL_STORAGE_ENABLED = "localstorageenabled"; - public static final String GUEST_IP_TYPE = "guestiptype"; - public static final String GUEST_IP6_PREFIX = "guestip6prefix"; - public static final String XENSERVER_NETWORK_LABEL = "xennetworklabel"; - public static final String KVM_NETWORK_LABEL = "kvmnetworklabel"; - public static final String VMWARE_NETWORK_LABEL = "vmwarenetworklabel"; - public static final String HYPERV_NETWORK_LABEL = "hypervnetworklabel"; - public static final String OVM3_NETWORK_LABEL = "ovm3networklabel"; - public static final String NETWORK_SERVICE_PROVIDER_ID = "nspid"; - public static final String SERVICE_LIST = "servicelist"; - public static final String CAN_ENABLE_INDIVIDUAL_SERVICE = "canenableindividualservice"; - public static final String SUPPORTED_SERVICES = "supportedservices"; - public static final String NSP_ID = "nspid"; - public static final String ACL_TYPE = "acltype"; - public static final String ACL_REASON = "reason"; - public static final String ACL_RULE_PARTIAL_UPGRADE = "partialupgrade"; - public static final String SUBDOMAIN_ACCESS = "subdomainaccess"; - public static final String LOAD_BALANCER_DEVICE_ID = "lbdeviceid"; - public static final String LOAD_BALANCER_DEVICE_NAME = "lbdevicename"; - public static final String LOAD_BALANCER_DEVICE_STATE = "lbdevicestate"; - public static final String LOAD_BALANCER_DEVICE_CAPACITY = "lbdevicecapacity"; - public static final String LOAD_BALANCER_DEVICE_DEDICATED = "lbdevicededicated"; - public static final String LOAD_BALANCER_RULE = "loadbalancerrule"; - public static final String LOAD_BALANCER_RULE_LIST = "loadbalancerrulelist"; - public static final String FIREWALL_DEVICE_ID = "fwdeviceid"; - public static final String FIREWALL_DEVICE_NAME = "fwdevicename"; - public static final String FIREWALL_DEVICE_STATE = "fwdevicestate"; - public static final String FIREWALL_DEVICE_CAPACITY = "fwdevicecapacity"; - public static final String FIREWALL_DEVICE_DEDICATED = "fwdevicededicated"; - public static final String SERVICE = "service"; - public static final String ASSOCIATED_NETWORK = "associatednetwork"; - public static final String ASSOCIATED_NETWORK_ID = "associatednetworkid"; - public static final String ASSOCIATED_NETWORK_NAME = "associatednetworkname"; - public static final String ASSOCIATED_VPC_ID = "associatedvpcid"; - public static final String ASSOCIATED_VPC_NAME = "associatedvpcname"; - public static final String SOURCE_NAT_SUPPORTED = "sourcenatsupported"; - public static final String RESOURCE_STATE = "resourcestate"; - public static final String PROJECT_INVITE_REQUIRED = "projectinviterequired"; - public static final String REQUIRED = "required"; - public static final String RESTART_REQUIRED = "restartrequired"; - public static final String ALLOW_USER_CREATE_PROJECTS = "allowusercreateprojects"; - public static final String ALLOW_USER_DRIVEN_BACKUPS = "allowuserdrivenbackups"; - public static final String ALLOW_USER_SPECIFY_VR_MTU = "allowuserspecifyvrmtu"; - public static final String CONSERVE_MODE = "conservemode"; - public static final String TRAFFIC_TYPE_IMPLEMENTOR = "traffictypeimplementor"; - public static final String KEYWORD = "keyword"; - public static final String LIST_ALL = "listall"; - public static final String LIST_ONLY_REMOVED = "listonlyremoved"; - public static final String LIST_SYSTEM_VMS = "listsystemvms"; - public static final String LIST_VM_DETAILS = "listvmdetails"; - public static final String IP_RANGES = "ipranges"; - public static final String IPV4_ROUTING = "ip4routing"; - public static final String IPV4_ROUTES = "ip4routes"; - public static final String IPV6_ROUTING = "ip6routing"; - public static final String IPV6_ROUTES = "ip6routes"; - public static final String SPECIFY_IP_RANGES = "specifyipranges"; - public static final String IS_SOURCE_NAT = "issourcenat"; - public static final String IS_STATIC_NAT = "isstaticnat"; - public static final String ITERATIONS = "iterations"; - public static final String SORT_BY = "sortby"; - public static final String CHANGE_CIDR = "changecidr"; - public static final String PURPOSE = "purpose"; - public static final String IS_TAGGED = "istagged"; - public static final String INSTANCE_NAME = "instancename"; - public static final String CONSIDER_LAST_HOST = "considerlasthost"; - public static final String START_VM = "startvm"; - public static final String HA_HOST = "hahost"; - public static final String CUSTOM_DISK_OFF_MIN_SIZE = "customdiskofferingminsize"; - 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 AUTO_MIGRATE = "automigrate"; - public static final String GUID = "guid"; - public static final String VM_SNAPSHOT_ENABELD = "vmsnapshotenabled"; - public static final String VSWITCH_TYPE_GUEST_TRAFFIC = "guestvswitchtype"; - public static final String VSWITCH_TYPE_PUBLIC_TRAFFIC = "publicvswitchtype"; - public static final String VSWITCH_NAME_GUEST_TRAFFIC = "guestvswitchname"; - public static final String VSWITCH_NAME_PUBLIC_TRAFFIC = "publicvswitchname"; - - // NSX - public static final String EDGE_CLUSTER = "edgecluster"; - public static final String TIER0_GATEWAY = "tier0gateway"; - - public static final String TRANSPORT_ZONE = "transportzone"; - // Tungsten-Fabric - public static final String TUNGSTEN_VIRTUAL_ROUTER_UUID = "tungstenvirtualrouteruuid"; - public static final String TUNGSTEN_PROVIDER_HOSTNAME = "tungstenproviderhostname"; - public static final String TUNGSTEN_PROVIDER_PORT = "tungstenproviderport"; - public static final String TUNGSTEN_PROVIDER_UUID = "tungstenprovideruuid"; - public static final String TUNGSTEN_GATEWAY = "tungstengateway"; - public static final String TUNGSTEN_PROVIDER_VROUTER_PORT = "tungstenprovidervrouterport"; - public static final String TUNGSTEN_PROVIDER_INTROSPECT_PORT = "tungstenproviderintrospectport"; - public static final String SRC_NETWORK = "srcnetwork"; - public static final String SRC_IP_PREFIX = "srcipprefix"; - public static final String SRC_IP_PREFIX_LEN = "srcipprefixlen"; - public static final String SRC_START_PORT = "srcstartport"; - public static final String SRC_END_PORT = "srcendport"; - public static final String DEST_NETWORK = "destnetwork"; - public static final String DEST_IP_PREFIX = "destipprefix"; - public static final String DEST_IP_PREFIX_LEN = "destipprefixlen"; - public static final String DEST_START_PORT = "deststartport"; - public static final String DEST_END_PORT = "destendport"; - public static final String MAJOR_SEQUENCE = "majorsequence"; - public static final String MINOR_SEQUENCE = "minorsequence"; - public static final String POLICY_UUID = "policyuuid"; - public static final String RULE_UUID = "ruleuuid"; - public static final String DIRECTION = "direction"; - public static final String TAGGED_RESOURCES = "taggedresources"; - public static final String TAG_UUID = "taguuid"; - public static final String TAG_TYPE = "tagtype"; - public static final String TAG_VALUE = "tagvalue"; - public static final String TAG_TYPE_UUID = "tagtypeuuid"; - public static final String NETWORK_UUID = "networkuuid"; - public static final String NIC_UUID = "nicuuid"; - public static final String VM_UUID = "vmuuid"; - public static final String ONE_WAY = "oneway"; - public static final String POLICY = "policy"; - public static final String VM = "vm"; - public static final String FIREWALL_POLICY = "firewallpolicy"; - public static final String FIREWALL_RULE = "firewallrule"; - public static final String TAG = "tag"; - public static final String APPLICATION_POLICY_SET_UUID = "applicationpolicysetuuid"; - public static final String FIREWALL_POLICY_UUID = "firewallpolicyuuid"; - public static final String FIREWALL_RULE_UUID = "firewallruleuuid"; - public static final String ADDRESS_GROUP_UUID = "addressgroupuuid"; - public static final String SERVICE_GROUP_UUID = "servicegroupuuid"; - public static final String SEQUENCE = "sequence"; - public static final String SERVICE_GROUP = "servicegroup"; - public static final String SRC_ADDRESS_GROUP = "srcaddressgroup"; - public static final String DEST_ADDRESS_GROUP = "destaddressgroup"; - public static final String SRC_TAG = "srctag"; - public static final String DEST_TAG = "desttag"; - public static final String IP_PREFIX = "ipprefix"; - public static final String IP_PREFIX_LEN = "ipprefixlen"; - public static final String SRC_ADDRESS_GROUP_UUID = "srcaddressgroupuuid"; - public static final String DEST_ADDRESS_GROUP_UUID = "destaddressgroupuuid"; - public static final String SRC_TAG_UUID = "srctaguuid"; - public static final String DEST_TAG_UUID = "desttaguuid"; - public static final String SRC_NETWORK_UUID = "srcnetworkuuid"; - public static final String DEST_NETWORK_UUID = "destnetworkuuid"; - public static final String LOGICAL_ROUTER_UUID = "logicalrouteruuid"; - public static final String RETRY = "retry"; - public static final String HTTP_METHOD = "httpmethodtype"; - public static final String EXPECTED_CODE = "expectedcode"; - public static final String URL_PATH = "urlpath"; - - // Ovs controller - public static final String OVS_DEVICE_ID = "ovsdeviceid"; - public static final String OVS_DEVICE_NAME = "ovsdevicename"; - // OpenDaylight controller - public static final String ODL_DEVICE_ID = "odldeviceid"; - public static final String ODL_DEVICE_NAME = "odldevicename"; - public static final String ODL_TRANSPORT_ZONE_UUID = "transportzoneuuid"; - public static final String ODL_GATEWAYSERVICE_UUID = "l3gatewayserviceuuid"; - - public static final String EXTERNAL_SWITCH_MGMT_DEVICE_ID = "vsmdeviceid"; - public static final String EXTERNAL_SWITCH_MGMT_DEVICE_NAME = "vsmdevicename"; - public static final String EXTERNAL_SWITCH_MGMT_DEVICE_STATE = "vsmdevicestate"; - // Would we need to have a capacity field for Cisco N1KV VSM? Max hosts managed by it perhaps? May remove this - // later. - public static final String EXTERNAL_SWITCH_MGMT_DEVICE_CAPACITY = "vsmdevicecapacity"; - public static final String CISCO_NEXUS_VSM_NAME = "vsmname"; - public static final String VSM_USERNAME = "vsmusername"; - public static final String VSM_PASSWORD = "vsmpassword"; - public static final String VSM_IPADDRESS = "vsmipaddress"; - public static final String VSM_MGMT_VLAN_ID = "vsmmgmtvlanid"; - public static final String VSM_PKT_VLAN_ID = "vsmpktvlanid"; - public static final String VSM_CTRL_VLAN_ID = "vsmctrlvlanid"; - public static final String VSM_STORAGE_VLAN_ID = "vsmstoragevlanid"; - public static final String VSM_DOMAIN_ID = "vsmdomainid"; - public static final String VSM_CONFIG_MODE = "vsmconfigmode"; - public static final String VSM_CONFIG_STATE = "vsmconfigstate"; - public static final String VSM_DEVICE_STATE = "vsmdevicestate"; - public static final String VCENTER = "vcenter"; - public static final String EXISTING_VCENTER_ID = "existingvcenterid"; - public static final String ADD_VSM_FLAG = "addvsmflag"; - public static final String END_POINT = "endpoint"; - public static final String REGION_ID = "regionid"; - public static final String VPC_OFF_ID = "vpcofferingid"; - public static final String VPC_OFF_NAME = "vpcofferingname"; - public static final String VPC_OFFERING_CONSERVE_MODE = "vpcofferingconservemode"; - public static final String NETWORK = "network"; - public static final String VPC_ID = "vpcid"; - public static final String VPC_NAME = "vpcname"; - public static final String VPC_GATEWAY_ID = "vpcgatewayid"; - public static final String VPC_GATEWAY_IP = "vpcgatewayip"; - public static final String GATEWAY_ID = "gatewayid"; - public static final String CAN_USE_FOR_DEPLOY = "canusefordeploy"; - public static final String RESOURCE_IDS = "resourceids"; - public static final String RESOURCE_ID = "resourceid"; - public static final String CUSTOMER = "customer"; - public static final String S2S_VPN_GATEWAY_ID = "s2svpngatewayid"; - public static final String S2S_CUSTOMER_GATEWAY_ID = "s2scustomergatewayid"; - public static final String IPSEC_PSK = "ipsecpsk"; - public static final String GUEST_IP = "guestip"; - public static final String REMOVED = "removed"; - public static final String REMOVER_ACCOUNT_ID = "removeraccountid"; - public static final String REMOVAL_REASON = "removalreason"; - public static final String COMPLETED = "completed"; - public static final String IKE_VERSION = "ikeversion"; - public static final String IKE_POLICY = "ikepolicy"; - public static final String ESP_POLICY = "esppolicy"; - public static final String IKE_LIFETIME = "ikelifetime"; - public static final String ESP_LIFETIME = "esplifetime"; - public static final String DPD = "dpd"; - public static final String FORCE_ENCAP = "forceencap"; - public static final String SPLIT_CONNECTIONS = "splitconnections"; - public static final String FOR_VPC = "forvpc"; - public static final String FOR_NSX = "fornsx"; - public static final String FOR_CKS = "forcks"; - public static final String NSX_SUPPORT_LB = "nsxsupportlb"; - public static final String NSX_SUPPORTS_INTERNAL_LB = "nsxsupportsinternallb"; - public static final String FOR_TUNGSTEN = "fortungsten"; - public static final String SHRINK_OK = "shrinkok"; - public static final String NICIRA_NVP_DEVICE_ID = "nvpdeviceid"; - public static final String NICIRA_NVP_TRANSPORT_ZONE_UUID = "transportzoneuuid"; - public static final String NICIRA_NVP_DEVICE_NAME = "niciradevicename"; - public static final String NICIRA_NVP_GATEWAYSERVICE_UUID = "l3gatewayserviceuuid"; - public static final String NICIRA_NVP_L2_GATEWAYSERVICE_UUID = "l2gatewayserviceuuid"; - public static final String NSX_LOGICAL_SWITCH = "nsxlogicalswitch"; - public static final String NSX_LOGICAL_SWITCH_PORT = "nsxlogicalswitchport"; - public static final String NSX_PROVIDER_UUID = "nsxprovideruuid"; - public static final String NSX_PROVIDER_HOSTNAME = "nsxproviderhostname"; - - public static final String NSX_PROVIDER_PORT = "nsxproviderport"; - public static final String NSX_CONTROLLER_ID = "nsxcontrollerid"; - public static final String S3_ACCESS_KEY = "accesskey"; - public static final String SECRET_KEY = "secretkey"; - public static final String S3_END_POINT = "endpoint"; - public static final String S3_BUCKET_NAME = "bucket"; - public static final String S3_SIGNER = "s3signer"; - public static final String S3_V3_SIGNER = "S3SignerType"; - public static final String S3_V4_SIGNER = "AWSS3V4SignerType"; - public static final String S3_HTTPS_FLAG = "usehttps"; - public static final String S3_CONNECTION_TIMEOUT = "connectiontimeout"; - public static final String S3_CONNECTION_TTL = "connectionttl"; - public static final String S3_MAX_ERROR_RETRY = "maxerrorretry"; - public static final String S3_SOCKET_TIMEOUT = "sockettimeout"; - public static final String S3_USE_TCP_KEEPALIVE = "usetcpkeepalive"; - public static final String INCL_ZONES = "includezones"; - public static final String EXCL_ZONES = "excludezones"; - public static final String SOURCE = "source"; - public static final String COUNTER_ID = "counterid"; - public static final String AGGR_OPERATOR = "aggroperator"; - public static final String AGGR_FUNCTION = "aggrfunction"; - public static final String AGGR_VALUE = "aggrvalue"; - public static final String THRESHOLD = "threshold"; - public static final String RELATIONAL_OPERATOR = "relationaloperator"; - public static final String OTHER_DEPLOY_PARAMS = "otherdeployparams"; - public static final String MIN_MEMBERS = "minmembers"; - public static final String MAX_MEMBERS = "maxmembers"; - public static final String AUTOSCALE_EXPUNGE_VM_GRACE_PERIOD = "expungevmgraceperiod"; - public static final String VMPROFILE_ID = "vmprofileid"; - public static final String VMGROUP_ID = "vmgroupid"; - public static final String CS_URL = "csurl"; - public static final String IDP_ID = "idpid"; - public static final String SCALEUP_POLICY_IDS = "scaleuppolicyids"; - public static final String SCALEDOWN_POLICY_IDS = "scaledownpolicyids"; - public static final String SCALEUP_POLICIES = "scaleuppolicies"; - public static final String SCALEDOWN_POLICIES = "scaledownpolicies"; - public static final String INTERVAL = "interval"; - public static final String QUIETTIME = "quiettime"; - public static final String ACTION = "action"; - public static final String CONDITION_ID = "conditionid"; - public static final String CONDITION_IDS = "conditionids"; - public static final String COUNTERPARAM_LIST = "counterparam"; - public static final String AUTOSCALE_USER_ID = "autoscaleuserid"; - public static final String AUTOSCALE_VMGROUP_ID = "autoscalevmgroupid"; - public static final String AUTOSCALE_VMGROUP_NAME = "autoscalevmgroupname"; - public static final String BAREMETAL_DISCOVER_NAME = "baremetaldiscovername"; - public static final String BAREMETAL_RCT_URL = "baremetalrcturl"; - public static final String UCS_DN = "ucsdn"; - public static final String GSLB_PROVIDER = "gslbprovider"; - public static final String EXCLUSIVE_GSLB_PROVIDER = "isexclusivegslbprovider"; - public static final String GSLB_PROVIDER_PUBLIC_IP = "gslbproviderpublicip"; - public static final String GSLB_PROVIDER_PRIVATE_IP = "gslbproviderprivateip"; - public static final String VM_SNAPSHOT_DESCRIPTION = "description"; - public static final String VM_SNAPSHOT_DISPLAYNAME = "name"; - public static final String VM_SNAPSHOT_ID = "vmsnapshotid"; - public static final String VM_SNAPSHOT_IDS = "vmsnapshotids"; - public static final String VM_SNAPSHOT_DISK_IDS = "vmsnapshotdiskids"; - public static final String VM_SNAPSHOT_MEMORY = "snapshotmemory"; - public static final String VM_SNAPSHOT_QUIESCEVM = "quiescevm"; - public static final String IMAGE_STORE_UUID = "imagestoreuuid"; - public static final String IMAGE_STORE_ID = "imagestoreid"; - public static final String GUEST_VM_CIDR = "guestvmcidr"; - public static final String NETWORK_CIDR = "networkcidr"; - public static final String RESERVED_IP_RANGE = "reservediprange"; - public static final String UCS_MANAGER_ID = "ucsmanagerid"; - public static final String UCS_PROFILE_DN = "profiledn"; - public static final String UCS_BLADE_DN = "bladedn"; - public static final String UCS_BLADE_ID = "bladeid"; - public static final String VM_GUEST_IP = "vmguestip"; - public static final String HEALTHCHECK_FAILED = "healthchecksfailed"; - public static final String HEALTHCHECK_RESPONSE_TIMEOUT = "responsetimeout"; - public static final String HEALTHCHECK_INTERVAL_TIME = "intervaltime"; - public static final String HEALTHCHECK_HEALTHY_THRESHOLD = "healthythreshold"; - public static final String HEALTHCHECK_UNHEALTHY_THRESHOLD = "unhealthythreshold"; - public static final String HEALTHCHECK_PINGPATH = "pingpath"; - public static final String SOURCE_PORT = "sourceport"; - public static final String INSTANCE_PORT = "instanceport"; - public static final String SOURCE_IP = "sourceipaddress"; - public static final String SOURCE_IP_NETWORK_ID = "sourceipaddressnetworkid"; - public static final String SCHEME = "scheme"; - public static final String PROVIDER_TYPE = "providertype"; - public static final String AFFINITY_GROUP_IDS = "affinitygroupids"; - public static final String AFFINITY_GROUP_NAMES = "affinitygroupnames"; - public static final String ASA_INSIDE_PORT_PROFILE = "insideportprofile"; - public static final String AFFINITY_GROUP_ID = "affinitygroupid"; - public static final String DEPLOYMENT_PLANNER = "deploymentplanner"; - public static final String ACL_ID = "aclid"; - public static final String ACL_NAME = "aclname"; - public static final String NUMBER = "number"; - public static final String IS_DYNAMICALLY_SCALABLE = "isdynamicallyscalable"; - public static final String ROUTED_MODE_ENABLED = "routedmodeenabled"; - public static final String ROUTING = "isrouting"; - public static final String ROUTING_MODE = "routingmode"; - public static final String MAX_CONNECTIONS = "maxconnections"; - public static final String SERVICE_STATE = "servicestate"; - - public static final String IAM_GROUPS = "groups"; - public static final String ENTITY_TYPE = "entitytype"; - public static final String ENTITY_ID = "entityid"; - public static final String ENTITY_NAME = "entityname"; - public static final String EXTERNAL_ID = "externalid"; - public static final String ACCESS_TYPE = "accesstype"; - - public static final String RESOURCE_DETAILS = "resourcedetails"; - public static final String RESOURCE_ICON = "icon"; - public static final String RESOURCE_MAP = "resourcemap"; - public static final String EXPUNGE = "expunge"; - public static final String FOR_DISPLAY = "fordisplay"; - public static final String PASSIVE = "passive"; - public static final String VERSION = "version"; - public static final String START = "start"; - public static final String GPUGROUP = "gpugroup"; - public static final String GPUGROUPNAME = "gpugroupname"; - public static final String VGPU = "vgpu"; - public static final String VGPUTYPE = "vgputype"; - public static final String VIDEORAM = "videoram"; - public static final String MAXHEADS = "maxheads"; - public static final String MAXRESOLUTIONX = "maxresolutionx"; - public static final String MAXRESOLUTIONY = "maxresolutiony"; - public static final String MAXVGPUPERPGPU = "maxvgpuperpgpu"; - public static final String REMAININGCAPACITY = "remainingcapacity"; - public static final String MAXCAPACITY = "maxcapacity"; - public static final String DISTRIBUTED_VPC_ROUTER = "distributedvpcrouter"; - public static final String REDUNDANT_ROUTER = "redundantrouter"; - public static final String REDUNDANT_VPC_ROUTER = "redundantvpcrouter"; - public static final String READ_ONLY = "readonly"; - public static final String SUPPORTS_REGION_LEVEL_VPC = "supportsregionLevelvpc"; - public static final String SUPPORTS_STRECHED_L2_SUBNET = "supportsstrechedl2subnet"; - public static final String SUPPORTS_PUBLIC_ACCESS = "supportspublicaccess"; - public static final String SUPPORTS_INTERNAL_LB = "supportsinternallb"; - public static final String SUPPORTS_VM_AUTOSCALING = "supportsvmautoscaling"; - public static final String REGION_LEVEL_VPC = "regionlevelvpc"; - public static final String STRECHED_L2_SUBNET = "strechedl2subnet"; - public static final String NETWORK_NAME = "networkname"; - public static final String NETWORK_SPANNED_ZONES = "zonesnetworkspans"; - public static final String METADATA = "metadata"; - public static final String PHYSICAL_SIZE = "physicalsize"; - public static final String CHAIN_SIZE = "chainsize"; - public static final String OVM3_POOL = "ovm3pool"; - public static final String OVM3_CLUSTER = "ovm3cluster"; - public static final String OVM3_VIP = "ovm3vip"; - public static final String CLEAN_UP_DETAILS = "cleanupdetails"; - public static final String CLEAN_UP_EXTERNAL_DETAILS = "cleanupexternaldetails"; - public static final String CLEAN_UP_EXTRA_CONFIG = "cleanupextraconfig"; - public static final String CLEAN_UP_PARAMETERS = "cleanupparameters"; - public static final String VIRTUAL_SIZE = "virtualsize"; - public static final String NETSCALER_CONTROLCENTER_ID = "netscalercontrolcenterid"; - public static final String NETSCALER_SERVICEPACKAGE_ID = "netscalerservicepackageid"; - public static final String FETCH_ROUTER_HEALTH_CHECK_RESULTS = "fetchhealthcheckresults"; - - public static final String ZONE_ID_LIST = "zoneids"; - public static final String DESTINATION_ZONE_ID_LIST = "destzoneids"; - public static final String STORAGE_ID_LIST = "storageids"; - public static final String ADMIN = "admin"; - public static final String CHECKSUM_PARAMETER_PREFIX_DESCRIPTION = "The parameter containing the checksum will be considered a MD5sum if it is not prefixed\n" - + " and just a plain ascii/utf8 representation of a hexadecimal string. If it is required to\n" - + " use another algorithm the hexadecimal string is to be prefixed with a string of the form,\n" - + " \"{}\", not including the double quotes. In this is the exact string\n" - + " representing the java supported algorithm, i.e. MD5 or SHA-256. Note that java does not\n" + " contain an algorithm called SHA256 or one called sha-256, only SHA-256."; - - public static final String HAS_ANNOTATIONS = "hasannotations"; - public static final String LAST_ANNOTATED = "lastannotated"; - public static final String LDAP_DOMAIN = "ldapdomain"; - - public static final String STDOUT = "stdout"; - public static final String STDERR = "stderr"; - public static final String EXITCODE = "exitcode"; - public static final String TARGET_ID = "targetid"; - public static final String FILES = "files"; - public static final String SRC_POOL = "srcpool"; - public static final String DEST_POOL = "destpool"; - public static final String DEST_POOLS = "destpools"; - public static final String VOLUME_IDS = "volumeids"; - - public static final String ROUTER_ID = "routerid"; - public static final String ROUTER_HEALTH_CHECKS = "healthchecks"; - public static final String ROUTER_CHECK_NAME = "checkname"; - public static final String ROUTER_CHECK_TYPE = "checktype"; - public static final String ROUTER_IP = "routerip"; - public static final String ROUTER_IPV6 = "routeripv6"; - public static final String ROUTER_PRIVATE_INTERFACE_MAX_MTU = "routerprivateinterfacemaxmtu"; - public static final String ROUTER_PUBLIC_INTERFACE_MAX_MTU = "routerpublicinterfacemaxmtu"; - public static final String LAST_UPDATED = "lastupdated"; - public static final String PERFORM_FRESH_CHECKS = "performfreshchecks"; - public static final String CACHE_MODE = "cachemode"; - - public static final String CONSOLE_END_POINT = "consoleendpoint"; - public static final String EXTERNAL_LOAD_BALANCER_IP_ADDRESS = "externalloadbalanceripaddress"; - public static final String DOCKER_REGISTRY_USER_NAME = "dockerregistryusername"; - public static final String DOCKER_REGISTRY_PASSWORD = "dockerregistrypassword"; - public static final String DOCKER_REGISTRY_URL = "dockerregistryurl"; - public static final String DOCKER_REGISTRY_EMAIL = "dockerregistryemail"; - public static final String ISO_NAME = "isoname"; - public static final String ISO_STATE = "isostate"; - public static final String ISO_URL = "isourl"; - public static final String SEMANTIC_VERSION = "semanticversion"; - public static final String KUBERNETES_VERSION_ID = "kubernetesversionid"; - public static final String KUBERNETES_VERSION_NAME = "kubernetesversionname"; - public static final String MASTER_NODES = "masternodes"; - public static final String NODE_IDS = "nodeids"; - public static final String CONTROL_NODES = "controlnodes"; - public static final String ETCD_NODES = "etcdnodes"; - public static final String EXTERNAL_NODES = "externalnodes"; - public static final String IS_EXTERNAL_NODE = "isexternalnode"; - public static final String IS_ETCD_NODE = "isetcdnode"; - public static final String MIN_SEMANTIC_VERSION = "minimumsemanticversion"; - public static final String MIN_KUBERNETES_VERSION_ID = "minimumkubernetesversionid"; - public static final String NODE_ROOT_DISK_SIZE = "noderootdisksize"; - public static final String SUPPORTS_HA = "supportsha"; - public static final String SUPPORTS_AUTOSCALING = "supportsautoscaling"; - public static final String AUTOSCALING_ENABLED = "autoscalingenabled"; - public static final String MIN_SIZE = "minsize"; - public static final String MAX_SIZE = "maxsize"; - public static final String NODE_TYPE_OFFERING_MAP = "nodeofferings"; - public static final String NODE_TYPE_TEMPLATE_MAP = "nodetemplates"; - public static final String NODE_TYPE_AFFINITY_GROUP_MAP = "nodeaffinitygroups"; - public static final String CONTROL_AFFINITY_GROUP_IDS = "controlaffinitygroupids"; - public static final String CONTROL_AFFINITY_GROUP_NAMES = "controlaffinitygroupnames"; - public static final String WORKER_AFFINITY_GROUP_IDS = "workeraffinitygroupids"; - public static final String WORKER_AFFINITY_GROUP_NAMES = "workeraffinitygroupnames"; - public static final String ETCD_AFFINITY_GROUP_IDS = "etcdaffinitygroupids"; - public static final String ETCD_AFFINITY_GROUP_NAMES = "etcdaffinitygroupnames"; - - public static final String BOOT_TYPE = "boottype"; - public static final String BOOT_MODE = "bootmode"; - public static final String BOOT_INTO_SETUP = "bootintosetup"; - public static final String DEPLOY_AS_IS = "deployasis"; - public static final String DEPLOY_AS_IS_DETAILS = "deployasisdetails"; - public static final String CROSS_ZONES = "crossZones"; - public static final String SOURCETEMPLATEID = "sourcetemplateid"; - public static final String DYNAMIC_SCALING_ENABLED = "dynamicscalingenabled"; - public static final String IOTHREADS_ENABLED = "iothreadsenabled"; - public static final String IO_DRIVER_POLICY = "iodriverpolicy"; - - public static final String POOL_TYPE = "pooltype"; - public static final String REDUNDANT_STATE = "redundantstate"; - - public static final String ADMINS_ONLY = "adminsonly"; - public static final String ANNOTATION_FILTER = "annotationfilter"; - public static final String CODE_FOR_2FA = "codefor2fa"; - public static final String PROVIDER_FOR_2FA = "providerfor2fa"; - public static final String ISSUER_FOR_2FA = "issuerfor2fa"; - public static final String MANDATE_2FA = "mandate2fa"; - public static final String PASSWORD_CHANGE_REQUIRED = "passwordchangerequired"; - public static final String SECRET_CODE = "secretcode"; - public static final String LOGIN = "login"; - public static final String LOGOUT = "logout"; - public static final String LIST_IDPS = "listIdps"; - - public static final String MAINTENANCE_INITIATED = "maintenanceinitiated"; - public static final String SHUTDOWN_TRIGGERED = "shutdowntriggered"; - public static final String READY_FOR_SHUTDOWN = "readyforshutdown"; - public static final String PENDING_JOBS_COUNT = "pendingjobscount"; - public static final String AGENTS_COUNT = "agentscount"; - public static final String AGENTS = "agents"; - public static final String LAST_AGENTS = "lastagents"; - - public static final String PUBLIC_MTU = "publicmtu"; - public static final String PRIVATE_MTU = "privatemtu"; - public static final String MTU = "mtu"; - public static final String AUTO_ENABLE_KVM_HOST = "autoenablekvmhost"; - public static final String LIST_APIS = "listApis"; - public static final String VERSIONING = "versioning"; - public static final String OBJECT_LOCKING = "objectlocking"; - public static final String ENCRYPTION = "encryption"; - public static final String QUOTA = "quota"; - public static final String QUOTA_CONSUMED = "quotaconsumed"; - public static final String QUOTA_USAGE = "quotausage"; - public static final String ACCESS_KEY = "accesskey"; - - public static final String SOURCE_NAT_IP = "sourcenatipaddress"; - public static final String SOURCE_NAT_IP_ID = "sourcenatipaddressid"; - public static final String HAS_RULES = "hasrules"; - public static final String NSX_DETAIL_KEY = "forNsx"; - public static final String NETRIS_DETAIL_KEY = "forNetris"; - public static final String NETRIS_TAG = "netristag"; - public static final String NETRIS_VXLAN_ID = "netrisvxlanid"; - public static final String NETRIS_URL = "netrisurl"; - public static final String DISK_PATH = "diskpath"; - public static final String IMPORT_SOURCE = "importsource"; - public static final String TEMP_PATH = "temppath"; - public static final String HEURISTIC_RULE = "heuristicrule"; - public static final String HEURISTIC_TYPE_VALID_OPTIONS = "Valid options are: ISO, SNAPSHOT, TEMPLATE and VOLUME."; - public static final String MANAGEMENT = "management"; - public static final String IS_VNF = "isvnf"; - public static final String VNF_NICS = "vnfnics"; - public static final String VNF_DETAILS = "vnfdetails"; - public static final String CLEAN_UP_VNF_DETAILS = "cleanupvnfdetails"; - public static final String CLEAN_UP_VNF_NICS = "cleanupvnfnics"; - public static final String VNF_CONFIGURE_MANAGEMENT = "vnfconfiguremanagement"; - public static final String VNF_CIDR_LIST = "vnfcidrlist"; - - public static final String CLIENT_ID = "clientid"; - public static final String REDIRECT_URI = "redirecturi"; - - public static final String IS_TAG_A_RULE = "istagarule"; - - public static final String PARAMETER_DESCRIPTION_IS_TAG_A_RULE = "Whether the informed tag is a JS interpretable rule or not."; - - public static final String WEBHOOK_ID = "webhookid"; - public static final String WEBHOOK_NAME = "webhookname"; - - public static final String NFS_MOUNT_OPTIONS = "nfsmountopts"; - public static final String MOUNT_OPTIONS = "mountopts"; - - public static final String SHAREDFSVM_MIN_CPU_COUNT = "sharedfsvmmincpucount"; - public static final String SHAREDFSVM_MIN_RAM_SIZE = "sharedfsvmminramsize"; - - // Object Storage related - public static final String BUCKET_AVAILABLE = "bucketavailable"; - public static final String BUCKET_LIMIT = "bucketlimit"; - public static final String BUCKET_TOTAL = "buckettotal"; - public static final String OBJECT_STORAGE_ID = "objectstorageid"; - public static final String OBJECT_STORAGE = "objectstore"; - public static final String OBJECT_STORAGE_AVAILABLE = "objectstorageavailable"; - public static final String OBJECT_STORAGE_LIMIT = "objectstoragelimit"; - public static final String OBJECT_STORAGE_TOTAL = "objectstoragetotal"; - - public static final String KEEP_MAC_ADDRESS_ON_PUBLIC_NIC = "keepmacaddressonpublicnic"; - - public static final String PARAMETER_DESCRIPTION_KEEP_MAC_ADDRESS_ON_PUBLIC_NIC = - "Indicates whether to use the same MAC address for the public NIC of VRs on the same network. If \"true\", when creating redundant routers or recreating" + - " a VR, CloudStack will use the same MAC address for the public NIC of all VRs. Otherwise, if \"false\", new public NICs will always have " + - " a new MAC address."; - - public static final String PARAMETER_DESCRIPTION_ACTIVATION_RULE = "Quota tariff's activation rule. It can receive a JS script that results in either " + - "a boolean or a numeric value: if it results in a boolean value, the tariff value will be applied according to the result; if it results in a numeric value, the " + - "numeric value will be applied; if the result is neither a boolean nor a numeric value, the tariff will not be applied. If the rule is not informed, the tariff " + - "value will be applied."; - - public static final String PARAMETER_DESCRIPTION_START_DATE_POSSIBLE_FORMATS = "The recommended format is \"yyyy-MM-dd'T'HH:mm:ssZ\" (e.g.: \"2023-01-01T12:00:00+0100\"); " + - "however, the following formats are also accepted: \"yyyy-MM-dd HH:mm:ss\" (e.g.: \"2023-01-01 12:00:00\") and \"yyyy-MM-dd\" (e.g.: \"2023-01-01\" - if the time is not " + - "added, it will be interpreted as \"00:00:00\"). If the recommended format is not used, the date will be considered in the server timezone."; - - public static final String PARAMETER_DESCRIPTION_END_DATE_POSSIBLE_FORMATS = "The recommended format is \"yyyy-MM-dd'T'HH:mm:ssZ\" (e.g.: \"2023-01-01T12:00:00+0100\"); " + - "however, the following formats are also accepted: \"yyyy-MM-dd HH:mm:ss\" (e.g.: \"2023-01-01 12:00:00\") and \"yyyy-MM-dd\" (e.g.: \"2023-01-01\" - if the time is not " + - "added, it will be interpreted as \"23:59:59\"). If the recommended format is not used, the date will be considered in the server timezone."; - - public static final String PARAMETER_DESCRIPTION_MAX_BACKUPS = "The maximum number of backups to keep for a VM. " + - "If \"0\", no retention policy will be applied and, thus, no backups from the schedule will be automatically deleted. " + - "This parameter is only supported for the Dummy, NAS and EMC Networker backup provider."; - - public static final String VMWARE_DC = "vmwaredc"; - - public static final String CSS = "css"; - - public static final String JSON_CONFIGURATION = "jsonconfiguration"; - - public static final String COMMON_NAMES = "commonnames"; - - public static final String COMMON_NAME = "commonname"; - - public static final String DOMAIN_IDS = "domainids"; - - public static final String SHOW_PUBLIC = "showpublic"; - - public static final String LIST_ONLY_DEFAULT_THEME = "listonlydefaulttheme"; - - public static final String RECURSIVE_DOMAINS = "recursivedomains"; - - public static final String VPN_CUSTOMER_GATEWAY_PARAMETERS = "vpncustomergatewayparameters"; - public static final String OBSOLETE_PARAMETERS = "obsoleteparameters"; - public static final String EXCLUDED_PARAMETERS = "excludedparameters"; - - /** - * This enum specifies IO Drivers, each option controls specific policies on I/O. - * Qemu guests support "threads" and "native" options Since 0.8.8 ; "io_uring" is supported Since 6.3.0 (QEMU 5.0). - */ - public enum IoDriverPolicy { - NATIVE("native"), - THREADS("threads"), - IO_URING("io_uring"), - STORAGE_SPECIFIC("storage_specific"); - - String ioDriver; - - IoDriverPolicy(String driver) { - ioDriver = driver; - } - - @Override - public String toString() { - return ioDriver; - } - } - - public enum BootType { - UEFI, BIOS; - - @Override - public String toString() { - return this.name(); - } - } - - public enum BootMode { - LEGACY, SECURE; - - @Override - public String toString() { - return this.name(); - } - } - - public enum HostDetails { - all, capacity, events, stats, min; - } - - public enum VMDetails { - all, group, nics, stats, secgrp, tmpl, servoff, diskoff, backoff, iso, volume, min, affgrp, vnfnics; - } - - public enum DomainDetails { - all, resource, min; - } - - public enum ExtensionDetails { - all, resource, external, min; - } - - public enum ApiKeyAccess { - DISABLED(false), - ENABLED(true), - INHERIT(null); - - Boolean apiKeyAccess; - - ApiKeyAccess(Boolean keyAccess) { - apiKeyAccess = keyAccess; - } - - public Boolean toBoolean() { - return apiKeyAccess; - } - - public static ApiKeyAccess fromBoolean(Boolean value) { - if (value == null) { - return INHERIT; - } else if (value) { - return ENABLED; - } else { - return DISABLED; - } - } - } -} + public static final String NIC_MAC_ADDRESS_LIST = "nicmacaddresslist"; + public static final String NIC_MULTIQUEUE_NUMBER = "nicmultiqueuenumber"; + public static final String NIC_PACKED_VIRTQUEUES_ENABLED = "nicpackedvirtqueuesenabled"; + public static final String NEW_START_IP = "newstartip"; + public static final String NEW_END_IP = "newendip"; + public static final String KUBERNETES_NODE_VERSION = "kubernetesnodeversion"; + public static final String NUMA_NODE = "numanode"; + public static final String NUM_RETRIES = "numretries"; + public static final String OFFER_HA = "offerha"; + public static final String OS_DISTRIBUTION = "osdistribution"; + public static final String IS_SYSTEM_OFFERING = "issystem"; + public static final String IS_DEFAULT_USE = "defaultuse"; + public static final String OLD_FORMAT = "oldformat"; + public static final String OP = "op"; + public static final String OPTION = "option"; + public static final String OPTIONS = "options"; + public static final String OS_CATEGORY_ID = "oscategoryid"; + public static final String OS_CATEGORY_NAME = "oscategoryname"; + public static final String OS_NAME = "osname"; + 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"; + public static final String GPU_CARD_ID = "gpucardid"; + public static final String GPU_CARD_NAME = "gpucardname"; + public static final String GPU_COUNT = "gpucount"; + public static final String GPU_DISPLAY = "gpudisplay"; + public static final String GPU_DEVICE_TYPE = "gpudevicetype"; + public static final String GPU_ENABLED = "gpuenabled"; + public static final String MAX_VGPU_PER_PHYSICAL_GPU = "maxvgpuperphysicalgpu"; + public static final String GUEST_OS_LIST = "guestoslist"; + public static final String GUEST_OS_COUNT = "guestoscount"; + public static final String OS_MAPPING_CHECK_ENABLED = "osmappingcheckenabled"; + public static final String OUTOFBANDMANAGEMENT_POWERSTATE = "outofbandmanagementpowerstate"; + public static final String OUTOFBANDMANAGEMENT_ENABLED = "outofbandmanagementenabled"; + public static final String OUTPUT = "output"; + public static final String PROPERTIES = "properties"; + public static final String PARAMS = "params"; + public static final String PARENT = "parent"; + public static final String PARENT_ID = "parentid"; + public static final String PARENT_DOMAIN_ID = "parentdomainid"; + public static final String PARENT_GPU_DEVICE_ID = "parentgpudeviceid"; + public static final String PARENT_SUBNET = "parentsubnet"; + public static final String PARENT_TEMPLATE_ID = "parenttemplateid"; + public static final String PASSWORD = "password"; + public static final String PCI_ROOT = "pciroot"; + public static final String CURRENT_PASSWORD = "currentpassword"; + public static final String SHOULD_UPDATE_PASSWORD = "update_passwd_on_host"; + public static final String PASSWORD_ENABLED = "passwordenabled"; + public static final String SSHKEY_ENABLED = "sshkeyenabled"; + public static final String PATH = "path"; + public static final String PATH_READY = "pathready"; + public static final String PAYLOAD = "payload"; + public static final String PAYLOAD_URL = "payloadurl"; + public static final String PEERS = "peers"; + public static final String PEER_ID = "peerid"; + public static final String PEER_NAME = "peername"; + public static final String PEER_MSID = "peermsid"; + public static final String PEER_RUNID = "peerrunid"; + public static final String PEER_SERVICE_IP = "peerserviceip"; + public static final String PEER_SERVICE_PORT = "peerserviceport"; + public static final String PEER_STATE = "peerstate"; + public static final String POD_ID = "podid"; + public static final String POD_NAME = "podname"; + public static final String POD_IDS = "podids"; + public static final String POLICY_ID = "policyid"; + public static final String PORT = "port"; + 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 PRECEDENCE = "precedence"; + public static final String PREPARE_VM = "preparevm"; + public static final String PRESERVE_IP = "preserveip"; + public static final String PRIVATE_INTERFACE = "privateinterface"; + public static final String PRIVATE_IP = "privateip"; + public static final String PRIVATE_PORT = "privateport"; + public static final String PRIVATE_START_PORT = "privateport"; + public static final String PRIVATE_END_PORT = "privateendport"; + public static final String PRIVATE_ZONE = "privatezone"; + public static final String PROTOCOL = "protocol"; + public static final String PROVISIONINGTYPE = "provisioningtype"; + public static final String PUBLIC_INTERFACE = "publicinterface"; + public static final String PUBLIC_IP_ID = "publicipid"; + public static final String PUBLIC_IP = "publicip"; + public static final String PUBLIC_PORT = "publicport"; + public static final String PUBLIC_START_PORT = "publicport"; + public static final String PUBLIC_END_PORT = "publicendport"; + public static final String PUBLIC_ZONE = "publiczone"; + public static final String PURGE_RESOURCES = "purgeresources"; + public static final String RAM = "RAM"; + public static final String REBALANCE = "rebalance"; + public static final String RECEIVED_BYTES = "receivedbytes"; + public static final String RECONNECT = "reconnect"; + public static final String RECOVER = "recover"; + public static final String REPAIR = "repair"; + public static final String REPETITION_ALLOWED = "repetitionallowed"; + public static final String REQUIRES_HVM = "requireshvm"; + public static final String RESERVED_RESOURCE_DETAILS = "reservedresourcedetails"; + public static final String RESOURCES = "resources"; + public static final String RESOURCE_COUNT = "resourcecount"; + public static final String RESOURCE_NAME = "resourcename"; + public static final String RESOURCE_TYPE = "resourcetype"; + public static final String RESOURCE_TYPE_NAME = "resourcetypename"; + public static final String RESPONSE = "response"; + public static final String RETRIEVE_ONLY_RESOURCE_COUNT = "retrieveonlyresourcecount"; + public static final String REVERTABLE = "revertable"; + public static final String REVOKED = "revoked"; + public static final String REGISTERED = "registered"; + public static final String QUALIFIERS = "qualifiers"; + public static final String QUERY_FILTER = "queryfilter"; + public static final String QUIESCE_VM = "quiescevm"; + public static final String SCHEDULE = "schedule"; + public static final String SCHEDULE_ID = "scheduleid"; + public static final String SCOPE = "scope"; + public static final String SEARCH_BASE = "searchbase"; + public static final String SECONDARY_IP = "secondaryip"; + public static final String SECURITY_GROUP_IDS = "securitygroupids"; + public static final String SECURITY_GROUP_NAMES = "securitygroupnames"; + public static final String SECURITY_GROUP_NAME = "securitygroupname"; + public static final String SECURITY_GROUP_ID = "securitygroupid"; + public static final String SENT = "sent"; + public static final String SENT_BYTES = "sentbytes"; + public static final String SERIAL = "serial"; + public static final String SERVICE_IP = "serviceip"; + public static final String SERVICE_OFFERING_ID = "serviceofferingid"; + public static final String SERVICE_OFFERING_NAME = "serviceofferingname"; + public static final String SESSIONKEY = "sessionkey"; + public static final String SHOW_CAPACITIES = "showcapacities"; + public static final String SHOW_REMOVED = "showremoved"; + public static final String SHOW_RESOURCES = "showresources"; + public static final String SHOW_RESOURCE_ICON = "showicon"; + public static final String SHOW_INACTIVE = "showinactive"; + public static final String SHOW_UNIQUE = "showunique"; + public static final String SHOW_PERMISSIONS = "showpermissions"; + public static final String SIGNATURE = "signature"; + public static final String SIGNATURE_VERSION = "signatureversion"; + public static final String SINCE = "since"; + public static final String SITE_NAME = "sitename"; + public static final String SIZE = "size"; + public static final String SIZEGB = "sizegb"; + public static final String SNAPSHOT = "snapshot"; + public static final String SNAPSHOT_ID = "snapshotid"; + public static final String SNAPSHOT_POLICY_ID = "snapshotpolicyid"; + public static final String SNAPSHOT_TYPE = "snapshottype"; + public static final String SNAPSHOT_QUIESCEVM = "quiescevm"; + + public static final String USE_STORAGE_REPLICATION = "usestoragereplication"; + + public static final String SOURCE_CIDR_LIST = "sourcecidrlist"; + public static final String SOURCE_OFFERING_ID = "sourceofferingid"; + public static final String SOURCE_ZONE_ID = "sourcezoneid"; + public static final String SSL_VERIFICATION = "sslverification"; + public static final String START_ASN = "startasn"; + public static final String START_DATE = "startdate"; + public static final String START_ID = "startid"; + public static final String START_IP = "startip"; + public static final String START_IPV6 = "startipv6"; + public static final String START_PORT = "startport"; + public static final String STATE = "state"; + public static final String STATS = "stats"; + public static final String STATUS = "status"; + public static final String STORAGE_TYPE = "storagetype"; + public static final String STORAGE_POLICY = "storagepolicy"; + public static final String STORAGE_MOTION_ENABLED = "storagemotionenabled"; + public static final String STORAGE_CAPABILITIES = "storagecapabilities"; + public static final String STORAGE_CUSTOM_STATS = "storagecustomstats"; + public static final String SUBNET = "subnet"; + public static final String OWNER = "owner"; + public static final String SWAP_OWNER = "swapowner"; + public static final String SYSTEM_VM_TYPE = "systemvmtype"; + public static final String TAGS = "tags"; + public static final String STORAGE_TAGS = "storagetags"; + public static final String STORAGE_ACCESS_GROUPS = "storageaccessgroups"; + public static final String STORAGE_ACCESS_GROUP = "storageaccessgroup"; + public static final String CLUSTER_STORAGE_ACCESS_GROUPS = "clusterstorageaccessgroups"; + public static final String POD_STORAGE_ACCESS_GROUPS = "podstorageaccessgroups"; + public static final String ZONE_STORAGE_ACCESS_GROUPS = "zonestorageaccessgroups"; + public static final String SUCCESS = "success"; + public static final String SUCCESS_MESSAGE = "successmessage"; + public static final String SUITABLE_FOR_VM = "suitableforvirtualmachine"; + public static final String SUPPORTS_STORAGE_SNAPSHOT = "supportsstoragesnapshot"; + public static final String TARGET_IQN = "targetiqn"; + public static final String TASKS_FILTER = "tasksfilter"; + public static final String TEMPLATE_FILTER = "templatefilter"; + public static final String TEMPLATE_ID = "templateid"; + public static final String TEMPLATE_IDS = "templateids"; + public static final String TEMPLATE_NAME = "templatename"; + public static final String TEMPLATE_TYPE = "templatetype"; + public static final String TEMPLATE_FORMAT = "templateformat"; + public static final String TIMEOUT = "timeout"; + public static final String TIMEZONE = "timezone"; + public static final String TIMEZONEOFFSET = "timezoneoffset"; + public static final String TENANT_NAME = "tenantname"; + public static final String TOTAL = "total"; + public static final String TOTAL_SUBNETS = "totalsubnets"; + public static final String TO_CHECKPOINT_ID = "tocheckpointid"; + public static final String TOTAL_QUOTA = "totalquota"; + public static final String TYPE = "type"; + public static final String TRUST_STORE = "truststore"; + public static final String TRUST_STORE_PASSWORD = "truststorepass"; + public static final String UNIT = "unit"; + public static final String URL = "url"; + public static final String USAGE_INTERFACE = "usageinterface"; + public static final String USED = "used"; + public static final String USED_SUBNETS = "usedsubnets"; + public static final String USED_IOPS = "usediops"; + public static final String USER_DATA = "userdata"; + + public static final String USER_DATA_NAME = "userdataname"; + public static final String USER_DATA_ID = "userdataid"; + public static final String USER_DATA_POLICY = "userdatapolicy"; + public static final String USER_DATA_DETAILS = "userdatadetails"; + public static final String USER_DATA_PARAMS = "userdataparams"; + public static final String USER_FILTER = "userfilter"; + public static final String USER_ID = "userid"; + public static final String USER_SOURCE = "usersource"; + public static final String USER_CONFLICT_SOURCE = "conflictingusersource"; + public static final String USE_SSL = "ssl"; + public static final String USERNAME = "username"; + public static final String USER_CONFIGURABLE = "userconfigurable"; + public static final String USER_SECURITY_GROUP_LIST = "usersecuritygrouplist"; + public static final String USER_SECRET_KEY = "usersecretkey"; + public static final String USE_VDDK = "usevddk"; + public static final String USE_VIRTUAL_NETWORK = "usevirtualnetwork"; + public static final String USE_VIRTUAL_ROUTER_IP_RESOLVER = "userouteripresolver"; + public static final String UPDATE_IN_SEQUENCE = "updateinsequence"; + public static final String VALIDATION_FORMAT = "validationformat"; + public static final String VALUE = "value"; + public static final String VALUE_OPTIONS = "valueoptions"; + public static final String VENDOR_ID = "vendorid"; + public static final String VENDOR_NAME = "vendorname"; + public static final String VGPU_PROFILE_ID = "vgpuprofileid"; + public static final String VGPU_PROFILE_NAME = "vgpuprofilename"; + public static final String VIRTUAL_MACHINE = "virtualmachine"; + public static final String VIRTUAL_MACHINE_ID = "virtualmachineid"; + public static final String VIRTUAL_MACHINE_IDS = "virtualmachineids"; + public static final String VIRTUAL_MACHINE_NAME = "virtualmachinename"; + public static final String VIRTUAL_MACHINE_ID_IP = "vmidipmap"; + public static final String VIRTUAL_MACHINE_COUNT = "virtualmachinecount"; + public static final String VIRTUAL_MACHINE_TYPE = "virtualmachinetype"; + public static final String VIRTUAL_MACHINE_STATE = "vmstate"; + public static final String VIRTUAL_MACHINES = "virtualmachines"; + public static final String USAGE_ID = "usageid"; + public static final String USAGE_TYPE = "usagetype"; + public static final String INCLUDE_TAGS = "includetags"; + + public static final String VLAN = "vlan"; + public static final String VLAN_RANGE = "vlanrange"; + public static final String WORKER_SERVICE_OFFERING_ID = "workerofferingid"; + public static final String WORKER_SERVICE_OFFERING_NAME = "workerofferingname"; + public static final String CONTROL_SERVICE_OFFERING_ID = "controlofferingid"; + public static final String CONTROL_SERVICE_OFFERING_NAME = "controlofferingname"; + public static final String ETCD_SERVICE_OFFERING_ID = "etcdofferingid"; + public static final String ETCD_SERVICE_OFFERING_NAME = "etcdofferingname"; + 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 IS_ALLOCATED = "isallocated"; + public static final String IS_DEDICATED = "isdedicated"; + public static final String TAKEN = "taken"; + public static final String VM_AVAILABLE = "vmavailable"; + public static final String VM_DETAILS = "vmdetails"; + public static final String VM_LIMIT = "vmlimit"; + public static final String VM_TOTAL = "vmtotal"; + public static final String VM_SETTINGS = "vmsettings"; + public static final String VM_TYPE = "vmtype"; + public static final String VNET = "vnet"; + public static final String IS_VOLATILE = "isvolatile"; + public static final String VOLUME_ID = "volumeid"; + public static final String VOLUMES = "volumes"; + public static final String VOLUME_CHECK_RESULT = "volumecheckresult"; + public static final String VOLUME_REPAIR_RESULT = "volumerepairresult"; + + public static final String ZONE = "zone"; + public static final String ZONE_ID = "zoneid"; + public static final String ZONE_NAME = "zonename"; + public static final String ZONE_WISE = "zonewise"; + public static final String NETWORK_TYPE = "networktype"; + public static final String PAGE = "page"; + public static final String PAGE_SIZE = "pagesize"; + public static final String COUNT = "count"; + public static final String TRAFFIC_TYPE = "traffictype"; + public static final String NETWORK_OFFERING_ID = "networkofferingid"; + public static final String TIER_NETWORK_OFFERINGS = "tiernetworkofferings"; + public static final String NETWORK_IDS = "networkids"; + public static final String NETWORK_ID = "networkid"; + public static final String NETWORK_FILTER = "networkfilter"; + public static final String NIC_ID = "nicid"; + public static final String SPECIFY_AS_NUMBER = "specifyasnumber"; + public static final String SPECIFY_VLAN = "specifyvlan"; + public static final String IS_DEFAULT = "isdefault"; + public static final String IS_SYSTEM = "issystem"; + public static final String IS_USER_DEFINED = "isuserdefined"; + public static final String AVAILABILITY = "availability"; + public static final String NETWORKRATE = "networkrate"; + public static final String HOST_TAGS = "hosttags"; + public static final String SSH_KEYPAIR = "keypair"; + public static final String SSH_KEYPAIRS = "keypairs"; + public static final String HTTPMETHOD = "httpmethod"; + public static final String HOST_CPU_CAPACITY = "hostcpucapacity"; + public static final String HOST_CPU_NUM = "hostcpunum"; + public static final String HOST_MEM_CAPACITY = "hostmemcapacity"; + public static final String HOST_MAC = "hostmac"; + public static final String HOST_TAG = "hosttag"; + public static final String PXE_SERVER_TYPE = "pxeservertype"; + public static final String LINMIN_USERNAME = "linminusername"; + public static final String LINMIN_PASSWORD = "linminpassword"; + public static final String LINMIN_APID = "linminapid"; + public static final String DHCP_SERVER_TYPE = "dhcpservertype"; + public static final String LINK_LOCAL_IP = "linklocalip"; + public static final String LINK_LOCAL_MAC_ADDRESS = "linklocalmacaddress"; + public static final String LINK_LOCAL_MAC_NETMASK = "linklocalnetmask"; + public static final String LINK_LOCAL_NETWORK_ID = "linklocalnetworkid"; + public static final String PRIVATE_MAC_ADDRESS = "privatemacaddress"; + public static final String PRIVATE_NETMASK = "privatenetmask"; + public static final String PRIVATE_NETWORK_ID = "privatenetworkid"; + public static final String ALLOCATION_STATE = "allocationstate"; + public static final String MANAGED_STATE = "managedstate"; + public static final String MANAGEMENT_SERVER_ID = "managementserverid"; + public static final String MANAGEMENT_SERVER_NAME = "managementservername"; + public static final String STORAGE = "storage"; + public static final String STORAGE_ID = "storageid"; + public static final String PING_STORAGE_SERVER_IP = "pingstorageserverip"; + public static final String PING_DIR = "pingdir"; + public static final String TFTP_DIR = "tftpdir"; + public static final String PING_CIFS_USERNAME = "pingcifsusername"; + public static final String PING_CIFS_PASSWORD = "pingcifspassword"; + public static final String CHECKSUM = "checksum"; + public static final String NETWORK_DEVICE_TYPE = "networkdevicetype"; + public static final String NETWORK_DEVICE_PARAMETER_LIST = "networkdeviceparameterlist"; + public static final String ZONE_TOKEN = "zonetoken"; + public static final String DHCP_PROVIDER = "dhcpprovider"; + public static final String RESULT = "result"; + public static final String RESUME = "resume"; + public static final String LUN_ID = "lunId"; + public static final String IQN = "iqn"; + public static final String AGGREGATE_NAME = "aggregatename"; + public static final String POOL_NAME = "poolname"; + public static final String VOLUME_NAME = "volumename"; + public static final String VOLUME_STATE = "volumestate"; + public static final String SNAPSHOT_POLICY = "snapshotpolicy"; + public static final String SNAPSHOT_RESERVATION = "snapshotreservation"; + public static final String IP_NETWORK_LIST = "iptonetworklist"; + public static final String PARAM_LIST = "param"; + public static final String FOR_LOAD_BALANCING = "forloadbalancing"; + public static final String KEYBOARD = "keyboard"; + public static final String OPEN_FIREWALL = "openfirewall"; + public static final String TEMPLATE_TAG = "templatetag"; + public static final String HYPERVISOR_VERSION = "hypervisorversion"; + public static final String MAX_GUESTS_LIMIT = "maxguestslimit"; + public static final String MAX_DATA_VOLUMES_LIMIT = "maxdatavolumeslimit"; + public static final String MAX_HOSTS_PER_CLUSTER = "maxhostspercluster"; + public static final String PROJECT_ID = "projectid"; + public static final String PROJECT_IDS = "projectids"; + public static final String PROJECT = "project"; + public static final String ROLE = "role"; + public static final String ROLE_ID = "roleid"; + public static final String PROJECT_ROLE_ID = "projectroleid"; + public static final String PROJECT_ROLE_NAME = "projectrolename"; + public static final String ROLE_TYPE = "roletype"; + public static final String ROLE_NAME = "rolename"; + public static final String PERMISSION = "permission"; + public static final String PERMISSIONS = "permissions"; + public static final String RULE = "rule"; + public static final String RULES = "rules"; + public static final String RULE_ID = "ruleid"; + public static final String PROJECT_ROLE_PERMISSION_ID = "projectrolepermissionid"; + public static final String RULE_ORDER = "ruleorder"; + public static final String USER = "user"; + public static final String ACTIVE_ONLY = "activeonly"; + public static final String TOKEN = "token"; + public static final String ACCEPT = "accept"; + public static final String SORT_KEY = "sortkey"; + public static final String ACCOUNT_DETAILS = "accountdetails"; + public static final String SERVICE_OFFERING_DETAILS = "serviceofferingdetails"; + public static final String SERVICE_PROVIDER_LIST = "serviceproviderlist"; + public static final String SERVICE_CAPABILITY_LIST = "servicecapabilitylist"; + public static final String CAN_CHOOSE_SERVICE_CAPABILITY = "canchooseservicecapability"; + public static final String PROVIDER = "provider"; + public static final String OAUTH_PROVIDER = "oauthprovider"; + public static final String OAUTH_SECRET_KEY = "secretkey"; + public static final String MANAGED = "managed"; + public static final String CAPACITY_BYTES = "capacitybytes"; + public static final String CAPACITY_IOPS = "capacityiops"; + public static final String NETWORK_SPEED = "networkspeed"; + public static final String BROADCAST_DOMAIN_RANGE = "broadcastdomainrange"; + public static final String BROADCAST_URI = "broadcasturi"; + public static final String ISOLATION_METHOD = "isolationmethod"; + public static final String ISOLATION_METHODS = "isolationmethods"; + public static final String PHYSICAL_NETWORK_ID = "physicalnetworkid"; + public static final String PHYSICAL_NETWORK_NAME = "physicalnetworkname"; + public static final String DEST_PHYSICAL_NETWORK_ID = "destinationphysicalnetworkid"; + public static final String ENABLE = "enable"; + public static final String ENABLED = "enabled"; + public static final String SERVICE_NAME = "servicename"; + public static final String DHCP_RANGE = "dhcprange"; + public static final String UUID = "uuid"; + public static final String SECURITY_GROUP_EANBLED = "securitygroupenabled"; + public static final String LOCAL_STORAGE_ENABLED = "localstorageenabled"; + public static final String GUEST_IP_TYPE = "guestiptype"; + public static final String GUEST_IP6_PREFIX = "guestip6prefix"; + public static final String XENSERVER_NETWORK_LABEL = "xennetworklabel"; + public static final String KVM_NETWORK_LABEL = "kvmnetworklabel"; + public static final String VMWARE_NETWORK_LABEL = "vmwarenetworklabel"; + public static final String HYPERV_NETWORK_LABEL = "hypervnetworklabel"; + public static final String OVM3_NETWORK_LABEL = "ovm3networklabel"; + public static final String NETWORK_SERVICE_PROVIDER_ID = "nspid"; + public static final String SERVICE_LIST = "servicelist"; + public static final String CAN_ENABLE_INDIVIDUAL_SERVICE = "canenableindividualservice"; + public static final String SUPPORTED_SERVICES = "supportedservices"; + public static final String NSP_ID = "nspid"; + public static final String ACL_TYPE = "acltype"; + public static final String ACL_REASON = "reason"; + public static final String ACL_RULE_PARTIAL_UPGRADE = "partialupgrade"; + public static final String SUBDOMAIN_ACCESS = "subdomainaccess"; + public static final String LOAD_BALANCER_DEVICE_ID = "lbdeviceid"; + public static final String LOAD_BALANCER_DEVICE_NAME = "lbdevicename"; + public static final String LOAD_BALANCER_DEVICE_STATE = "lbdevicestate"; + public static final String LOAD_BALANCER_DEVICE_CAPACITY = "lbdevicecapacity"; + public static final String LOAD_BALANCER_DEVICE_DEDICATED = "lbdevicededicated"; + public static final String LOAD_BALANCER_RULE = "loadbalancerrule"; + public static final String LOAD_BALANCER_RULE_LIST = "loadbalancerrulelist"; + public static final String FIREWALL_DEVICE_ID = "fwdeviceid"; + public static final String FIREWALL_DEVICE_NAME = "fwdevicename"; + public static final String FIREWALL_DEVICE_STATE = "fwdevicestate"; + public static final String FIREWALL_DEVICE_CAPACITY = "fwdevicecapacity"; + public static final String FIREWALL_DEVICE_DEDICATED = "fwdevicededicated"; + public static final String SERVICE = "service"; + public static final String ASSOCIATED_NETWORK = "associatednetwork"; + public static final String ASSOCIATED_NETWORK_ID = "associatednetworkid"; + public static final String ASSOCIATED_NETWORK_NAME = "associatednetworkname"; + public static final String ASSOCIATED_VPC_ID = "associatedvpcid"; + public static final String ASSOCIATED_VPC_NAME = "associatedvpcname"; + public static final String SOURCE_NAT_SUPPORTED = "sourcenatsupported"; + public static final String RESOURCE_STATE = "resourcestate"; + public static final String PROJECT_INVITE_REQUIRED = "projectinviterequired"; + public static final String REQUIRED = "required"; + public static final String RESTART_REQUIRED = "restartrequired"; + public static final String ALLOW_USER_CREATE_PROJECTS = "allowusercreateprojects"; + public static final String ALLOW_USER_DRIVEN_BACKUPS = "allowuserdrivenbackups"; + public static final String ALLOW_USER_SPECIFY_VR_MTU = "allowuserspecifyvrmtu"; + public static final String CONSERVE_MODE = "conservemode"; + public static final String TRAFFIC_TYPE_IMPLEMENTOR = "traffictypeimplementor"; + public static final String KEYWORD = "keyword"; + public static final String LIST_ALL = "listall"; + public static final String LIST_ONLY_REMOVED = "listonlyremoved"; + public static final String LIST_SYSTEM_VMS = "listsystemvms"; + public static final String LIST_VM_DETAILS = "listvmdetails"; + public static final String IP_RANGES = "ipranges"; + public static final String IPV4_ROUTING = "ip4routing"; + public static final String IPV4_ROUTES = "ip4routes"; + public static final String IPV6_ROUTING = "ip6routing"; + public static final String IPV6_ROUTES = "ip6routes"; + public static final String SPECIFY_IP_RANGES = "specifyipranges"; + public static final String IS_SOURCE_NAT = "issourcenat"; + public static final String IS_STATIC_NAT = "isstaticnat"; + public static final String ITERATIONS = "iterations"; + public static final String SORT_BY = "sortby"; + public static final String CHANGE_CIDR = "changecidr"; + public static final String PURPOSE = "purpose"; + public static final String IS_TAGGED = "istagged"; + public static final String INSTANCE_NAME = "instancename"; + public static final String CONSIDER_LAST_HOST = "considerlasthost"; + public static final String START_VM = "startvm"; + public static final String HA_HOST = "hahost"; + public static final String CUSTOM_DISK_OFF_MIN_SIZE = "customdiskofferingminsize"; + 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 AUTO_MIGRATE = "automigrate"; + public static final String GUID = "guid"; + public static final String VM_SNAPSHOT_ENABELD = "vmsnapshotenabled"; + public static final String VSWITCH_TYPE_GUEST_TRAFFIC = "guestvswitchtype"; + public static final String VSWITCH_TYPE_PUBLIC_TRAFFIC = "publicvswitchtype"; + public static final String VSWITCH_NAME_GUEST_TRAFFIC = "guestvswitchname"; + public static final String VSWITCH_NAME_PUBLIC_TRAFFIC = "publicvswitchname"; + + // NSX + public static final String EDGE_CLUSTER = "edgecluster"; + public static final String TIER0_GATEWAY = "tier0gateway"; + + public static final String TRANSPORT_ZONE = "transportzone"; + // Tungsten-Fabric + public static final String TUNGSTEN_VIRTUAL_ROUTER_UUID = "tungstenvirtualrouteruuid"; + public static final String TUNGSTEN_PROVIDER_HOSTNAME = "tungstenproviderhostname"; + public static final String TUNGSTEN_PROVIDER_PORT = "tungstenproviderport"; + public static final String TUNGSTEN_PROVIDER_UUID = "tungstenprovideruuid"; + public static final String TUNGSTEN_GATEWAY = "tungstengateway"; + public static final String TUNGSTEN_PROVIDER_VROUTER_PORT = "tungstenprovidervrouterport"; + public static final String TUNGSTEN_PROVIDER_INTROSPECT_PORT = "tungstenproviderintrospectport"; + public static final String SRC_NETWORK = "srcnetwork"; + public static final String SRC_IP_PREFIX = "srcipprefix"; + public static final String SRC_IP_PREFIX_LEN = "srcipprefixlen"; + public static final String SRC_START_PORT = "srcstartport"; + public static final String SRC_END_PORT = "srcendport"; + public static final String DEST_NETWORK = "destnetwork"; + public static final String DEST_IP_PREFIX = "destipprefix"; + public static final String DEST_IP_PREFIX_LEN = "destipprefixlen"; + public static final String DEST_START_PORT = "deststartport"; + public static final String DEST_END_PORT = "destendport"; + public static final String MAJOR_SEQUENCE = "majorsequence"; + public static final String MINOR_SEQUENCE = "minorsequence"; + public static final String POLICY_UUID = "policyuuid"; + public static final String RULE_UUID = "ruleuuid"; + public static final String DIRECTION = "direction"; + public static final String TAGGED_RESOURCES = "taggedresources"; + public static final String TAG_UUID = "taguuid"; + public static final String TAG_TYPE = "tagtype"; + public static final String TAG_VALUE = "tagvalue"; + public static final String TAG_TYPE_UUID = "tagtypeuuid"; + public static final String NETWORK_UUID = "networkuuid"; + public static final String NIC_UUID = "nicuuid"; + public static final String VM_UUID = "vmuuid"; + public static final String ONE_WAY = "oneway"; + public static final String POLICY = "policy"; + public static final String VM = "vm"; + public static final String FIREWALL_POLICY = "firewallpolicy"; + public static final String FIREWALL_RULE = "firewallrule"; + public static final String TAG = "tag"; + public static final String APPLICATION_POLICY_SET_UUID = "applicationpolicysetuuid"; + public static final String FIREWALL_POLICY_UUID = "firewallpolicyuuid"; + public static final String FIREWALL_RULE_UUID = "firewallruleuuid"; + public static final String ADDRESS_GROUP_UUID = "addressgroupuuid"; + public static final String SERVICE_GROUP_UUID = "servicegroupuuid"; + public static final String SEQUENCE = "sequence"; + public static final String SERVICE_GROUP = "servicegroup"; + public static final String SRC_ADDRESS_GROUP = "srcaddressgroup"; + public static final String DEST_ADDRESS_GROUP = "destaddressgroup"; + public static final String SRC_TAG = "srctag"; + public static final String DEST_TAG = "desttag"; + public static final String IP_PREFIX = "ipprefix"; + public static final String IP_PREFIX_LEN = "ipprefixlen"; + public static final String SRC_ADDRESS_GROUP_UUID = "srcaddressgroupuuid"; + public static final String DEST_ADDRESS_GROUP_UUID = "destaddressgroupuuid"; + public static final String SRC_TAG_UUID = "srctaguuid"; + public static final String DEST_TAG_UUID = "desttaguuid"; + public static final String SRC_NETWORK_UUID = "srcnetworkuuid"; + public static final String DEST_NETWORK_UUID = "destnetworkuuid"; + public static final String LOGICAL_ROUTER_UUID = "logicalrouteruuid"; + public static final String RETRY = "retry"; + public static final String HTTP_METHOD = "httpmethodtype"; + public static final String EXPECTED_CODE = "expectedcode"; + public static final String URL_PATH = "urlpath"; + + // Ovs controller + public static final String OVS_DEVICE_ID = "ovsdeviceid"; + public static final String OVS_DEVICE_NAME = "ovsdevicename"; + // OpenDaylight controller + public static final String ODL_DEVICE_ID = "odldeviceid"; + public static final String ODL_DEVICE_NAME = "odldevicename"; + public static final String ODL_TRANSPORT_ZONE_UUID = "transportzoneuuid"; + public static final String ODL_GATEWAYSERVICE_UUID = "l3gatewayserviceuuid"; + + public static final String EXTERNAL_SWITCH_MGMT_DEVICE_ID = "vsmdeviceid"; + public static final String EXTERNAL_SWITCH_MGMT_DEVICE_NAME = "vsmdevicename"; + public static final String EXTERNAL_SWITCH_MGMT_DEVICE_STATE = "vsmdevicestate"; + // Would we need to have a capacity field for Cisco N1KV VSM? Max hosts managed by it perhaps? May remove this + // later. + public static final String EXTERNAL_SWITCH_MGMT_DEVICE_CAPACITY = "vsmdevicecapacity"; + public static final String CISCO_NEXUS_VSM_NAME = "vsmname"; + public static final String VSM_USERNAME = "vsmusername"; + public static final String VSM_PASSWORD = "vsmpassword"; + public static final String VSM_IPADDRESS = "vsmipaddress"; + public static final String VSM_MGMT_VLAN_ID = "vsmmgmtvlanid"; + public static final String VSM_PKT_VLAN_ID = "vsmpktvlanid"; + public static final String VSM_CTRL_VLAN_ID = "vsmctrlvlanid"; + public static final String VSM_STORAGE_VLAN_ID = "vsmstoragevlanid"; + public static final String VSM_DOMAIN_ID = "vsmdomainid"; + public static final String VSM_CONFIG_MODE = "vsmconfigmode"; + public static final String VSM_CONFIG_STATE = "vsmconfigstate"; + public static final String VSM_DEVICE_STATE = "vsmdevicestate"; + public static final String VCENTER = "vcenter"; + public static final String EXISTING_VCENTER_ID = "existingvcenterid"; + public static final String ADD_VSM_FLAG = "addvsmflag"; + public static final String END_POINT = "endpoint"; + public static final String REGION_ID = "regionid"; + public static final String VPC_OFF_ID = "vpcofferingid"; + public static final String VPC_OFF_NAME = "vpcofferingname"; + public static final String VPC_OFFERING_CONSERVE_MODE = "vpcofferingconservemode"; + public static final String NETWORK = "network"; + public static final String VPC_ID = "vpcid"; + public static final String VPC_NAME = "vpcname"; + public static final String VPC_GATEWAY_ID = "vpcgatewayid"; + public static final String VPC_GATEWAY_IP = "vpcgatewayip"; + public static final String GATEWAY_ID = "gatewayid"; + public static final String CAN_USE_FOR_DEPLOY = "canusefordeploy"; + public static final String RESOURCE_IDS = "resourceids"; + public static final String RESOURCE_ID = "resourceid"; + public static final String CUSTOMER = "customer"; + public static final String S2S_VPN_GATEWAY_ID = "s2svpngatewayid"; + public static final String S2S_CUSTOMER_GATEWAY_ID = "s2scustomergatewayid"; + public static final String IPSEC_PSK = "ipsecpsk"; + public static final String GUEST_IP = "guestip"; + public static final String REMOVED = "removed"; + public static final String REMOVER_ACCOUNT_ID = "removeraccountid"; + public static final String REMOVAL_REASON = "removalreason"; + public static final String COMPLETED = "completed"; + public static final String IKE_VERSION = "ikeversion"; + public static final String IKE_POLICY = "ikepolicy"; + public static final String ESP_POLICY = "esppolicy"; + public static final String IKE_LIFETIME = "ikelifetime"; + public static final String ESP_LIFETIME = "esplifetime"; + public static final String DPD = "dpd"; + public static final String FORCE_ENCAP = "forceencap"; + public static final String SPLIT_CONNECTIONS = "splitconnections"; + public static final String FOR_VPC = "forvpc"; + public static final String FOR_NSX = "fornsx"; + public static final String FOR_CKS = "forcks"; + public static final String NSX_SUPPORT_LB = "nsxsupportlb"; + public static final String NSX_SUPPORTS_INTERNAL_LB = "nsxsupportsinternallb"; + public static final String FOR_TUNGSTEN = "fortungsten"; + public static final String SHRINK_OK = "shrinkok"; + public static final String NICIRA_NVP_DEVICE_ID = "nvpdeviceid"; + public static final String NICIRA_NVP_TRANSPORT_ZONE_UUID = "transportzoneuuid"; + public static final String NICIRA_NVP_DEVICE_NAME = "niciradevicename"; + public static final String NICIRA_NVP_GATEWAYSERVICE_UUID = "l3gatewayserviceuuid"; + public static final String NICIRA_NVP_L2_GATEWAYSERVICE_UUID = "l2gatewayserviceuuid"; + public static final String NSX_LOGICAL_SWITCH = "nsxlogicalswitch"; + public static final String NSX_LOGICAL_SWITCH_PORT = "nsxlogicalswitchport"; + public static final String NSX_PROVIDER_UUID = "nsxprovideruuid"; + public static final String NSX_PROVIDER_HOSTNAME = "nsxproviderhostname"; + + public static final String NSX_PROVIDER_PORT = "nsxproviderport"; + public static final String NSX_CONTROLLER_ID = "nsxcontrollerid"; + public static final String S3_ACCESS_KEY = "accesskey"; + public static final String SECRET_KEY = "secretkey"; + public static final String S3_END_POINT = "endpoint"; + public static final String S3_BUCKET_NAME = "bucket"; + public static final String S3_SIGNER = "s3signer"; + public static final String S3_V3_SIGNER = "S3SignerType"; + public static final String S3_V4_SIGNER = "AWSS3V4SignerType"; + public static final String S3_HTTPS_FLAG = "usehttps"; + public static final String S3_CONNECTION_TIMEOUT = "connectiontimeout"; + public static final String S3_CONNECTION_TTL = "connectionttl"; + public static final String S3_MAX_ERROR_RETRY = "maxerrorretry"; + public static final String S3_SOCKET_TIMEOUT = "sockettimeout"; + public static final String S3_USE_TCP_KEEPALIVE = "usetcpkeepalive"; + public static final String INCL_ZONES = "includezones"; + public static final String EXCL_ZONES = "excludezones"; + public static final String SOURCE = "source"; + public static final String COUNTER_ID = "counterid"; + public static final String AGGR_OPERATOR = "aggroperator"; + public static final String AGGR_FUNCTION = "aggrfunction"; + public static final String AGGR_VALUE = "aggrvalue"; + public static final String THRESHOLD = "threshold"; + public static final String RELATIONAL_OPERATOR = "relationaloperator"; + public static final String OTHER_DEPLOY_PARAMS = "otherdeployparams"; + public static final String MIN_MEMBERS = "minmembers"; + public static final String MAX_MEMBERS = "maxmembers"; + public static final String AUTOSCALE_EXPUNGE_VM_GRACE_PERIOD = "expungevmgraceperiod"; + public static final String VMPROFILE_ID = "vmprofileid"; + public static final String VMGROUP_ID = "vmgroupid"; + public static final String CS_URL = "csurl"; + public static final String IDP_ID = "idpid"; + public static final String SCALEUP_POLICY_IDS = "scaleuppolicyids"; + public static final String SCALEDOWN_POLICY_IDS = "scaledownpolicyids"; + public static final String SCALEUP_POLICIES = "scaleuppolicies"; + public static final String SCALEDOWN_POLICIES = "scaledownpolicies"; + public static final String INTERVAL = "interval"; + public static final String QUIETTIME = "quiettime"; + public static final String ACTION = "action"; + public static final String CONDITION_ID = "conditionid"; + public static final String CONDITION_IDS = "conditionids"; + public static final String COUNTERPARAM_LIST = "counterparam"; + public static final String AUTOSCALE_USER_ID = "autoscaleuserid"; + public static final String AUTOSCALE_VMGROUP_ID = "autoscalevmgroupid"; + public static final String AUTOSCALE_VMGROUP_NAME = "autoscalevmgroupname"; + public static final String BAREMETAL_DISCOVER_NAME = "baremetaldiscovername"; + public static final String BAREMETAL_RCT_URL = "baremetalrcturl"; + public static final String UCS_DN = "ucsdn"; + public static final String GSLB_PROVIDER = "gslbprovider"; + public static final String EXCLUSIVE_GSLB_PROVIDER = "isexclusivegslbprovider"; + public static final String GSLB_PROVIDER_PUBLIC_IP = "gslbproviderpublicip"; + public static final String GSLB_PROVIDER_PRIVATE_IP = "gslbproviderprivateip"; + public static final String VM_SNAPSHOT_DESCRIPTION = "description"; + public static final String VM_SNAPSHOT_DISPLAYNAME = "name"; + public static final String VM_SNAPSHOT_ID = "vmsnapshotid"; + public static final String VM_SNAPSHOT_IDS = "vmsnapshotids"; + public static final String VM_SNAPSHOT_DISK_IDS = "vmsnapshotdiskids"; + public static final String VM_SNAPSHOT_MEMORY = "snapshotmemory"; + public static final String VM_SNAPSHOT_QUIESCEVM = "quiescevm"; + public static final String IMAGE_STORE_UUID = "imagestoreuuid"; + public static final String IMAGE_STORE_ID = "imagestoreid"; + public static final String GUEST_VM_CIDR = "guestvmcidr"; + public static final String NETWORK_CIDR = "networkcidr"; + public static final String RESERVED_IP_RANGE = "reservediprange"; + public static final String UCS_MANAGER_ID = "ucsmanagerid"; + public static final String UCS_PROFILE_DN = "profiledn"; + public static final String UCS_BLADE_DN = "bladedn"; + public static final String UCS_BLADE_ID = "bladeid"; + public static final String VM_GUEST_IP = "vmguestip"; + public static final String HEALTHCHECK_FAILED = "healthchecksfailed"; + public static final String HEALTHCHECK_RESPONSE_TIMEOUT = "responsetimeout"; + public static final String HEALTHCHECK_INTERVAL_TIME = "intervaltime"; + public static final String HEALTHCHECK_HEALTHY_THRESHOLD = "healthythreshold"; + public static final String HEALTHCHECK_UNHEALTHY_THRESHOLD = "unhealthythreshold"; + public static final String HEALTHCHECK_PINGPATH = "pingpath"; + public static final String SOURCE_PORT = "sourceport"; + public static final String INSTANCE_PORT = "instanceport"; + public static final String SOURCE_IP = "sourceipaddress"; + public static final String SOURCE_IP_NETWORK_ID = "sourceipaddressnetworkid"; + public static final String SCHEME = "scheme"; + public static final String PROVIDER_TYPE = "providertype"; + public static final String AFFINITY_GROUP_IDS = "affinitygroupids"; + public static final String AFFINITY_GROUP_NAMES = "affinitygroupnames"; + public static final String ASA_INSIDE_PORT_PROFILE = "insideportprofile"; + public static final String AFFINITY_GROUP_ID = "affinitygroupid"; + public static final String DEPLOYMENT_PLANNER = "deploymentplanner"; + public static final String ACL_ID = "aclid"; + public static final String ACL_NAME = "aclname"; + public static final String NUMBER = "number"; + public static final String IS_DYNAMICALLY_SCALABLE = "isdynamicallyscalable"; + public static final String ROUTED_MODE_ENABLED = "routedmodeenabled"; + public static final String ROUTING = "isrouting"; + public static final String ROUTING_MODE = "routingmode"; + public static final String MAX_CONNECTIONS = "maxconnections"; + public static final String SERVICE_STATE = "servicestate"; + + public static final String IAM_GROUPS = "groups"; + public static final String ENTITY_TYPE = "entitytype"; + public static final String ENTITY_ID = "entityid"; + public static final String ENTITY_NAME = "entityname"; + public static final String EXTERNAL_ID = "externalid"; + public static final String ACCESS_TYPE = "accesstype"; + + public static final String RESOURCE_DETAILS = "resourcedetails"; + public static final String RESOURCE_ICON = "icon"; + public static final String RESOURCE_MAP = "resourcemap"; + public static final String EXPUNGE = "expunge"; + public static final String FOR_DISPLAY = "fordisplay"; + public static final String PASSIVE = "passive"; + public static final String VERSION = "version"; + public static final String START = "start"; + public static final String GPUGROUP = "gpugroup"; + public static final String GPUGROUPNAME = "gpugroupname"; + public static final String VGPU = "vgpu"; + public static final String VGPUTYPE = "vgputype"; + public static final String VIDEORAM = "videoram"; + public static final String MAXHEADS = "maxheads"; + public static final String MAXRESOLUTIONX = "maxresolutionx"; + public static final String MAXRESOLUTIONY = "maxresolutiony"; + public static final String MAXVGPUPERPGPU = "maxvgpuperpgpu"; + public static final String REMAININGCAPACITY = "remainingcapacity"; + public static final String MAXCAPACITY = "maxcapacity"; + public static final String DISTRIBUTED_VPC_ROUTER = "distributedvpcrouter"; + public static final String REDUNDANT_ROUTER = "redundantrouter"; + public static final String REDUNDANT_VPC_ROUTER = "redundantvpcrouter"; + public static final String READ_ONLY = "readonly"; + public static final String SUPPORTS_REGION_LEVEL_VPC = "supportsregionLevelvpc"; + public static final String SUPPORTS_STRECHED_L2_SUBNET = "supportsstrechedl2subnet"; + public static final String SUPPORTS_PUBLIC_ACCESS = "supportspublicaccess"; + public static final String SUPPORTS_INTERNAL_LB = "supportsinternallb"; + public static final String SUPPORTS_VM_AUTOSCALING = "supportsvmautoscaling"; + public static final String REGION_LEVEL_VPC = "regionlevelvpc"; + public static final String STRECHED_L2_SUBNET = "strechedl2subnet"; + public static final String NETWORK_NAME = "networkname"; + public static final String NETWORK_SPANNED_ZONES = "zonesnetworkspans"; + public static final String METADATA = "metadata"; + public static final String PHYSICAL_SIZE = "physicalsize"; + public static final String CHAIN_SIZE = "chainsize"; + public static final String OVM3_POOL = "ovm3pool"; + public static final String OVM3_CLUSTER = "ovm3cluster"; + public static final String OVM3_VIP = "ovm3vip"; + public static final String CLEAN_UP_DETAILS = "cleanupdetails"; + public static final String CLEAN_UP_EXTERNAL_DETAILS = "cleanupexternaldetails"; + public static final String CLEAN_UP_EXTRA_CONFIG = "cleanupextraconfig"; + public static final String CLEAN_UP_PARAMETERS = "cleanupparameters"; + public static final String VIRTUAL_SIZE = "virtualsize"; + public static final String NETSCALER_CONTROLCENTER_ID = "netscalercontrolcenterid"; + public static final String NETSCALER_SERVICEPACKAGE_ID = "netscalerservicepackageid"; + public static final String FETCH_ROUTER_HEALTH_CHECK_RESULTS = "fetchhealthcheckresults"; + + public static final String ZONE_ID_LIST = "zoneids"; + public static final String DESTINATION_ZONE_ID_LIST = "destzoneids"; + public static final String STORAGE_ID_LIST = "storageids"; + public static final String ADMIN = "admin"; + public static final String CHECKSUM_PARAMETER_PREFIX_DESCRIPTION = "The parameter containing the checksum will be considered a MD5sum if it is not prefixed\n" + + " and just a plain ascii/utf8 representation of a hexadecimal string. If it is required to\n" + + " use another algorithm the hexadecimal string is to be prefixed with a string of the form,\n" + + " \"{}\", not including the double quotes. In this is the exact string\n" + + " representing the java supported algorithm, i.e. MD5 or SHA-256. Note that java does not\n" + " contain an algorithm called SHA256 or one called sha-256, only SHA-256."; + + public static final String HAS_ANNOTATIONS = "hasannotations"; + public static final String LAST_ANNOTATED = "lastannotated"; + public static final String LDAP_DOMAIN = "ldapdomain"; + + public static final String STDOUT = "stdout"; + public static final String STDERR = "stderr"; + public static final String EXITCODE = "exitcode"; + public static final String TARGET_ID = "targetid"; + public static final String FILES = "files"; + public static final String SRC_POOL = "srcpool"; + public static final String DEST_POOL = "destpool"; + public static final String DEST_POOLS = "destpools"; + public static final String VOLUME_IDS = "volumeids"; + + public static final String ROUTER_ID = "routerid"; + public static final String ROUTER_HEALTH_CHECKS = "healthchecks"; + public static final String ROUTER_CHECK_NAME = "checkname"; + public static final String ROUTER_CHECK_TYPE = "checktype"; + public static final String ROUTER_IP = "routerip"; + public static final String ROUTER_IPV6 = "routeripv6"; + public static final String ROUTER_PRIVATE_INTERFACE_MAX_MTU = "routerprivateinterfacemaxmtu"; + public static final String ROUTER_PUBLIC_INTERFACE_MAX_MTU = "routerpublicinterfacemaxmtu"; + public static final String LAST_UPDATED = "lastupdated"; + public static final String PERFORM_FRESH_CHECKS = "performfreshchecks"; + public static final String CACHE_MODE = "cachemode"; + + public static final String CONSOLE_END_POINT = "consoleendpoint"; + public static final String EXTERNAL_LOAD_BALANCER_IP_ADDRESS = "externalloadbalanceripaddress"; + public static final String DOCKER_REGISTRY_USER_NAME = "dockerregistryusername"; + public static final String DOCKER_REGISTRY_PASSWORD = "dockerregistrypassword"; + public static final String DOCKER_REGISTRY_URL = "dockerregistryurl"; + public static final String DOCKER_REGISTRY_EMAIL = "dockerregistryemail"; + public static final String ISO_NAME = "isoname"; + public static final String ISO_STATE = "isostate"; + public static final String ISO_URL = "isourl"; + public static final String SEMANTIC_VERSION = "semanticversion"; + public static final String KUBERNETES_VERSION_ID = "kubernetesversionid"; + public static final String KUBERNETES_VERSION_NAME = "kubernetesversionname"; + public static final String MASTER_NODES = "masternodes"; + public static final String NODE_IDS = "nodeids"; + public static final String CONTROL_NODES = "controlnodes"; + public static final String ETCD_NODES = "etcdnodes"; + public static final String EXTERNAL_NODES = "externalnodes"; + public static final String IS_EXTERNAL_NODE = "isexternalnode"; + public static final String IS_ETCD_NODE = "isetcdnode"; + public static final String MIN_SEMANTIC_VERSION = "minimumsemanticversion"; + public static final String MIN_KUBERNETES_VERSION_ID = "minimumkubernetesversionid"; + public static final String NODE_ROOT_DISK_SIZE = "noderootdisksize"; + public static final String SUPPORTS_HA = "supportsha"; + public static final String SUPPORTS_AUTOSCALING = "supportsautoscaling"; + public static final String AUTOSCALING_ENABLED = "autoscalingenabled"; + public static final String MIN_SIZE = "minsize"; + public static final String MAX_SIZE = "maxsize"; + public static final String NODE_TYPE_OFFERING_MAP = "nodeofferings"; + public static final String NODE_TYPE_TEMPLATE_MAP = "nodetemplates"; + public static final String NODE_TYPE_AFFINITY_GROUP_MAP = "nodeaffinitygroups"; + public static final String CONTROL_AFFINITY_GROUP_IDS = "controlaffinitygroupids"; + public static final String CONTROL_AFFINITY_GROUP_NAMES = "controlaffinitygroupnames"; + public static final String WORKER_AFFINITY_GROUP_IDS = "workeraffinitygroupids"; + public static final String WORKER_AFFINITY_GROUP_NAMES = "workeraffinitygroupnames"; + public static final String ETCD_AFFINITY_GROUP_IDS = "etcdaffinitygroupids"; + public static final String ETCD_AFFINITY_GROUP_NAMES = "etcdaffinitygroupnames"; + + public static final String BOOT_TYPE = "boottype"; + public static final String BOOT_MODE = "bootmode"; + public static final String BOOT_INTO_SETUP = "bootintosetup"; + public static final String DEPLOY_AS_IS = "deployasis"; + public static final String DEPLOY_AS_IS_DETAILS = "deployasisdetails"; + public static final String CROSS_ZONES = "crossZones"; + public static final String SOURCETEMPLATEID = "sourcetemplateid"; + public static final String DYNAMIC_SCALING_ENABLED = "dynamicscalingenabled"; + public static final String IOTHREADS_ENABLED = "iothreadsenabled"; + public static final String IO_DRIVER_POLICY = "iodriverpolicy"; + + public static final String POOL_TYPE = "pooltype"; + public static final String REDUNDANT_STATE = "redundantstate"; + + public static final String ADMINS_ONLY = "adminsonly"; + public static final String ANNOTATION_FILTER = "annotationfilter"; + public static final String CODE_FOR_2FA = "codefor2fa"; + public static final String PROVIDER_FOR_2FA = "providerfor2fa"; + public static final String ISSUER_FOR_2FA = "issuerfor2fa"; + public static final String MANDATE_2FA = "mandate2fa"; + public static final String PASSWORD_CHANGE_REQUIRED = "passwordchangerequired"; + public static final String SECRET_CODE = "secretcode"; + public static final String LOGIN = "login"; + public static final String LOGOUT = "logout"; + public static final String LIST_IDPS = "listIdps"; + + public static final String MAINTENANCE_INITIATED = "maintenanceinitiated"; + public static final String SHUTDOWN_TRIGGERED = "shutdowntriggered"; + public static final String READY_FOR_SHUTDOWN = "readyforshutdown"; + public static final String PENDING_JOBS_COUNT = "pendingjobscount"; + public static final String AGENTS_COUNT = "agentscount"; + public static final String AGENTS = "agents"; + public static final String LAST_AGENTS = "lastagents"; + + public static final String PUBLIC_MTU = "publicmtu"; + public static final String PRIVATE_MTU = "privatemtu"; + public static final String MTU = "mtu"; + public static final String AUTO_ENABLE_KVM_HOST = "autoenablekvmhost"; + public static final String LIST_APIS = "listApis"; + public static final String VERSIONING = "versioning"; + public static final String OBJECT_LOCKING = "objectlocking"; + public static final String ENCRYPTION = "encryption"; + public static final String QUOTA = "quota"; + public static final String QUOTA_CONSUMED = "quotaconsumed"; + public static final String QUOTA_USAGE = "quotausage"; + public static final String ACCESS_KEY = "accesskey"; + + public static final String SOURCE_NAT_IP = "sourcenatipaddress"; + public static final String SOURCE_NAT_IP_ID = "sourcenatipaddressid"; + public static final String HAS_RULES = "hasrules"; + public static final String NSX_DETAIL_KEY = "forNsx"; + public static final String NETRIS_DETAIL_KEY = "forNetris"; + public static final String NETRIS_TAG = "netristag"; + public static final String NETRIS_VXLAN_ID = "netrisvxlanid"; + public static final String NETRIS_URL = "netrisurl"; + public static final String DISK_PATH = "diskpath"; + public static final String IMPORT_SOURCE = "importsource"; + public static final String TEMP_PATH = "temppath"; + public static final String HEURISTIC_RULE = "heuristicrule"; + public static final String HEURISTIC_TYPE_VALID_OPTIONS = "Valid options are: ISO, SNAPSHOT, TEMPLATE and VOLUME."; + public static final String MANAGEMENT = "management"; + public static final String IS_VNF = "isvnf"; + public static final String VNF_NICS = "vnfnics"; + public static final String VNF_DETAILS = "vnfdetails"; + public static final String CLEAN_UP_VNF_DETAILS = "cleanupvnfdetails"; + public static final String CLEAN_UP_VNF_NICS = "cleanupvnfnics"; + public static final String VNF_CONFIGURE_MANAGEMENT = "vnfconfiguremanagement"; + public static final String VNF_CIDR_LIST = "vnfcidrlist"; + + public static final String CLIENT_ID = "clientid"; + public static final String REDIRECT_URI = "redirecturi"; + + public static final String IS_TAG_A_RULE = "istagarule"; + + public static final String PARAMETER_DESCRIPTION_IS_TAG_A_RULE = "Whether the informed tag is a JS interpretable rule or not."; + + public static final String WEBHOOK_ID = "webhookid"; + public static final String WEBHOOK_NAME = "webhookname"; + + public static final String NFS_MOUNT_OPTIONS = "nfsmountopts"; + public static final String MOUNT_OPTIONS = "mountopts"; + + public static final String SHAREDFSVM_MIN_CPU_COUNT = "sharedfsvmmincpucount"; + public static final String SHAREDFSVM_MIN_RAM_SIZE = "sharedfsvmminramsize"; + + // Object Storage related + public static final String BUCKET_AVAILABLE = "bucketavailable"; + public static final String BUCKET_LIMIT = "bucketlimit"; + public static final String BUCKET_TOTAL = "buckettotal"; + public static final String OBJECT_STORAGE_ID = "objectstorageid"; + public static final String OBJECT_STORAGE = "objectstore"; + public static final String OBJECT_STORAGE_AVAILABLE = "objectstorageavailable"; + public static final String OBJECT_STORAGE_LIMIT = "objectstoragelimit"; + public static final String OBJECT_STORAGE_TOTAL = "objectstoragetotal"; + + public static final String KEEP_MAC_ADDRESS_ON_PUBLIC_NIC = "keepmacaddressonpublicnic"; + + public static final String PARAMETER_DESCRIPTION_KEEP_MAC_ADDRESS_ON_PUBLIC_NIC = + "Indicates whether to use the same MAC address for the public NIC of VRs on the same network. If \"true\", when creating redundant routers or recreating" + + " a VR, CloudStack will use the same MAC address for the public NIC of all VRs. Otherwise, if \"false\", new public NICs will always have " + + " a new MAC address."; + + public static final String PARAMETER_DESCRIPTION_ACTIVATION_RULE = "Quota tariff's activation rule. It can receive a JS script that results in either " + + "a boolean or a numeric value: if it results in a boolean value, the tariff value will be applied according to the result; if it results in a numeric value, the " + + "numeric value will be applied; if the result is neither a boolean nor a numeric value, the tariff will not be applied. If the rule is not informed, the tariff " + + "value will be applied."; + + public static final String PARAMETER_DESCRIPTION_START_DATE_POSSIBLE_FORMATS = "The recommended format is \"yyyy-MM-dd'T'HH:mm:ssZ\" (e.g.: \"2023-01-01T12:00:00+0100\"); " + + "however, the following formats are also accepted: \"yyyy-MM-dd HH:mm:ss\" (e.g.: \"2023-01-01 12:00:00\") and \"yyyy-MM-dd\" (e.g.: \"2023-01-01\" - if the time is not " + + "added, it will be interpreted as \"00:00:00\"). If the recommended format is not used, the date will be considered in the server timezone."; + + public static final String PARAMETER_DESCRIPTION_END_DATE_POSSIBLE_FORMATS = "The recommended format is \"yyyy-MM-dd'T'HH:mm:ssZ\" (e.g.: \"2023-01-01T12:00:00+0100\"); " + + "however, the following formats are also accepted: \"yyyy-MM-dd HH:mm:ss\" (e.g.: \"2023-01-01 12:00:00\") and \"yyyy-MM-dd\" (e.g.: \"2023-01-01\" - if the time is not " + + "added, it will be interpreted as \"23:59:59\"). If the recommended format is not used, the date will be considered in the server timezone."; + + public static final String PARAMETER_DESCRIPTION_MAX_BACKUPS = "The maximum number of backups to keep for a VM. " + + "If \"0\", no retention policy will be applied and, thus, no backups from the schedule will be automatically deleted. " + + "This parameter is only supported for the Dummy, NAS and EMC Networker backup provider."; + + public static final String VMWARE_DC = "vmwaredc"; + + public static final String CSS = "css"; + + public static final String JSON_CONFIGURATION = "jsonconfiguration"; + + public static final String COMMON_NAMES = "commonnames"; + + public static final String COMMON_NAME = "commonname"; + + public static final String DOMAIN_IDS = "domainids"; + + public static final String SHOW_PUBLIC = "showpublic"; + + public static final String LIST_ONLY_DEFAULT_THEME = "listonlydefaulttheme"; + + public static final String RECURSIVE_DOMAINS = "recursivedomains"; + + public static final String VPN_CUSTOMER_GATEWAY_PARAMETERS = "vpncustomergatewayparameters"; + public static final String OBSOLETE_PARAMETERS = "obsoleteparameters"; + public static final String EXCLUDED_PARAMETERS = "excludedparameters"; + + /** + * This enum specifies IO Drivers, each option controls specific policies on I/O. + * Qemu guests support "threads" and "native" options Since 0.8.8 ; "io_uring" is supported Since 6.3.0 (QEMU 5.0). + */ + public enum IoDriverPolicy { + NATIVE("native"), + THREADS("threads"), + IO_URING("io_uring"), + STORAGE_SPECIFIC("storage_specific"); + + String ioDriver; + + IoDriverPolicy(String driver) { + ioDriver = driver; + } + + @Override + public String toString() { + return ioDriver; + } + } + + public enum BootType { + UEFI, BIOS; + + @Override + public String toString() { + return this.name(); + } + } + + public enum BootMode { + LEGACY, SECURE; + + @Override + public String toString() { + return this.name(); + } + } + + public enum HostDetails { + all, capacity, events, stats, min; + } + + public enum VMDetails { + all, group, nics, stats, secgrp, tmpl, servoff, diskoff, backoff, iso, volume, min, affgrp, vnfnics; + } + + public enum DomainDetails { + all, resource, min; + } + + public enum ExtensionDetails { + all, resource, external, min; + } + + public enum ApiKeyAccess { + DISABLED(false), + ENABLED(true), + INHERIT(null); + + Boolean apiKeyAccess; + + ApiKeyAccess(Boolean keyAccess) { + apiKeyAccess = keyAccess; + } + + public Boolean toBoolean() { + return apiKeyAccess; + } + + public static ApiKeyAccess fromBoolean(Boolean value) { + if (value == null) { + return INHERIT; + } else if (value) { + return ENABLED; + } else { + return DISABLED; + } + } + } +} 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 396418aaaa0c..380c34528c40 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 @@ -1,282 +1,281 @@ -// 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.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.commons.lang.BooleanUtils; -import org.apache.commons.lang3.StringUtils; - -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; - -@APICommand(name = "importUnmanagedInstance", - description = "Import unmanaged Instance 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 { - - @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 name of the Instance as it is known to the hypervisor") - 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 Instance. 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, - description = "The ID of the Template for the Instance") - private Long templateId; - - @Parameter(name = ApiConstants.SERVICE_OFFERING_ID, - type = CommandType.UUID, - entityType = ServiceOfferingResponse.class, - required = true, - description = "The service offering for the Instance") - private Long serviceOfferingId; - - @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, ip4Address") - private Map nicIpAddressList; - - @Parameter(name = ApiConstants.NIC_MAC_ADDRESS_LIST, - type = CommandType.MAP, - description = "VM NIC to MAC address mapping using keys nic and mac. " + - "Example: nicmacaddresslist[0].nic=nic1&nicmacaddresslist[0].mac=aa:bb:cc:dd:ee:ff. " + - "Overrides the MAC address reported by the hypervisor for the given NIC.", - since = "4.21.0") - private Map nicMacAddressList; - - @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 = "Instance and its volumes are allowed to migrate to different host/pool when offerings passed are incompatible with current host/pool") - private Boolean migrateAllowed; - - @Parameter(name = ApiConstants.FORCED, - type = CommandType.BOOLEAN, - description = "Instance is imported despite some of its NIC's MAC addresses are already present, in case the MAC address exists then a new MAC address is generated") - private Boolean forced; - - ///////////////////////////////////////////////////// - /////////////////// 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 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); - logger.debug("Checking if NIC '{}' can be mapped on network '{}'", nic, networkUuid); - if (StringUtils.isAnyEmpty(nic, 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 = StringUtils.defaultIfEmpty(entry.get(VmDetailConstants.IP4_ADDRESS), null); - logger.debug("Checking if IP address '{}' can be mapped to NIC '{}'", ipAddress, nic); - if (StringUtils.isEmpty(nic)) { - throw new InvalidParameterValueException(String.format("NIC ID: '%s' is invalid for IP address mapping", nic)); - } - if (StringUtils.isEmpty(ipAddress)) { - throw new InvalidParameterValueException(String.format("Empty address for NIC ID: %s is invalid", nic)); - } - if (StringUtils.isNotEmpty(ipAddress) && !ipAddress.equals("auto") && !NetUtils.isValidIp4(ipAddress)) { - throw new InvalidParameterValueException(String.format("IP address '%s' for NIC ID: %s is invalid", ipAddress, nic)); - } - Network.IpAddresses ipAddresses = new Network.IpAddresses(ipAddress, null); - nicIpAddressMap.put(nic, ipAddresses); - } - } - return nicIpAddressMap; - } - - public Map getNicMacAddressList() { - Map nicMacMap = new HashMap<>(); - if (MapUtils.isEmpty(nicMacAddressList)) { - return nicMacMap; - } - for (Map entry : (Collection>) nicMacAddressList.values()) { - String nic = entry.get(VmDetailConstants.NIC); - String mac = entry.get(VmDetailConstants.NIC_MAC_ADDRESS); - logger.debug("Checking if MAC address '{}' can be mapped to NIC '{}'", mac, nic); - if (StringUtils.isEmpty(nic)) { - throw new InvalidParameterValueException(String.format("NIC ID: '%s' is invalid for MAC address mapping", nic)); - } - if (StringUtils.isEmpty(mac)) { - throw new InvalidParameterValueException(String.format("Empty MAC address for NIC ID: %s is invalid", nic)); - } - if (!NetUtils.isValidMac(mac)) { - throw new InvalidParameterValueException(String.format("MAC address '%s' for NIC ID: %s is not valid", mac, nic)); - } - if (!NetUtils.isUnicastMac(mac)) { - throw new InvalidParameterValueException(String.format("MAC address '%s' for NIC ID: %s is not a unicast address", mac, nic)); - } - nicMacMap.put(nic, NetUtils.standardizeMacAddress(mac)); - } - return nicMacMap; - } - - public Map getDataDiskToDiskOfferingList() { - Map dataDiskToDiskOfferingMap = new HashMap<>(); - if (MapUtils.isNotEmpty(dataDiskToDiskOfferingList)) { - for (Map entry : (Collection>)dataDiskToDiskOfferingList.values()) { - String disk = entry.get(VmDetailConstants.DISK); - String offeringUuid = entry.get(VmDetailConstants.DISK_OFFERING); - logger.trace("Checking if offering '{}' can be used on disk '{}'", offeringUuid, disk); - if (StringUtils.isAnyEmpty(disk, offeringUuid) || _entityMgr.findByUuid(DiskOffering.class, offeringUuid) == null) { - throw new InvalidParameterValueException(String.format("Disk offering ID: %s for disk ID: %s is invalid", offeringUuid, disk)); - } - dataDiskToDiskOfferingMap.put(disk, _entityMgr.findByUuid(DiskOffering.class, offeringUuid).getId()); - \ No newline at end of file +// 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.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.commons.lang.BooleanUtils; +import org.apache.commons.lang3.StringUtils; + +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; + +@APICommand(name = "importUnmanagedInstance", + description = "Import unmanaged Instance 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 { + + @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 name of the Instance as it is known to the hypervisor") + 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 Instance. 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, + description = "The ID of the Template for the Instance") + private Long templateId; + + @Parameter(name = ApiConstants.SERVICE_OFFERING_ID, + type = CommandType.UUID, + entityType = ServiceOfferingResponse.class, + required = true, + description = "The service offering for the Instance") + private Long serviceOfferingId; + + @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, ip4Address") + private Map nicIpAddressList; + + @Parameter(name = ApiConstants.NIC_MAC_ADDRESS_LIST, + type = CommandType.MAP, + description = "VM NIC to MAC address mapping using keys nic and mac. " + + "Example: nicmacaddresslist[0].nic=nic1&nicmacaddresslist[0].mac=aa:bb:cc:dd:ee:ff. " + + "Overrides the MAC address reported by the hypervisor for the given NIC.", + since = "4.21.0") + private Map nicMacAddressList; + + @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 = "Instance and its volumes are allowed to migrate to different host/pool when offerings passed are incompatible with current host/pool") + private Boolean migrateAllowed; + + @Parameter(name = ApiConstants.FORCED, + type = CommandType.BOOLEAN, + description = "Instance is imported despite some of its NIC's MAC addresses are already present, in case the MAC address exists then a new MAC address is generated") + private Boolean forced; + + ///////////////////////////////////////////////////// + /////////////////// 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 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); + logger.debug("Checking if NIC '{}' can be mapped on network '{}'", nic, networkUuid); + if (StringUtils.isAnyEmpty(nic, 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 = StringUtils.defaultIfEmpty(entry.get(VmDetailConstants.IP4_ADDRESS), null); + logger.debug("Checking if IP address '{}' can be mapped to NIC '{}'", ipAddress, nic); + if (StringUtils.isEmpty(nic)) { + throw new InvalidParameterValueException(String.format("NIC ID: '%s' is invalid for IP address mapping", nic)); + } + if (StringUtils.isEmpty(ipAddress)) { + throw new InvalidParameterValueException(String.format("Empty address for NIC ID: %s is invalid", nic)); + } + if (StringUtils.isNotEmpty(ipAddress) && !ipAddress.equals("auto") && !NetUtils.isValidIp4(ipAddress)) { + throw new InvalidParameterValueException(String.format("IP address '%s' for NIC ID: %s is invalid", ipAddress, nic)); + } + Network.IpAddresses ipAddresses = new Network.IpAddresses(ipAddress, null); + nicIpAddressMap.put(nic, ipAddresses); + } + } + return nicIpAddressMap; + } + + public Map getNicMacAddressList() { + Map nicMacMap = new HashMap<>(); + if (MapUtils.isEmpty(nicMacAddressList)) { + return nicMacMap; + } + for (Map entry : (Collection>) nicMacAddressList.values()) { + String nic = entry.get(VmDetailConstants.NIC); + String mac = entry.get(VmDetailConstants.NIC_MAC_ADDRESS); + logger.debug("Checking if MAC address '{}' can be mapped to NIC '{}'", mac, nic); + if (StringUtils.isEmpty(nic)) { + throw new InvalidParameterValueException(String.format("NIC ID: '%s' is invalid for MAC address mapping", nic)); + } + if (StringUtils.isEmpty(mac)) { + throw new InvalidParameterValueException(String.format("Empty MAC address for NIC ID: %s is invalid", nic)); + } + if (!NetUtils.isValidMac(mac)) { + throw new InvalidParameterValueException(String.format("MAC address '%s' for NIC ID: %s is not valid", mac, nic)); + } + if (!NetUtils.isUnicastMac(mac)) { + throw new InvalidParameterValueException(String.format("MAC address '%s' for NIC ID: %s is not a unicast address", mac, nic)); + } + nicMacMap.put(nic, NetUtils.standardizeMacAddress(mac)); + } + return nicMacMap; + } + + public Map getDataDiskToDiskOfferingList() { + Map dataDiskToDiskOfferingMap = new HashMap<>(); + if (MapUtils.isNotEmpty(dataDiskToDiskOfferingList)) { + for (Map entry : (Collection>)dataDiskToDiskOfferingList.values()) { + String disk = entry.get(VmDetailConstants.DISK); + String offeringUuid = entry.get(VmDetailConstants.DISK_OFFERING); + logger.trace("Checking if offering '{}' can be used on disk '{}'", offeringUuid, disk); + if (StringUtils.isAnyEmpty(disk, offeringUuid) || _entityMgr.findByUuid(DiskOffering.class, offeringUuid) == null) { + throw new InvalidParameterValueException(String.format("Disk offering ID: %s for disk ID: %s is invalid", offeringUuid, disk)); + } + dataDiskToDiskOfferingMap.put(disk, _entityMgr.findByUuid(DiskOffering.class, offeringUuid).getId()); diff --git a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java index 07e965fd6fb6..577bf14f0838 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java @@ -1,3177 +1,3177 @@ -// 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 com.cloud.agent.AgentManager; -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.CheckConvertInstanceAnswer; -import com.cloud.agent.api.CheckConvertInstanceCommand; -import com.cloud.agent.api.CheckVolumeAnswer; -import com.cloud.agent.api.CheckVolumeCommand; -import com.cloud.agent.api.ConvertInstanceAnswer; -import com.cloud.agent.api.ConvertInstanceCommand; -import com.cloud.agent.api.CopyRemoteVolumeAnswer; -import com.cloud.agent.api.CopyRemoteVolumeCommand; -import com.cloud.agent.api.GetRemoteVmsAnswer; -import com.cloud.agent.api.GetRemoteVmsCommand; -import com.cloud.agent.api.GetUnmanagedInstancesAnswer; -import com.cloud.agent.api.GetUnmanagedInstancesCommand; -import com.cloud.agent.api.ImportConvertedInstanceAnswer; -import com.cloud.agent.api.ImportConvertedInstanceCommand; -import com.cloud.agent.api.PrepareUnmanageVMInstanceAnswer; -import com.cloud.agent.api.PrepareUnmanageVMInstanceCommand; -import com.cloud.agent.api.to.DataStoreTO; -import com.cloud.agent.api.to.RemoteInstanceTO; -import com.cloud.agent.api.to.StorageFilerTO; -import com.cloud.configuration.Config; -import com.cloud.configuration.Resource; -import com.cloud.dc.DataCenter; -import com.cloud.dc.DataCenterVO; -import com.cloud.dc.VmwareDatacenterVO; -import com.cloud.dc.dao.ClusterDao; -import com.cloud.dc.dao.DataCenterDao; -import com.cloud.dc.dao.VmwareDatacenterDao; -import com.cloud.deploy.DataCenterDeployment; -import com.cloud.deploy.DeployDestination; -import com.cloud.deploy.DeploymentPlanner; -import com.cloud.deploy.DeploymentPlanningManager; -import com.cloud.event.ActionEvent; -import com.cloud.event.ActionEventUtils; -import com.cloud.event.EventTypes; -import com.cloud.event.EventVO; -import com.cloud.event.UsageEventUtils; -import com.cloud.exception.AgentUnavailableException; -import com.cloud.exception.InsufficientAddressCapacityException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.InsufficientVirtualNetworkCapacityException; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.OperationTimedoutException; -import com.cloud.exception.PermissionDeniedException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.UnsupportedServiceException; -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.hypervisor.HypervisorGuru; -import com.cloud.hypervisor.HypervisorGuruManager; -import com.cloud.network.Network; -import com.cloud.network.NetworkModel; -import com.cloud.network.Networks; -import com.cloud.network.PhysicalNetwork; -import com.cloud.network.dao.NetworkDao; -import com.cloud.network.dao.NetworkVO; -import com.cloud.network.dao.PhysicalNetworkDao; -import com.cloud.offering.DiskOffering; -import com.cloud.offering.NetworkOffering; -import com.cloud.offering.ServiceOffering; -import com.cloud.offerings.NetworkOfferingVO; -import com.cloud.offerings.dao.NetworkOfferingDao; -import com.cloud.org.Cluster; -import com.cloud.resource.ResourceManager; -import com.cloud.resource.ResourceState; -import com.cloud.resourcelimit.CheckedReservation; -import com.cloud.resourcelimit.ReservationHelper; -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.DataStoreRole; -import com.cloud.storage.DiskOfferingVO; -import com.cloud.storage.GuestOS; -import com.cloud.storage.GuestOSHypervisor; -import com.cloud.storage.ScopeType; -import com.cloud.storage.Snapshot; -import com.cloud.storage.SnapshotVO; -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.SnapshotDao; -import com.cloud.storage.dao.StoragePoolHostDao; -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.LogUtils; -import com.cloud.utils.Pair; -import com.cloud.utils.UuidUtils; -import com.cloud.utils.db.EntityManager; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.net.NetUtils; -import com.cloud.vm.DiskProfile; -import com.cloud.vm.NicProfile; -import com.cloud.vm.NicVO; -import com.cloud.vm.UserVmManager; -import com.cloud.vm.UserVmVO; -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.UserVmDao; -import com.cloud.vm.dao.VMInstanceDetailsDao; -import com.cloud.vm.dao.VMInstanceDao; -import com.google.gson.Gson; -import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.cloudstack.api.ApiConstants; -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.ImportVmCmd; -import org.apache.cloudstack.api.command.admin.vm.ListImportVMTasksCmd; -import org.apache.cloudstack.api.command.admin.vm.ListUnmanagedInstancesCmd; -import org.apache.cloudstack.api.command.admin.vm.ListVmsForImportCmd; -import org.apache.cloudstack.api.command.admin.vm.UnmanageVMInstanceCmd; -import org.apache.cloudstack.api.response.ListResponse; -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.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; -import org.apache.cloudstack.framework.config.ConfigKey; -import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.cloudstack.reservation.dao.ReservationDao; -import org.apache.cloudstack.resourcelimit.Reserver; -import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; -import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.cloudstack.storage.volume.VolumeOnStorageTO; -import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.collections.MapUtils; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.commons.lang3.ObjectUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import javax.inject.Inject; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.stream.Collectors; - -import static org.apache.cloudstack.api.ApiConstants.MAX_IOPS; -import static org.apache.cloudstack.api.ApiConstants.MIN_IOPS; -import static org.apache.cloudstack.storage.volume.VolumeImportUnmanageService.AllowImportVolumeWithBackingFile; -import static org.apache.cloudstack.vm.ImportVmTask.Step.CloningInstance; -import static org.apache.cloudstack.vm.ImportVmTask.Step.Completed; -import static org.apache.cloudstack.vm.ImportVmTask.Step.ConvertingInstance; -import static org.apache.cloudstack.vm.ImportVmTask.Step.Importing; - -public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { - protected Logger logger = LogManager.getLogger(UnmanagedVMsManagerImpl.class); - private static final long OTHER_LINUX_64_GUEST_OS_ID = 99; - private static final List importUnmanagedInstancesSupportedHypervisors = - Arrays.asList(Hypervisor.HypervisorType.VMware, Hypervisor.HypervisorType.KVM); - - private static final List forceConvertToPoolAllowedTypes = - Arrays.asList(Storage.StoragePoolType.NetworkFilesystem, Storage.StoragePoolType.Filesystem, - Storage.StoragePoolType.SharedMountPoint); - private static final String DETAIL_VDDK_TRANSPORTS = "vddk.transports"; - private static final String DETAIL_VDDK_THUMBPRINT = "vddk.thumbprint"; - - ConfigKey ConvertVmwareInstanceToKvmExtraParamsAllowed = new ConfigKey<>(Boolean.class, - "convert.vmware.instance.to.kvm.extra.params.allowed", - "Advanced", - "false", - "Disabled by default. If enabled, allows extra parameters to be passed to the virt-v2v binary on KVM conversion hosts", - true, - ConfigKey.Scope.Global, - null); - - ConfigKey ConvertVmwareInstanceToKvmExtraParamsAllowedList = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED, - String.class, - "convert.vmware.instance.to.kvm.extra.params.allowed.list", - "", - "Comma separated list of allowed extra parameters to be passed to the virt-v2v binary on KVM conversion hosts", - true, - ConfigKey.Kind.CSV, - null); - - @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 ReservationDao reservationDao; - @Inject - private VMInstanceDetailsDao vmInstanceDetailsDao; - @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 VolumeApiService volumeApiService; - @Inject - private DeploymentPlanningManager deploymentPlanningManager; - @Inject - private VirtualMachineManager virtualMachineManager; - @Inject - private ManagementService managementService; - @Inject - private NicDao nicDao; - @Inject - private NetworkModel networkModel; - @Inject - private ConfigurationDao configurationDao; - @Inject - private GuestOSDao guestOSDao; - @Inject - private GuestOSHypervisorDao guestOSHypervisorDao; - @Inject - private SnapshotDao snapshotDao; - @Inject - private UserVmDao userVmDao; - @Inject - private NetworkOfferingDao networkOfferingDao; - @Inject - EntityManager entityMgr; - @Inject - private NetworkOrchestrationService networkMgr; - @Inject - private PhysicalNetworkDao physicalNetworkDao; - @Inject - private StoragePoolHostDao storagePoolHostDao; - @Inject - private HypervisorGuruManager hypervisorGuruManager; - @Inject - private VmwareDatacenterDao vmwareDatacenterDao; - @Inject - private ImageStoreDao imageStoreDao; - @Inject - private DataStoreManager dataStoreManager; - @Inject - private ImportVmTasksManager importVmTasksManager; - - protected Gson gson; - - public UnmanagedVMsManagerImpl() { - gson = GsonHelper.getGsonLogger(); - } - - private VMTemplateVO createDefaultDummyVmImportTemplate(boolean isKVM) { - String templateName = (isKVM) ? KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME : VM_IMPORT_DEFAULT_TEMPLATE_NAME; - VMTemplateVO template = null; - try { - template = VMTemplateVO.createSystemIso(templateDao.getNextInSequence(Long.class, "id"), templateName, templateName, true, - "", true, 64, Account.ACCOUNT_ID_SYSTEM, "", - "VM Import Default Template", false, OTHER_LINUX_64_GUEST_OS_ID); - template.setState(VirtualMachineTemplate.State.Inactive); - template = templateDao.persist(template); - if (template == null) { - return null; - } - templateDao.remove(template.getId()); - template = templateDao.findByName(templateName); - } catch (Exception e) { - logger.error("Unable to create default dummy template for VM import", e); - } - return template; - } - - private List getAdditionalNameFilters(Cluster cluster) { - List additionalNameFilter = new ArrayList<>(); - if (cluster == null) { - return additionalNameFilter; - } - 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 (StringUtils.isEmpty(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 (StringUtils.isNotEmpty(path)) { - if (!additionalNameFilter.contains(path)) { - volumeFileNames.add(path); - } - if (path.contains("-")) { - split = path.split("-"); - path = split[0]; - if (StringUtils.isNotEmpty(path) && !path.equals("ROOT") && !additionalNameFilter.contains(path)) { - volumeFileNames.add(path); - } - } - } - } - } catch (Exception e) { - logger.warn("Unable to find volume file name for volume: {} while adding filters unmanaged VMs", volumeVO, e); - } - if (!volumeFileNames.isEmpty()) { - additionalNameFilter.addAll(volumeFileNames); - } - } - } - return additionalNameFilter; - } - - private List getHostsManagedVms(List hosts) { - if (CollectionUtils.isEmpty(hosts)) { - return new ArrayList<>(); - } - List instances = vmDao.listByHostOrLastHostOrHostPod(hosts.stream().map(HostVO::getId).collect(Collectors.toList()), hosts.get(0).getPodId()); - List managedVms = instances.stream().map(VMInstanceVO::getInstanceName).collect(Collectors.toList()); - return managedVms; - } - - private boolean hostSupportsServiceOfferingAndTemplate(HostVO host, ServiceOffering serviceOffering, VirtualMachineTemplate template) { - if (StringUtils.isAllEmpty(serviceOffering.getHostTag(), template.getTemplateTag())) { - return true; - } - hostDao.loadHostTags(host); - return host.checkHostServiceOfferingAndTemplateTags(serviceOffering, template, UserVmManager.getStrictHostTags()); - } - - private boolean storagePoolSupportsDiskOffering(StoragePool pool, DiskOffering diskOffering) { - if (pool == null) { - return false; - } - if (diskOffering == null) { - return false; - } - return volumeApiService.doesStoragePoolSupportDiskOffering(pool, diskOffering); - } - - private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedInstanceTO instance, ServiceOfferingVO serviceOffering, final Account owner, final DataCenter zone, final Map details, Hypervisor.HypervisorType hypervisorType) - throws ServerApiException, PermissionDeniedException, ResourceAllocationException { - if (instance == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Cannot find VM to import."); - } - if (serviceOffering == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Cannot find service offering used to import VM [%s].", instance.getName())); - } - 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 [%s] is not valid for importing VM [%s].", cpu, instance.getName())); - } - if (memory == null || memory == 0) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Memory [%s] is not valid for importing VM [%s].", memory, instance.getName())); - } - - if (serviceOffering.isDynamic()) { - if (details.containsKey(VmDetailConstants.CPU_SPEED)) { - try { - cpuSpeed = Integer.parseInt(details.get(VmDetailConstants.CPU_SPEED)); - } catch (Exception e) { - logger.error("Failed to get CPU speed for importing VM [{}] due to [{}].", instance, e.getMessage(), e); - } - } - 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(UnmanagedInstanceTO.PowerState.PowerOff)) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %d CPU cores do not match 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(UnmanagedInstanceTO.PowerState.PowerOff)) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %dMB memory does not match VM memory %dMB and VM is not in powered off state (Power state: %s)", serviceOffering.getUuid(), serviceOffering.getRamSize(), memory, instance.getPowerState())); - } - if (hypervisorType == Hypervisor.HypervisorType.VMware && 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 match VM CPU speed %dMHz and VM is not in powered off state (Power state: %s)", serviceOffering.getUuid(), serviceOffering.getSpeed(), cpuSpeed, instance.getPowerState())); - } - } - return serviceOffering; - } - - /** - * Merges caller-supplied MAC addresses into the NIC IP address map. - * For each NIC entry in {@code nicMacAddressMap}, the MAC address is set on the corresponding - * {@link Network.IpAddresses} object. If no IP address entry exists for a given NIC, a new - * {@link Network.IpAddresses} object is created to carry the MAC. - * - * @param nicIpAddressMap map of NIC ID to IP addresses (may be empty, never null after cmd getter) - * @param nicMacAddressMap map of NIC ID to validated/standardized MAC address strings - * @return merged map with MAC addresses populated where supplied by the caller - */ - protected Map mergeNicMacAddresses( - final Map nicIpAddressMap, - final Map nicMacAddressMap) { - if (MapUtils.isEmpty(nicMacAddressMap)) { - return nicIpAddressMap; - } - Map merged = new HashMap<>(nicIpAddressMap); - for (Map.Entry entry : nicMacAddressMap.entrySet()) { - String nicId = entry.getKey(); - String mac = entry.getValue(); - Network.IpAddresses existing = merged.get(nicId); - if (existing != null) { - existing.setMacAddress(mac); - } else { - merged.put(nicId, new Network.IpAddresses(null, null, mac)); - } - } - return merged; - } - - private Map getNicIpAddresses(final List nics, final Map callerNicIpAddressMap) { - Map nicIpAddresses = new HashMap<>(); - for (UnmanagedInstanceTO.Nic nic : nics) { - Network.IpAddresses ipAddresses = null; - if (MapUtils.isNotEmpty(callerNicIpAddressMap) && callerNicIpAddressMap.containsKey(nic.getNicId())) { - ipAddresses = callerNicIpAddressMap.get(nic.getNicId()); - } - // If IP is set to auto-assign, check NIC doesn't have more that one IP from SDK - if (ipAddresses != null && ipAddresses.getIp4Address() != null && ipAddresses.getIp4Address().equals("auto") && !CollectionUtils.isEmpty(nic.getIpAddress())) { - if (nic.getIpAddress().size() > 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())); - } - String address = nic.getIpAddress().get(0); - if (NetUtils.isValidIp4(address)) { - ipAddresses.setIp4Address(address); - } - } - if (ipAddresses != null) { - nicIpAddresses.put(nic.getNicId(), ipAddresses); - } - } - return nicIpAddresses; - } - - private StoragePool getStoragePool(final UnmanagedInstanceTO.Disk disk, final DataCenter zone, final Cluster cluster, DiskOffering diskOffering) { - StoragePool storagePool = null; - final String dsHost = disk.getDatastoreHost(); - final String dsPath = disk.getDatastorePath(); - final String dsType = disk.getDatastoreType(); - final String dsName = disk.getDatastoreName(); - if (dsType != null) { - List pools = primaryDataStoreDao.listPoolByHostPath(dsHost, dsPath); - for (StoragePool pool : pools) { - if (pool.getDataCenterId() == zone.getId() && - (pool.getClusterId() == null || pool.getClusterId().equals(cluster.getId())) && - volumeApiService.doesStoragePoolSupportDiskOffering(pool, diskOffering)) { - storagePool = pool; - break; - } - } - } - - if (storagePool == null) { - Set pools = new HashSet<>(primaryDataStoreDao.listPoolsByCluster(cluster.getId())); - pools.addAll(primaryDataStoreDao.listByDataCenterId(zone.getId())); - boolean isNameUuid = StringUtils.isNotBlank(dsName) && UuidUtils.isUuid(dsName); - for (StoragePool pool : pools) { - String searchPoolParam = StringUtils.isNotBlank(dsPath) ? dsPath : dsName; - if ((StringUtils.contains(pool.getPath(), searchPoolParam) || isNameUuid && pool.getUuid().equals(dsName)) && - volumeApiService.doesStoragePoolSupportDiskOffering(pool, diskOffering)) { - 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; - } - - private Pair> getRootAndDataDisks( - List disks, - final Map dataDiskOfferingMap) { - UnmanagedInstanceTO.Disk rootDisk = null; - List dataDisks = new ArrayList<>(); - - Set callerDiskIds = dataDiskOfferingMap.keySet(); - if (callerDiskIds.size() != disks.size() - 1) { - String msg = String.format("VM has total %d disks for which %d disk offering mappings provided. %d disks need a disk offering for import", disks.size(), callerDiskIds.size(), disks.size() - 1); - logger.error(String.format("%s. %s parameter can be used to provide disk offerings for the disks", msg, ApiConstants.DATADISK_OFFERING_LIST)); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, msg); - } - List diskIdsWithoutOffering = new ArrayList<>(); - for (UnmanagedInstanceTO.Disk disk : disks) { - String diskId = disk.getDiskId(); - if (!callerDiskIds.contains(diskId)) { - diskIdsWithoutOffering.add(diskId); - rootDisk = disk; - } else { - dataDisks.add(disk); - DiskOffering diskOffering = diskOfferingDao.findById(dataDiskOfferingMap.getOrDefault(disk.getDiskId(), null)); - if ((disk.getCapacity() == null || disk.getCapacity() <= 0) && diskOffering != null) { - disk.setCapacity(diskOffering.getDiskSize()); - } - } - } - if (diskIdsWithoutOffering.size() > 1 || rootDisk == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM has total %d disks, disk offering mapping not provided for %d disks. Disk IDs that may need a disk offering - %s", disks.size(), diskIdsWithoutOffering.size() - 1, String.join(", ", diskIdsWithoutOffering))); - } - - return new Pair<>(rootDisk, dataDisks); - } - - private void checkUnmanagedDiskAndOfferingForImport(String instanceName, UnmanagedInstanceTO.Disk disk, DiskOffering diskOffering, ServiceOffering serviceOffering, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed, List reservations) - throws ServerApiException, PermissionDeniedException, ResourceAllocationException { - if (serviceOffering == null && diskOffering == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID [%s] not found during VM [%s] import.", disk.getDiskId(), instanceName)); - } - if (diskOffering != null) { - accountService.checkAccess(owner, diskOffering, zone); - } - 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 != 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 != 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)))); - } - diskOffering = diskOffering != null ? diskOffering : diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); - StoragePool storagePool = getStoragePool(disk, zone, cluster, 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())); - } - resourceLimitService.checkVolumeResourceLimit(owner, true, disk.getCapacity(), diskOffering, reservations); - } - - private void checkUnmanagedDiskAndOfferingForImport(String intanceName, List disks, final Map diskOfferingMap, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed, List reservations) - throws ServerApiException, PermissionDeniedException, ResourceAllocationException { - String diskController = null; - for (UnmanagedInstanceTO.Disk disk : disks) { - if (disk == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve disk details for VM [%s].", intanceName)); - } - 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 (StringUtils.isEmpty(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 data disk controllers are of the same type", diskController, disk.getController())); - } - } - checkUnmanagedDiskAndOfferingForImport(intanceName, disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), null, owner, zone, cluster, migrateAllowed, reservations); - } - } - - private void checkUnmanagedNicAndNetworkForImport(String instanceName, UnmanagedInstanceTO.Nic nic, Network network, final DataCenter zone, final Account owner, final boolean autoAssign, Hypervisor.HypervisorType hypervisorType) throws ServerApiException { - basicNetworkChecks(instanceName, nic, network); - 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 (!autoAssign && network.getGuestType().equals(Network.GuestType.Isolated)) { - return; - } - checksOnlyNeededForVmware(nic, network, hypervisorType); - } - - private void checksOnlyNeededForVmware(UnmanagedInstanceTO.Nic nic, Network network, final Hypervisor.HypervisorType hypervisorType) { - if (hypervisorType == Hypervisor.HypervisorType.VMware) { - String networkBroadcastUri = network.getBroadcastUri() == null ? null : network.getBroadcastUri().toString(); - if (nic.getVlan() != null && nic.getVlan() != 0 && nic.getPvlan() == null && - (StringUtils.isEmpty(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())); - } - String pvLanType = nic.getPvlanType() == null ? "" : nic.getPvlanType().toLowerCase().substring(0, 1); - if (nic.getVlan() != null && nic.getVlan() != 0 && nic.getPvlan() != null && nic.getPvlan() != 0 && - (StringUtils.isEmpty(networkBroadcastUri) || !String.format("pvlan://%d-%s%d", nic.getVlan(), pvLanType, nic.getPvlan()).equals(networkBroadcastUri))) { - 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-%s%d during VM import", network.getUuid(), networkBroadcastUri, nic.getNicId(), nic.getVlan(), pvLanType, nic.getPvlan())); - } - } - } - - private void basicNetworkChecks(String instanceName, UnmanagedInstanceTO.Nic nic, Network network) { - if (nic == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve the NIC details used by VM [%s] from VMware. Please check if this VM have NICs in VMWare.", instanceName)); - } - if (network == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import.", nic.getNicId())); - } - } - - private void checkUnmanagedNicAndNetworkHostnameForImport(String instanceName, UnmanagedInstanceTO.Nic nic, Network network, final String hostName) throws ServerApiException { - basicNetworkChecks(instanceName, nic, network); - // 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(String.format("VM with Name [%s] already exists in the network [%s] domain [%s]. Cannot import another VM with the same name. Please try again with a different name.", hostName, network, network.getNetworkDomain())); - } - } - - private void checkUnmanagedNicIpAndNetworkForImport(String instanceName, UnmanagedInstanceTO.Nic nic, Network network, final Network.IpAddresses ipAddresses) throws ServerApiException { - basicNetworkChecks(instanceName, nic, network); - // Check IP is assigned for non L2 networks - if (!network.getGuestType().equals(Network.GuestType.L2) && (ipAddresses == null || StringUtils.isEmpty(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 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 && StringUtils.isNotEmpty(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())); - } - } - } - - private Map getUnmanagedNicNetworkMap(String instanceName, List nics, final Map callerNicNetworkMap, - final Map callerNicIpAddressMap, final DataCenter zone, final String hostName, - final Account owner, Hypervisor.HypervisorType hypervisorType) throws ServerApiException { - Map nicNetworkMap = new HashMap<>(); - String nicAdapter = null; - for (int i = 0; i < nics.size(); i++) { - UnmanagedInstanceTO.Nic nic = nics.get(i); - if (StringUtils.isEmpty(nicAdapter)) { - 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())); - } - } - 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 && nic.getVlan() != 0) { - // 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(instanceName, nic, networkVO, zone, owner, true, hypervisorType); - network = networkVO; - } catch (Exception e) { - logger.error(String.format("Error when checking NIC [%s] of unmanaged instance to import due to [%s].", nic.getNicId(), e.getMessage()), e); - } - if (network != null) { - checkUnmanagedNicAndNetworkHostnameForImport(instanceName, nic, network, hostName); - checkUnmanagedNicIpAndNetworkForImport(instanceName, nic, network, ipAddresses); - break; - } - } - } - } else { - network = networkDao.findById(callerNicNetworkMap.get(nic.getNicId())); - boolean autoImport = false; - if (hypervisorType == Hypervisor.HypervisorType.KVM) { - autoImport = ipAddresses != null && ipAddresses.getIp4Address() != null && ipAddresses.getIp4Address().equalsIgnoreCase("auto"); - } - checkUnmanagedNicAndNetworkForImport(instanceName, nic, network, zone, owner, autoImport, hypervisorType); - checkUnmanagedNicAndNetworkHostnameForImport(instanceName, nic, network, hostName); - checkUnmanagedNicIpAndNetworkForImport(instanceName, 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())); - } - nicNetworkMap.put(nic.getNicId(), network.getId()); - } - return nicNetworkMap; - } - - private Pair importExternalDisk(UnmanagedInstanceTO.Disk disk, VirtualMachine vm, DeployDestination dest, DiskOffering diskOffering, - Volume.Type type, VirtualMachineTemplate template,Long deviceId, String remoteUrl, String username, String password, - String tmpPath, DiskProfile diskProfile) { - final String path = StringUtils.isEmpty(disk.getDatastorePath()) ? disk.getImagePath() : disk.getDatastorePath(); - String chainInfo = disk.getChainInfo(); - if (StringUtils.isEmpty(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); - } - Map storage = dest.getStorageForDisks(); - Volume volume = volumeDao.findById(diskProfile.getVolumeId()); - StoragePool storagePool = storage.get(volume); - CopyRemoteVolumeCommand copyRemoteVolumeCommand = new CopyRemoteVolumeCommand(); - copyRemoteVolumeCommand.setRemoteIp(remoteUrl); - copyRemoteVolumeCommand.setUsername(username); - copyRemoteVolumeCommand.setPassword(password); - copyRemoteVolumeCommand.setSrcFile(path); - StorageFilerTO storageTO = new StorageFilerTO(storagePool); - copyRemoteVolumeCommand.setStorageFilerTO(storageTO); - if(tmpPath == null || tmpPath.length() < 1) { - tmpPath = "/tmp/"; - } else { - // Add / if path doesn't end with / - if(tmpPath.charAt(tmpPath.length() - 1) != '/') { - tmpPath += "/"; - } - } - copyRemoteVolumeCommand.setTempPath(tmpPath); - int copyTimeout = UnmanagedVMsManager.RemoteKvmInstanceDisksCopyTimeout.value(); - if (copyTimeout <= 0) { - copyTimeout = Integer.valueOf(UnmanagedVMsManager.RemoteKvmInstanceDisksCopyTimeout.defaultValue()); - } - int copyTimeoutInSecs = copyTimeout * 60; - copyRemoteVolumeCommand.setWait(copyTimeoutInSecs); - logger.error(String.format("Initiating copy remote volume %s from %s, timeout %d secs", path, remoteUrl, copyTimeoutInSecs)); - Answer answer = agentManager.easySend(dest.getHost().getId(), copyRemoteVolumeCommand); - if (!(answer instanceof CopyRemoteVolumeAnswer)) { - throw new CloudRuntimeException("Error while copying volume of remote instance: " + answer.getDetails()); - } - CopyRemoteVolumeAnswer copyRemoteVolumeAnswer = (CopyRemoteVolumeAnswer) answer; - checkVolume(copyRemoteVolumeAnswer.getVolumeDetails()); - if (!copyRemoteVolumeAnswer.getResult()) { - throw new CloudRuntimeException("Unable to copy volume of remote instance"); - } - diskProfile.setSize(copyRemoteVolumeAnswer.getSize()); - DiskProfile profile = volumeManager.updateImportedVolume(type, diskOffering, vm, template, deviceId, - storagePool.getId(), storagePool.getPoolType(), copyRemoteVolumeAnswer.getFilename(), chainInfo, diskProfile); - - return new Pair<>(profile, storagePool); - } - - private Pair importKVMLocalDisk(VirtualMachine vm, DiskOffering diskOffering, - Volume.Type type, VirtualMachineTemplate template, - Long deviceId, Long hostId, String diskPath, DiskProfile diskProfile) { - List storagePools = primaryDataStoreDao.findLocalStoragePoolsByHostAndTags(hostId, null); - if(storagePools.size() < 1) { - throw new CloudRuntimeException("Local Storage not found for host"); - } - - StoragePool storagePool = storagePools.get(0); - - DiskProfile profile = volumeManager.updateImportedVolume(type, diskOffering, vm, template, deviceId, - storagePool.getId(), storagePool.getPoolType(), diskPath, null, diskProfile); - - return new Pair<>(profile, storagePool); - } - - private Pair importKVMSharedDisk(VirtualMachine vm, DiskOffering diskOffering, - Volume.Type type, VirtualMachineTemplate template, - Long deviceId, Long poolId, String diskPath, DiskProfile diskProfile) { - StoragePool storagePool = primaryDataStoreDao.findById(poolId); - - DiskProfile profile = volumeManager.updateImportedVolume(type, diskOffering, vm, template, deviceId, - poolId, storagePool.getPoolType(), diskPath, null, diskProfile); - - return new Pair<>(profile, storagePool); - } - - private Pair importDisk(UnmanagedInstanceTO.Disk disk, VirtualMachine vm, Cluster cluster, DiskOffering diskOffering, - 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 = StringUtils.isEmpty(disk.getFileBaseName()) ? disk.getImagePath() : disk.getFileBaseName(); - String chainInfo = disk.getChainInfo(); - if (vm.getHypervisorType() == Hypervisor.HypervisorType.VMware && StringUtils.isEmpty(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, diskOffering); - DiskProfile profile = volumeManager.importVolume(type, name, diskOffering, diskSize, - minIops, maxIops, vm.getDataCenterId(), vm.getHypervisorType(), vm, template, owner, deviceId, storagePool.getId(), storagePool.getPoolType(), path, chainInfo); - - return new Pair(profile, storagePool); - } - - protected NicProfile importNic(UnmanagedInstanceTO.Nic nic, VirtualMachine vm, Network network, Network.IpAddresses ipAddresses, int deviceId, boolean isDefaultNic, boolean forced) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException { - // Prefer caller-supplied MAC (from nicmacaddresslist); fall back to hypervisor-reported MAC - String macAddress = (ipAddresses != null && StringUtils.isNotEmpty(ipAddresses.getMacAddress())) - ? ipAddresses.getMacAddress() - : nic.getMacAddress(); - DataCenterVO dataCenterVO = dataCenterDao.findById(network.getDataCenterId()); - Pair result = networkOrchestrationService.importNic(macAddress, deviceId, network, isDefaultNic, vm, ipAddresses, dataCenterVO, forced); - if (result == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC ID: %s import failed", nic.getNicId())); - } - return result.first(); - } - - 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 - try { - networkOrchestrationService.release(profile, true); - } catch (Exception e) { - logger.error("Unable to release NICs for unsuccessful import unmanaged VM: {}", userVm, e); - nicDao.removeNicsForInstance(userVm.getId()); - } - // Remove vm - vmDao.remove(userVm.getId()); - } - - 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")); - } - if (sourceHost == null || serviceOffering == null || diskProfileStoragePoolList == null) { - logger.error(String.format("Failed to check migrations need during import, VM: %s", userVm)); - cleanupFailedImportVM(vm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to check migrations need during import, VM: %s", userVm.getInstanceName())); - } - if (!hostSupportsServiceOfferingAndTemplate(sourceHost, serviceOffering, template)) { - logger.debug("VM {} needs to be migrated", vm); - final VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm, template, serviceOffering, owner, null); - profile.setServiceOffering(serviceOfferingDao.findById(vm.getId(), serviceOffering.getId())); - 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) { - String errorMsg = String.format("VM import failed for Unmanaged VM [%s] during VM migration, cannot find deployment destination due to [%s].", vm, e.getMessage()); - logger.warn(errorMsg, e); - cleanupFailedImportVM(vm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg); - } - 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())); - } - try { - 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) { - String errorMsg = String.format("VM import failed for Unmanaged VM [%s] during VM migration due to [%s].", vm, e.getMessage()); - logger.error(errorMsg, e); - cleanupFailedImportVM(vm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg); - } - } - 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; - } - boolean poolSupportsOfferings = storagePoolSupportsDiskOffering(diskProfileStoragePool.second(), dOffering); - if (poolSupportsOfferings) { - continue; - } - logger.debug("Volume {} needs to be migrated", volumeVO); - Pair, List> poolsPair = managementService.listStoragePoolsForSystemMigrationOfVolume(profile.getVolumeId(), null, null, null, null, false, true); - 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(s) found", userVm.getInstanceName(), volumeVO.getUuid())); - } - List storagePools = poolsPair.second(); - StoragePool storagePool = null; - if (CollectionUtils.isNotEmpty(storagePools)) { - for (StoragePool pool : storagePools) { - if (diskProfileStoragePool.second().getId() != pool.getId() && - storagePoolSupportsDiskOffering(pool, dOffering) - ) { - 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) - ) { - storagePool = pool; - break; - } - } - } - 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("Found storage pool {} for migrating the volume {} to", storagePool, volumeVO); - } - try { - Volume volume = null; - if (vm.getState().equals(VirtualMachine.State.Running)) { - volume = volumeManager.liveMigrateVolume(volumeVO, storagePool); - } else { - volume = volumeManager.migrateVolume(volumeVO, storagePool); - } - if (volume == null) { - String msg = ""; - if (vm.getState().equals(VirtualMachine.State.Running)) { - msg = String.format("Live migration for volume: %s to destination pool: %s failed", volumeVO, storagePool); - } else { - msg = String.format("Migration for volume: %s to destination pool: %s failed", volumeVO, storagePool); - } - logger.error(msg); - throw new CloudRuntimeException(msg); - } - } catch (Exception e) { - logger.error("VM import failed for unmanaged vm: {} during volume migration", vm, e); - cleanupFailedImportVM(vm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume migration. %s", userVm.getInstanceName(), StringUtils.defaultString(e.getMessage()))); - } - } - return userVm; - } - - private void publishVMUsageUpdateResourceCount(final UserVm userVm, ServiceOfferingVO serviceOfferingVO, VirtualMachineTemplate templateVO) { - if (userVm == null || serviceOfferingVO == null) { - logger.error("Failed to publish usage records during VM import because VM [{}] or ServiceOffering [{}] is null.", userVm, serviceOfferingVO); - cleanupFailedImportVM(userVm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "VM import failed for Unmanaged VM during publishing Usage Records."); - } - try { - if (!serviceOfferingVO.isDynamic()) { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, 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_CREATE, userVm.getAccountId(), userVm.getAccountId(), userVm.getDataCenterId(), userVm.getHostName(), serviceOfferingVO.getId(), userVm.getTemplateId(), - userVm.getHypervisorType().toString(), VirtualMachine.class.getName(), userVm.getUuid(), userVm.getDetails(), userVm.isDisplayVm()); - } - if (userVm.getState() == VirtualMachine.State.Running) { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_START, userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), userVm.getHostName(), serviceOfferingVO.getId(), userVm.getTemplateId(), - userVm.getHypervisorType().toString(), VirtualMachine.class.getName(), userVm.getUuid(), userVm.isDisplayVm()); - } - } catch (Exception e) { - logger.error("Failed to publish usage records during VM import for unmanaged VM [{}] due to [{}].", userVm, e.getMessage(), e); - cleanupFailedImportVM(userVm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm %s during publishing usage records", userVm.getInstanceName())); - } - resourceLimitService.incrementVmResourceCount(userVm.getAccountId(), userVm.isDisplayVm(), serviceOfferingVO, templateVO); - // Save usage event and update resource count for user vm volumes - List volumes = volumeDao.findByInstance(userVm.getId()); - for (VolumeVO volume : volumes) { - 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("Failed to publish volume ID: {} usage records during VM import", volume, e); - } - resourceLimitService.incrementVolumeResourceCount(userVm.getAccountId(), volume.isDisplayVolume(), - volume.getSize(), diskOfferingDao.findById(volume.getDiskOfferingId())); - } - - List nics = nicDao.listByVmId(userVm.getId()); - for (NicVO nic : nics) { - try { - NetworkVO network = networkDao.findById(nic.getNetworkId()); - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), - Long.toString(nic.getId()), network.getNetworkOfferingId(), null, 1L, VirtualMachine.class.getName(), userVm.getUuid(), userVm.isDisplay()); - } catch (Exception e) { - logger.error(String.format("Failed to publish network usage records during VM import. %s", StringUtils.defaultString(e.getMessage()))); - } - } - } - - private UserVm importVirtualMachineInternal(final UnmanagedInstanceTO unmanagedInstance, final String instanceNameInternal, 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 Map dataDiskOfferingMap, - final Map nicNetworkMap, final Map callerNicIpAddressMap, final Long guestOsId, - final Map details, final boolean migrateAllowed, final boolean forced, final boolean isImportUnmanagedFromSameHypervisor) { - logger.debug(LogUtils.logGsonWithoutException("Trying to import VM [%s] with name [%s], in zone [%s], cluster [%s], and host [%s], using template [%s], service offering [%s], disks map [%s], NICs map [%s] and details [%s].", - unmanagedInstance, displayName, zone, cluster, host, template, serviceOffering, dataDiskOfferingMap, nicNetworkMap, details)); - UserVm userVm = null; - ServiceOfferingVO validatedServiceOffering = null; - try { - validatedServiceOffering = getUnmanagedInstanceServiceOffering(unmanagedInstance, serviceOffering, owner, zone, details, cluster.getHypervisorType()); - } catch (Exception e) { - String errorMsg = String.format("Failed to import Unmanaged VM [%s] because the service offering [%s] is not compatible due to [%s].", unmanagedInstance, serviceOffering, StringUtils.defaultIfEmpty(e.getMessage(), "")); - logger.error(errorMsg, e); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg); - } - - String internalCSName = unmanagedInstance.getInternalCSName(); - if (StringUtils.isEmpty(internalCSName)) { - internalCSName = instanceNameInternal; - } - 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 && host != null && !hostSupportsServiceOfferingAndTemplate(host, validatedServiceOffering, template)) { - throw new InvalidParameterValueException(String.format("Service offering: %s or template: %s is not compatible with host: %s of unmanaged VM: %s", serviceOffering.getUuid(), template.getUuid(), host.getUuid(), displayName)); - } - // 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", displayName)); - } - Pair> rootAndDataDisksPair = getRootAndDataDisks(unmanagedInstanceDisks, dataDiskOfferingMap); - final UnmanagedInstanceTO.Disk rootDisk = rootAndDataDisksPair.first(); - final List dataDisks = rootAndDataDisksPair.second(); - if (rootDisk == null || StringUtils.isEmpty(rootDisk.getController())) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed. Unable to retrieve root disk details for VM: %s ", displayName)); - } - if (cluster.getHypervisorType() == Hypervisor.HypervisorType.KVM) { - Long rootDiskOfferingId = validatedServiceOffering.getDiskOfferingId(); - DiskOffering rootDiskOffering = diskOfferingDao.findById(rootDiskOfferingId); - if ((rootDisk.getCapacity() == null || rootDisk.getCapacity() <= 0) && rootDiskOffering != null) { - rootDisk.setCapacity(rootDiskOffering.getDiskSize()); - } - } - allDetails.put(VmDetailConstants.ROOT_DISK_CONTROLLER, rootDisk.getController()); - if (cluster.getHypervisorType() == Hypervisor.HypervisorType.KVM && isImportUnmanagedFromSameHypervisor) { - long size = Double.valueOf(Math.ceil((double)rootDisk.getCapacity() / Resource.ResourceType.bytesToGiB)).longValue(); - allDetails.put(VmDetailConstants.ROOT_DISK_SIZE, String.valueOf(size)); - } - - List reservations = new ArrayList<>(); - try { - checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), rootDisk, null, validatedServiceOffering, owner, zone, cluster, migrateAllowed, reservations); - if (CollectionUtils.isNotEmpty(dataDisks)) { // Data disk(s) present - checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), dataDisks, dataDiskOfferingMap, owner, zone, cluster, migrateAllowed, reservations); - allDetails.put(VmDetailConstants.DATA_DISK_CONTROLLER, dataDisks.get(0).getController()); - } - - // Check NICs and supplied networks - Map nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap); - Map allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getName(), unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner, cluster.getHypervisorType()); - if (!CollectionUtils.isEmpty(unmanagedInstance.getNics())) { - allDetails.put(VmDetailConstants.NIC_ADAPTER, unmanagedInstance.getNics().get(0).getAdapterType()); - } - - if (StringUtils.isNotEmpty(unmanagedInstance.getVncPassword())) { - allDetails.put(VmDetailConstants.KVM_VNC_PASSWORD, unmanagedInstance.getVncPassword()); - } - - addImportingVMBootTypeAndModeDetails(unmanagedInstance.getBootType(), unmanagedInstance.getBootMode(), allDetails); - - VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff; - if (unmanagedInstance.getPowerState().equals(UnmanagedInstanceTO.PowerState.PowerOn)) { - powerState = VirtualMachine.PowerState.PowerOn; - } - - try { - userVm = userVmManager.importVM(zone, host, template, internalCSName, displayName, owner, - null, caller, true, null, owner.getAccountId(), userId, - validatedServiceOffering, null, guestOsId, hostName, - cluster.getHypervisorType(), allDetails, powerState, null); - } catch (InsufficientCapacityException ice) { - String errorMsg = String.format("Failed to import VM [%s] due to [%s].", displayName, ice.getMessage()); - logger.error(errorMsg, ice); - throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, errorMsg); - } - - if (userVm == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import vm name: %s", displayName)); - } - List> diskProfileStoragePoolList = new ArrayList<>(); - try { - if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) { - throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId())); - } - Long minIops = null; - if (details.containsKey(MIN_IOPS)) { - minIops = Long.parseLong(details.get(MIN_IOPS)); - } - Long maxIops = null; - if (details.containsKey(MAX_IOPS)) { - maxIops = Long.parseLong(details.get(MAX_IOPS)); - } - DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); - diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, cluster, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()), - rootDisk.getCapacity(), minIops, maxIops, template, owner, null)); - long deviceId = 1L; - 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(), offering.getMinIops(), offering.getMaxIops(), - template, owner, deviceId)); - deviceId++; - } - } catch (Exception e) { - logger.error(String.format("Failed to import volumes while importing vm: %s", displayName), e); - cleanupFailedImportVM(userVm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", displayName, StringUtils.defaultString(e.getMessage()))); - } - try { - int nicIndex = 0; - 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, nicIndex, nicIndex == 0, forced); - nicIndex++; - } - } catch (Exception e) { - logger.error(String.format("Failed to import NICs while importing vm: %s", displayName), e); - cleanupFailedImportVM(userVm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import NICs while importing vm: %s. %s", displayName, StringUtils.defaultString(e.getMessage()))); - } - if (migrateAllowed) { - userVm = migrateImportedVM(host, template, validatedServiceOffering, userVm, owner, diskProfileStoragePoolList); - } - publishVMUsageUpdateResourceCount(userVm, validatedServiceOffering, template); - return userVm; - - } catch (ResourceAllocationException e) { // This will be thrown by checkUnmanagedDiskAndOfferingForImport, so the VM was not imported yet - logger.error("Volume resource allocation error for owner: {}", owner, e); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resource allocation error for owner: %s. %s", owner.getUuid(), StringUtils.defaultString(e.getMessage()))); - } finally { - ReservationHelper.closeAll(reservations); - } - } - - private void addImportingVMBootTypeAndModeDetails(String bootType, String bootMode, Map allDetails) { - if (StringUtils.isNotBlank(bootType) && bootType.equalsIgnoreCase("uefi") && StringUtils.isNotBlank(bootMode)) { - allDetails.put("UEFI", bootMode); - } - } - - private HashMap getUnmanagedInstancesForHost(HostVO host, String instanceName, List managedVms) { - HashMap unmanagedInstances = new HashMap<>(); - if (host.isInMaintenanceStates()) { - return unmanagedInstances; - } - - GetUnmanagedInstancesCommand command = new GetUnmanagedInstancesCommand(); - command.setInstanceName(instanceName); - command.setManagedInstancesNames(managedVms); - Answer answer = agentManager.easySend(host.getId(), command); - if (!(answer instanceof GetUnmanagedInstancesAnswer) || !answer.getResult()) { - return unmanagedInstances; - } - GetUnmanagedInstancesAnswer unmanagedInstancesAnswer = (GetUnmanagedInstancesAnswer) answer; - unmanagedInstances = unmanagedInstancesAnswer.getUnmanagedInstances(); - return unmanagedInstances; - } - - protected Cluster basicAccessChecks(Long clusterId) { - final Account caller = CallContext.current().getCallingAccount(); - if (caller.getType() != Account.Type.ADMIN) { - throw new PermissionDeniedException(String.format("Cannot perform this operation, caller account [%s] is not ROOT Admin.", caller.getUuid())); - } - if (clusterId == null) { - throw new InvalidParameterValueException("Cluster ID cannot be null."); - } - final Cluster cluster = clusterDao.findById(clusterId); - if (cluster == null) { - throw new InvalidParameterValueException(String.format("Cluster with ID [%d] cannot be found.", clusterId)); - } - - if (!importUnmanagedInstancesSupportedHypervisors.contains(cluster.getHypervisorType())) { - throw new InvalidParameterValueException(String.format("VM import is currently not supported for hypervisor [%s].", cluster.getHypervisorType().toString())); - } - return cluster; - } - - @Override - public ListResponse listUnmanagedInstances(ListUnmanagedInstancesCmd cmd) { - Long clusterId = cmd.getClusterId(); - Cluster cluster = basicAccessChecks(clusterId); - String keyword = cmd.getKeyword(); - if (StringUtils.isNotEmpty(keyword)) { - keyword = keyword.toLowerCase(); - } - List hosts = resourceManager.listHostsInClusterByStatus(clusterId, Status.Up); - List additionalNameFilters = getAdditionalNameFilters(cluster); - List managedVms = new ArrayList<>(additionalNameFilters); - managedVms.addAll(getHostsManagedVms(hosts)); - List responses = new ArrayList<>(); - for (HostVO host : hosts) { - HashMap unmanagedInstances = getUnmanagedInstancesForHost(host, cmd.getName(), managedVms); - Set keys = unmanagedInstances.keySet(); - for (String key : keys) { - UnmanagedInstanceTO instance = unmanagedInstances.get(key); - if (StringUtils.isNotEmpty(keyword) && - !instance.getName().toLowerCase().contains(keyword)) { - continue; - } - responses.add(responseGenerator.createUnmanagedInstanceResponse(instance, cluster, host)); - } - } - ListResponse listResponses = new ListResponse<>(); - listResponses.setResponses(responses, responses.size()); - return listResponses; - } - - @Override - public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { - return baseImportInstance(cmd); - } - - /** - * Base logic for import virtual machines (unmanaged, external) into CloudStack - * @param cmd importVM or importUnmanagedInstance command - * @return imported user vm - */ - private UserVmResponse baseImportInstance(ImportUnmanagedInstanceCmd cmd) { - basicParametersCheckForImportInstance(cmd.getName(), cmd.getDomainId(), cmd.getAccountName()); - - final String instanceName = cmd.getName(); - Long clusterId = cmd.getClusterId(); - Cluster cluster = basicAccessChecks(clusterId); - - if (!cluster.getAllocationState().equals(Cluster.AllocationState.Enabled)) { - throw new InvalidParameterValueException(String.format("Cluster [%s] is not enabled.", cluster)); - } - - final Account caller = CallContext.current().getCallingAccount(); - final DataCenter zone = dataCenterDao.findById(cluster.getDataCenterId()); - final Account owner = accountService.getActiveAccountById(cmd.getEntityOwnerId()); - long userId = getUserIdForImportInstance(owner); - - VMTemplateVO template = getTemplateForImportInstance(cmd.getTemplateId(), cluster.getHypervisorType()); - ServiceOfferingVO serviceOffering = getServiceOfferingForImportInstance(cmd.getServiceOfferingId(), owner, zone); - - String displayName = getDisplayNameForImportInstance(cmd.getDisplayName(), instanceName); - String hostName = getHostNameForImportInstance(cmd.getHostName(), cluster.getHypervisorType(), instanceName, displayName); - - checkVmwareInstanceNameForImportInstance(cluster.getHypervisorType(), instanceName, hostName, zone); - final Map nicNetworkMap = cmd.getNicNetworkList(); - final Map nicIpAddressMap = mergeNicMacAddresses(cmd.getNicIpAddressList(), cmd.getNicMacAddressList()); - final Map dataDiskOfferingMap = cmd.getDataDiskToDiskOfferingList(); - final Map details = cmd.getDetails(); - final boolean forced = cmd.isForced(); - List hosts = resourceManager.listHostsInClusterByStatus(clusterId, Status.Up); - UserVm userVm = null; - List additionalNameFilters = getAdditionalNameFilters(cluster); - List managedVms = new ArrayList<>(additionalNameFilters); - managedVms.addAll(getHostsManagedVms(hosts)); - - try { - - ActionEventUtils.onStartedActionEvent(userId, owner.getId(), EventTypes.EVENT_VM_IMPORT, - cmd.getEventDescription(), null, null, true, 0); - - if (cmd instanceof ImportVmCmd) { - ImportVmCmd importVmCmd = (ImportVmCmd) cmd; - if (StringUtils.isBlank(importVmCmd.getImportSource())) { - throw new CloudRuntimeException("Please provide an import source for importing the VM"); - } - String source = importVmCmd.getImportSource().toUpperCase(); - ImportSource importSource = Enum.valueOf(ImportSource.class, source); - if (ImportSource.VMWARE == importSource) { - userVm = importUnmanagedInstanceFromVmwareToKvm(zone, cluster, - template, instanceName, displayName, hostName, caller, owner, userId, - serviceOffering, dataDiskOfferingMap, - nicNetworkMap, nicIpAddressMap, - details, importVmCmd, forced); - } - } else { - if (List.of(Hypervisor.HypervisorType.VMware, Hypervisor.HypervisorType.KVM).contains(cluster.getHypervisorType())) { - userVm = importUnmanagedInstanceFromHypervisor(zone, cluster, hosts, additionalNameFilters, - template, instanceName, displayName, hostName, caller, owner, userId, - serviceOffering, dataDiskOfferingMap, - nicNetworkMap, nicIpAddressMap, - details, cmd.getMigrateAllowed(), managedVms, forced); - } - } - - } 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(), StringUtils.defaultString(e.getMessage()))); - } - - if (userVm == null) { - ActionEventUtils.onCompletedActionEvent(userId, owner.getId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_IMPORT, - cmd.getEventDescription(), null, null, 0); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to find unmanaged vm with name: %s in cluster: %s", instanceName, cluster.getUuid())); - } - ActionEventUtils.onCompletedActionEvent(userId, owner.getId(), EventVO.LEVEL_INFO, EventTypes.EVENT_VM_IMPORT, - cmd.getEventDescription(), userVm.getId(), ApiCommandResourceType.VirtualMachine.toString(), 0); - return responseGenerator.createUserVmResponse(ResponseObject.ResponseView.Full, "virtualmachine", userVm).get(0); - } - - protected void checkExtraParamsAllowed(String extraParams) { - if (StringUtils.isBlank(extraParams)) { - return; - } - if (BooleanUtils.isFalse(ConvertVmwareInstanceToKvmExtraParamsAllowed.value())) { - throw new ServerApiException(ApiErrorCode.PARAM_ERROR, - "Extra parameters for Vmware to KVM conversion are disabled by the administrator"); - } - String allowedParamsStr = ConvertVmwareInstanceToKvmExtraParamsAllowedList.value(); - if (StringUtils.isBlank(allowedParamsStr)) { - throw new ServerApiException(ApiErrorCode.PARAM_ERROR, - "Extra parameters for Vmware to KVM conversion are enabled but the allowed list of parameters is empty"); - } - List allowedParams = Arrays.asList(allowedParamsStr.split(",")); - List sanitizedParams = Arrays.asList(extraParams.split(" ")) - .stream() - .filter(x -> x.startsWith("-")) - .map(s -> s.replaceFirst("^-+", "").trim()) //Remove the starting hyphens as in --X or -x - .collect(Collectors.toList()); - for (String param : sanitizedParams) { - if (!allowedParams.contains(param)) { - throw new ServerApiException(ApiErrorCode.PARAM_ERROR, - String.format("The parameter %s is not allowed by the administrator", param)); - } - } - } - - private long getUserIdForImportInstance(Account owner) { - long userId = CallContext.current().getCallingUserId(); - List userVOs = userDao.listByAccount(owner.getAccountId()); - if (CollectionUtils.isNotEmpty(userVOs)) { - userId = userVOs.get(0).getId(); - } - return userId; - } - - protected void basicParametersCheckForImportInstance(String name, Long domainId, String accountName) { - if (StringUtils.isEmpty(name)) { - throw new InvalidParameterValueException("Instance name cannot be empty"); - } - if (domainId != null && StringUtils.isEmpty(accountName)) { - throw new InvalidParameterValueException(String.format("%s parameter must be specified with %s parameter", ApiConstants.DOMAIN_ID, ApiConstants.ACCOUNT)); - } - } - - private void checkVmwareInstanceNameForImportInstance(Hypervisor.HypervisorType hypervisorType, String instanceName, String hostName, DataCenter zone) { - if (hypervisorType.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())); - } - } - } - - private String getHostNameForImportInstance(String hostName, Hypervisor.HypervisorType hypervisorType, - String instanceName, String displayName) { - if (StringUtils.isEmpty(hostName)) { - hostName = hypervisorType == Hypervisor.HypervisorType.VMware ? instanceName : displayName; - if (!NetUtils.verifyDomainNameLabel(hostName, true)) { - throw new InvalidParameterValueException("Please provide a valid hostname for the VM. VM name contains unsupported characters that cannot be used as hostname."); - } - } - 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"); - } - return hostName; - } - - private String getDisplayNameForImportInstance(String displayName, String instanceName) { - return StringUtils.isEmpty(displayName) ? instanceName : displayName; - } - - private ServiceOfferingVO getServiceOfferingForImportInstance(Long serviceOfferingId, Account owner, DataCenter zone) { - if (serviceOfferingId == null) { - throw new InvalidParameterValueException("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); - return serviceOffering; - } - - protected VMTemplateVO getTemplateForImportInstance(Long templateId, Hypervisor.HypervisorType hypervisorType) { - VMTemplateVO template; - if (templateId == null) { - boolean isKVMHypervisor = Hypervisor.HypervisorType.KVM.equals(hypervisorType); - String templateName = (isKVMHypervisor) ? KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME : VM_IMPORT_DEFAULT_TEMPLATE_NAME; - template = templateDao.findByName(templateName); - if (template == null) { - template = createDefaultDummyVmImportTemplate(isKVMHypervisor); - 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 parameter for import", templateName, hypervisorType.toString())); - } - } - } else { - template = templateDao.findById(templateId); - } - if (template == null) { - throw new InvalidParameterValueException(String.format("Template ID: %d cannot be found", templateId)); - } - return template; - } - - @Override - @ActionEvent(eventType = EventTypes.EVENT_VM_IMPORT, eventDescription = "importing VM", async = true) - public UserVmResponse importVm(ImportVmCmd cmd) { - String source = cmd.getImportSource().toUpperCase(); - ImportSource importSource = Enum.valueOf(ImportSource.class, source); - if (ImportSource.VMWARE == importSource || ImportSource.UNMANAGED == importSource) { - checkExtraParamsAllowed(cmd.getExtraParams()); - return baseImportInstance(cmd); - } else { - return importKvmInstance(cmd); - } - } - - private UserVm importUnmanagedInstanceFromHypervisor(DataCenter zone, Cluster cluster, - List hosts, List additionalNameFilters, - VMTemplateVO template, String instanceName, String displayName, - String hostName, Account caller, Account owner, long userId, - ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap, - Map nicNetworkMap, Map nicIpAddressMap, - Map details, Boolean migrateAllowed, List managedVms, boolean forced) throws ResourceAllocationException { - UserVm userVm = null; - for (HostVO host : hosts) { - HashMap unmanagedInstances = getUnmanagedInstancesForHost(host, instanceName, managedVms); - if (MapUtils.isEmpty(unmanagedInstances)) { - continue; - } - Set names = unmanagedInstances.keySet(); - for (String name : names) { - if (!instanceName.equals(name)) { - continue; - } - 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)); - } - - if (template.getName().equals(VM_IMPORT_DEFAULT_TEMPLATE_NAME) && cluster.getHypervisorType().equals(Hypervisor.HypervisorType.KVM)) { - throw new InvalidParameterValueException("Template is needed and unable to use default template for hypervisor " + host.getHypervisorType().toString()); - } - - if (template.getName().equals(VM_IMPORT_DEFAULT_TEMPLATE_NAME)) { - String osName = unmanagedInstance.getOperatingSystem(); - GuestOS guestOS = null; - if (StringUtils.isNotEmpty(osName)) { - guestOS = guestOSDao.findOneByDisplayName(osName); - } - - GuestOSHypervisor guestOSHypervisor = null; - if (guestOS != null) { - guestOSHypervisor = guestOSHypervisorDao.findByOsIdAndHypervisor(guestOS.getId(), host.getHypervisorType().toString(), host.getHypervisorVersion()); - } - if (guestOSHypervisor == null && StringUtils.isNotEmpty(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())); - } - 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(guestOSHypervisor.getGuestOsId()); - } - - List reservations = new ArrayList<>(); - try { - checkVmResourceLimitsForUnmanagedInstanceImport(owner, unmanagedInstance, serviceOffering, template, reservations); - userVm = importVirtualMachineInternal(unmanagedInstance, instanceName, zone, cluster, host, - template, displayName, hostName, CallContext.current().getCallingAccount(), owner, userId, - serviceOffering, dataDiskOfferingMap, - nicNetworkMap, nicIpAddressMap, null, - details, migrateAllowed, forced, true); - } finally { - ReservationHelper.closeAll(reservations); - } - break; - } - if (userVm != null) { - break; - } - } - return userVm; - } - - protected void checkVmResourceLimitsForUnmanagedInstanceImport(Account owner, UnmanagedInstanceTO unmanagedInstance, ServiceOfferingVO serviceOffering, VMTemplateVO template, List reservations) throws ResourceAllocationException { - // When importing an unmanaged instance, the amount of CPUs and memory is obtained from the hypervisor unless powered off - // and not using a dynamic offering, unlike the external VM import that always obtains it from the compute offering - Integer cpu = serviceOffering.getCpu(); - Integer memory = serviceOffering.getRamSize(); - - if (serviceOffering.isDynamic() || !UnmanagedInstanceTO.PowerState.PowerOff.equals(unmanagedInstance.getPowerState())) { - cpu = unmanagedInstance.getCpuCores(); - memory = unmanagedInstance.getMemory(); - } - - if (cpu == null || cpu == 0) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("CPU cores [%s] is not valid for importing VM [%s].", cpu, unmanagedInstance.getName())); - } - if (memory == null || memory == 0) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Memory [%s] is not valid for importing VM [%s].", memory, unmanagedInstance.getName())); - } - - List resourceLimitHostTags = resourceLimitService.getResourceLimitHostTags(serviceOffering, template); - - CheckedReservation vmReservation = new CheckedReservation(owner, Resource.ResourceType.user_vm, resourceLimitHostTags, 1L, reservationDao, resourceLimitService); - reservations.add(vmReservation); - - CheckedReservation cpuReservation = new CheckedReservation(owner, Resource.ResourceType.cpu, resourceLimitHostTags, cpu.longValue(), reservationDao, resourceLimitService); - reservations.add(cpuReservation); - - CheckedReservation memReservation = new CheckedReservation(owner, Resource.ResourceType.memory, resourceLimitHostTags, memory.longValue(), reservationDao, resourceLimitService); - reservations.add(memReservation); - } - - private Pair getSourceVmwareUnmanagedInstance(String vcenter, String datacenterName, String username, - String password, String clusterName, String sourceHostName, - String sourceVM, ServiceOfferingVO serviceOffering) { - HypervisorGuru vmwareGuru = hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware); - - Map params = createParamsForTemplateFromVmwareVmMigration(vcenter, datacenterName, - username, password, clusterName, sourceHostName, sourceVM); - addServiceOfferingDetailsToParams(params, serviceOffering); - - return vmwareGuru.getHypervisorVMOutOfBandAndCloneIfRequired(sourceHostName, sourceVM, params); - } - - /** - * Add the minimum resources to check on the hypervisor source VM before converting the instance against the selected offering resources - * @param params sets the minimum CPU number, CPU speed and memory to be checked against the source VM - * @param serviceOffering service offering for the converted VM - */ - protected void addServiceOfferingDetailsToParams(Map params, ServiceOfferingVO serviceOffering) { - if (serviceOffering != null) { - serviceOfferingDao.loadDetails(serviceOffering); - Map serviceOfferingDetails = serviceOffering.getDetails(); - - if (serviceOffering.getCpu() != null) { - params.put(VmDetailConstants.CPU_NUMBER, String.valueOf(serviceOffering.getCpu())); - } else if (MapUtils.isNotEmpty(serviceOfferingDetails) && serviceOfferingDetails.containsKey(ApiConstants.MIN_CPU_NUMBER)) { - params.put(VmDetailConstants.CPU_NUMBER, serviceOfferingDetails.get(ApiConstants.MIN_CPU_NUMBER)); - } - - if (serviceOffering.getSpeed() != null) { - params.put(VmDetailConstants.CPU_SPEED, String.valueOf(serviceOffering.getSpeed())); - } - - if (serviceOffering.getRamSize() != null) { - params.put(VmDetailConstants.MEMORY, String.valueOf(serviceOffering.getRamSize())); - } else if (MapUtils.isNotEmpty(serviceOfferingDetails) && serviceOfferingDetails.containsKey(ApiConstants.MIN_MEMORY)) { - params.put(VmDetailConstants.MEMORY, serviceOfferingDetails.get(ApiConstants.MIN_MEMORY)); - } - } - } - - private String createOvfTemplateOfSourceVmwareUnmanagedInstance(String vcenter, String datacenterName, String username, - String password, String clusterName, String sourceHostName, - String sourceVMwareInstanceName, DataStoreTO convertLocation, int threadsCountToExportOvf) { - HypervisorGuru vmwareGuru = hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware); - - Map params = createParamsForTemplateFromVmwareVmMigration(vcenter, datacenterName, - username, password, clusterName, sourceHostName, sourceVMwareInstanceName); - - return vmwareGuru.createVMTemplateOutOfBand(sourceHostName, sourceVMwareInstanceName, params, convertLocation, threadsCountToExportOvf); - } - - protected UserVm importUnmanagedInstanceFromVmwareToKvm(DataCenter zone, Cluster destinationCluster, VMTemplateVO template, - String sourceVMName, String displayName, String hostName, - Account caller, Account owner, long userId, - ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap, - Map nicNetworkMap, Map nicIpAddressMap, - Map details, ImportVmCmd cmd, boolean forced) throws ResourceAllocationException { - Long existingVcenterId = cmd.getExistingVcenterId(); - String vcenter = cmd.getVcenter(); - String datacenterName = cmd.getDatacenterName(); - String username = cmd.getUsername(); - String password = cmd.getPassword(); - String clusterName = cmd.getClusterName(); - String sourceHostName = cmd.getHostIp(); - Long convertInstanceHostId = cmd.getConvertInstanceHostId(); - Long importInstanceHostId = cmd.getImportInstanceHostId(); - Long convertStoragePoolId = cmd.getConvertStoragePoolId(); - String extraParams = cmd.getExtraParams(); - boolean forceConvertToPool = cmd.getForceConvertToPool(); - Long guestOsId = cmd.getGuestOsId(); - boolean forceMsToImportVmFiles = Boolean.TRUE.equals(cmd.getForceMsToImportVmFiles()); - boolean useVddk = cmd.getUseVddk(); - - if ((existingVcenterId == null && vcenter == null) || (existingVcenterId != null && vcenter != null)) { - throw new ServerApiException(ApiErrorCode.PARAM_ERROR, - "Please provide an existing vCenter ID or a vCenter IP/Name, parameters are mutually exclusive"); - } - if (existingVcenterId == null && StringUtils.isAnyBlank(vcenter, datacenterName, username, password)) { - throw new ServerApiException(ApiErrorCode.PARAM_ERROR, - "Please set all the information for a vCenter IP/Name, datacenter, username and password"); - } - if (forceMsToImportVmFiles && useVddk) { - throw new ServerApiException(ApiErrorCode.PARAM_ERROR, - String.format("Parameters %s and %s are mutually exclusive", - ApiConstants.FORCE_MS_TO_IMPORT_VM_FILES, ApiConstants.USE_VDDK)); - } - - checkConversionStoragePool(convertStoragePoolId, forceConvertToPool); - validateSelectedConversionStoragePoolForVddk(useVddk, convertStoragePoolId, serviceOffering, dataDiskOfferingMap); - - checkExtraParamsAllowed(extraParams); - - if (existingVcenterId != null) { - VmwareDatacenterVO existingDC = vmwareDatacenterDao.findById(existingVcenterId); - if (existingDC == null) { - String err = String.format("Cannot find any existing VMware DC with ID %s", existingVcenterId); - logger.error(err); - throw new CloudRuntimeException(err); - } - vcenter = existingDC.getVcenterHost(); - datacenterName = existingDC.getVmwareDatacenterName(); - username = existingDC.getUser(); - password = existingDC.getPassword(); - } - - boolean isClonedInstance = false; - UnmanagedInstanceTO sourceVMwareInstance = null; - DataStoreTO temporaryConvertLocation = null; - String ovfTemplateOnConvertLocation = null; - ImportVmTask importVMTask = null; - List reservations = new ArrayList<>(); - try { - HostVO convertHost = selectKVMHostForConversionInCluster(destinationCluster, convertInstanceHostId, useVddk); - HostVO importHost = (useVddk && importInstanceHostId == null) - ? convertHost - : selectKVMHostForImportingInCluster(destinationCluster, importInstanceHostId); - - boolean isOvfExportSupported = false; - CheckConvertInstanceAnswer conversionSupportAnswer = checkConversionSupportOnHost(convertHost, sourceVMName, false, useVddk, details); - if (!useVddk) { - isOvfExportSupported = conversionSupportAnswer.isOvfExportSupported(); - } - logger.debug("The host {} is selected to execute the conversion of the " + - "instance {} from VMware to KVM ", convertHost, sourceVMName); - - temporaryConvertLocation = selectInstanceConversionTemporaryLocation( - destinationCluster, convertHost, importHost, convertStoragePoolId, forceConvertToPool); - List convertStoragePools = findInstanceConversionDestinationStoragePoolsInCluster(destinationCluster, serviceOffering, dataDiskOfferingMap, temporaryConvertLocation, forceConvertToPool); - - long importStartTime = System.currentTimeMillis(); - importVMTask = importVmTasksManager.createImportVMTaskRecord(zone, owner, userId, displayName, vcenter, datacenterName, sourceVMName, - convertHost, importHost); - importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, null, CloningInstance); - - // sourceVMwareInstance could be a cloned instance from sourceVMName, of the sourceVMName itself if its powered off. - // isClonedInstance indicates if the VM is a clone of sourceVMName - - Pair sourceInstanceDetails = getSourceVmwareUnmanagedInstance(vcenter, datacenterName, username, password, clusterName, sourceHostName, sourceVMName, serviceOffering); - sourceVMwareInstance = sourceInstanceDetails.first(); - isClonedInstance = sourceInstanceDetails.second(); - - // Ensure that the configured resource limits will not be exceeded before beginning the conversion process - checkVmResourceLimitsForUnmanagedInstanceImport(owner, sourceVMwareInstance, serviceOffering, template, reservations); - - boolean isWindowsVm = sourceVMwareInstance.getOperatingSystem().toLowerCase().contains("windows"); - if (isWindowsVm) { - checkConversionSupportOnHost(convertHost, sourceVMName, true, useVddk, details); - } - - checkNetworkingBeforeConvertingVmwareInstance(zone, owner, displayName, hostName, sourceVMwareInstance, nicNetworkMap, nicIpAddressMap, forced); - UnmanagedInstanceTO convertedInstance; - if (!useVddk && (forceMsToImportVmFiles || !isOvfExportSupported)) { - // Uses MS for OVF export to temporary conversion location - int noOfThreads = UnmanagedVMsManager.ThreadsOnMSToImportVMwareVMFiles.value(); - importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, null, ConvertingInstance); - ovfTemplateOnConvertLocation = createOvfTemplateOfSourceVmwareUnmanagedInstance( - vcenter, datacenterName, username, password, clusterName, sourceHostName, - sourceVMwareInstance.getName(), temporaryConvertLocation, noOfThreads); - convertedInstance = convertVmwareInstanceToKVMWithOVFOnConvertLocation(sourceVMName, - sourceVMwareInstance, convertHost, importHost, convertStoragePools, - serviceOffering, dataDiskOfferingMap, temporaryConvertLocation, - ovfTemplateOnConvertLocation, forceConvertToPool, extraParams); - } else { - // Uses KVM Host for direct conversion using VDDK, or for OVF export to temporary conversion location through ovftool - importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, null, ConvertingInstance); - convertedInstance = convertVmwareInstanceToKVMUsingVDDKOrAfterExportingOVFToConvertLocation( - sourceVMName, sourceVMwareInstance, convertHost, importHost, - convertStoragePools, serviceOffering, dataDiskOfferingMap, - temporaryConvertLocation, vcenter, username, password, datacenterName, forceConvertToPool, extraParams, useVddk, details); - } - - sanitizeConvertedInstance(convertedInstance, sourceVMwareInstance); - importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, null, Importing); - UserVm userVm = importVirtualMachineInternal(convertedInstance, null, zone, destinationCluster, null, - template, displayName, hostName, caller, owner, userId, - serviceOffering, dataDiskOfferingMap, - nicNetworkMap, nicIpAddressMap, guestOsId, - details, false, forced, false); - long timeElapsedInSecs = (System.currentTimeMillis() - importStartTime) / 1000; - logger.debug(String.format("VMware VM %s imported successfully to CloudStack instance %s (%s), Time taken: %d secs, OVF files imported from %s, Source VMware VM details - OS: %s, PowerState: %s, Disks: %s, NICs: %s", - sourceVMName, displayName, displayName, timeElapsedInSecs, (ovfTemplateOnConvertLocation != null)? "MS" : "KVM Host", sourceVMwareInstance.getOperatingSystem(), sourceVMwareInstance.getPowerState(), sourceVMwareInstance.getDisks(), sourceVMwareInstance.getNics())); - importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, userVm.getId(), Completed); - return userVm; - } catch (CloudRuntimeException e) { - logger.error(String.format("Error importing VM: %s", e.getMessage()), e); - importVmTasksManager.updateImportVMTaskErrorState(importVMTask, ImportVmTask.TaskState.Failed, e.getMessage()); - ActionEventUtils.onCompletedActionEvent(userId, owner.getId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_IMPORT, - cmd.getEventDescription(), null, null, 0); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); - } finally { - if (isClonedInstance && sourceVMwareInstance != null) { - removeClonedInstance(vcenter, datacenterName, username, password, sourceHostName, sourceVMwareInstance.getName(), sourceVMName); - } - if (temporaryConvertLocation != null && StringUtils.isNotBlank(ovfTemplateOnConvertLocation)) { - removeTemplate(temporaryConvertLocation, ovfTemplateOnConvertLocation); - } - ReservationHelper.closeAll(reservations); - } - } - - /** - * Check whether the conversion storage pool exists and is suitable for the conversion or not. - * Secondary storage is only allowed when forceConvertToPool is false. - * @param convertStoragePoolId the ID of the storage pool (primary or secondary) - * @param forceConvertToPool when true, only primary storage pool must be allowed - * @throws CloudRuntimeException in case these requirements are not met - */ - protected void checkConversionStoragePool(Long convertStoragePoolId, boolean forceConvertToPool) { - if (forceConvertToPool && convertStoragePoolId == null) { - String msg = "The parameter forceconverttopool is set to true, but a primary storage pool has not been provided for conversion"; - logFailureAndThrowException(msg); - } - if (convertStoragePoolId != null) { - StoragePoolVO selectedStoragePool = primaryDataStoreDao.findById(convertStoragePoolId); - if (selectedStoragePool == null) { - logFailureAndThrowException(String.format("Cannot find a storage pool with ID %s", convertStoragePoolId)); - } - if (forceConvertToPool && !forceConvertToPoolAllowedTypes.contains(selectedStoragePool.getPoolType())) { - logFailureAndThrowException(String.format("The selected storage pool %s does not support direct conversion " + - "as its type %s", selectedStoragePool.getName(), selectedStoragePool.getPoolType().name())); - } - } - } - - protected void validateSelectedConversionStoragePoolForVddk(boolean useVddk, Long convertStoragePoolId, - ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap) { - if (!useVddk || convertStoragePoolId == null) { - return; - } - - StoragePoolVO selectedStoragePool = primaryDataStoreDao.findById(convertStoragePoolId); - if (selectedStoragePool == null) { - return; - } - - if (serviceOffering.getDiskOfferingId() != null) { - DiskOfferingVO rootDiskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); - if (rootDiskOffering == null) { - throw new InvalidParameterValueException(String.format("Cannot find disk offering with ID %s that belongs to the service offering %s", - serviceOffering.getDiskOfferingId(), serviceOffering.getName())); - } - if (!volumeApiService.doesStoragePoolSupportDiskOffering(selectedStoragePool, rootDiskOffering)) { - throw new InvalidParameterValueException(String.format("The root disk offering '%s' is not supported by the selected conversion storage pool '%s'. " + - "When using VDDK, all selected disk offerings must be compatible with the conversion storage pool, as it will become the primary storage for the imported volumes.", - rootDiskOffering.getName(), selectedStoragePool.getName())); - } - } - - if (MapUtils.isNotEmpty(dataDiskOfferingMap)) { - for (Long diskOfferingId : dataDiskOfferingMap.values()) { - DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId); - if (diskOffering == null) { - throw new InvalidParameterValueException(String.format("Cannot find disk offering with ID %s", diskOfferingId)); - } - if (!volumeApiService.doesStoragePoolSupportDiskOffering(selectedStoragePool, diskOffering)) { - throw new InvalidParameterValueException(String.format("The data disk offering '%s' is not supported by the selected conversion storage pool '%s'. " + - "When using VDDK, all selected disk offerings must be compatible with the conversion storage pool, as it will become the primary storage for the imported volumes.", - diskOffering.getName(), selectedStoragePool.getName())); - } - } - } - } - - private void checkNetworkingBeforeConvertingVmwareInstance(DataCenter zone, Account owner, String displayName, - String hostName, UnmanagedInstanceTO sourceVMwareInstance, - Map nicNetworkMap, - Map nicIpAddressMap, - boolean forced) { - List nics = sourceVMwareInstance.getNics(); - List networkIds = new ArrayList<>(nicNetworkMap.values()); - if (nics.size() != networkIds.size()) { - String msg = String.format("Different number of nics found on instance %s: %s vs %s nics provided", - sourceVMwareInstance.getName(), nics.size(), networkIds.size()); - logger.error(msg); - throw new CloudRuntimeException(msg); - } - - for (UnmanagedInstanceTO.Nic nic : nics) { - Long networkId = nicNetworkMap.get(nic.getNicId()); - NetworkVO network = networkDao.findById(networkId); - if (network == null) { - String err = String.format("Cannot find a network with id = %s", networkId); - logger.error(err); - throw new CloudRuntimeException(err); - } - Network.IpAddresses ipAddresses = null; - if (MapUtils.isNotEmpty(nicIpAddressMap) && nicIpAddressMap.containsKey(nic.getNicId())) { - ipAddresses = nicIpAddressMap.get(nic.getNicId()); - } - boolean autoImport = ipAddresses != null && ipAddresses.getIp4Address() != null && ipAddresses.getIp4Address().equalsIgnoreCase("auto"); - checkUnmanagedNicAndNetworkMacAddressForImport(network, nic, forced); - checkUnmanagedNicAndNetworkForImport(displayName, nic, network, zone, owner, autoImport, Hypervisor.HypervisorType.KVM); - checkUnmanagedNicAndNetworkHostnameForImport(displayName, nic, network, hostName); - checkUnmanagedNicIpAndNetworkForImport(displayName, nic, network, ipAddresses); - } - } - - private void checkUnmanagedNicAndNetworkMacAddressForImport(NetworkVO network, UnmanagedInstanceTO.Nic nic, boolean forced) { - NicVO existingNic = nicDao.findByNetworkIdAndMacAddress(network.getId(), nic.getMacAddress()); - if (existingNic != null && !forced) { - String err = String.format("NIC %s with MAC address %s already exists on network %s and forced flag is disabled. " + - "Retry with forced flag enabled if a new MAC address to be generated.", nic, nic.getMacAddress(), network); - logger.error(err); - throw new CloudRuntimeException(err); - } - } - - private void sanitizeConvertedInstance(UnmanagedInstanceTO convertedInstance, UnmanagedInstanceTO sourceVMwareInstance) { - convertedInstance.setCpuCores(sourceVMwareInstance.getCpuCores()); - convertedInstance.setCpuSpeed(sourceVMwareInstance.getCpuSpeed()); - convertedInstance.setCpuCoresPerSocket(sourceVMwareInstance.getCpuCoresPerSocket()); - convertedInstance.setMemory(sourceVMwareInstance.getMemory()); - convertedInstance.setPowerState(UnmanagedInstanceTO.PowerState.PowerOff); - List convertedInstanceDisks = convertedInstance.getDisks(); - List sourceVMwareInstanceDisks = sourceVMwareInstance.getDisks(); - for (int i = 0; i < convertedInstanceDisks.size(); i++) { - UnmanagedInstanceTO.Disk disk = convertedInstanceDisks.get(i); - disk.setDiskId(sourceVMwareInstanceDisks.get(i).getDiskId()); - } - List convertedInstanceNics = convertedInstance.getNics(); - List sourceVMwareInstanceNics = sourceVMwareInstance.getNics(); - if (CollectionUtils.isEmpty(convertedInstanceNics) && CollectionUtils.isNotEmpty(sourceVMwareInstanceNics)) { - for (UnmanagedInstanceTO.Nic nic : sourceVMwareInstanceNics) { - // In case the NICs information is not parsed from the converted XML domain, use the cloned instance NICs with virtio adapter - nic.setAdapterType("virtio"); - } - convertedInstance.setNics(sourceVMwareInstanceNics); - for (int i = 0; i < convertedInstanceNics.size(); i++) { - UnmanagedInstanceTO.Nic nic = convertedInstanceNics.get(i); - nic.setNicId(sourceVMwareInstanceNics.get(i).getNicId()); - } - } else if (CollectionUtils.isNotEmpty(convertedInstanceNics) && CollectionUtils.isNotEmpty(sourceVMwareInstanceNics) - && convertedInstanceNics.size() == sourceVMwareInstanceNics.size()) { - for (int i = 0; i < convertedInstanceNics.size(); i++) { - UnmanagedInstanceTO.Nic nic = convertedInstanceNics.get(i); - nic.setNicId(sourceVMwareInstanceNics.get(i).getNicId()); - if (nic.getMacAddress() == null) { - nic.setMacAddress(sourceVMwareInstanceNics.get(i).getMacAddress()); - } - } - } - } - - private void removeClonedInstance(String vcenter, String datacenterName, String username, String password, - String sourceHostName, String clonedInstanceName, String sourceVM) { - HypervisorGuru vmwareGuru = hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware); - Map params = createParamsForRemoveClonedInstance(vcenter, datacenterName, username, password, sourceVM); - boolean result = vmwareGuru.removeClonedHypervisorVMOutOfBand(sourceHostName, clonedInstanceName, params); - if (!result) { - String msg = String.format("Could not properly remove the cloned instance %s from VMware datacenter %s:%s", - clonedInstanceName, vcenter, datacenterName); - logger.warn(msg); - return; - } - logger.debug(String.format("Removed the cloned instance %s from VMWare datacenter %s/%s", - clonedInstanceName, vcenter, datacenterName)); - } - - private void removeTemplate(DataStoreTO convertLocation, String ovfTemplateOnConvertLocation) { - HypervisorGuru vmwareGuru = hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware); - boolean result = vmwareGuru.removeVMTemplateOutOfBand(convertLocation, ovfTemplateOnConvertLocation); - if (!result) { - String msg = String.format("Could not remove the template file %s on datastore %s", - ovfTemplateOnConvertLocation, convertLocation.getUrl()); - logger.warn(msg); - return; - } - logger.debug(String.format("Removed the template file %s on datastore %s", - ovfTemplateOnConvertLocation, convertLocation.getUrl())); - } - - private Map createParamsForRemoveClonedInstance(String vcenter, String datacenterName, String username, - String password, String sourceVM) { - Map params = new HashMap<>(); - params.put(VmDetailConstants.VMWARE_VCENTER_HOST, vcenter); - params.put(VmDetailConstants.VMWARE_DATACENTER_NAME, datacenterName); - params.put(VmDetailConstants.VMWARE_VCENTER_USERNAME, username); - params.put(VmDetailConstants.VMWARE_VCENTER_PASSWORD, password); - return params; - } - - HostVO selectKVMHostForImportingInCluster(Cluster destinationCluster, Long importInstanceHostId) { - if (importInstanceHostId != null) { - String err = null; - HostVO selectedHost = hostDao.findById(importInstanceHostId); - if (selectedHost == null) { - err = String.format("Cannot find host with ID %s to import the instance", - importInstanceHostId); - } else if (selectedHost.getResourceState() != ResourceState.Enabled) { - err = String.format( - "Cannot import the converted instance on the host %s as it is not in Enabled state", - selectedHost); - } else if (selectedHost.getStatus() != Status.Up) { - err = String.format( - "Cannot import the converted instance on the host %s as it is not running", - selectedHost); - } else if (selectedHost.getType() != Host.Type.Routing) { - err = String.format( - "Cannot import the converted instance on the host %s as it is not a routing host", - selectedHost); - } else if (destinationCluster.getId() != selectedHost.getClusterId()) { - err = String.format( - "Cannot import the converted instance on the host %s as it is not in the same cluster as the destination cluster", - selectedHost); - } - - if (err != null) { - logger.error(err); - throw new CloudRuntimeException(err); - } - return selectedHost; - } - - List hosts = hostDao.listByClusterAndHypervisorType(destinationCluster.getId(), destinationCluster.getHypervisorType()); - if (CollectionUtils.isNotEmpty(hosts)) { - return hosts.get(new Random().nextInt(hosts.size())); - } - - String err = String.format( - "Could not find any suitable %s host in cluster %s to import the converted instance", - destinationCluster.getHypervisorType(), destinationCluster); - logger.error(err); - throw new CloudRuntimeException(err); - } - - HostVO selectKVMHostForConversionInCluster(Cluster destinationCluster, Long convertInstanceHostId, boolean useVddk) { - if (convertInstanceHostId != null) { - HostVO selectedHost = hostDao.findById(convertInstanceHostId); - String err = null; - if (selectedHost == null) { - err = String.format("Cannot find host with ID %s for conversion", - convertInstanceHostId); - } else if (!List.of(ResourceState.Enabled, ResourceState.Disabled).contains(selectedHost.getResourceState())) { - err = String.format( - "Cannot perform the conversion on the host %s as the host is in %s state", - selectedHost, selectedHost.getResourceState()); - } else if (selectedHost.getStatus() != Status.Up) { - err = String.format( - "Cannot perform the conversion on the host %s as it is not running", - selectedHost); - } else if (selectedHost.getType() != Host.Type.Routing) { - err = String.format( - "Cannot perform the conversion on the host %s as it is not a routing host", - selectedHost); - } else if (destinationCluster.getDataCenterId() != selectedHost.getDataCenterId()) { - err = String.format( - "Cannot perform the conversion on the host %s as it is not in the same zone as the destination cluster", - selectedHost); - } - if (err != null) { - logger.error(err); - throw new CloudRuntimeException(err); - } - return selectedHost; - } - - // Auto select host with conversion capability - List hosts = hostDao.listByClusterHypervisorTypeAndHostCapability(destinationCluster.getId(), destinationCluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION); - if (CollectionUtils.isNotEmpty(hosts)) { - if (useVddk) { - List vddkHosts = filterHostsWithVddkSupport(hosts); - if (CollectionUtils.isNotEmpty(vddkHosts)) { - hosts = vddkHosts; - } - } - if (CollectionUtils.isNotEmpty(hosts)) { - return hosts.get(new Random().nextInt(hosts.size())); - } - } - - // Try without host capability check - hosts = hostDao.listByClusterAndHypervisorType(destinationCluster.getId(), destinationCluster.getHypervisorType()); - if (CollectionUtils.isNotEmpty(hosts)) { - if (useVddk) { - List vddkHosts = filterHostsWithVddkSupport(hosts); - if (CollectionUtils.isNotEmpty(vddkHosts)) { - hosts = vddkHosts; - } - } - if (CollectionUtils.isNotEmpty(hosts)) { - return hosts.get(new Random().nextInt(hosts.size())); - } - } - - String err = useVddk - ? String.format("Could not find any suitable %s host in cluster %s with '%s' configured to perform the VDDK-based instance conversion", - destinationCluster.getHypervisorType(), destinationCluster, Host.HOST_VDDK_SUPPORT) - : String.format("Could not find any suitable %s host in cluster %s to perform the instance conversion", - destinationCluster.getHypervisorType(), destinationCluster); - logger.error(err); - throw new CloudRuntimeException(err); - } - - private List filterHostsWithVddkSupport(List hosts) { - return hosts.stream().filter(h -> { - hostDao.loadDetails(h); - return Boolean.parseBoolean(h.getDetail(Host.HOST_VDDK_SUPPORT)); - }).collect(Collectors.toList()); - } - - private CheckConvertInstanceAnswer checkConversionSupportOnHost(HostVO convertHost, String sourceVM, - boolean checkWindowsGuestConversionSupport, - boolean useVddk, Map details) { - logger.debug(String.format("Checking the %s%s conversion support on the host %s", - useVddk ? "VDDK " : "", - checkWindowsGuestConversionSupport ? "windows guest " : "", - convertHost)); - CheckConvertInstanceCommand cmd = new CheckConvertInstanceCommand(checkWindowsGuestConversionSupport, useVddk); - if (MapUtils.isNotEmpty(details)) { - cmd.setVddkLibDir(StringUtils.trimToNull(details.get(Host.HOST_VDDK_LIB_DIR))); - } - int timeoutSeconds = 60; - cmd.setWait(timeoutSeconds); - - CheckConvertInstanceAnswer checkConvertInstanceAnswer; - try { - checkConvertInstanceAnswer = (CheckConvertInstanceAnswer) agentManager.send(convertHost.getId(), cmd); - } catch (AgentUnavailableException | OperationTimedoutException e) { - String err = String.format("Failed to check %s conversion support on the host %s for converting instance %s from VMware to KVM due to: %s", - checkWindowsGuestConversionSupport? "windows guest" : "", convertHost, sourceVM, e.getMessage()); - logger.error(err); - throw new CloudRuntimeException(err); - } - - if (!checkConvertInstanceAnswer.getResult()) { - String err = String.format("The host %s doesn't support conversion of instance %s from VMware to KVM due to: %s", - convertHost, sourceVM, checkConvertInstanceAnswer.getDetails()); - logger.error(err); - throw new CloudRuntimeException(err); - } - - return checkConvertInstanceAnswer; - } - - private UnmanagedInstanceTO convertVmwareInstanceToKVMWithOVFOnConvertLocation( - String sourceVM, UnmanagedInstanceTO sourceVMwareInstance, HostVO convertHost, - HostVO importHost, List convertStoragePools, - ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap, - DataStoreTO temporaryConvertLocation, String ovfTemplateDirConvertLocation, - boolean forceConvertToPool, String extraParams) { - - logger.debug("Delegating the conversion of instance {} from VMware to KVM to the host {} using OVF {} on conversion datastore", - sourceVM, convertHost, ovfTemplateDirConvertLocation); - - RemoteInstanceTO remoteInstanceTO = new RemoteInstanceTO(sourceVM, sourceVMwareInstance.getClusterName(), sourceVMwareInstance.getHostName()); - List destinationStoragePools = selectInstanceConversionStoragePools(convertStoragePools, sourceVMwareInstance.getDisks(), serviceOffering, dataDiskOfferingMap); - ConvertInstanceCommand cmd = new ConvertInstanceCommand(remoteInstanceTO, - Hypervisor.HypervisorType.KVM, temporaryConvertLocation, - ovfTemplateDirConvertLocation, false, false, sourceVM); - if (StringUtils.isNotBlank(extraParams)) { - cmd.setExtraParams(extraParams); - } - int timeoutSeconds = UnmanagedVMsManager.ConvertVmwareInstanceToKvmTimeout.value() * 60 * 60; - cmd.setWait(timeoutSeconds); - - return convertAndImportToKVM(cmd, convertHost, importHost, sourceVM, - remoteInstanceTO, destinationStoragePools, temporaryConvertLocation, forceConvertToPool); - } - - private UnmanagedInstanceTO convertVmwareInstanceToKVMUsingVDDKOrAfterExportingOVFToConvertLocation( - String sourceVM, UnmanagedInstanceTO sourceVMwareInstance, HostVO convertHost, - HostVO importHost, List convertStoragePools, - ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap, - DataStoreTO temporaryConvertLocation, String vcenterHost, String vcenterUsername, - String vcenterPassword, String datacenterName, boolean forceConvertToPool, String extraParams, - boolean useVddk, Map details) { - logger.debug("Delegating the conversion of instance {} from VMware to KVM to the host {} after OVF export through ovftool", sourceVM, convertHost); - - RemoteInstanceTO remoteInstanceTO = new RemoteInstanceTO(sourceVMwareInstance.getName(), sourceVMwareInstance.getPath(), vcenterHost, vcenterUsername, vcenterPassword, datacenterName, sourceVMwareInstance.getClusterName(), sourceVMwareInstance.getHostName()); - List destinationStoragePools = selectInstanceConversionStoragePools(convertStoragePools, sourceVMwareInstance.getDisks(), serviceOffering, dataDiskOfferingMap); - ConvertInstanceCommand cmd = new ConvertInstanceCommand(remoteInstanceTO, - Hypervisor.HypervisorType.KVM, temporaryConvertLocation, null, false, true, sourceVM); - int timeoutSeconds = UnmanagedVMsManager.ConvertVmwareInstanceToKvmTimeout.value() * 60 * 60; - cmd.setWait(timeoutSeconds); - int noOfThreads = UnmanagedVMsManager.ThreadsOnKVMHostToImportVMwareVMFiles.value(); - if (noOfThreads == 0) { - // Use no. of threads as the disks count - noOfThreads = sourceVMwareInstance.getDisks().size(); - } - cmd.setThreadsCountToExportOvf(noOfThreads); - if (StringUtils.isNotBlank(extraParams)) { - cmd.setExtraParams(extraParams); - } - cmd.setUseVddk(useVddk); - applyVddkOverridesFromDetails(cmd, details); - return convertAndImportToKVM(cmd, convertHost, importHost, sourceVM, - remoteInstanceTO, destinationStoragePools, temporaryConvertLocation, forceConvertToPool); - } - - private void applyVddkOverridesFromDetails(ConvertInstanceCommand cmd, Map details) { - if (MapUtils.isEmpty(details)) { - return; - } - - cmd.setVddkLibDir(StringUtils.trimToNull(details.get(Host.HOST_VDDK_LIB_DIR))); - cmd.setVddkTransports(StringUtils.trimToNull(details.get(DETAIL_VDDK_TRANSPORTS))); - cmd.setVddkThumbprint(StringUtils.trimToNull(details.get(DETAIL_VDDK_THUMBPRINT))); - } - - private UnmanagedInstanceTO convertAndImportToKVM(ConvertInstanceCommand convertInstanceCommand, HostVO convertHost, HostVO importHost, - String sourceVM, - RemoteInstanceTO remoteInstanceTO, - List destinationStoragePools, - DataStoreTO temporaryConvertLocation, - boolean forceConvertToPool) { - Answer convertAnswer; - try { - convertAnswer = agentManager.send(convertHost.getId(), convertInstanceCommand); - } catch (AgentUnavailableException | OperationTimedoutException e) { - String err = String.format("Could not send the convert instance command to host %s due to: %s", - convertHost, e.getMessage()); - logger.error(err, e); - throw new CloudRuntimeException(err); - } - - if (!convertAnswer.getResult()) { - String err = String.format("The convert process failed for instance %s from VMware to KVM on host %s: %s", - sourceVM, convertHost, convertAnswer.getDetails()); - logger.error(err); - throw new CloudRuntimeException(err); - } - - Answer importAnswer; - try { - ImportConvertedInstanceCommand importCmd = new ImportConvertedInstanceCommand( - remoteInstanceTO, destinationStoragePools, temporaryConvertLocation, - ((ConvertInstanceAnswer)convertAnswer).getTemporaryConvertUuid(), forceConvertToPool); - importAnswer = agentManager.send(importHost.getId(), importCmd); - } catch (AgentUnavailableException | OperationTimedoutException e) { - String err = String.format( - "Could not send the import converted instance command to host %s due to: %s", - importHost, e.getMessage()); - logger.error(err, e); - throw new CloudRuntimeException(err); - } - - if (!importAnswer.getResult()) { - String err = String.format( - "The import process failed for instance %s from VMware to KVM on host %s: %s", - sourceVM, importHost, importAnswer.getDetails()); - logger.error(err); - throw new CloudRuntimeException(err); - } - - return ((ImportConvertedInstanceAnswer) importAnswer).getConvertedInstance(); - } - - private List findInstanceConversionDestinationStoragePoolsInCluster( - Cluster destinationCluster, ServiceOfferingVO serviceOffering, - Map dataDiskOfferingMap, - DataStoreTO temporaryConvertLocation, boolean forceConvertToPool) { - List poolsList; - if (!forceConvertToPool) { - Set pools = new HashSet<>(primaryDataStoreDao.findClusterWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)); - pools.addAll(primaryDataStoreDao.findZoneWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getDataCenterId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)); - if (pools.isEmpty()) { - String msg = String.format("Cannot find suitable storage pools in the cluster %s for the conversion", destinationCluster.getName()); - logger.error(msg); - throw new CloudRuntimeException(msg); - } - poolsList = new ArrayList<>(pools); - } else { - DataStore dataStore = dataStoreManager.getDataStore(temporaryConvertLocation.getUuid(), temporaryConvertLocation.getRole()); - poolsList = Collections.singletonList(primaryDataStoreDao.findById(dataStore.getId())); - } - - if (serviceOffering.getDiskOfferingId() != null) { - DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); - if (diskOffering == null) { - String msg = String.format("Cannot find disk offering with ID %s that belongs to the service offering %s", serviceOffering.getDiskOfferingId(), serviceOffering.getName()); - logger.error(msg); - throw new CloudRuntimeException(msg); - } - if (getStoragePoolWithTags(poolsList, diskOffering.getTags()) == null) { - String msg = String.format("Cannot find suitable storage pool for disk offering %s that belongs to the service offering %s", diskOffering.getName(), serviceOffering.getName()); - logger.error(msg); - throw new CloudRuntimeException(msg); - } - } - for (Long diskOfferingId : dataDiskOfferingMap.values()) { - DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId); - if (diskOffering == null) { - String msg = String.format("Cannot find disk offering with ID %s", diskOfferingId); - logger.error(msg); - throw new CloudRuntimeException(msg); - } - if (getStoragePoolWithTags(poolsList, diskOffering.getTags()) == null) { - String msg = String.format("Cannot find suitable storage pool for disk offering %s", diskOffering.getName()); - logger.error(msg); - throw new CloudRuntimeException(msg); - } - } - - return poolsList; - } - - private StoragePoolVO getStoragePoolWithTags(List pools, String tags) { - if (StringUtils.isEmpty(tags)) { - return pools.get(0); - } - for (StoragePoolVO pool : pools) { - if (volumeApiService.doesStoragePoolSupportDiskOfferingTags(pool, tags)) { - return pool; - } - } - return null; - } - - private List selectInstanceConversionStoragePools( - List pools, List disks, - ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap - ) { - List storagePools = new ArrayList<>(disks.size()); - Set dataDiskIds = dataDiskOfferingMap.keySet(); - for (UnmanagedInstanceTO.Disk disk : disks) { - Long diskOfferingId = null; - if (dataDiskIds.contains(disk.getDiskId())) { - diskOfferingId = dataDiskOfferingMap.get(disk.getDiskId()); - } else { - diskOfferingId = serviceOffering.getDiskOfferingId(); - } - - //TODO: Choose pools by capacity - if (diskOfferingId == null) { - storagePools.add(pools.get(0).getUuid()); - } else { - DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId); - StoragePoolVO pool = getStoragePoolWithTags(pools, diskOffering.getTags()); - storagePools.add(pool.getUuid()); - } - } - return storagePools; - } - - private void logFailureAndThrowException(String msg) { - logger.error(msg); - throw new CloudRuntimeException(msg); - } - - private void checkBeforeSelectingTemporaryConversionStoragePool(StoragePoolVO selectedStoragePool, Long convertStoragePoolId, Cluster destinationCluster, HostVO convertHost) { - if (selectedStoragePool == null) { - logFailureAndThrowException(String.format("Cannot find a storage pool with ID %s", convertStoragePoolId)); - } - if ((selectedStoragePool.getScope() == ScopeType.CLUSTER && selectedStoragePool.getClusterId() != destinationCluster.getId()) || - (selectedStoragePool.getScope() == ScopeType.ZONE && selectedStoragePool.getDataCenterId() != destinationCluster.getDataCenterId())) { - logFailureAndThrowException(String.format("Cannot use the storage pool %s for the instance conversion as " + - "it is not in the scope of the cluster %s", selectedStoragePool.getName(), destinationCluster.getName())); - } - if (convertHost != null && selectedStoragePool.getScope() == ScopeType.CLUSTER && !selectedStoragePool.getClusterId().equals(convertHost.getClusterId())) { - logFailureAndThrowException(String.format("Cannot use the storage pool %s for the instance conversion as " + - "the host %s for conversion is in a different cluster", selectedStoragePool.getName(), convertHost.getName())); - } - } - - private DataStoreTO getImageStoreOnDestinationZoneForTemporaryConversion(Cluster destinationCluster, boolean forceConvertToPool) { - if (forceConvertToPool) { - logFailureAndThrowException("Please select a primary storage pool when the parameter forceconverttopool is set to true"); - } - long zoneId = destinationCluster.getDataCenterId(); - ImageStoreVO imageStore = imageStoreDao.findOneByZoneAndProtocol(zoneId, "nfs"); - if (imageStore == null) { - logFailureAndThrowException(String.format("Could not find an NFS secondary storage pool on zone %s to use as a temporary location " + - "for instance conversion", zoneId)); - } - DataStore dataStore = dataStoreManager.getDataStore(imageStore.getId(), DataStoreRole.Image); - return dataStore.getTO(); - } - - private void checkDestinationOrTemporaryStoragePoolForConversion(StoragePoolVO selectedStoragePool, boolean forceConvertToPool, HostVO convertHost, HostVO importHost) { - if (selectedStoragePool.getScope() == ScopeType.HOST && (ObjectUtils.anyNull(convertHost, importHost) || - ObjectUtils.allNotNull(convertHost, importHost) && convertHost.getId() != importHost.getId() || - !forceConvertToPool) ) { - logFailureAndThrowException("Please select the same host as convert and importing host and " + - "set forceconvertopool to true to use a local storage pool for conversion"); - } - if (!forceConvertToPool && selectedStoragePool.getPoolType() != Storage.StoragePoolType.NetworkFilesystem) { - logFailureAndThrowException(String.format("The storage pool %s is not supported for temporary conversion location," + - "only NFS storage pools are supported when forceconverttopool is set to false", selectedStoragePool.getName())); - } - } - - protected DataStoreTO selectInstanceConversionTemporaryLocation(Cluster destinationCluster, - HostVO convertHost, HostVO importHost, - Long convertStoragePoolId, boolean forceConvertToPool) { - if (convertStoragePoolId == null) { - String msg = String.format("No convert storage pool has been provided, " + - "selecting an NFS secondary storage pool from the destination cluster (%s) zone", destinationCluster.getName()); - logger.debug(msg); - return getImageStoreOnDestinationZoneForTemporaryConversion(destinationCluster, forceConvertToPool); - } - - StoragePoolVO selectedStoragePool = primaryDataStoreDao.findById(convertStoragePoolId); - checkBeforeSelectingTemporaryConversionStoragePool(selectedStoragePool, convertStoragePoolId, destinationCluster, convertHost); - checkDestinationOrTemporaryStoragePoolForConversion(selectedStoragePool, forceConvertToPool, convertHost, importHost); - - return dataStoreManager.getPrimaryDataStore(convertStoragePoolId).getTO(); - } - - protected Map createParamsForTemplateFromVmwareVmMigration(String vcenterHost, String datacenterName, - String username, String password, - String clusterName, String sourceHostName, - String sourceVMName) { - Map params = new HashMap<>(); - params.put(VmDetailConstants.VMWARE_VCENTER_HOST, vcenterHost); - params.put(VmDetailConstants.VMWARE_DATACENTER_NAME, datacenterName); - params.put(VmDetailConstants.VMWARE_VCENTER_USERNAME, username); - params.put(VmDetailConstants.VMWARE_VCENTER_PASSWORD, password); - params.put(VmDetailConstants.VMWARE_CLUSTER_NAME, clusterName); - params.put(VmDetailConstants.VMWARE_HOST_NAME, sourceHostName); - params.put(VmDetailConstants.VMWARE_VM_NAME, sourceVMName); - return params; - } - - @Override - public List> getCommands() { - final List> cmdList = new ArrayList>(); - cmdList.add(ListUnmanagedInstancesCmd.class); - cmdList.add(ImportUnmanagedInstanceCmd.class); - cmdList.add(UnmanageVMInstanceCmd.class); - cmdList.add(ListVmsForImportCmd.class); - cmdList.add(ImportVmCmd.class); - cmdList.add(ListImportVMTasksCmd.class); - return cmdList; - } - - /** - * Perform validations before attempting to unmanage a VM from CloudStack: - * - VM must not have any associated volume snapshot - * - VM must not have an attached ISO - * - VM must not belong to any CKS cluster - * @throws UnsupportedServiceException in case any of the validations above fail - */ - void performUnmanageVMInstancePrechecks(VMInstanceVO vmVO) { - if (hasVolumeSnapshotsPriorToUnmanageVM(vmVO)) { - throw new UnsupportedServiceException("Cannot unmanage VM with id = " + vmVO.getUuid() + - " as there are volume snapshots for its volume(s). Please remove snapshots before unmanaging."); - } - - if (hasISOAttached(vmVO)) { - throw new UnsupportedServiceException("Cannot unmanage VM with id = " + vmVO.getUuid() + - " as there is an ISO attached. Please detach ISO before unmanaging."); - } - - if (userVmManager.isVMPartOfAnyCKSCluster(vmVO)) { - throw new UnsupportedServiceException("Cannot unmanage VM with id = " + vmVO.getUuid() + - " as it belongs to a CKS cluster. Please remove the VM from the CKS cluster before unmanaging."); - } - } - - private boolean hasVolumeSnapshotsPriorToUnmanageVM(VMInstanceVO vmVO) { - List volumes = volumeDao.findByInstance(vmVO.getId()); - for (VolumeVO volume : volumes) { - List snaps = snapshotDao.listByVolumeId(volume.getId()); - if (CollectionUtils.isNotEmpty(snaps)) { - for (SnapshotVO snap : snaps) { - if (snap.getState() != Snapshot.State.Destroyed && snap.getRemoved() == null) { - return true; - } - } - } - } - return false; - } - - private boolean hasISOAttached(VMInstanceVO vmVO) { - UserVmVO userVM = userVmDao.findById(vmVO.getId()); - if (userVM == null) { - throw new InvalidParameterValueException("Could not find user VM with ID = " + vmVO.getUuid()); - } - return userVM.getIsoId() != null; - } - - /** - * Find a suitable host within the scope of the VM to unmanage to verify the VM exists - */ - private Long findSuitableHostId(VMInstanceVO vmVO) { - Long hostId = vmVO.getHostId(); - if (hostId == null) { - long zoneId = vmVO.getDataCenterId(); - List hosts = hostDao.listAllHostsUpByZoneAndHypervisor(zoneId, vmVO.getHypervisorType()); - for (HostVO host : hosts) { - if (host.isInMaintenanceStates() || host.getState() != Status.Up || host.getStatus() != Status.Up) { - continue; - } - hostId = host.getId(); - break; - } - } - - if (hostId == null) { - throw new CloudRuntimeException(String.format("Cannot find a host to verify if the VM [%s] exists. Thus we are unable to unmanage it.", vmVO.getUuid())); - } - return hostId; - } - - @Override - @ActionEvent(eventType = EventTypes.EVENT_VM_UNMANAGE, eventDescription = "unmanaging VM", async = true) - public Pair unmanageVMInstance(long vmId, Long paramHostId, boolean isForced) { - VMInstanceVO vmVO = vmDao.findById(vmId); - if (vmVO == null || vmVO.getRemoved() != null) { - throw new InvalidParameterValueException("Could not find VM to unmanage, it is either removed or not existing VM"); - } else if (vmVO.getState() != VirtualMachine.State.Running && vmVO.getState() != VirtualMachine.State.Stopped) { - throw new InvalidParameterValueException("VM with id = " + vmVO.getUuid() + " must be running or stopped to be unmanaged"); - } else if (!UnmanagedVMsManager.isSupported(vmVO.getHypervisorType())) { - throw new UnsupportedServiceException("Unmanage VM is currently not allowed for hypervisor " + - vmVO.getHypervisorType().toString()); - } else if (vmVO.getType() != VirtualMachine.Type.User) { - throw new UnsupportedServiceException("Unmanage VM is currently allowed for guest VMs only"); - } else if (paramHostId != null && - (vmVO.getHypervisorType() != Hypervisor.HypervisorType.KVM || vmVO.getState() != VirtualMachine.State.Stopped)) { - throw new UnsupportedServiceException("Param hostid is only supported for KVM hypervisor for stopped Instances."); - } else if (!isForced && vmVO.getHypervisorType() == Hypervisor.HypervisorType.KVM - && vmInstanceDetailsDao.findDetail(vmId, VmDetailConstants.CONFIG_DRIVE_LOCATION) != null) { - throw new UnsupportedServiceException("Config drive is attached to Instance, use forced param true from API to unmanage it."); - } - - if (vmVO.getType().equals(VirtualMachine.Type.User)) { - UserVmVO userVm = userVmDao.findById(vmId); - if (UserVmManager.SHAREDFSVM.equals(userVm.getUserVmType())) { - throw new InvalidParameterValueException("Operation not supported on Shared FileSystem Instance"); - } - } - - performUnmanageVMInstancePrechecks(vmVO); - - boolean isKvmVmStopped = VirtualMachine.State.Stopped.equals(vmVO.getState()) && vmVO.getHypervisorType() == Hypervisor.HypervisorType.KVM; - Long hostId = isKvmVmStopped ? vmVO.getLastHostId() : findSuitableHostId(vmVO); - String instanceName = vmVO.getInstanceName(); - - if (!isKvmVmStopped && !existsVMToUnmanage(instanceName, hostId)) { - throw new CloudRuntimeException(String.format("VM %s is not found in the hypervisor", vmVO)); - } - - return userVmManager.unmanageUserVM(vmId, paramHostId); - } - - /** - * Verify the VM to unmanage exists on the hypervisor - */ - private boolean existsVMToUnmanage(String instanceName, Long hostId) { - PrepareUnmanageVMInstanceCommand command = new PrepareUnmanageVMInstanceCommand(); - command.setInstanceName(instanceName); - Answer ans = agentManager.easySend(hostId, command); - if (!(ans instanceof PrepareUnmanageVMInstanceAnswer)) { - throw new CloudRuntimeException(String.format("Error communicating with host %s", hostDao.findById(hostId))); - } - PrepareUnmanageVMInstanceAnswer answer = (PrepareUnmanageVMInstanceAnswer) ans; - if (!answer.getResult()) { - logger.error("Error verifying VM {} exists on host {}: {}", instanceName::toString, () -> hostDao.findById(hostId), answer::getDetails); - } - return answer.getResult(); - } - - private UserVmResponse importKvmInstance(ImportVmCmd cmd) { - final Account caller = CallContext.current().getCallingAccount(); - if (caller.getType() != Account.Type.ADMIN) { - throw new PermissionDeniedException(String.format("Cannot perform this operation, Calling account is not root admin: %s", caller.getUuid())); - } - final Long zoneId = cmd.getZoneId(); - final DataCenterVO zone = dataCenterDao.findById(zoneId); - if (zone == null) { - throw new InvalidParameterValueException("Please specify a valid zone."); - } - final String hypervisorType = cmd.getHypervisor(); - if (!Hypervisor.HypervisorType.KVM.toString().equalsIgnoreCase(hypervisorType)) { - throw new InvalidParameterValueException(String.format("VM import is currently not supported for hypervisor: %s", hypervisorType)); - } - - final String instanceName = cmd.getName(); - if (StringUtils.isEmpty(instanceName)) { - throw new InvalidParameterValueException(String.format("Instance name cannot be empty")); - } - if (cmd.getDomainId() != null && StringUtils.isEmpty(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()); - if (CollectionUtils.isNotEmpty(userVOs)) { - userId = userVOs.get(0).getId(); - } - VMTemplateVO template = getTemplateForImportInstance(cmd.getTemplateId(), Hypervisor.HypervisorType.KVM); - 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); - String displayName = cmd.getDisplayName(); - if (StringUtils.isEmpty(displayName)) { - displayName = instanceName; - } - String hostName = cmd.getHostName(); - if (StringUtils.isEmpty(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 = mergeNicMacAddresses(cmd.getNicIpAddressList(), cmd.getNicMacAddressList()); - final Map dataDiskOfferingMap = cmd.getDataDiskToDiskOfferingList(); - final Map details = cmd.getDetails(); - - String remoteUrl = cmd.getHost(); - String source = cmd.getImportSource().toUpperCase(); - String diskPath = cmd.getDiskPath(); - ImportSource importSource = Enum.valueOf(ImportSource.class, source); - Long hostId = cmd.getHostId(); - Long poolId = cmd.getStoragePoolId(); - Long networkId = cmd.getNetworkId(); - - UnmanagedInstanceTO unmanagedInstanceTO = null; - if (ImportSource.EXTERNAL == importSource) { - if (StringUtils.isBlank(cmd.getUsername())) { - throw new InvalidParameterValueException("Username need to be provided."); - } - - HashMap instancesMap = getRemoteVmsOnKVMHost(zoneId, remoteUrl, cmd.getUsername(), cmd.getPassword()); - unmanagedInstanceTO = instancesMap.get(cmd.getName()); - if (unmanagedInstanceTO == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM with name: %s not found on remote host %s", instanceName, remoteUrl)); - } - } - - if (ImportSource.SHARED == importSource || ImportSource.LOCAL == importSource) { - if (diskPath == null) { - throw new InvalidParameterValueException("Disk Path is required for Import from shared/local storage"); - } - - if (networkId == null) { - throw new InvalidParameterValueException("Network is required for Import from shared/local storage"); - } - - if (poolId == null) { - throw new InvalidParameterValueException("Storage Pool is required for Import from shared/local storage"); - } - - StoragePool storagePool = primaryDataStoreDao.findById(poolId); - if (storagePool == null) { - throw new InvalidParameterValueException("Storage Pool not found"); - } - - if (volumeDao.findByPoolIdAndPath(poolId, diskPath) != null) { - throw new InvalidParameterValueException("Disk image is already in use"); - } - - DiskOffering diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); - - if (diskOffering != null && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) { - throw new InvalidParameterValueException(String.format("Service offering: %s storage tags are not compatible with selected storage pool: %s", serviceOffering.getUuid(), storagePool.getUuid())); - } - } - - if (ImportSource.LOCAL == importSource) { - if (hostId == null) { - throw new InvalidParameterValueException("Host is required for Import from local storage"); - } - - if (hostDao.findById(hostId) == null) { - throw new InvalidParameterValueException("Host not found"); - } - - if(storagePoolHostDao.findByPoolHost(poolId, hostId) == null) { - throw new InvalidParameterValueException("Specified Local Storage Pool not found on Host"); - } - } - - UserVm userVm = null; - - try { - - if (ImportSource.EXTERNAL == importSource) { - String username = cmd.getUsername(); - String password = cmd.getPassword(); - String tmpPath = cmd.getTmpPath(); - userVm = importExternalKvmVirtualMachine(unmanagedInstanceTO, instanceName, zone, - template, displayName, hostName, caller, owner, userId, - serviceOffering, dataDiskOfferingMap, - nicNetworkMap, nicIpAddressMap, remoteUrl, username, password, tmpPath, details); - } else if (ImportSource.SHARED == importSource || ImportSource.LOCAL == importSource) { - try { - userVm = importKvmVirtualMachineFromDisk(importSource, instanceName, zone, - template, displayName, hostName, caller, owner, userId, - serviceOffering, dataDiskOfferingMap, networkId, hostId, poolId, diskPath, - details); - } catch (InsufficientCapacityException e) { - throw new RuntimeException(e); - } catch (ResourceAllocationException e) { - throw new RuntimeException(e); - } - } - - } 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(), StringUtils.defaultString(e.getMessage()))); - } - - if (userVm == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import Vm with name: %s ", instanceName)); - } - - CallContext.current().setEventResourceId(userVm.getId()); - CallContext.current().setEventResourceType(ApiCommandResourceType.VirtualMachine); - return responseGenerator.createUserVmResponse(ResponseObject.ResponseView.Full, "virtualmachine", userVm).get(0); - } - - private UserVm importExternalKvmVirtualMachine(final UnmanagedInstanceTO unmanagedInstance, final String instanceName, final DataCenter zone, - final VirtualMachineTemplate template, final String displayName, final String hostName, final Account caller, final Account owner, final Long userId, - final ServiceOfferingVO serviceOffering, final Map dataDiskOfferingMap, - final Map nicNetworkMap, final Map callerNicIpAddressMap, - final String remoteUrl, String username, String password, String tmpPath, final Map details) throws ResourceAllocationException { - UserVm userVm = null; - - Map allDetails = new HashMap<>(details); - // 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)); - } - - DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); - Pair> rootAndDataDisksPair = getRootAndDataDisks(unmanagedInstanceDisks, dataDiskOfferingMap); - final UnmanagedInstanceTO.Disk rootDisk = rootAndDataDisksPair.first(); - final List dataDisks = rootAndDataDisksPair.second(); - if (rootDisk == null || StringUtils.isEmpty(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 reservations = new ArrayList<>(); - try { - checkVmResourceLimitsForExternalKvmVmImport(owner, serviceOffering, (VMTemplateVO) template, details, reservations); - checkVolumeResourceLimitsForExternalKvmVmImport(owner, rootDisk, dataDisks, diskOffering, dataDiskOfferingMap, reservations); - - // Check NICs and supplied networks - Map nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap); - Map allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getName(), unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner, Hypervisor.HypervisorType.KVM); - if (!CollectionUtils.isEmpty(unmanagedInstance.getNics())) { - allDetails.put(VmDetailConstants.NIC_ADAPTER, unmanagedInstance.getNics().get(0).getAdapterType()); - } - VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff; - - try { - userVm = userVmManager.importVM(zone, null, template, null, displayName, owner, - null, caller, true, null, owner.getAccountId(), userId, - serviceOffering, null, null, hostName, - Hypervisor.HypervisorType.KVM, allDetails, powerState, null); - } 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)); - } - String rootVolumeName = String.format("ROOT-%s", userVm.getId()); - DiskProfile diskProfile = volumeManager.allocateRawVolume(Volume.Type.ROOT, rootVolumeName, diskOffering, null, null, null, userVm, template, owner, null, false); - - DiskProfile[] dataDiskProfiles = new DiskProfile[dataDisks.size()]; - int diskSeq = 0; - for (UnmanagedInstanceTO.Disk disk : dataDisks) { - DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId())); - DiskProfile dataDiskProfile = volumeManager.allocateRawVolume(Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()), offering, null, null, null, userVm, template, owner, null, false); - dataDiskProfiles[diskSeq++] = dataDiskProfile; - } - - final VirtualMachineProfile profile = new VirtualMachineProfileImpl(userVm, template, serviceOffering, owner, null); - ServiceOfferingVO dummyOffering = serviceOfferingDao.findById(userVm.getId(), serviceOffering.getId()); - profile.setServiceOffering(dummyOffering); - DeploymentPlanner.ExcludeList excludeList = new DeploymentPlanner.ExcludeList(); - final DataCenterDeployment plan = new DataCenterDeployment(zone.getId(), null, null, null, null, null); - DeployDestination dest = null; - try { - dest = deploymentPlanningManager.planDeployment(profile, plan, excludeList, null); - } catch (Exception e) { - logger.warn("Import failed for Vm: {} while finding deployment destination", userVm, e); - cleanupFailedImportVM(userVm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s while finding deployment destination", userVm.getInstanceName())); - } - if(dest == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s. Suitable deployment destination not found", userVm.getInstanceName())); - } - - List> diskProfileStoragePoolList = new ArrayList<>(); - try { - diskProfileStoragePoolList.add(importExternalDisk(rootDisk, userVm, dest, diskOffering, Volume.Type.ROOT, - template, null, remoteUrl, username, password, tmpPath, diskProfile)); - - long deviceId = 1L; - diskSeq = 0; - for (UnmanagedInstanceTO.Disk disk : dataDisks) { - DiskProfile dataDiskProfile = dataDiskProfiles[diskSeq++]; - DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId())); - - diskProfileStoragePoolList.add(importExternalDisk(disk, userVm, dest, offering, Volume.Type.DATADISK, - template, deviceId, remoteUrl, username, password, tmpPath, dataDiskProfile)); - deviceId++; - } - } catch (Exception e) { - logger.error(String.format("Failed to import volumes while importing vm: %s", instanceName), e); - cleanupFailedImportVM(userVm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", instanceName, StringUtils.defaultString(e.getMessage()))); - } - try { - int nicIndex = 0; - 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, nicIndex, nicIndex==0, true); - nicIndex++; - } - } catch (Exception e) { - logger.error(String.format("Failed to import NICs while importing vm: %s", instanceName), e); - cleanupFailedImportVM(userVm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import NICs while importing vm: %s. %s", instanceName, StringUtils.defaultString(e.getMessage()))); - } - publishVMUsageUpdateResourceCount(userVm, dummyOffering, template); - return userVm; - - } finally { - ReservationHelper.closeAll(reservations); - } - } - - protected void checkVolumeResourceLimitsForExternalKvmVmImport(Account owner, UnmanagedInstanceTO.Disk rootDisk, - List dataDisks, DiskOfferingVO rootDiskOffering, - Map dataDiskOfferingMap, List reservations) throws ResourceAllocationException { - if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) { - throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId())); - } - resourceLimitService.checkVolumeResourceLimit(owner, true, rootDisk.getCapacity(), rootDiskOffering, reservations); - - if (CollectionUtils.isEmpty(dataDisks)) { - return; - } - for (UnmanagedInstanceTO.Disk disk : dataDisks) { - if (disk.getCapacity() == null || disk.getCapacity() == 0) { - throw new InvalidParameterValueException(String.format("Data disk ID: %s size is invalid", disk.getDiskId())); - } - DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId())); - resourceLimitService.checkVolumeResourceLimit(owner, true, disk.getCapacity(), offering, reservations); - } - } - - private UserVm importKvmVirtualMachineFromDisk(final ImportSource importSource, final String instanceName, final DataCenter zone, - final VirtualMachineTemplate template, final String displayName, final String hostName, final Account caller, final Account owner, final Long userId, - final ServiceOfferingVO serviceOffering, final Map dataDiskOfferingMap, final Long networkId, - final Long hostId, final Long poolId, final String diskPath, final Map details) throws InsufficientCapacityException, ResourceAllocationException { - - UserVm userVm = null; - - Map allDetails = new HashMap<>(details); - - VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff; - - NetworkVO network = networkDao.findById(networkId); - if (network == null) { - throw new InvalidParameterValueException("Unable to find network by id " + networkId); - } - - networkModel.checkNetworkPermissions(owner, network); - - // don't allow to use system networks - NetworkOffering networkOffering = entityMgr.findById(NetworkOffering.class, network.getNetworkOfferingId()); - if (networkOffering.isSystemOnly()) { - throw new InvalidParameterValueException("Network id=" + networkId + " is system only and can't be used for vm deployment"); - } - - LinkedHashMap> networkNicMap = new LinkedHashMap<>(); - - if ((network.getDataCenterId() != zone.getId())) { - if (!network.isStrechedL2Network()) { - throw new InvalidParameterValueException("Network id=" + network.getId() + - " doesn't belong to zone " + zone.getId()); - } - } - - String macAddress = networkModel.getNextAvailableMacAddressInNetwork(networkId); - - String ipAddress = network.getGuestType() != Network.GuestType.L2 ? "auto" : null; - - Network.IpAddresses requestedIpPair = new Network.IpAddresses(ipAddress, null, macAddress); - - NicProfile nicProfile = new NicProfile(requestedIpPair.getIp4Address(), requestedIpPair.getIp6Address(), requestedIpPair.getMacAddress()); - nicProfile.setOrderIndex(0); - - boolean securityGroupEnabled = false; - if (networkModel.isSecurityGroupSupportedInNetwork(network)) { - securityGroupEnabled = true; - } - List profiles = networkNicMap.get(network.getUuid()); - if (CollectionUtils.isEmpty(profiles)) { - profiles = new ArrayList<>(); - } - profiles.add(nicProfile); - networkNicMap.put(network.getUuid(), profiles); - - List reservations = new ArrayList<>(); - try { - checkVmResourceLimitsForExternalKvmVmImport(owner, serviceOffering, (VMTemplateVO) template, details, reservations); - userVm = userVmManager.importVM(zone, null, template, null, displayName, owner, - null, caller, true, null, owner.getAccountId(), userId, - serviceOffering, null, null, hostName, - Hypervisor.HypervisorType.KVM, allDetails, powerState, networkNicMap); - - if (userVm == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import vm name: %s", instanceName)); - } - - DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); - List resourceLimitStorageTags = resourceLimitService.getResourceLimitStorageTagsForResourceCountOperation(true, diskOffering); - CheckedReservation volumeReservation = new CheckedReservation(owner, Resource.ResourceType.volume, resourceLimitStorageTags, - CollectionUtils.isNotEmpty(resourceLimitStorageTags) ? 1L : 0L, reservationDao, resourceLimitService); - reservations.add(volumeReservation); - - String rootVolumeName = String.format("ROOT-%s", userVm.getId()); - DiskProfile diskProfile = volumeManager.allocateRawVolume(Volume.Type.ROOT, rootVolumeName, diskOffering, null, null, null, userVm, template, owner, null, false); - - final VirtualMachineProfile profile = new VirtualMachineProfileImpl(userVm, template, serviceOffering, owner, null); - ServiceOfferingVO dummyOffering = serviceOfferingDao.findById(userVm.getId(), serviceOffering.getId()); - profile.setServiceOffering(dummyOffering); - DeploymentPlanner.ExcludeList excludeList = new DeploymentPlanner.ExcludeList(); - final DataCenterDeployment plan = new DataCenterDeployment(zone.getId(), null, null, hostId, poolId, null); - DeployDestination dest = null; - try { - dest = deploymentPlanningManager.planDeployment(profile, plan, excludeList, null); - } catch (Exception e) { - logger.warn("Import failed for Vm: {} while finding deployment destination", userVm, e); - cleanupFailedImportVM(userVm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s while finding deployment destination", userVm.getInstanceName())); - } - if(dest == null) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s. Suitable deployment destination not found", userVm.getInstanceName())); - } - - Map storage = dest.getStorageForDisks(); - Volume volume = volumeDao.findById(diskProfile.getVolumeId()); - StoragePool storagePool = storage.get(volume); - CheckVolumeCommand checkVolumeCommand = new CheckVolumeCommand(); - checkVolumeCommand.setSrcFile(diskPath); - StorageFilerTO storageTO = new StorageFilerTO(storagePool); - checkVolumeCommand.setStorageFilerTO(storageTO); - Answer answer = agentManager.easySend(dest.getHost().getId(), checkVolumeCommand); - if (!(answer instanceof CheckVolumeAnswer)) { - cleanupFailedImportVM(userVm); - throw new CloudRuntimeException("Disk not found or is invalid"); - } - CheckVolumeAnswer checkVolumeAnswer = (CheckVolumeAnswer) answer; - try { - checkVolume(checkVolumeAnswer.getVolumeDetails()); - } catch (CloudRuntimeException e) { - cleanupFailedImportVM(userVm); - throw e; - } - if (!checkVolumeAnswer.getResult()) { - cleanupFailedImportVM(userVm); - throw new CloudRuntimeException("Disk not found or is invalid"); - } - diskProfile.setSize(checkVolumeAnswer.getSize()); - - CheckedReservation primaryStorageReservation = new CheckedReservation(owner, Resource.ResourceType.primary_storage, resourceLimitStorageTags, - CollectionUtils.isNotEmpty(resourceLimitStorageTags) ? diskProfile.getSize() : 0L, reservationDao, resourceLimitService); - reservations.add(primaryStorageReservation); - - List> diskProfileStoragePoolList = new ArrayList<>(); - try { - long deviceId = 1L; - if(ImportSource.SHARED == importSource) { - diskProfileStoragePoolList.add(importKVMSharedDisk(userVm, diskOffering, Volume.Type.ROOT, - template, deviceId, poolId, diskPath, diskProfile)); - } else if(ImportSource.LOCAL == importSource) { - diskProfileStoragePoolList.add(importKVMLocalDisk(userVm, diskOffering, Volume.Type.ROOT, - template, deviceId, hostId, diskPath, diskProfile)); - } - } catch (Exception e) { - logger.error(String.format("Failed to import volumes while importing vm: %s", instanceName), e); - cleanupFailedImportVM(userVm); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", instanceName, StringUtils.defaultString(e.getMessage()))); - } - networkOrchestrationService.importNic(macAddress, 0, network, true, userVm, requestedIpPair, zone, true); - publishVMUsageUpdateResourceCount(userVm, dummyOffering, template); - return userVm; - - } catch (InsufficientCapacityException ice) { // This will be thrown by com.cloud.vm.UserVmService.importVM - logger.error(String.format("Failed to import vm name: %s", instanceName), ice); - throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ice.getMessage()); - } catch (ResourceAllocationException e) { - cleanupFailedImportVM(userVm); - throw e; - } finally { - ReservationHelper.closeAll(reservations); - } - } - - protected void checkVmResourceLimitsForExternalKvmVmImport(Account owner, ServiceOfferingVO serviceOffering, VMTemplateVO template, Map details, List reservations) throws ResourceAllocationException { - // When importing an external VM, the amount of CPUs and memory is always obtained from the compute offering, - // unlike the unmanaged instance import that obtains it from the hypervisor unless the VM is powered off and the offering is fixed - Integer cpu = serviceOffering.getCpu(); - Integer memory = serviceOffering.getRamSize(); - - if (serviceOffering.isDynamic()) { - cpu = getDetailAsInteger(VmDetailConstants.CPU_NUMBER, details); - memory = getDetailAsInteger(VmDetailConstants.MEMORY, details); - } - - List resourceLimitHostTags = resourceLimitService.getResourceLimitHostTags(serviceOffering, template); - - CheckedReservation vmReservation = new CheckedReservation(owner, Resource.ResourceType.user_vm, resourceLimitHostTags, 1L, reservationDao, resourceLimitService); - reservations.add(vmReservation); - - CheckedReservation cpuReservation = new CheckedReservation(owner, Resource.ResourceType.cpu, resourceLimitHostTags, cpu.longValue(), reservationDao, resourceLimitService); - reservations.add(cpuReservation); - - CheckedReservation memReservation = new CheckedReservation(owner, Resource.ResourceType.memory, resourceLimitHostTags, memory.longValue(), reservationDao, resourceLimitService); - reservations.add(memReservation); - } - - protected Integer getDetailAsInteger(String key, Map details) { - String detail = details.get(key); - if (detail == null) { - throw new InvalidParameterValueException(String.format("Detail '%s' must be provided.", key)); - } - try { - return Integer.valueOf(detail); - } catch (NumberFormatException e) { - throw new InvalidParameterValueException(String.format("Please provide a valid integer value for detail '%s'.", key)); - } - } - - private void checkVolume(Map volumeDetails) { - if (MapUtils.isEmpty(volumeDetails)) { - return; - } - - if (volumeDetails.containsKey(VolumeOnStorageTO.Detail.IS_LOCKED)) { - String isLocked = volumeDetails.get(VolumeOnStorageTO.Detail.IS_LOCKED); - if (Boolean.parseBoolean(isLocked)) { - logFailureAndThrowException("Locked volume cannot be imported or unmanaged."); - } - } - if (volumeDetails.containsKey(VolumeOnStorageTO.Detail.IS_ENCRYPTED)) { - String isEncrypted = volumeDetails.get(VolumeOnStorageTO.Detail.IS_ENCRYPTED); - if (Boolean.parseBoolean(isEncrypted)) { - logFailureAndThrowException("Encrypted volume cannot be imported or unmanaged."); - } - } - if (volumeDetails.containsKey(VolumeOnStorageTO.Detail.BACKING_FILE)) { - String backingFile = volumeDetails.get(VolumeOnStorageTO.Detail.BACKING_FILE); - if (StringUtils.isNotBlank(backingFile) && !AllowImportVolumeWithBackingFile.value()) { - logFailureAndThrowException("Volume with backing file cannot be imported or unmanaged."); - } - } - } - - private NetworkVO getDefaultNetwork(DataCenter zone, Account owner, boolean selectAny) throws InsufficientCapacityException, ResourceAllocationException { - NetworkVO defaultNetwork = null; - - // if no network is passed in - // Check if default virtual network offering has - // Availability=Required. If it's true, search for corresponding - // network - // * if network is found, use it. If more than 1 virtual network is - // found, throw an error - // * if network is not found, create a new one and use it - - List requiredOfferings = networkOfferingDao.listByAvailability(NetworkOffering.Availability.Required, false); - if (requiredOfferings.size() < 1) { - throw new InvalidParameterValueException("Unable to find network offering with availability=" + NetworkOffering.Availability.Required - + " to automatically create the network as a part of vm creation"); - } - - if (requiredOfferings.get(0).getState() == NetworkOffering.State.Enabled) { - // get Virtual networks - List virtualNetworks = networkModel.listNetworksForAccount(owner.getId(), zone.getId(), Network.GuestType.Isolated); - if (virtualNetworks == null) { - throw new InvalidParameterValueException("No (virtual) networks are found for account " + owner); - } - if (virtualNetworks.isEmpty()) { - defaultNetwork = createDefaultNetworkForAccount(zone, owner, requiredOfferings); - } else if (virtualNetworks.size() > 1 && !selectAny) { - throw new InvalidParameterValueException("More than 1 default Isolated networks are found for account " + owner + "; please specify networkIds"); - } else { - defaultNetwork = networkDao.findById(virtualNetworks.get(0).getId()); - } - } else { - throw new InvalidParameterValueException("Required network offering id=" + requiredOfferings.get(0).getId() + " is not in " + NetworkOffering.State.Enabled); - } - - return defaultNetwork; - } - - private NetworkVO createDefaultNetworkForAccount(DataCenter zone, Account owner, List requiredOfferings) - throws InsufficientCapacityException, ResourceAllocationException { - NetworkVO defaultNetwork = null; - long physicalNetworkId = networkModel.findPhysicalNetworkId(zone.getId(), requiredOfferings.get(0).getTags(), requiredOfferings.get(0).getTrafficType()); - // Validate physical network - PhysicalNetwork physicalNetwork = physicalNetworkDao.findById(physicalNetworkId); - if (physicalNetwork == null) { - throw new InvalidParameterValueException("Unable to find physical network with id: " + physicalNetworkId + " and tag: " - + requiredOfferings.get(0).getTags()); - } - logger.debug("Creating network for account {} from the network offering {} as a part of deployVM process", owner, requiredOfferings.get(0)); - Network newNetwork = networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName() + "-network", - null, null, null, false, null, owner, null, physicalNetwork, zone.getId(), ControlledEntity.ACLType.Account, null, null, null, null, true, null, null, - null, null, null, null, null, null, null, null, null); - if (newNetwork != null) { - defaultNetwork = networkDao.findById(newNetwork.getId()); - } - return defaultNetwork; - } - - public ListResponse listVmsForImport(ListVmsForImportCmd cmd) { - final Account caller = CallContext.current().getCallingAccount(); - if (caller.getType() != Account.Type.ADMIN) { - throw new PermissionDeniedException(String.format("Cannot perform this operation, Calling account is not root admin: %s", caller.getUuid())); - } - final Long zoneId = cmd.getZoneId(); - final DataCenterVO zone = dataCenterDao.findById(zoneId); - if (zone == null) { - throw new InvalidParameterValueException("Please specify a valid zone."); - } - final String hypervisorType = cmd.getHypervisor(); - if (!Hypervisor.HypervisorType.KVM.toString().equalsIgnoreCase(hypervisorType)) { - throw new InvalidParameterValueException(String.format("VM Import is currently not supported for hypervisor: %s", hypervisorType)); - } - - String keyword = cmd.getKeyword(); - if (StringUtils.isNotEmpty(keyword)) { - keyword = keyword.toLowerCase(); - } - - List responses = new ArrayList<>(); - HashMap vmMap = getRemoteVmsOnKVMHost(zoneId, cmd.getHost(), cmd.getUsername(), cmd.getPassword()); - for (String key : vmMap.keySet()) { - UnmanagedInstanceTO instance = vmMap.get(key); - if (StringUtils.isNotEmpty(keyword) && - !instance.getName().toLowerCase().contains(keyword)) { - continue; - } - responses.add(responseGenerator.createUnmanagedInstanceResp \ No newline at end of file +// 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 com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CheckConvertInstanceAnswer; +import com.cloud.agent.api.CheckConvertInstanceCommand; +import com.cloud.agent.api.CheckVolumeAnswer; +import com.cloud.agent.api.CheckVolumeCommand; +import com.cloud.agent.api.ConvertInstanceAnswer; +import com.cloud.agent.api.ConvertInstanceCommand; +import com.cloud.agent.api.CopyRemoteVolumeAnswer; +import com.cloud.agent.api.CopyRemoteVolumeCommand; +import com.cloud.agent.api.GetRemoteVmsAnswer; +import com.cloud.agent.api.GetRemoteVmsCommand; +import com.cloud.agent.api.GetUnmanagedInstancesAnswer; +import com.cloud.agent.api.GetUnmanagedInstancesCommand; +import com.cloud.agent.api.ImportConvertedInstanceAnswer; +import com.cloud.agent.api.ImportConvertedInstanceCommand; +import com.cloud.agent.api.PrepareUnmanageVMInstanceAnswer; +import com.cloud.agent.api.PrepareUnmanageVMInstanceCommand; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.RemoteInstanceTO; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.configuration.Config; +import com.cloud.configuration.Resource; +import com.cloud.dc.DataCenter; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.VmwareDatacenterVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.VmwareDatacenterDao; +import com.cloud.deploy.DataCenterDeployment; +import com.cloud.deploy.DeployDestination; +import com.cloud.deploy.DeploymentPlanner; +import com.cloud.deploy.DeploymentPlanningManager; +import com.cloud.event.ActionEvent; +import com.cloud.event.ActionEventUtils; +import com.cloud.event.EventTypes; +import com.cloud.event.EventVO; +import com.cloud.event.UsageEventUtils; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.InsufficientAddressCapacityException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InsufficientVirtualNetworkCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.OperationTimedoutException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.UnsupportedServiceException; +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.hypervisor.HypervisorGuru; +import com.cloud.hypervisor.HypervisorGuruManager; +import com.cloud.network.Network; +import com.cloud.network.NetworkModel; +import com.cloud.network.Networks; +import com.cloud.network.PhysicalNetwork; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkVO; +import com.cloud.network.dao.PhysicalNetworkDao; +import com.cloud.offering.DiskOffering; +import com.cloud.offering.NetworkOffering; +import com.cloud.offering.ServiceOffering; +import com.cloud.offerings.NetworkOfferingVO; +import com.cloud.offerings.dao.NetworkOfferingDao; +import com.cloud.org.Cluster; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceState; +import com.cloud.resourcelimit.CheckedReservation; +import com.cloud.resourcelimit.ReservationHelper; +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.DataStoreRole; +import com.cloud.storage.DiskOfferingVO; +import com.cloud.storage.GuestOS; +import com.cloud.storage.GuestOSHypervisor; +import com.cloud.storage.ScopeType; +import com.cloud.storage.Snapshot; +import com.cloud.storage.SnapshotVO; +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.SnapshotDao; +import com.cloud.storage.dao.StoragePoolHostDao; +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.LogUtils; +import com.cloud.utils.Pair; +import com.cloud.utils.UuidUtils; +import com.cloud.utils.db.EntityManager; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.net.NetUtils; +import com.cloud.vm.DiskProfile; +import com.cloud.vm.NicProfile; +import com.cloud.vm.NicVO; +import com.cloud.vm.UserVmManager; +import com.cloud.vm.UserVmVO; +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.UserVmDao; +import com.cloud.vm.dao.VMInstanceDetailsDao; +import com.cloud.vm.dao.VMInstanceDao; +import com.google.gson.Gson; +import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.ApiCommandResourceType; +import org.apache.cloudstack.api.ApiConstants; +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.ImportVmCmd; +import org.apache.cloudstack.api.command.admin.vm.ListImportVMTasksCmd; +import org.apache.cloudstack.api.command.admin.vm.ListUnmanagedInstancesCmd; +import org.apache.cloudstack.api.command.admin.vm.ListVmsForImportCmd; +import org.apache.cloudstack.api.command.admin.vm.UnmanageVMInstanceCmd; +import org.apache.cloudstack.api.response.ListResponse; +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.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.framework.config.ConfigKey; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.reservation.dao.ReservationDao; +import org.apache.cloudstack.resourcelimit.Reserver; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.storage.volume.VolumeOnStorageTO; +import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import javax.inject.Inject; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.stream.Collectors; + +import static org.apache.cloudstack.api.ApiConstants.MAX_IOPS; +import static org.apache.cloudstack.api.ApiConstants.MIN_IOPS; +import static org.apache.cloudstack.storage.volume.VolumeImportUnmanageService.AllowImportVolumeWithBackingFile; +import static org.apache.cloudstack.vm.ImportVmTask.Step.CloningInstance; +import static org.apache.cloudstack.vm.ImportVmTask.Step.Completed; +import static org.apache.cloudstack.vm.ImportVmTask.Step.ConvertingInstance; +import static org.apache.cloudstack.vm.ImportVmTask.Step.Importing; + +public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { + protected Logger logger = LogManager.getLogger(UnmanagedVMsManagerImpl.class); + private static final long OTHER_LINUX_64_GUEST_OS_ID = 99; + private static final List importUnmanagedInstancesSupportedHypervisors = + Arrays.asList(Hypervisor.HypervisorType.VMware, Hypervisor.HypervisorType.KVM); + + private static final List forceConvertToPoolAllowedTypes = + Arrays.asList(Storage.StoragePoolType.NetworkFilesystem, Storage.StoragePoolType.Filesystem, + Storage.StoragePoolType.SharedMountPoint); + private static final String DETAIL_VDDK_TRANSPORTS = "vddk.transports"; + private static final String DETAIL_VDDK_THUMBPRINT = "vddk.thumbprint"; + + ConfigKey ConvertVmwareInstanceToKvmExtraParamsAllowed = new ConfigKey<>(Boolean.class, + "convert.vmware.instance.to.kvm.extra.params.allowed", + "Advanced", + "false", + "Disabled by default. If enabled, allows extra parameters to be passed to the virt-v2v binary on KVM conversion hosts", + true, + ConfigKey.Scope.Global, + null); + + ConfigKey ConvertVmwareInstanceToKvmExtraParamsAllowedList = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED, + String.class, + "convert.vmware.instance.to.kvm.extra.params.allowed.list", + "", + "Comma separated list of allowed extra parameters to be passed to the virt-v2v binary on KVM conversion hosts", + true, + ConfigKey.Kind.CSV, + null); + + @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 ReservationDao reservationDao; + @Inject + private VMInstanceDetailsDao vmInstanceDetailsDao; + @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 VolumeApiService volumeApiService; + @Inject + private DeploymentPlanningManager deploymentPlanningManager; + @Inject + private VirtualMachineManager virtualMachineManager; + @Inject + private ManagementService managementService; + @Inject + private NicDao nicDao; + @Inject + private NetworkModel networkModel; + @Inject + private ConfigurationDao configurationDao; + @Inject + private GuestOSDao guestOSDao; + @Inject + private GuestOSHypervisorDao guestOSHypervisorDao; + @Inject + private SnapshotDao snapshotDao; + @Inject + private UserVmDao userVmDao; + @Inject + private NetworkOfferingDao networkOfferingDao; + @Inject + EntityManager entityMgr; + @Inject + private NetworkOrchestrationService networkMgr; + @Inject + private PhysicalNetworkDao physicalNetworkDao; + @Inject + private StoragePoolHostDao storagePoolHostDao; + @Inject + private HypervisorGuruManager hypervisorGuruManager; + @Inject + private VmwareDatacenterDao vmwareDatacenterDao; + @Inject + private ImageStoreDao imageStoreDao; + @Inject + private DataStoreManager dataStoreManager; + @Inject + private ImportVmTasksManager importVmTasksManager; + + protected Gson gson; + + public UnmanagedVMsManagerImpl() { + gson = GsonHelper.getGsonLogger(); + } + + private VMTemplateVO createDefaultDummyVmImportTemplate(boolean isKVM) { + String templateName = (isKVM) ? KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME : VM_IMPORT_DEFAULT_TEMPLATE_NAME; + VMTemplateVO template = null; + try { + template = VMTemplateVO.createSystemIso(templateDao.getNextInSequence(Long.class, "id"), templateName, templateName, true, + "", true, 64, Account.ACCOUNT_ID_SYSTEM, "", + "VM Import Default Template", false, OTHER_LINUX_64_GUEST_OS_ID); + template.setState(VirtualMachineTemplate.State.Inactive); + template = templateDao.persist(template); + if (template == null) { + return null; + } + templateDao.remove(template.getId()); + template = templateDao.findByName(templateName); + } catch (Exception e) { + logger.error("Unable to create default dummy template for VM import", e); + } + return template; + } + + private List getAdditionalNameFilters(Cluster cluster) { + List additionalNameFilter = new ArrayList<>(); + if (cluster == null) { + return additionalNameFilter; + } + 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 (StringUtils.isEmpty(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 (StringUtils.isNotEmpty(path)) { + if (!additionalNameFilter.contains(path)) { + volumeFileNames.add(path); + } + if (path.contains("-")) { + split = path.split("-"); + path = split[0]; + if (StringUtils.isNotEmpty(path) && !path.equals("ROOT") && !additionalNameFilter.contains(path)) { + volumeFileNames.add(path); + } + } + } + } + } catch (Exception e) { + logger.warn("Unable to find volume file name for volume: {} while adding filters unmanaged VMs", volumeVO, e); + } + if (!volumeFileNames.isEmpty()) { + additionalNameFilter.addAll(volumeFileNames); + } + } + } + return additionalNameFilter; + } + + private List getHostsManagedVms(List hosts) { + if (CollectionUtils.isEmpty(hosts)) { + return new ArrayList<>(); + } + List instances = vmDao.listByHostOrLastHostOrHostPod(hosts.stream().map(HostVO::getId).collect(Collectors.toList()), hosts.get(0).getPodId()); + List managedVms = instances.stream().map(VMInstanceVO::getInstanceName).collect(Collectors.toList()); + return managedVms; + } + + private boolean hostSupportsServiceOfferingAndTemplate(HostVO host, ServiceOffering serviceOffering, VirtualMachineTemplate template) { + if (StringUtils.isAllEmpty(serviceOffering.getHostTag(), template.getTemplateTag())) { + return true; + } + hostDao.loadHostTags(host); + return host.checkHostServiceOfferingAndTemplateTags(serviceOffering, template, UserVmManager.getStrictHostTags()); + } + + private boolean storagePoolSupportsDiskOffering(StoragePool pool, DiskOffering diskOffering) { + if (pool == null) { + return false; + } + if (diskOffering == null) { + return false; + } + return volumeApiService.doesStoragePoolSupportDiskOffering(pool, diskOffering); + } + + private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedInstanceTO instance, ServiceOfferingVO serviceOffering, final Account owner, final DataCenter zone, final Map details, Hypervisor.HypervisorType hypervisorType) + throws ServerApiException, PermissionDeniedException, ResourceAllocationException { + if (instance == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Cannot find VM to import."); + } + if (serviceOffering == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Cannot find service offering used to import VM [%s].", instance.getName())); + } + 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 [%s] is not valid for importing VM [%s].", cpu, instance.getName())); + } + if (memory == null || memory == 0) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Memory [%s] is not valid for importing VM [%s].", memory, instance.getName())); + } + + if (serviceOffering.isDynamic()) { + if (details.containsKey(VmDetailConstants.CPU_SPEED)) { + try { + cpuSpeed = Integer.parseInt(details.get(VmDetailConstants.CPU_SPEED)); + } catch (Exception e) { + logger.error("Failed to get CPU speed for importing VM [{}] due to [{}].", instance, e.getMessage(), e); + } + } + 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(UnmanagedInstanceTO.PowerState.PowerOff)) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %d CPU cores do not match 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(UnmanagedInstanceTO.PowerState.PowerOff)) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Service offering (%s) %dMB memory does not match VM memory %dMB and VM is not in powered off state (Power state: %s)", serviceOffering.getUuid(), serviceOffering.getRamSize(), memory, instance.getPowerState())); + } + if (hypervisorType == Hypervisor.HypervisorType.VMware && 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 match VM CPU speed %dMHz and VM is not in powered off state (Power state: %s)", serviceOffering.getUuid(), serviceOffering.getSpeed(), cpuSpeed, instance.getPowerState())); + } + } + return serviceOffering; + } + + /** + * Merges caller-supplied MAC addresses into the NIC IP address map. + * For each NIC entry in {@code nicMacAddressMap}, the MAC address is set on the corresponding + * {@link Network.IpAddresses} object. If no IP address entry exists for a given NIC, a new + * {@link Network.IpAddresses} object is created to carry the MAC. + * + * @param nicIpAddressMap map of NIC ID to IP addresses (may be empty, never null after cmd getter) + * @param nicMacAddressMap map of NIC ID to validated/standardized MAC address strings + * @return merged map with MAC addresses populated where supplied by the caller + */ + protected Map mergeNicMacAddresses( + final Map nicIpAddressMap, + final Map nicMacAddressMap) { + if (MapUtils.isEmpty(nicMacAddressMap)) { + return nicIpAddressMap; + } + Map merged = new HashMap<>(nicIpAddressMap); + for (Map.Entry entry : nicMacAddressMap.entrySet()) { + String nicId = entry.getKey(); + String mac = entry.getValue(); + Network.IpAddresses existing = merged.get(nicId); + if (existing != null) { + existing.setMacAddress(mac); + } else { + merged.put(nicId, new Network.IpAddresses(null, null, mac)); + } + } + return merged; + } + + private Map getNicIpAddresses(final List nics, final Map callerNicIpAddressMap) { + Map nicIpAddresses = new HashMap<>(); + for (UnmanagedInstanceTO.Nic nic : nics) { + Network.IpAddresses ipAddresses = null; + if (MapUtils.isNotEmpty(callerNicIpAddressMap) && callerNicIpAddressMap.containsKey(nic.getNicId())) { + ipAddresses = callerNicIpAddressMap.get(nic.getNicId()); + } + // If IP is set to auto-assign, check NIC doesn't have more that one IP from SDK + if (ipAddresses != null && ipAddresses.getIp4Address() != null && ipAddresses.getIp4Address().equals("auto") && !CollectionUtils.isEmpty(nic.getIpAddress())) { + if (nic.getIpAddress().size() > 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())); + } + String address = nic.getIpAddress().get(0); + if (NetUtils.isValidIp4(address)) { + ipAddresses.setIp4Address(address); + } + } + if (ipAddresses != null) { + nicIpAddresses.put(nic.getNicId(), ipAddresses); + } + } + return nicIpAddresses; + } + + private StoragePool getStoragePool(final UnmanagedInstanceTO.Disk disk, final DataCenter zone, final Cluster cluster, DiskOffering diskOffering) { + StoragePool storagePool = null; + final String dsHost = disk.getDatastoreHost(); + final String dsPath = disk.getDatastorePath(); + final String dsType = disk.getDatastoreType(); + final String dsName = disk.getDatastoreName(); + if (dsType != null) { + List pools = primaryDataStoreDao.listPoolByHostPath(dsHost, dsPath); + for (StoragePool pool : pools) { + if (pool.getDataCenterId() == zone.getId() && + (pool.getClusterId() == null || pool.getClusterId().equals(cluster.getId())) && + volumeApiService.doesStoragePoolSupportDiskOffering(pool, diskOffering)) { + storagePool = pool; + break; + } + } + } + + if (storagePool == null) { + Set pools = new HashSet<>(primaryDataStoreDao.listPoolsByCluster(cluster.getId())); + pools.addAll(primaryDataStoreDao.listByDataCenterId(zone.getId())); + boolean isNameUuid = StringUtils.isNotBlank(dsName) && UuidUtils.isUuid(dsName); + for (StoragePool pool : pools) { + String searchPoolParam = StringUtils.isNotBlank(dsPath) ? dsPath : dsName; + if ((StringUtils.contains(pool.getPath(), searchPoolParam) || isNameUuid && pool.getUuid().equals(dsName)) && + volumeApiService.doesStoragePoolSupportDiskOffering(pool, diskOffering)) { + 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; + } + + private Pair> getRootAndDataDisks( + List disks, + final Map dataDiskOfferingMap) { + UnmanagedInstanceTO.Disk rootDisk = null; + List dataDisks = new ArrayList<>(); + + Set callerDiskIds = dataDiskOfferingMap.keySet(); + if (callerDiskIds.size() != disks.size() - 1) { + String msg = String.format("VM has total %d disks for which %d disk offering mappings provided. %d disks need a disk offering for import", disks.size(), callerDiskIds.size(), disks.size() - 1); + logger.error(String.format("%s. %s parameter can be used to provide disk offerings for the disks", msg, ApiConstants.DATADISK_OFFERING_LIST)); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, msg); + } + List diskIdsWithoutOffering = new ArrayList<>(); + for (UnmanagedInstanceTO.Disk disk : disks) { + String diskId = disk.getDiskId(); + if (!callerDiskIds.contains(diskId)) { + diskIdsWithoutOffering.add(diskId); + rootDisk = disk; + } else { + dataDisks.add(disk); + DiskOffering diskOffering = diskOfferingDao.findById(dataDiskOfferingMap.getOrDefault(disk.getDiskId(), null)); + if ((disk.getCapacity() == null || disk.getCapacity() <= 0) && diskOffering != null) { + disk.setCapacity(diskOffering.getDiskSize()); + } + } + } + if (diskIdsWithoutOffering.size() > 1 || rootDisk == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM has total %d disks, disk offering mapping not provided for %d disks. Disk IDs that may need a disk offering - %s", disks.size(), diskIdsWithoutOffering.size() - 1, String.join(", ", diskIdsWithoutOffering))); + } + + return new Pair<>(rootDisk, dataDisks); + } + + private void checkUnmanagedDiskAndOfferingForImport(String instanceName, UnmanagedInstanceTO.Disk disk, DiskOffering diskOffering, ServiceOffering serviceOffering, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed, List reservations) + throws ServerApiException, PermissionDeniedException, ResourceAllocationException { + if (serviceOffering == null && diskOffering == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Disk offering for disk ID [%s] not found during VM [%s] import.", disk.getDiskId(), instanceName)); + } + if (diskOffering != null) { + accountService.checkAccess(owner, diskOffering, zone); + } + 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 != 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 != 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)))); + } + diskOffering = diskOffering != null ? diskOffering : diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); + StoragePool storagePool = getStoragePool(disk, zone, cluster, 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())); + } + resourceLimitService.checkVolumeResourceLimit(owner, true, disk.getCapacity(), diskOffering, reservations); + } + + private void checkUnmanagedDiskAndOfferingForImport(String intanceName, List disks, final Map diskOfferingMap, final Account owner, final DataCenter zone, final Cluster cluster, final boolean migrateAllowed, List reservations) + throws ServerApiException, PermissionDeniedException, ResourceAllocationException { + String diskController = null; + for (UnmanagedInstanceTO.Disk disk : disks) { + if (disk == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve disk details for VM [%s].", intanceName)); + } + 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 (StringUtils.isEmpty(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 data disk controllers are of the same type", diskController, disk.getController())); + } + } + checkUnmanagedDiskAndOfferingForImport(intanceName, disk, diskOfferingDao.findById(diskOfferingMap.get(disk.getDiskId())), null, owner, zone, cluster, migrateAllowed, reservations); + } + } + + private void checkUnmanagedNicAndNetworkForImport(String instanceName, UnmanagedInstanceTO.Nic nic, Network network, final DataCenter zone, final Account owner, final boolean autoAssign, Hypervisor.HypervisorType hypervisorType) throws ServerApiException { + basicNetworkChecks(instanceName, nic, network); + 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 (!autoAssign && network.getGuestType().equals(Network.GuestType.Isolated)) { + return; + } + checksOnlyNeededForVmware(nic, network, hypervisorType); + } + + private void checksOnlyNeededForVmware(UnmanagedInstanceTO.Nic nic, Network network, final Hypervisor.HypervisorType hypervisorType) { + if (hypervisorType == Hypervisor.HypervisorType.VMware) { + String networkBroadcastUri = network.getBroadcastUri() == null ? null : network.getBroadcastUri().toString(); + if (nic.getVlan() != null && nic.getVlan() != 0 && nic.getPvlan() == null && + (StringUtils.isEmpty(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())); + } + String pvLanType = nic.getPvlanType() == null ? "" : nic.getPvlanType().toLowerCase().substring(0, 1); + if (nic.getVlan() != null && nic.getVlan() != 0 && nic.getPvlan() != null && nic.getPvlan() != 0 && + (StringUtils.isEmpty(networkBroadcastUri) || !String.format("pvlan://%d-%s%d", nic.getVlan(), pvLanType, nic.getPvlan()).equals(networkBroadcastUri))) { + 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-%s%d during VM import", network.getUuid(), networkBroadcastUri, nic.getNicId(), nic.getVlan(), pvLanType, nic.getPvlan())); + } + } + } + + private void basicNetworkChecks(String instanceName, UnmanagedInstanceTO.Nic nic, Network network) { + if (nic == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Unable to retrieve the NIC details used by VM [%s] from VMware. Please check if this VM have NICs in VMWare.", instanceName)); + } + if (network == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Network for nic ID: %s not found during VM import.", nic.getNicId())); + } + } + + private void checkUnmanagedNicAndNetworkHostnameForImport(String instanceName, UnmanagedInstanceTO.Nic nic, Network network, final String hostName) throws ServerApiException { + basicNetworkChecks(instanceName, nic, network); + // 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(String.format("VM with Name [%s] already exists in the network [%s] domain [%s]. Cannot import another VM with the same name. Please try again with a different name.", hostName, network, network.getNetworkDomain())); + } + } + + private void checkUnmanagedNicIpAndNetworkForImport(String instanceName, UnmanagedInstanceTO.Nic nic, Network network, final Network.IpAddresses ipAddresses) throws ServerApiException { + basicNetworkChecks(instanceName, nic, network); + // Check IP is assigned for non L2 networks + if (!network.getGuestType().equals(Network.GuestType.L2) && (ipAddresses == null || StringUtils.isEmpty(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 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 && StringUtils.isNotEmpty(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())); + } + } + } + + private Map getUnmanagedNicNetworkMap(String instanceName, List nics, final Map callerNicNetworkMap, + final Map callerNicIpAddressMap, final DataCenter zone, final String hostName, + final Account owner, Hypervisor.HypervisorType hypervisorType) throws ServerApiException { + Map nicNetworkMap = new HashMap<>(); + String nicAdapter = null; + for (int i = 0; i < nics.size(); i++) { + UnmanagedInstanceTO.Nic nic = nics.get(i); + if (StringUtils.isEmpty(nicAdapter)) { + 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())); + } + } + 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 && nic.getVlan() != 0) { + // 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(instanceName, nic, networkVO, zone, owner, true, hypervisorType); + network = networkVO; + } catch (Exception e) { + logger.error(String.format("Error when checking NIC [%s] of unmanaged instance to import due to [%s].", nic.getNicId(), e.getMessage()), e); + } + if (network != null) { + checkUnmanagedNicAndNetworkHostnameForImport(instanceName, nic, network, hostName); + checkUnmanagedNicIpAndNetworkForImport(instanceName, nic, network, ipAddresses); + break; + } + } + } + } else { + network = networkDao.findById(callerNicNetworkMap.get(nic.getNicId())); + boolean autoImport = false; + if (hypervisorType == Hypervisor.HypervisorType.KVM) { + autoImport = ipAddresses != null && ipAddresses.getIp4Address() != null && ipAddresses.getIp4Address().equalsIgnoreCase("auto"); + } + checkUnmanagedNicAndNetworkForImport(instanceName, nic, network, zone, owner, autoImport, hypervisorType); + checkUnmanagedNicAndNetworkHostnameForImport(instanceName, nic, network, hostName); + checkUnmanagedNicIpAndNetworkForImport(instanceName, 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())); + } + nicNetworkMap.put(nic.getNicId(), network.getId()); + } + return nicNetworkMap; + } + + private Pair importExternalDisk(UnmanagedInstanceTO.Disk disk, VirtualMachine vm, DeployDestination dest, DiskOffering diskOffering, + Volume.Type type, VirtualMachineTemplate template,Long deviceId, String remoteUrl, String username, String password, + String tmpPath, DiskProfile diskProfile) { + final String path = StringUtils.isEmpty(disk.getDatastorePath()) ? disk.getImagePath() : disk.getDatastorePath(); + String chainInfo = disk.getChainInfo(); + if (StringUtils.isEmpty(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); + } + Map storage = dest.getStorageForDisks(); + Volume volume = volumeDao.findById(diskProfile.getVolumeId()); + StoragePool storagePool = storage.get(volume); + CopyRemoteVolumeCommand copyRemoteVolumeCommand = new CopyRemoteVolumeCommand(); + copyRemoteVolumeCommand.setRemoteIp(remoteUrl); + copyRemoteVolumeCommand.setUsername(username); + copyRemoteVolumeCommand.setPassword(password); + copyRemoteVolumeCommand.setSrcFile(path); + StorageFilerTO storageTO = new StorageFilerTO(storagePool); + copyRemoteVolumeCommand.setStorageFilerTO(storageTO); + if(tmpPath == null || tmpPath.length() < 1) { + tmpPath = "/tmp/"; + } else { + // Add / if path doesn't end with / + if(tmpPath.charAt(tmpPath.length() - 1) != '/') { + tmpPath += "/"; + } + } + copyRemoteVolumeCommand.setTempPath(tmpPath); + int copyTimeout = UnmanagedVMsManager.RemoteKvmInstanceDisksCopyTimeout.value(); + if (copyTimeout <= 0) { + copyTimeout = Integer.valueOf(UnmanagedVMsManager.RemoteKvmInstanceDisksCopyTimeout.defaultValue()); + } + int copyTimeoutInSecs = copyTimeout * 60; + copyRemoteVolumeCommand.setWait(copyTimeoutInSecs); + logger.error(String.format("Initiating copy remote volume %s from %s, timeout %d secs", path, remoteUrl, copyTimeoutInSecs)); + Answer answer = agentManager.easySend(dest.getHost().getId(), copyRemoteVolumeCommand); + if (!(answer instanceof CopyRemoteVolumeAnswer)) { + throw new CloudRuntimeException("Error while copying volume of remote instance: " + answer.getDetails()); + } + CopyRemoteVolumeAnswer copyRemoteVolumeAnswer = (CopyRemoteVolumeAnswer) answer; + checkVolume(copyRemoteVolumeAnswer.getVolumeDetails()); + if (!copyRemoteVolumeAnswer.getResult()) { + throw new CloudRuntimeException("Unable to copy volume of remote instance"); + } + diskProfile.setSize(copyRemoteVolumeAnswer.getSize()); + DiskProfile profile = volumeManager.updateImportedVolume(type, diskOffering, vm, template, deviceId, + storagePool.getId(), storagePool.getPoolType(), copyRemoteVolumeAnswer.getFilename(), chainInfo, diskProfile); + + return new Pair<>(profile, storagePool); + } + + private Pair importKVMLocalDisk(VirtualMachine vm, DiskOffering diskOffering, + Volume.Type type, VirtualMachineTemplate template, + Long deviceId, Long hostId, String diskPath, DiskProfile diskProfile) { + List storagePools = primaryDataStoreDao.findLocalStoragePoolsByHostAndTags(hostId, null); + if(storagePools.size() < 1) { + throw new CloudRuntimeException("Local Storage not found for host"); + } + + StoragePool storagePool = storagePools.get(0); + + DiskProfile profile = volumeManager.updateImportedVolume(type, diskOffering, vm, template, deviceId, + storagePool.getId(), storagePool.getPoolType(), diskPath, null, diskProfile); + + return new Pair<>(profile, storagePool); + } + + private Pair importKVMSharedDisk(VirtualMachine vm, DiskOffering diskOffering, + Volume.Type type, VirtualMachineTemplate template, + Long deviceId, Long poolId, String diskPath, DiskProfile diskProfile) { + StoragePool storagePool = primaryDataStoreDao.findById(poolId); + + DiskProfile profile = volumeManager.updateImportedVolume(type, diskOffering, vm, template, deviceId, + poolId, storagePool.getPoolType(), diskPath, null, diskProfile); + + return new Pair<>(profile, storagePool); + } + + private Pair importDisk(UnmanagedInstanceTO.Disk disk, VirtualMachine vm, Cluster cluster, DiskOffering diskOffering, + 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 = StringUtils.isEmpty(disk.getFileBaseName()) ? disk.getImagePath() : disk.getFileBaseName(); + String chainInfo = disk.getChainInfo(); + if (vm.getHypervisorType() == Hypervisor.HypervisorType.VMware && StringUtils.isEmpty(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, diskOffering); + DiskProfile profile = volumeManager.importVolume(type, name, diskOffering, diskSize, + minIops, maxIops, vm.getDataCenterId(), vm.getHypervisorType(), vm, template, owner, deviceId, storagePool.getId(), storagePool.getPoolType(), path, chainInfo); + + return new Pair(profile, storagePool); + } + + protected NicProfile importNic(UnmanagedInstanceTO.Nic nic, VirtualMachine vm, Network network, Network.IpAddresses ipAddresses, int deviceId, boolean isDefaultNic, boolean forced) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException { + // Prefer caller-supplied MAC (from nicmacaddresslist); fall back to hypervisor-reported MAC + String macAddress = (ipAddresses != null && StringUtils.isNotEmpty(ipAddresses.getMacAddress())) + ? ipAddresses.getMacAddress() + : nic.getMacAddress(); + DataCenterVO dataCenterVO = dataCenterDao.findById(network.getDataCenterId()); + Pair result = networkOrchestrationService.importNic(macAddress, deviceId, network, isDefaultNic, vm, ipAddresses, dataCenterVO, forced); + if (result == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC ID: %s import failed", nic.getNicId())); + } + return result.first(); + } + + 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 + try { + networkOrchestrationService.release(profile, true); + } catch (Exception e) { + logger.error("Unable to release NICs for unsuccessful import unmanaged VM: {}", userVm, e); + nicDao.removeNicsForInstance(userVm.getId()); + } + // Remove vm + vmDao.remove(userVm.getId()); + } + + 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")); + } + if (sourceHost == null || serviceOffering == null || diskProfileStoragePoolList == null) { + logger.error(String.format("Failed to check migrations need during import, VM: %s", userVm)); + cleanupFailedImportVM(vm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to check migrations need during import, VM: %s", userVm.getInstanceName())); + } + if (!hostSupportsServiceOfferingAndTemplate(sourceHost, serviceOffering, template)) { + logger.debug("VM {} needs to be migrated", vm); + final VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm, template, serviceOffering, owner, null); + profile.setServiceOffering(serviceOfferingDao.findById(vm.getId(), serviceOffering.getId())); + 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) { + String errorMsg = String.format("VM import failed for Unmanaged VM [%s] during VM migration, cannot find deployment destination due to [%s].", vm, e.getMessage()); + logger.warn(errorMsg, e); + cleanupFailedImportVM(vm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg); + } + 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())); + } + try { + 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) { + String errorMsg = String.format("VM import failed for Unmanaged VM [%s] during VM migration due to [%s].", vm, e.getMessage()); + logger.error(errorMsg, e); + cleanupFailedImportVM(vm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg); + } + } + 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; + } + boolean poolSupportsOfferings = storagePoolSupportsDiskOffering(diskProfileStoragePool.second(), dOffering); + if (poolSupportsOfferings) { + continue; + } + logger.debug("Volume {} needs to be migrated", volumeVO); + Pair, List> poolsPair = managementService.listStoragePoolsForSystemMigrationOfVolume(profile.getVolumeId(), null, null, null, null, false, true); + 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(s) found", userVm.getInstanceName(), volumeVO.getUuid())); + } + List storagePools = poolsPair.second(); + StoragePool storagePool = null; + if (CollectionUtils.isNotEmpty(storagePools)) { + for (StoragePool pool : storagePools) { + if (diskProfileStoragePool.second().getId() != pool.getId() && + storagePoolSupportsDiskOffering(pool, dOffering) + ) { + 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) + ) { + storagePool = pool; + break; + } + } + } + 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("Found storage pool {} for migrating the volume {} to", storagePool, volumeVO); + } + try { + Volume volume = null; + if (vm.getState().equals(VirtualMachine.State.Running)) { + volume = volumeManager.liveMigrateVolume(volumeVO, storagePool); + } else { + volume = volumeManager.migrateVolume(volumeVO, storagePool); + } + if (volume == null) { + String msg = ""; + if (vm.getState().equals(VirtualMachine.State.Running)) { + msg = String.format("Live migration for volume: %s to destination pool: %s failed", volumeVO, storagePool); + } else { + msg = String.format("Migration for volume: %s to destination pool: %s failed", volumeVO, storagePool); + } + logger.error(msg); + throw new CloudRuntimeException(msg); + } + } catch (Exception e) { + logger.error("VM import failed for unmanaged vm: {} during volume migration", vm, e); + cleanupFailedImportVM(vm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm: %s during volume migration. %s", userVm.getInstanceName(), StringUtils.defaultString(e.getMessage()))); + } + } + return userVm; + } + + private void publishVMUsageUpdateResourceCount(final UserVm userVm, ServiceOfferingVO serviceOfferingVO, VirtualMachineTemplate templateVO) { + if (userVm == null || serviceOfferingVO == null) { + logger.error("Failed to publish usage records during VM import because VM [{}] or ServiceOffering [{}] is null.", userVm, serviceOfferingVO); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "VM import failed for Unmanaged VM during publishing Usage Records."); + } + try { + if (!serviceOfferingVO.isDynamic()) { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, 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_CREATE, userVm.getAccountId(), userVm.getAccountId(), userVm.getDataCenterId(), userVm.getHostName(), serviceOfferingVO.getId(), userVm.getTemplateId(), + userVm.getHypervisorType().toString(), VirtualMachine.class.getName(), userVm.getUuid(), userVm.getDetails(), userVm.isDisplayVm()); + } + if (userVm.getState() == VirtualMachine.State.Running) { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_START, userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), userVm.getHostName(), serviceOfferingVO.getId(), userVm.getTemplateId(), + userVm.getHypervisorType().toString(), VirtualMachine.class.getName(), userVm.getUuid(), userVm.isDisplayVm()); + } + } catch (Exception e) { + logger.error("Failed to publish usage records during VM import for unmanaged VM [{}] due to [{}].", userVm, e.getMessage(), e); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed for unmanaged vm %s during publishing usage records", userVm.getInstanceName())); + } + resourceLimitService.incrementVmResourceCount(userVm.getAccountId(), userVm.isDisplayVm(), serviceOfferingVO, templateVO); + // Save usage event and update resource count for user vm volumes + List volumes = volumeDao.findByInstance(userVm.getId()); + for (VolumeVO volume : volumes) { + 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("Failed to publish volume ID: {} usage records during VM import", volume, e); + } + resourceLimitService.incrementVolumeResourceCount(userVm.getAccountId(), volume.isDisplayVolume(), + volume.getSize(), diskOfferingDao.findById(volume.getDiskOfferingId())); + } + + List nics = nicDao.listByVmId(userVm.getId()); + for (NicVO nic : nics) { + try { + NetworkVO network = networkDao.findById(nic.getNetworkId()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, userVm.getAccountId(), userVm.getDataCenterId(), userVm.getId(), + Long.toString(nic.getId()), network.getNetworkOfferingId(), null, 1L, VirtualMachine.class.getName(), userVm.getUuid(), userVm.isDisplay()); + } catch (Exception e) { + logger.error(String.format("Failed to publish network usage records during VM import. %s", StringUtils.defaultString(e.getMessage()))); + } + } + } + + private UserVm importVirtualMachineInternal(final UnmanagedInstanceTO unmanagedInstance, final String instanceNameInternal, 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 Map dataDiskOfferingMap, + final Map nicNetworkMap, final Map callerNicIpAddressMap, final Long guestOsId, + final Map details, final boolean migrateAllowed, final boolean forced, final boolean isImportUnmanagedFromSameHypervisor) { + logger.debug(LogUtils.logGsonWithoutException("Trying to import VM [%s] with name [%s], in zone [%s], cluster [%s], and host [%s], using template [%s], service offering [%s], disks map [%s], NICs map [%s] and details [%s].", + unmanagedInstance, displayName, zone, cluster, host, template, serviceOffering, dataDiskOfferingMap, nicNetworkMap, details)); + UserVm userVm = null; + ServiceOfferingVO validatedServiceOffering = null; + try { + validatedServiceOffering = getUnmanagedInstanceServiceOffering(unmanagedInstance, serviceOffering, owner, zone, details, cluster.getHypervisorType()); + } catch (Exception e) { + String errorMsg = String.format("Failed to import Unmanaged VM [%s] because the service offering [%s] is not compatible due to [%s].", unmanagedInstance, serviceOffering, StringUtils.defaultIfEmpty(e.getMessage(), "")); + logger.error(errorMsg, e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg); + } + + String internalCSName = unmanagedInstance.getInternalCSName(); + if (StringUtils.isEmpty(internalCSName)) { + internalCSName = instanceNameInternal; + } + 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 && host != null && !hostSupportsServiceOfferingAndTemplate(host, validatedServiceOffering, template)) { + throw new InvalidParameterValueException(String.format("Service offering: %s or template: %s is not compatible with host: %s of unmanaged VM: %s", serviceOffering.getUuid(), template.getUuid(), host.getUuid(), displayName)); + } + // 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", displayName)); + } + Pair> rootAndDataDisksPair = getRootAndDataDisks(unmanagedInstanceDisks, dataDiskOfferingMap); + final UnmanagedInstanceTO.Disk rootDisk = rootAndDataDisksPair.first(); + final List dataDisks = rootAndDataDisksPair.second(); + if (rootDisk == null || StringUtils.isEmpty(rootDisk.getController())) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM import failed. Unable to retrieve root disk details for VM: %s ", displayName)); + } + if (cluster.getHypervisorType() == Hypervisor.HypervisorType.KVM) { + Long rootDiskOfferingId = validatedServiceOffering.getDiskOfferingId(); + DiskOffering rootDiskOffering = diskOfferingDao.findById(rootDiskOfferingId); + if ((rootDisk.getCapacity() == null || rootDisk.getCapacity() <= 0) && rootDiskOffering != null) { + rootDisk.setCapacity(rootDiskOffering.getDiskSize()); + } + } + allDetails.put(VmDetailConstants.ROOT_DISK_CONTROLLER, rootDisk.getController()); + if (cluster.getHypervisorType() == Hypervisor.HypervisorType.KVM && isImportUnmanagedFromSameHypervisor) { + long size = Double.valueOf(Math.ceil((double)rootDisk.getCapacity() / Resource.ResourceType.bytesToGiB)).longValue(); + allDetails.put(VmDetailConstants.ROOT_DISK_SIZE, String.valueOf(size)); + } + + List reservations = new ArrayList<>(); + try { + checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), rootDisk, null, validatedServiceOffering, owner, zone, cluster, migrateAllowed, reservations); + if (CollectionUtils.isNotEmpty(dataDisks)) { // Data disk(s) present + checkUnmanagedDiskAndOfferingForImport(unmanagedInstance.getName(), dataDisks, dataDiskOfferingMap, owner, zone, cluster, migrateAllowed, reservations); + allDetails.put(VmDetailConstants.DATA_DISK_CONTROLLER, dataDisks.get(0).getController()); + } + + // Check NICs and supplied networks + Map nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap); + Map allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getName(), unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner, cluster.getHypervisorType()); + if (!CollectionUtils.isEmpty(unmanagedInstance.getNics())) { + allDetails.put(VmDetailConstants.NIC_ADAPTER, unmanagedInstance.getNics().get(0).getAdapterType()); + } + + if (StringUtils.isNotEmpty(unmanagedInstance.getVncPassword())) { + allDetails.put(VmDetailConstants.KVM_VNC_PASSWORD, unmanagedInstance.getVncPassword()); + } + + addImportingVMBootTypeAndModeDetails(unmanagedInstance.getBootType(), unmanagedInstance.getBootMode(), allDetails); + + VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff; + if (unmanagedInstance.getPowerState().equals(UnmanagedInstanceTO.PowerState.PowerOn)) { + powerState = VirtualMachine.PowerState.PowerOn; + } + + try { + userVm = userVmManager.importVM(zone, host, template, internalCSName, displayName, owner, + null, caller, true, null, owner.getAccountId(), userId, + validatedServiceOffering, null, guestOsId, hostName, + cluster.getHypervisorType(), allDetails, powerState, null); + } catch (InsufficientCapacityException ice) { + String errorMsg = String.format("Failed to import VM [%s] due to [%s].", displayName, ice.getMessage()); + logger.error(errorMsg, ice); + throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, errorMsg); + } + + if (userVm == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import vm name: %s", displayName)); + } + List> diskProfileStoragePoolList = new ArrayList<>(); + try { + if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) { + throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId())); + } + Long minIops = null; + if (details.containsKey(MIN_IOPS)) { + minIops = Long.parseLong(details.get(MIN_IOPS)); + } + Long maxIops = null; + if (details.containsKey(MAX_IOPS)) { + maxIops = Long.parseLong(details.get(MAX_IOPS)); + } + DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); + diskProfileStoragePoolList.add(importDisk(rootDisk, userVm, cluster, diskOffering, Volume.Type.ROOT, String.format("ROOT-%d", userVm.getId()), + rootDisk.getCapacity(), minIops, maxIops, template, owner, null)); + long deviceId = 1L; + 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(), offering.getMinIops(), offering.getMaxIops(), + template, owner, deviceId)); + deviceId++; + } + } catch (Exception e) { + logger.error(String.format("Failed to import volumes while importing vm: %s", displayName), e); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", displayName, StringUtils.defaultString(e.getMessage()))); + } + try { + int nicIndex = 0; + 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, nicIndex, nicIndex == 0, forced); + nicIndex++; + } + } catch (Exception e) { + logger.error(String.format("Failed to import NICs while importing vm: %s", displayName), e); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import NICs while importing vm: %s. %s", displayName, StringUtils.defaultString(e.getMessage()))); + } + if (migrateAllowed) { + userVm = migrateImportedVM(host, template, validatedServiceOffering, userVm, owner, diskProfileStoragePoolList); + } + publishVMUsageUpdateResourceCount(userVm, validatedServiceOffering, template); + return userVm; + + } catch (ResourceAllocationException e) { // This will be thrown by checkUnmanagedDiskAndOfferingForImport, so the VM was not imported yet + logger.error("Volume resource allocation error for owner: {}", owner, e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resource allocation error for owner: %s. %s", owner.getUuid(), StringUtils.defaultString(e.getMessage()))); + } finally { + ReservationHelper.closeAll(reservations); + } + } + + private void addImportingVMBootTypeAndModeDetails(String bootType, String bootMode, Map allDetails) { + if (StringUtils.isNotBlank(bootType) && bootType.equalsIgnoreCase("uefi") && StringUtils.isNotBlank(bootMode)) { + allDetails.put("UEFI", bootMode); + } + } + + private HashMap getUnmanagedInstancesForHost(HostVO host, String instanceName, List managedVms) { + HashMap unmanagedInstances = new HashMap<>(); + if (host.isInMaintenanceStates()) { + return unmanagedInstances; + } + + GetUnmanagedInstancesCommand command = new GetUnmanagedInstancesCommand(); + command.setInstanceName(instanceName); + command.setManagedInstancesNames(managedVms); + Answer answer = agentManager.easySend(host.getId(), command); + if (!(answer instanceof GetUnmanagedInstancesAnswer) || !answer.getResult()) { + return unmanagedInstances; + } + GetUnmanagedInstancesAnswer unmanagedInstancesAnswer = (GetUnmanagedInstancesAnswer) answer; + unmanagedInstances = unmanagedInstancesAnswer.getUnmanagedInstances(); + return unmanagedInstances; + } + + protected Cluster basicAccessChecks(Long clusterId) { + final Account caller = CallContext.current().getCallingAccount(); + if (caller.getType() != Account.Type.ADMIN) { + throw new PermissionDeniedException(String.format("Cannot perform this operation, caller account [%s] is not ROOT Admin.", caller.getUuid())); + } + if (clusterId == null) { + throw new InvalidParameterValueException("Cluster ID cannot be null."); + } + final Cluster cluster = clusterDao.findById(clusterId); + if (cluster == null) { + throw new InvalidParameterValueException(String.format("Cluster with ID [%d] cannot be found.", clusterId)); + } + + if (!importUnmanagedInstancesSupportedHypervisors.contains(cluster.getHypervisorType())) { + throw new InvalidParameterValueException(String.format("VM import is currently not supported for hypervisor [%s].", cluster.getHypervisorType().toString())); + } + return cluster; + } + + @Override + public ListResponse listUnmanagedInstances(ListUnmanagedInstancesCmd cmd) { + Long clusterId = cmd.getClusterId(); + Cluster cluster = basicAccessChecks(clusterId); + String keyword = cmd.getKeyword(); + if (StringUtils.isNotEmpty(keyword)) { + keyword = keyword.toLowerCase(); + } + List hosts = resourceManager.listHostsInClusterByStatus(clusterId, Status.Up); + List additionalNameFilters = getAdditionalNameFilters(cluster); + List managedVms = new ArrayList<>(additionalNameFilters); + managedVms.addAll(getHostsManagedVms(hosts)); + List responses = new ArrayList<>(); + for (HostVO host : hosts) { + HashMap unmanagedInstances = getUnmanagedInstancesForHost(host, cmd.getName(), managedVms); + Set keys = unmanagedInstances.keySet(); + for (String key : keys) { + UnmanagedInstanceTO instance = unmanagedInstances.get(key); + if (StringUtils.isNotEmpty(keyword) && + !instance.getName().toLowerCase().contains(keyword)) { + continue; + } + responses.add(responseGenerator.createUnmanagedInstanceResponse(instance, cluster, host)); + } + } + ListResponse listResponses = new ListResponse<>(); + listResponses.setResponses(responses, responses.size()); + return listResponses; + } + + @Override + public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { + return baseImportInstance(cmd); + } + + /** + * Base logic for import virtual machines (unmanaged, external) into CloudStack + * @param cmd importVM or importUnmanagedInstance command + * @return imported user vm + */ + private UserVmResponse baseImportInstance(ImportUnmanagedInstanceCmd cmd) { + basicParametersCheckForImportInstance(cmd.getName(), cmd.getDomainId(), cmd.getAccountName()); + + final String instanceName = cmd.getName(); + Long clusterId = cmd.getClusterId(); + Cluster cluster = basicAccessChecks(clusterId); + + if (!cluster.getAllocationState().equals(Cluster.AllocationState.Enabled)) { + throw new InvalidParameterValueException(String.format("Cluster [%s] is not enabled.", cluster)); + } + + final Account caller = CallContext.current().getCallingAccount(); + final DataCenter zone = dataCenterDao.findById(cluster.getDataCenterId()); + final Account owner = accountService.getActiveAccountById(cmd.getEntityOwnerId()); + long userId = getUserIdForImportInstance(owner); + + VMTemplateVO template = getTemplateForImportInstance(cmd.getTemplateId(), cluster.getHypervisorType()); + ServiceOfferingVO serviceOffering = getServiceOfferingForImportInstance(cmd.getServiceOfferingId(), owner, zone); + + String displayName = getDisplayNameForImportInstance(cmd.getDisplayName(), instanceName); + String hostName = getHostNameForImportInstance(cmd.getHostName(), cluster.getHypervisorType(), instanceName, displayName); + + checkVmwareInstanceNameForImportInstance(cluster.getHypervisorType(), instanceName, hostName, zone); + final Map nicNetworkMap = cmd.getNicNetworkList(); + final Map nicIpAddressMap = mergeNicMacAddresses(cmd.getNicIpAddressList(), cmd.getNicMacAddressList()); + final Map dataDiskOfferingMap = cmd.getDataDiskToDiskOfferingList(); + final Map details = cmd.getDetails(); + final boolean forced = cmd.isForced(); + List hosts = resourceManager.listHostsInClusterByStatus(clusterId, Status.Up); + UserVm userVm = null; + List additionalNameFilters = getAdditionalNameFilters(cluster); + List managedVms = new ArrayList<>(additionalNameFilters); + managedVms.addAll(getHostsManagedVms(hosts)); + + try { + + ActionEventUtils.onStartedActionEvent(userId, owner.getId(), EventTypes.EVENT_VM_IMPORT, + cmd.getEventDescription(), null, null, true, 0); + + if (cmd instanceof ImportVmCmd) { + ImportVmCmd importVmCmd = (ImportVmCmd) cmd; + if (StringUtils.isBlank(importVmCmd.getImportSource())) { + throw new CloudRuntimeException("Please provide an import source for importing the VM"); + } + String source = importVmCmd.getImportSource().toUpperCase(); + ImportSource importSource = Enum.valueOf(ImportSource.class, source); + if (ImportSource.VMWARE == importSource) { + userVm = importUnmanagedInstanceFromVmwareToKvm(zone, cluster, + template, instanceName, displayName, hostName, caller, owner, userId, + serviceOffering, dataDiskOfferingMap, + nicNetworkMap, nicIpAddressMap, + details, importVmCmd, forced); + } + } else { + if (List.of(Hypervisor.HypervisorType.VMware, Hypervisor.HypervisorType.KVM).contains(cluster.getHypervisorType())) { + userVm = importUnmanagedInstanceFromHypervisor(zone, cluster, hosts, additionalNameFilters, + template, instanceName, displayName, hostName, caller, owner, userId, + serviceOffering, dataDiskOfferingMap, + nicNetworkMap, nicIpAddressMap, + details, cmd.getMigrateAllowed(), managedVms, forced); + } + } + + } 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(), StringUtils.defaultString(e.getMessage()))); + } + + if (userVm == null) { + ActionEventUtils.onCompletedActionEvent(userId, owner.getId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_IMPORT, + cmd.getEventDescription(), null, null, 0); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to find unmanaged vm with name: %s in cluster: %s", instanceName, cluster.getUuid())); + } + ActionEventUtils.onCompletedActionEvent(userId, owner.getId(), EventVO.LEVEL_INFO, EventTypes.EVENT_VM_IMPORT, + cmd.getEventDescription(), userVm.getId(), ApiCommandResourceType.VirtualMachine.toString(), 0); + return responseGenerator.createUserVmResponse(ResponseObject.ResponseView.Full, "virtualmachine", userVm).get(0); + } + + protected void checkExtraParamsAllowed(String extraParams) { + if (StringUtils.isBlank(extraParams)) { + return; + } + if (BooleanUtils.isFalse(ConvertVmwareInstanceToKvmExtraParamsAllowed.value())) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, + "Extra parameters for Vmware to KVM conversion are disabled by the administrator"); + } + String allowedParamsStr = ConvertVmwareInstanceToKvmExtraParamsAllowedList.value(); + if (StringUtils.isBlank(allowedParamsStr)) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, + "Extra parameters for Vmware to KVM conversion are enabled but the allowed list of parameters is empty"); + } + List allowedParams = Arrays.asList(allowedParamsStr.split(",")); + List sanitizedParams = Arrays.asList(extraParams.split(" ")) + .stream() + .filter(x -> x.startsWith("-")) + .map(s -> s.replaceFirst("^-+", "").trim()) //Remove the starting hyphens as in --X or -x + .collect(Collectors.toList()); + for (String param : sanitizedParams) { + if (!allowedParams.contains(param)) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, + String.format("The parameter %s is not allowed by the administrator", param)); + } + } + } + + private long getUserIdForImportInstance(Account owner) { + long userId = CallContext.current().getCallingUserId(); + List userVOs = userDao.listByAccount(owner.getAccountId()); + if (CollectionUtils.isNotEmpty(userVOs)) { + userId = userVOs.get(0).getId(); + } + return userId; + } + + protected void basicParametersCheckForImportInstance(String name, Long domainId, String accountName) { + if (StringUtils.isEmpty(name)) { + throw new InvalidParameterValueException("Instance name cannot be empty"); + } + if (domainId != null && StringUtils.isEmpty(accountName)) { + throw new InvalidParameterValueException(String.format("%s parameter must be specified with %s parameter", ApiConstants.DOMAIN_ID, ApiConstants.ACCOUNT)); + } + } + + private void checkVmwareInstanceNameForImportInstance(Hypervisor.HypervisorType hypervisorType, String instanceName, String hostName, DataCenter zone) { + if (hypervisorType.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())); + } + } + } + + private String getHostNameForImportInstance(String hostName, Hypervisor.HypervisorType hypervisorType, + String instanceName, String displayName) { + if (StringUtils.isEmpty(hostName)) { + hostName = hypervisorType == Hypervisor.HypervisorType.VMware ? instanceName : displayName; + if (!NetUtils.verifyDomainNameLabel(hostName, true)) { + throw new InvalidParameterValueException("Please provide a valid hostname for the VM. VM name contains unsupported characters that cannot be used as hostname."); + } + } + 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"); + } + return hostName; + } + + private String getDisplayNameForImportInstance(String displayName, String instanceName) { + return StringUtils.isEmpty(displayName) ? instanceName : displayName; + } + + private ServiceOfferingVO getServiceOfferingForImportInstance(Long serviceOfferingId, Account owner, DataCenter zone) { + if (serviceOfferingId == null) { + throw new InvalidParameterValueException("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); + return serviceOffering; + } + + protected VMTemplateVO getTemplateForImportInstance(Long templateId, Hypervisor.HypervisorType hypervisorType) { + VMTemplateVO template; + if (templateId == null) { + boolean isKVMHypervisor = Hypervisor.HypervisorType.KVM.equals(hypervisorType); + String templateName = (isKVMHypervisor) ? KVM_VM_IMPORT_DEFAULT_TEMPLATE_NAME : VM_IMPORT_DEFAULT_TEMPLATE_NAME; + template = templateDao.findByName(templateName); + if (template == null) { + template = createDefaultDummyVmImportTemplate(isKVMHypervisor); + 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 parameter for import", templateName, hypervisorType.toString())); + } + } + } else { + template = templateDao.findById(templateId); + } + if (template == null) { + throw new InvalidParameterValueException(String.format("Template ID: %d cannot be found", templateId)); + } + return template; + } + + @Override + @ActionEvent(eventType = EventTypes.EVENT_VM_IMPORT, eventDescription = "importing VM", async = true) + public UserVmResponse importVm(ImportVmCmd cmd) { + String source = cmd.getImportSource().toUpperCase(); + ImportSource importSource = Enum.valueOf(ImportSource.class, source); + if (ImportSource.VMWARE == importSource || ImportSource.UNMANAGED == importSource) { + checkExtraParamsAllowed(cmd.getExtraParams()); + return baseImportInstance(cmd); + } else { + return importKvmInstance(cmd); + } + } + + private UserVm importUnmanagedInstanceFromHypervisor(DataCenter zone, Cluster cluster, + List hosts, List additionalNameFilters, + VMTemplateVO template, String instanceName, String displayName, + String hostName, Account caller, Account owner, long userId, + ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap, + Map nicNetworkMap, Map nicIpAddressMap, + Map details, Boolean migrateAllowed, List managedVms, boolean forced) throws ResourceAllocationException { + UserVm userVm = null; + for (HostVO host : hosts) { + HashMap unmanagedInstances = getUnmanagedInstancesForHost(host, instanceName, managedVms); + if (MapUtils.isEmpty(unmanagedInstances)) { + continue; + } + Set names = unmanagedInstances.keySet(); + for (String name : names) { + if (!instanceName.equals(name)) { + continue; + } + 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)); + } + + if (template.getName().equals(VM_IMPORT_DEFAULT_TEMPLATE_NAME) && cluster.getHypervisorType().equals(Hypervisor.HypervisorType.KVM)) { + throw new InvalidParameterValueException("Template is needed and unable to use default template for hypervisor " + host.getHypervisorType().toString()); + } + + if (template.getName().equals(VM_IMPORT_DEFAULT_TEMPLATE_NAME)) { + String osName = unmanagedInstance.getOperatingSystem(); + GuestOS guestOS = null; + if (StringUtils.isNotEmpty(osName)) { + guestOS = guestOSDao.findOneByDisplayName(osName); + } + + GuestOSHypervisor guestOSHypervisor = null; + if (guestOS != null) { + guestOSHypervisor = guestOSHypervisorDao.findByOsIdAndHypervisor(guestOS.getId(), host.getHypervisorType().toString(), host.getHypervisorVersion()); + } + if (guestOSHypervisor == null && StringUtils.isNotEmpty(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())); + } + 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(guestOSHypervisor.getGuestOsId()); + } + + List reservations = new ArrayList<>(); + try { + checkVmResourceLimitsForUnmanagedInstanceImport(owner, unmanagedInstance, serviceOffering, template, reservations); + userVm = importVirtualMachineInternal(unmanagedInstance, instanceName, zone, cluster, host, + template, displayName, hostName, CallContext.current().getCallingAccount(), owner, userId, + serviceOffering, dataDiskOfferingMap, + nicNetworkMap, nicIpAddressMap, null, + details, migrateAllowed, forced, true); + } finally { + ReservationHelper.closeAll(reservations); + } + break; + } + if (userVm != null) { + break; + } + } + return userVm; + } + + protected void checkVmResourceLimitsForUnmanagedInstanceImport(Account owner, UnmanagedInstanceTO unmanagedInstance, ServiceOfferingVO serviceOffering, VMTemplateVO template, List reservations) throws ResourceAllocationException { + // When importing an unmanaged instance, the amount of CPUs and memory is obtained from the hypervisor unless powered off + // and not using a dynamic offering, unlike the external VM import that always obtains it from the compute offering + Integer cpu = serviceOffering.getCpu(); + Integer memory = serviceOffering.getRamSize(); + + if (serviceOffering.isDynamic() || !UnmanagedInstanceTO.PowerState.PowerOff.equals(unmanagedInstance.getPowerState())) { + cpu = unmanagedInstance.getCpuCores(); + memory = unmanagedInstance.getMemory(); + } + + if (cpu == null || cpu == 0) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("CPU cores [%s] is not valid for importing VM [%s].", cpu, unmanagedInstance.getName())); + } + if (memory == null || memory == 0) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Memory [%s] is not valid for importing VM [%s].", memory, unmanagedInstance.getName())); + } + + List resourceLimitHostTags = resourceLimitService.getResourceLimitHostTags(serviceOffering, template); + + CheckedReservation vmReservation = new CheckedReservation(owner, Resource.ResourceType.user_vm, resourceLimitHostTags, 1L, reservationDao, resourceLimitService); + reservations.add(vmReservation); + + CheckedReservation cpuReservation = new CheckedReservation(owner, Resource.ResourceType.cpu, resourceLimitHostTags, cpu.longValue(), reservationDao, resourceLimitService); + reservations.add(cpuReservation); + + CheckedReservation memReservation = new CheckedReservation(owner, Resource.ResourceType.memory, resourceLimitHostTags, memory.longValue(), reservationDao, resourceLimitService); + reservations.add(memReservation); + } + + private Pair getSourceVmwareUnmanagedInstance(String vcenter, String datacenterName, String username, + String password, String clusterName, String sourceHostName, + String sourceVM, ServiceOfferingVO serviceOffering) { + HypervisorGuru vmwareGuru = hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware); + + Map params = createParamsForTemplateFromVmwareVmMigration(vcenter, datacenterName, + username, password, clusterName, sourceHostName, sourceVM); + addServiceOfferingDetailsToParams(params, serviceOffering); + + return vmwareGuru.getHypervisorVMOutOfBandAndCloneIfRequired(sourceHostName, sourceVM, params); + } + + /** + * Add the minimum resources to check on the hypervisor source VM before converting the instance against the selected offering resources + * @param params sets the minimum CPU number, CPU speed and memory to be checked against the source VM + * @param serviceOffering service offering for the converted VM + */ + protected void addServiceOfferingDetailsToParams(Map params, ServiceOfferingVO serviceOffering) { + if (serviceOffering != null) { + serviceOfferingDao.loadDetails(serviceOffering); + Map serviceOfferingDetails = serviceOffering.getDetails(); + + if (serviceOffering.getCpu() != null) { + params.put(VmDetailConstants.CPU_NUMBER, String.valueOf(serviceOffering.getCpu())); + } else if (MapUtils.isNotEmpty(serviceOfferingDetails) && serviceOfferingDetails.containsKey(ApiConstants.MIN_CPU_NUMBER)) { + params.put(VmDetailConstants.CPU_NUMBER, serviceOfferingDetails.get(ApiConstants.MIN_CPU_NUMBER)); + } + + if (serviceOffering.getSpeed() != null) { + params.put(VmDetailConstants.CPU_SPEED, String.valueOf(serviceOffering.getSpeed())); + } + + if (serviceOffering.getRamSize() != null) { + params.put(VmDetailConstants.MEMORY, String.valueOf(serviceOffering.getRamSize())); + } else if (MapUtils.isNotEmpty(serviceOfferingDetails) && serviceOfferingDetails.containsKey(ApiConstants.MIN_MEMORY)) { + params.put(VmDetailConstants.MEMORY, serviceOfferingDetails.get(ApiConstants.MIN_MEMORY)); + } + } + } + + private String createOvfTemplateOfSourceVmwareUnmanagedInstance(String vcenter, String datacenterName, String username, + String password, String clusterName, String sourceHostName, + String sourceVMwareInstanceName, DataStoreTO convertLocation, int threadsCountToExportOvf) { + HypervisorGuru vmwareGuru = hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware); + + Map params = createParamsForTemplateFromVmwareVmMigration(vcenter, datacenterName, + username, password, clusterName, sourceHostName, sourceVMwareInstanceName); + + return vmwareGuru.createVMTemplateOutOfBand(sourceHostName, sourceVMwareInstanceName, params, convertLocation, threadsCountToExportOvf); + } + + protected UserVm importUnmanagedInstanceFromVmwareToKvm(DataCenter zone, Cluster destinationCluster, VMTemplateVO template, + String sourceVMName, String displayName, String hostName, + Account caller, Account owner, long userId, + ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap, + Map nicNetworkMap, Map nicIpAddressMap, + Map details, ImportVmCmd cmd, boolean forced) throws ResourceAllocationException { + Long existingVcenterId = cmd.getExistingVcenterId(); + String vcenter = cmd.getVcenter(); + String datacenterName = cmd.getDatacenterName(); + String username = cmd.getUsername(); + String password = cmd.getPassword(); + String clusterName = cmd.getClusterName(); + String sourceHostName = cmd.getHostIp(); + Long convertInstanceHostId = cmd.getConvertInstanceHostId(); + Long importInstanceHostId = cmd.getImportInstanceHostId(); + Long convertStoragePoolId = cmd.getConvertStoragePoolId(); + String extraParams = cmd.getExtraParams(); + boolean forceConvertToPool = cmd.getForceConvertToPool(); + Long guestOsId = cmd.getGuestOsId(); + boolean forceMsToImportVmFiles = Boolean.TRUE.equals(cmd.getForceMsToImportVmFiles()); + boolean useVddk = cmd.getUseVddk(); + + if ((existingVcenterId == null && vcenter == null) || (existingVcenterId != null && vcenter != null)) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, + "Please provide an existing vCenter ID or a vCenter IP/Name, parameters are mutually exclusive"); + } + if (existingVcenterId == null && StringUtils.isAnyBlank(vcenter, datacenterName, username, password)) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, + "Please set all the information for a vCenter IP/Name, datacenter, username and password"); + } + if (forceMsToImportVmFiles && useVddk) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, + String.format("Parameters %s and %s are mutually exclusive", + ApiConstants.FORCE_MS_TO_IMPORT_VM_FILES, ApiConstants.USE_VDDK)); + } + + checkConversionStoragePool(convertStoragePoolId, forceConvertToPool); + validateSelectedConversionStoragePoolForVddk(useVddk, convertStoragePoolId, serviceOffering, dataDiskOfferingMap); + + checkExtraParamsAllowed(extraParams); + + if (existingVcenterId != null) { + VmwareDatacenterVO existingDC = vmwareDatacenterDao.findById(existingVcenterId); + if (existingDC == null) { + String err = String.format("Cannot find any existing VMware DC with ID %s", existingVcenterId); + logger.error(err); + throw new CloudRuntimeException(err); + } + vcenter = existingDC.getVcenterHost(); + datacenterName = existingDC.getVmwareDatacenterName(); + username = existingDC.getUser(); + password = existingDC.getPassword(); + } + + boolean isClonedInstance = false; + UnmanagedInstanceTO sourceVMwareInstance = null; + DataStoreTO temporaryConvertLocation = null; + String ovfTemplateOnConvertLocation = null; + ImportVmTask importVMTask = null; + List reservations = new ArrayList<>(); + try { + HostVO convertHost = selectKVMHostForConversionInCluster(destinationCluster, convertInstanceHostId, useVddk); + HostVO importHost = (useVddk && importInstanceHostId == null) + ? convertHost + : selectKVMHostForImportingInCluster(destinationCluster, importInstanceHostId); + + boolean isOvfExportSupported = false; + CheckConvertInstanceAnswer conversionSupportAnswer = checkConversionSupportOnHost(convertHost, sourceVMName, false, useVddk, details); + if (!useVddk) { + isOvfExportSupported = conversionSupportAnswer.isOvfExportSupported(); + } + logger.debug("The host {} is selected to execute the conversion of the " + + "instance {} from VMware to KVM ", convertHost, sourceVMName); + + temporaryConvertLocation = selectInstanceConversionTemporaryLocation( + destinationCluster, convertHost, importHost, convertStoragePoolId, forceConvertToPool); + List convertStoragePools = findInstanceConversionDestinationStoragePoolsInCluster(destinationCluster, serviceOffering, dataDiskOfferingMap, temporaryConvertLocation, forceConvertToPool); + + long importStartTime = System.currentTimeMillis(); + importVMTask = importVmTasksManager.createImportVMTaskRecord(zone, owner, userId, displayName, vcenter, datacenterName, sourceVMName, + convertHost, importHost); + importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, null, CloningInstance); + + // sourceVMwareInstance could be a cloned instance from sourceVMName, of the sourceVMName itself if its powered off. + // isClonedInstance indicates if the VM is a clone of sourceVMName + + Pair sourceInstanceDetails = getSourceVmwareUnmanagedInstance(vcenter, datacenterName, username, password, clusterName, sourceHostName, sourceVMName, serviceOffering); + sourceVMwareInstance = sourceInstanceDetails.first(); + isClonedInstance = sourceInstanceDetails.second(); + + // Ensure that the configured resource limits will not be exceeded before beginning the conversion process + checkVmResourceLimitsForUnmanagedInstanceImport(owner, sourceVMwareInstance, serviceOffering, template, reservations); + + boolean isWindowsVm = sourceVMwareInstance.getOperatingSystem().toLowerCase().contains("windows"); + if (isWindowsVm) { + checkConversionSupportOnHost(convertHost, sourceVMName, true, useVddk, details); + } + + checkNetworkingBeforeConvertingVmwareInstance(zone, owner, displayName, hostName, sourceVMwareInstance, nicNetworkMap, nicIpAddressMap, forced); + UnmanagedInstanceTO convertedInstance; + if (!useVddk && (forceMsToImportVmFiles || !isOvfExportSupported)) { + // Uses MS for OVF export to temporary conversion location + int noOfThreads = UnmanagedVMsManager.ThreadsOnMSToImportVMwareVMFiles.value(); + importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, null, ConvertingInstance); + ovfTemplateOnConvertLocation = createOvfTemplateOfSourceVmwareUnmanagedInstance( + vcenter, datacenterName, username, password, clusterName, sourceHostName, + sourceVMwareInstance.getName(), temporaryConvertLocation, noOfThreads); + convertedInstance = convertVmwareInstanceToKVMWithOVFOnConvertLocation(sourceVMName, + sourceVMwareInstance, convertHost, importHost, convertStoragePools, + serviceOffering, dataDiskOfferingMap, temporaryConvertLocation, + ovfTemplateOnConvertLocation, forceConvertToPool, extraParams); + } else { + // Uses KVM Host for direct conversion using VDDK, or for OVF export to temporary conversion location through ovftool + importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, null, ConvertingInstance); + convertedInstance = convertVmwareInstanceToKVMUsingVDDKOrAfterExportingOVFToConvertLocation( + sourceVMName, sourceVMwareInstance, convertHost, importHost, + convertStoragePools, serviceOffering, dataDiskOfferingMap, + temporaryConvertLocation, vcenter, username, password, datacenterName, forceConvertToPool, extraParams, useVddk, details); + } + + sanitizeConvertedInstance(convertedInstance, sourceVMwareInstance); + importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, null, Importing); + UserVm userVm = importVirtualMachineInternal(convertedInstance, null, zone, destinationCluster, null, + template, displayName, hostName, caller, owner, userId, + serviceOffering, dataDiskOfferingMap, + nicNetworkMap, nicIpAddressMap, guestOsId, + details, false, forced, false); + long timeElapsedInSecs = (System.currentTimeMillis() - importStartTime) / 1000; + logger.debug(String.format("VMware VM %s imported successfully to CloudStack instance %s (%s), Time taken: %d secs, OVF files imported from %s, Source VMware VM details - OS: %s, PowerState: %s, Disks: %s, NICs: %s", + sourceVMName, displayName, displayName, timeElapsedInSecs, (ovfTemplateOnConvertLocation != null)? "MS" : "KVM Host", sourceVMwareInstance.getOperatingSystem(), sourceVMwareInstance.getPowerState(), sourceVMwareInstance.getDisks(), sourceVMwareInstance.getNics())); + importVmTasksManager.updateImportVMTaskStep(importVMTask, zone, owner, convertHost, importHost, userVm.getId(), Completed); + return userVm; + } catch (CloudRuntimeException e) { + logger.error(String.format("Error importing VM: %s", e.getMessage()), e); + importVmTasksManager.updateImportVMTaskErrorState(importVMTask, ImportVmTask.TaskState.Failed, e.getMessage()); + ActionEventUtils.onCompletedActionEvent(userId, owner.getId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_VM_IMPORT, + cmd.getEventDescription(), null, null, 0); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); + } finally { + if (isClonedInstance && sourceVMwareInstance != null) { + removeClonedInstance(vcenter, datacenterName, username, password, sourceHostName, sourceVMwareInstance.getName(), sourceVMName); + } + if (temporaryConvertLocation != null && StringUtils.isNotBlank(ovfTemplateOnConvertLocation)) { + removeTemplate(temporaryConvertLocation, ovfTemplateOnConvertLocation); + } + ReservationHelper.closeAll(reservations); + } + } + + /** + * Check whether the conversion storage pool exists and is suitable for the conversion or not. + * Secondary storage is only allowed when forceConvertToPool is false. + * @param convertStoragePoolId the ID of the storage pool (primary or secondary) + * @param forceConvertToPool when true, only primary storage pool must be allowed + * @throws CloudRuntimeException in case these requirements are not met + */ + protected void checkConversionStoragePool(Long convertStoragePoolId, boolean forceConvertToPool) { + if (forceConvertToPool && convertStoragePoolId == null) { + String msg = "The parameter forceconverttopool is set to true, but a primary storage pool has not been provided for conversion"; + logFailureAndThrowException(msg); + } + if (convertStoragePoolId != null) { + StoragePoolVO selectedStoragePool = primaryDataStoreDao.findById(convertStoragePoolId); + if (selectedStoragePool == null) { + logFailureAndThrowException(String.format("Cannot find a storage pool with ID %s", convertStoragePoolId)); + } + if (forceConvertToPool && !forceConvertToPoolAllowedTypes.contains(selectedStoragePool.getPoolType())) { + logFailureAndThrowException(String.format("The selected storage pool %s does not support direct conversion " + + "as its type %s", selectedStoragePool.getName(), selectedStoragePool.getPoolType().name())); + } + } + } + + protected void validateSelectedConversionStoragePoolForVddk(boolean useVddk, Long convertStoragePoolId, + ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap) { + if (!useVddk || convertStoragePoolId == null) { + return; + } + + StoragePoolVO selectedStoragePool = primaryDataStoreDao.findById(convertStoragePoolId); + if (selectedStoragePool == null) { + return; + } + + if (serviceOffering.getDiskOfferingId() != null) { + DiskOfferingVO rootDiskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); + if (rootDiskOffering == null) { + throw new InvalidParameterValueException(String.format("Cannot find disk offering with ID %s that belongs to the service offering %s", + serviceOffering.getDiskOfferingId(), serviceOffering.getName())); + } + if (!volumeApiService.doesStoragePoolSupportDiskOffering(selectedStoragePool, rootDiskOffering)) { + throw new InvalidParameterValueException(String.format("The root disk offering '%s' is not supported by the selected conversion storage pool '%s'. " + + "When using VDDK, all selected disk offerings must be compatible with the conversion storage pool, as it will become the primary storage for the imported volumes.", + rootDiskOffering.getName(), selectedStoragePool.getName())); + } + } + + if (MapUtils.isNotEmpty(dataDiskOfferingMap)) { + for (Long diskOfferingId : dataDiskOfferingMap.values()) { + DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId); + if (diskOffering == null) { + throw new InvalidParameterValueException(String.format("Cannot find disk offering with ID %s", diskOfferingId)); + } + if (!volumeApiService.doesStoragePoolSupportDiskOffering(selectedStoragePool, diskOffering)) { + throw new InvalidParameterValueException(String.format("The data disk offering '%s' is not supported by the selected conversion storage pool '%s'. " + + "When using VDDK, all selected disk offerings must be compatible with the conversion storage pool, as it will become the primary storage for the imported volumes.", + diskOffering.getName(), selectedStoragePool.getName())); + } + } + } + } + + private void checkNetworkingBeforeConvertingVmwareInstance(DataCenter zone, Account owner, String displayName, + String hostName, UnmanagedInstanceTO sourceVMwareInstance, + Map nicNetworkMap, + Map nicIpAddressMap, + boolean forced) { + List nics = sourceVMwareInstance.getNics(); + List networkIds = new ArrayList<>(nicNetworkMap.values()); + if (nics.size() != networkIds.size()) { + String msg = String.format("Different number of nics found on instance %s: %s vs %s nics provided", + sourceVMwareInstance.getName(), nics.size(), networkIds.size()); + logger.error(msg); + throw new CloudRuntimeException(msg); + } + + for (UnmanagedInstanceTO.Nic nic : nics) { + Long networkId = nicNetworkMap.get(nic.getNicId()); + NetworkVO network = networkDao.findById(networkId); + if (network == null) { + String err = String.format("Cannot find a network with id = %s", networkId); + logger.error(err); + throw new CloudRuntimeException(err); + } + Network.IpAddresses ipAddresses = null; + if (MapUtils.isNotEmpty(nicIpAddressMap) && nicIpAddressMap.containsKey(nic.getNicId())) { + ipAddresses = nicIpAddressMap.get(nic.getNicId()); + } + boolean autoImport = ipAddresses != null && ipAddresses.getIp4Address() != null && ipAddresses.getIp4Address().equalsIgnoreCase("auto"); + checkUnmanagedNicAndNetworkMacAddressForImport(network, nic, forced); + checkUnmanagedNicAndNetworkForImport(displayName, nic, network, zone, owner, autoImport, Hypervisor.HypervisorType.KVM); + checkUnmanagedNicAndNetworkHostnameForImport(displayName, nic, network, hostName); + checkUnmanagedNicIpAndNetworkForImport(displayName, nic, network, ipAddresses); + } + } + + private void checkUnmanagedNicAndNetworkMacAddressForImport(NetworkVO network, UnmanagedInstanceTO.Nic nic, boolean forced) { + NicVO existingNic = nicDao.findByNetworkIdAndMacAddress(network.getId(), nic.getMacAddress()); + if (existingNic != null && !forced) { + String err = String.format("NIC %s with MAC address %s already exists on network %s and forced flag is disabled. " + + "Retry with forced flag enabled if a new MAC address to be generated.", nic, nic.getMacAddress(), network); + logger.error(err); + throw new CloudRuntimeException(err); + } + } + + private void sanitizeConvertedInstance(UnmanagedInstanceTO convertedInstance, UnmanagedInstanceTO sourceVMwareInstance) { + convertedInstance.setCpuCores(sourceVMwareInstance.getCpuCores()); + convertedInstance.setCpuSpeed(sourceVMwareInstance.getCpuSpeed()); + convertedInstance.setCpuCoresPerSocket(sourceVMwareInstance.getCpuCoresPerSocket()); + convertedInstance.setMemory(sourceVMwareInstance.getMemory()); + convertedInstance.setPowerState(UnmanagedInstanceTO.PowerState.PowerOff); + List convertedInstanceDisks = convertedInstance.getDisks(); + List sourceVMwareInstanceDisks = sourceVMwareInstance.getDisks(); + for (int i = 0; i < convertedInstanceDisks.size(); i++) { + UnmanagedInstanceTO.Disk disk = convertedInstanceDisks.get(i); + disk.setDiskId(sourceVMwareInstanceDisks.get(i).getDiskId()); + } + List convertedInstanceNics = convertedInstance.getNics(); + List sourceVMwareInstanceNics = sourceVMwareInstance.getNics(); + if (CollectionUtils.isEmpty(convertedInstanceNics) && CollectionUtils.isNotEmpty(sourceVMwareInstanceNics)) { + for (UnmanagedInstanceTO.Nic nic : sourceVMwareInstanceNics) { + // In case the NICs information is not parsed from the converted XML domain, use the cloned instance NICs with virtio adapter + nic.setAdapterType("virtio"); + } + convertedInstance.setNics(sourceVMwareInstanceNics); + for (int i = 0; i < convertedInstanceNics.size(); i++) { + UnmanagedInstanceTO.Nic nic = convertedInstanceNics.get(i); + nic.setNicId(sourceVMwareInstanceNics.get(i).getNicId()); + } + } else if (CollectionUtils.isNotEmpty(convertedInstanceNics) && CollectionUtils.isNotEmpty(sourceVMwareInstanceNics) + && convertedInstanceNics.size() == sourceVMwareInstanceNics.size()) { + for (int i = 0; i < convertedInstanceNics.size(); i++) { + UnmanagedInstanceTO.Nic nic = convertedInstanceNics.get(i); + nic.setNicId(sourceVMwareInstanceNics.get(i).getNicId()); + if (nic.getMacAddress() == null) { + nic.setMacAddress(sourceVMwareInstanceNics.get(i).getMacAddress()); + } + } + } + } + + private void removeClonedInstance(String vcenter, String datacenterName, String username, String password, + String sourceHostName, String clonedInstanceName, String sourceVM) { + HypervisorGuru vmwareGuru = hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware); + Map params = createParamsForRemoveClonedInstance(vcenter, datacenterName, username, password, sourceVM); + boolean result = vmwareGuru.removeClonedHypervisorVMOutOfBand(sourceHostName, clonedInstanceName, params); + if (!result) { + String msg = String.format("Could not properly remove the cloned instance %s from VMware datacenter %s:%s", + clonedInstanceName, vcenter, datacenterName); + logger.warn(msg); + return; + } + logger.debug(String.format("Removed the cloned instance %s from VMWare datacenter %s/%s", + clonedInstanceName, vcenter, datacenterName)); + } + + private void removeTemplate(DataStoreTO convertLocation, String ovfTemplateOnConvertLocation) { + HypervisorGuru vmwareGuru = hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware); + boolean result = vmwareGuru.removeVMTemplateOutOfBand(convertLocation, ovfTemplateOnConvertLocation); + if (!result) { + String msg = String.format("Could not remove the template file %s on datastore %s", + ovfTemplateOnConvertLocation, convertLocation.getUrl()); + logger.warn(msg); + return; + } + logger.debug(String.format("Removed the template file %s on datastore %s", + ovfTemplateOnConvertLocation, convertLocation.getUrl())); + } + + private Map createParamsForRemoveClonedInstance(String vcenter, String datacenterName, String username, + String password, String sourceVM) { + Map params = new HashMap<>(); + params.put(VmDetailConstants.VMWARE_VCENTER_HOST, vcenter); + params.put(VmDetailConstants.VMWARE_DATACENTER_NAME, datacenterName); + params.put(VmDetailConstants.VMWARE_VCENTER_USERNAME, username); + params.put(VmDetailConstants.VMWARE_VCENTER_PASSWORD, password); + return params; + } + + HostVO selectKVMHostForImportingInCluster(Cluster destinationCluster, Long importInstanceHostId) { + if (importInstanceHostId != null) { + String err = null; + HostVO selectedHost = hostDao.findById(importInstanceHostId); + if (selectedHost == null) { + err = String.format("Cannot find host with ID %s to import the instance", + importInstanceHostId); + } else if (selectedHost.getResourceState() != ResourceState.Enabled) { + err = String.format( + "Cannot import the converted instance on the host %s as it is not in Enabled state", + selectedHost); + } else if (selectedHost.getStatus() != Status.Up) { + err = String.format( + "Cannot import the converted instance on the host %s as it is not running", + selectedHost); + } else if (selectedHost.getType() != Host.Type.Routing) { + err = String.format( + "Cannot import the converted instance on the host %s as it is not a routing host", + selectedHost); + } else if (destinationCluster.getId() != selectedHost.getClusterId()) { + err = String.format( + "Cannot import the converted instance on the host %s as it is not in the same cluster as the destination cluster", + selectedHost); + } + + if (err != null) { + logger.error(err); + throw new CloudRuntimeException(err); + } + return selectedHost; + } + + List hosts = hostDao.listByClusterAndHypervisorType(destinationCluster.getId(), destinationCluster.getHypervisorType()); + if (CollectionUtils.isNotEmpty(hosts)) { + return hosts.get(new Random().nextInt(hosts.size())); + } + + String err = String.format( + "Could not find any suitable %s host in cluster %s to import the converted instance", + destinationCluster.getHypervisorType(), destinationCluster); + logger.error(err); + throw new CloudRuntimeException(err); + } + + HostVO selectKVMHostForConversionInCluster(Cluster destinationCluster, Long convertInstanceHostId, boolean useVddk) { + if (convertInstanceHostId != null) { + HostVO selectedHost = hostDao.findById(convertInstanceHostId); + String err = null; + if (selectedHost == null) { + err = String.format("Cannot find host with ID %s for conversion", + convertInstanceHostId); + } else if (!List.of(ResourceState.Enabled, ResourceState.Disabled).contains(selectedHost.getResourceState())) { + err = String.format( + "Cannot perform the conversion on the host %s as the host is in %s state", + selectedHost, selectedHost.getResourceState()); + } else if (selectedHost.getStatus() != Status.Up) { + err = String.format( + "Cannot perform the conversion on the host %s as it is not running", + selectedHost); + } else if (selectedHost.getType() != Host.Type.Routing) { + err = String.format( + "Cannot perform the conversion on the host %s as it is not a routing host", + selectedHost); + } else if (destinationCluster.getDataCenterId() != selectedHost.getDataCenterId()) { + err = String.format( + "Cannot perform the conversion on the host %s as it is not in the same zone as the destination cluster", + selectedHost); + } + if (err != null) { + logger.error(err); + throw new CloudRuntimeException(err); + } + return selectedHost; + } + + // Auto select host with conversion capability + List hosts = hostDao.listByClusterHypervisorTypeAndHostCapability(destinationCluster.getId(), destinationCluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION); + if (CollectionUtils.isNotEmpty(hosts)) { + if (useVddk) { + List vddkHosts = filterHostsWithVddkSupport(hosts); + if (CollectionUtils.isNotEmpty(vddkHosts)) { + hosts = vddkHosts; + } + } + if (CollectionUtils.isNotEmpty(hosts)) { + return hosts.get(new Random().nextInt(hosts.size())); + } + } + + // Try without host capability check + hosts = hostDao.listByClusterAndHypervisorType(destinationCluster.getId(), destinationCluster.getHypervisorType()); + if (CollectionUtils.isNotEmpty(hosts)) { + if (useVddk) { + List vddkHosts = filterHostsWithVddkSupport(hosts); + if (CollectionUtils.isNotEmpty(vddkHosts)) { + hosts = vddkHosts; + } + } + if (CollectionUtils.isNotEmpty(hosts)) { + return hosts.get(new Random().nextInt(hosts.size())); + } + } + + String err = useVddk + ? String.format("Could not find any suitable %s host in cluster %s with '%s' configured to perform the VDDK-based instance conversion", + destinationCluster.getHypervisorType(), destinationCluster, Host.HOST_VDDK_SUPPORT) + : String.format("Could not find any suitable %s host in cluster %s to perform the instance conversion", + destinationCluster.getHypervisorType(), destinationCluster); + logger.error(err); + throw new CloudRuntimeException(err); + } + + private List filterHostsWithVddkSupport(List hosts) { + return hosts.stream().filter(h -> { + hostDao.loadDetails(h); + return Boolean.parseBoolean(h.getDetail(Host.HOST_VDDK_SUPPORT)); + }).collect(Collectors.toList()); + } + + private CheckConvertInstanceAnswer checkConversionSupportOnHost(HostVO convertHost, String sourceVM, + boolean checkWindowsGuestConversionSupport, + boolean useVddk, Map details) { + logger.debug(String.format("Checking the %s%s conversion support on the host %s", + useVddk ? "VDDK " : "", + checkWindowsGuestConversionSupport ? "windows guest " : "", + convertHost)); + CheckConvertInstanceCommand cmd = new CheckConvertInstanceCommand(checkWindowsGuestConversionSupport, useVddk); + if (MapUtils.isNotEmpty(details)) { + cmd.setVddkLibDir(StringUtils.trimToNull(details.get(Host.HOST_VDDK_LIB_DIR))); + } + int timeoutSeconds = 60; + cmd.setWait(timeoutSeconds); + + CheckConvertInstanceAnswer checkConvertInstanceAnswer; + try { + checkConvertInstanceAnswer = (CheckConvertInstanceAnswer) agentManager.send(convertHost.getId(), cmd); + } catch (AgentUnavailableException | OperationTimedoutException e) { + String err = String.format("Failed to check %s conversion support on the host %s for converting instance %s from VMware to KVM due to: %s", + checkWindowsGuestConversionSupport? "windows guest" : "", convertHost, sourceVM, e.getMessage()); + logger.error(err); + throw new CloudRuntimeException(err); + } + + if (!checkConvertInstanceAnswer.getResult()) { + String err = String.format("The host %s doesn't support conversion of instance %s from VMware to KVM due to: %s", + convertHost, sourceVM, checkConvertInstanceAnswer.getDetails()); + logger.error(err); + throw new CloudRuntimeException(err); + } + + return checkConvertInstanceAnswer; + } + + private UnmanagedInstanceTO convertVmwareInstanceToKVMWithOVFOnConvertLocation( + String sourceVM, UnmanagedInstanceTO sourceVMwareInstance, HostVO convertHost, + HostVO importHost, List convertStoragePools, + ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap, + DataStoreTO temporaryConvertLocation, String ovfTemplateDirConvertLocation, + boolean forceConvertToPool, String extraParams) { + + logger.debug("Delegating the conversion of instance {} from VMware to KVM to the host {} using OVF {} on conversion datastore", + sourceVM, convertHost, ovfTemplateDirConvertLocation); + + RemoteInstanceTO remoteInstanceTO = new RemoteInstanceTO(sourceVM, sourceVMwareInstance.getClusterName(), sourceVMwareInstance.getHostName()); + List destinationStoragePools = selectInstanceConversionStoragePools(convertStoragePools, sourceVMwareInstance.getDisks(), serviceOffering, dataDiskOfferingMap); + ConvertInstanceCommand cmd = new ConvertInstanceCommand(remoteInstanceTO, + Hypervisor.HypervisorType.KVM, temporaryConvertLocation, + ovfTemplateDirConvertLocation, false, false, sourceVM); + if (StringUtils.isNotBlank(extraParams)) { + cmd.setExtraParams(extraParams); + } + int timeoutSeconds = UnmanagedVMsManager.ConvertVmwareInstanceToKvmTimeout.value() * 60 * 60; + cmd.setWait(timeoutSeconds); + + return convertAndImportToKVM(cmd, convertHost, importHost, sourceVM, + remoteInstanceTO, destinationStoragePools, temporaryConvertLocation, forceConvertToPool); + } + + private UnmanagedInstanceTO convertVmwareInstanceToKVMUsingVDDKOrAfterExportingOVFToConvertLocation( + String sourceVM, UnmanagedInstanceTO sourceVMwareInstance, HostVO convertHost, + HostVO importHost, List convertStoragePools, + ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap, + DataStoreTO temporaryConvertLocation, String vcenterHost, String vcenterUsername, + String vcenterPassword, String datacenterName, boolean forceConvertToPool, String extraParams, + boolean useVddk, Map details) { + logger.debug("Delegating the conversion of instance {} from VMware to KVM to the host {} after OVF export through ovftool", sourceVM, convertHost); + + RemoteInstanceTO remoteInstanceTO = new RemoteInstanceTO(sourceVMwareInstance.getName(), sourceVMwareInstance.getPath(), vcenterHost, vcenterUsername, vcenterPassword, datacenterName, sourceVMwareInstance.getClusterName(), sourceVMwareInstance.getHostName()); + List destinationStoragePools = selectInstanceConversionStoragePools(convertStoragePools, sourceVMwareInstance.getDisks(), serviceOffering, dataDiskOfferingMap); + ConvertInstanceCommand cmd = new ConvertInstanceCommand(remoteInstanceTO, + Hypervisor.HypervisorType.KVM, temporaryConvertLocation, null, false, true, sourceVM); + int timeoutSeconds = UnmanagedVMsManager.ConvertVmwareInstanceToKvmTimeout.value() * 60 * 60; + cmd.setWait(timeoutSeconds); + int noOfThreads = UnmanagedVMsManager.ThreadsOnKVMHostToImportVMwareVMFiles.value(); + if (noOfThreads == 0) { + // Use no. of threads as the disks count + noOfThreads = sourceVMwareInstance.getDisks().size(); + } + cmd.setThreadsCountToExportOvf(noOfThreads); + if (StringUtils.isNotBlank(extraParams)) { + cmd.setExtraParams(extraParams); + } + cmd.setUseVddk(useVddk); + applyVddkOverridesFromDetails(cmd, details); + return convertAndImportToKVM(cmd, convertHost, importHost, sourceVM, + remoteInstanceTO, destinationStoragePools, temporaryConvertLocation, forceConvertToPool); + } + + private void applyVddkOverridesFromDetails(ConvertInstanceCommand cmd, Map details) { + if (MapUtils.isEmpty(details)) { + return; + } + + cmd.setVddkLibDir(StringUtils.trimToNull(details.get(Host.HOST_VDDK_LIB_DIR))); + cmd.setVddkTransports(StringUtils.trimToNull(details.get(DETAIL_VDDK_TRANSPORTS))); + cmd.setVddkThumbprint(StringUtils.trimToNull(details.get(DETAIL_VDDK_THUMBPRINT))); + } + + private UnmanagedInstanceTO convertAndImportToKVM(ConvertInstanceCommand convertInstanceCommand, HostVO convertHost, HostVO importHost, + String sourceVM, + RemoteInstanceTO remoteInstanceTO, + List destinationStoragePools, + DataStoreTO temporaryConvertLocation, + boolean forceConvertToPool) { + Answer convertAnswer; + try { + convertAnswer = agentManager.send(convertHost.getId(), convertInstanceCommand); + } catch (AgentUnavailableException | OperationTimedoutException e) { + String err = String.format("Could not send the convert instance command to host %s due to: %s", + convertHost, e.getMessage()); + logger.error(err, e); + throw new CloudRuntimeException(err); + } + + if (!convertAnswer.getResult()) { + String err = String.format("The convert process failed for instance %s from VMware to KVM on host %s: %s", + sourceVM, convertHost, convertAnswer.getDetails()); + logger.error(err); + throw new CloudRuntimeException(err); + } + + Answer importAnswer; + try { + ImportConvertedInstanceCommand importCmd = new ImportConvertedInstanceCommand( + remoteInstanceTO, destinationStoragePools, temporaryConvertLocation, + ((ConvertInstanceAnswer)convertAnswer).getTemporaryConvertUuid(), forceConvertToPool); + importAnswer = agentManager.send(importHost.getId(), importCmd); + } catch (AgentUnavailableException | OperationTimedoutException e) { + String err = String.format( + "Could not send the import converted instance command to host %s due to: %s", + importHost, e.getMessage()); + logger.error(err, e); + throw new CloudRuntimeException(err); + } + + if (!importAnswer.getResult()) { + String err = String.format( + "The import process failed for instance %s from VMware to KVM on host %s: %s", + sourceVM, importHost, importAnswer.getDetails()); + logger.error(err); + throw new CloudRuntimeException(err); + } + + return ((ImportConvertedInstanceAnswer) importAnswer).getConvertedInstance(); + } + + private List findInstanceConversionDestinationStoragePoolsInCluster( + Cluster destinationCluster, ServiceOfferingVO serviceOffering, + Map dataDiskOfferingMap, + DataStoreTO temporaryConvertLocation, boolean forceConvertToPool) { + List poolsList; + if (!forceConvertToPool) { + Set pools = new HashSet<>(primaryDataStoreDao.findClusterWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)); + pools.addAll(primaryDataStoreDao.findZoneWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getDataCenterId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)); + if (pools.isEmpty()) { + String msg = String.format("Cannot find suitable storage pools in the cluster %s for the conversion", destinationCluster.getName()); + logger.error(msg); + throw new CloudRuntimeException(msg); + } + poolsList = new ArrayList<>(pools); + } else { + DataStore dataStore = dataStoreManager.getDataStore(temporaryConvertLocation.getUuid(), temporaryConvertLocation.getRole()); + poolsList = Collections.singletonList(primaryDataStoreDao.findById(dataStore.getId())); + } + + if (serviceOffering.getDiskOfferingId() != null) { + DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); + if (diskOffering == null) { + String msg = String.format("Cannot find disk offering with ID %s that belongs to the service offering %s", serviceOffering.getDiskOfferingId(), serviceOffering.getName()); + logger.error(msg); + throw new CloudRuntimeException(msg); + } + if (getStoragePoolWithTags(poolsList, diskOffering.getTags()) == null) { + String msg = String.format("Cannot find suitable storage pool for disk offering %s that belongs to the service offering %s", diskOffering.getName(), serviceOffering.getName()); + logger.error(msg); + throw new CloudRuntimeException(msg); + } + } + for (Long diskOfferingId : dataDiskOfferingMap.values()) { + DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId); + if (diskOffering == null) { + String msg = String.format("Cannot find disk offering with ID %s", diskOfferingId); + logger.error(msg); + throw new CloudRuntimeException(msg); + } + if (getStoragePoolWithTags(poolsList, diskOffering.getTags()) == null) { + String msg = String.format("Cannot find suitable storage pool for disk offering %s", diskOffering.getName()); + logger.error(msg); + throw new CloudRuntimeException(msg); + } + } + + return poolsList; + } + + private StoragePoolVO getStoragePoolWithTags(List pools, String tags) { + if (StringUtils.isEmpty(tags)) { + return pools.get(0); + } + for (StoragePoolVO pool : pools) { + if (volumeApiService.doesStoragePoolSupportDiskOfferingTags(pool, tags)) { + return pool; + } + } + return null; + } + + private List selectInstanceConversionStoragePools( + List pools, List disks, + ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap + ) { + List storagePools = new ArrayList<>(disks.size()); + Set dataDiskIds = dataDiskOfferingMap.keySet(); + for (UnmanagedInstanceTO.Disk disk : disks) { + Long diskOfferingId = null; + if (dataDiskIds.contains(disk.getDiskId())) { + diskOfferingId = dataDiskOfferingMap.get(disk.getDiskId()); + } else { + diskOfferingId = serviceOffering.getDiskOfferingId(); + } + + //TODO: Choose pools by capacity + if (diskOfferingId == null) { + storagePools.add(pools.get(0).getUuid()); + } else { + DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId); + StoragePoolVO pool = getStoragePoolWithTags(pools, diskOffering.getTags()); + storagePools.add(pool.getUuid()); + } + } + return storagePools; + } + + private void logFailureAndThrowException(String msg) { + logger.error(msg); + throw new CloudRuntimeException(msg); + } + + private void checkBeforeSelectingTemporaryConversionStoragePool(StoragePoolVO selectedStoragePool, Long convertStoragePoolId, Cluster destinationCluster, HostVO convertHost) { + if (selectedStoragePool == null) { + logFailureAndThrowException(String.format("Cannot find a storage pool with ID %s", convertStoragePoolId)); + } + if ((selectedStoragePool.getScope() == ScopeType.CLUSTER && selectedStoragePool.getClusterId() != destinationCluster.getId()) || + (selectedStoragePool.getScope() == ScopeType.ZONE && selectedStoragePool.getDataCenterId() != destinationCluster.getDataCenterId())) { + logFailureAndThrowException(String.format("Cannot use the storage pool %s for the instance conversion as " + + "it is not in the scope of the cluster %s", selectedStoragePool.getName(), destinationCluster.getName())); + } + if (convertHost != null && selectedStoragePool.getScope() == ScopeType.CLUSTER && !selectedStoragePool.getClusterId().equals(convertHost.getClusterId())) { + logFailureAndThrowException(String.format("Cannot use the storage pool %s for the instance conversion as " + + "the host %s for conversion is in a different cluster", selectedStoragePool.getName(), convertHost.getName())); + } + } + + private DataStoreTO getImageStoreOnDestinationZoneForTemporaryConversion(Cluster destinationCluster, boolean forceConvertToPool) { + if (forceConvertToPool) { + logFailureAndThrowException("Please select a primary storage pool when the parameter forceconverttopool is set to true"); + } + long zoneId = destinationCluster.getDataCenterId(); + ImageStoreVO imageStore = imageStoreDao.findOneByZoneAndProtocol(zoneId, "nfs"); + if (imageStore == null) { + logFailureAndThrowException(String.format("Could not find an NFS secondary storage pool on zone %s to use as a temporary location " + + "for instance conversion", zoneId)); + } + DataStore dataStore = dataStoreManager.getDataStore(imageStore.getId(), DataStoreRole.Image); + return dataStore.getTO(); + } + + private void checkDestinationOrTemporaryStoragePoolForConversion(StoragePoolVO selectedStoragePool, boolean forceConvertToPool, HostVO convertHost, HostVO importHost) { + if (selectedStoragePool.getScope() == ScopeType.HOST && (ObjectUtils.anyNull(convertHost, importHost) || + ObjectUtils.allNotNull(convertHost, importHost) && convertHost.getId() != importHost.getId() || + !forceConvertToPool) ) { + logFailureAndThrowException("Please select the same host as convert and importing host and " + + "set forceconvertopool to true to use a local storage pool for conversion"); + } + if (!forceConvertToPool && selectedStoragePool.getPoolType() != Storage.StoragePoolType.NetworkFilesystem) { + logFailureAndThrowException(String.format("The storage pool %s is not supported for temporary conversion location," + + "only NFS storage pools are supported when forceconverttopool is set to false", selectedStoragePool.getName())); + } + } + + protected DataStoreTO selectInstanceConversionTemporaryLocation(Cluster destinationCluster, + HostVO convertHost, HostVO importHost, + Long convertStoragePoolId, boolean forceConvertToPool) { + if (convertStoragePoolId == null) { + String msg = String.format("No convert storage pool has been provided, " + + "selecting an NFS secondary storage pool from the destination cluster (%s) zone", destinationCluster.getName()); + logger.debug(msg); + return getImageStoreOnDestinationZoneForTemporaryConversion(destinationCluster, forceConvertToPool); + } + + StoragePoolVO selectedStoragePool = primaryDataStoreDao.findById(convertStoragePoolId); + checkBeforeSelectingTemporaryConversionStoragePool(selectedStoragePool, convertStoragePoolId, destinationCluster, convertHost); + checkDestinationOrTemporaryStoragePoolForConversion(selectedStoragePool, forceConvertToPool, convertHost, importHost); + + return dataStoreManager.getPrimaryDataStore(convertStoragePoolId).getTO(); + } + + protected Map createParamsForTemplateFromVmwareVmMigration(String vcenterHost, String datacenterName, + String username, String password, + String clusterName, String sourceHostName, + String sourceVMName) { + Map params = new HashMap<>(); + params.put(VmDetailConstants.VMWARE_VCENTER_HOST, vcenterHost); + params.put(VmDetailConstants.VMWARE_DATACENTER_NAME, datacenterName); + params.put(VmDetailConstants.VMWARE_VCENTER_USERNAME, username); + params.put(VmDetailConstants.VMWARE_VCENTER_PASSWORD, password); + params.put(VmDetailConstants.VMWARE_CLUSTER_NAME, clusterName); + params.put(VmDetailConstants.VMWARE_HOST_NAME, sourceHostName); + params.put(VmDetailConstants.VMWARE_VM_NAME, sourceVMName); + return params; + } + + @Override + public List> getCommands() { + final List> cmdList = new ArrayList>(); + cmdList.add(ListUnmanagedInstancesCmd.class); + cmdList.add(ImportUnmanagedInstanceCmd.class); + cmdList.add(UnmanageVMInstanceCmd.class); + cmdList.add(ListVmsForImportCmd.class); + cmdList.add(ImportVmCmd.class); + cmdList.add(ListImportVMTasksCmd.class); + return cmdList; + } + + /** + * Perform validations before attempting to unmanage a VM from CloudStack: + * - VM must not have any associated volume snapshot + * - VM must not have an attached ISO + * - VM must not belong to any CKS cluster + * @throws UnsupportedServiceException in case any of the validations above fail + */ + void performUnmanageVMInstancePrechecks(VMInstanceVO vmVO) { + if (hasVolumeSnapshotsPriorToUnmanageVM(vmVO)) { + throw new UnsupportedServiceException("Cannot unmanage VM with id = " + vmVO.getUuid() + + " as there are volume snapshots for its volume(s). Please remove snapshots before unmanaging."); + } + + if (hasISOAttached(vmVO)) { + throw new UnsupportedServiceException("Cannot unmanage VM with id = " + vmVO.getUuid() + + " as there is an ISO attached. Please detach ISO before unmanaging."); + } + + if (userVmManager.isVMPartOfAnyCKSCluster(vmVO)) { + throw new UnsupportedServiceException("Cannot unmanage VM with id = " + vmVO.getUuid() + + " as it belongs to a CKS cluster. Please remove the VM from the CKS cluster before unmanaging."); + } + } + + private boolean hasVolumeSnapshotsPriorToUnmanageVM(VMInstanceVO vmVO) { + List volumes = volumeDao.findByInstance(vmVO.getId()); + for (VolumeVO volume : volumes) { + List snaps = snapshotDao.listByVolumeId(volume.getId()); + if (CollectionUtils.isNotEmpty(snaps)) { + for (SnapshotVO snap : snaps) { + if (snap.getState() != Snapshot.State.Destroyed && snap.getRemoved() == null) { + return true; + } + } + } + } + return false; + } + + private boolean hasISOAttached(VMInstanceVO vmVO) { + UserVmVO userVM = userVmDao.findById(vmVO.getId()); + if (userVM == null) { + throw new InvalidParameterValueException("Could not find user VM with ID = " + vmVO.getUuid()); + } + return userVM.getIsoId() != null; + } + + /** + * Find a suitable host within the scope of the VM to unmanage to verify the VM exists + */ + private Long findSuitableHostId(VMInstanceVO vmVO) { + Long hostId = vmVO.getHostId(); + if (hostId == null) { + long zoneId = vmVO.getDataCenterId(); + List hosts = hostDao.listAllHostsUpByZoneAndHypervisor(zoneId, vmVO.getHypervisorType()); + for (HostVO host : hosts) { + if (host.isInMaintenanceStates() || host.getState() != Status.Up || host.getStatus() != Status.Up) { + continue; + } + hostId = host.getId(); + break; + } + } + + if (hostId == null) { + throw new CloudRuntimeException(String.format("Cannot find a host to verify if the VM [%s] exists. Thus we are unable to unmanage it.", vmVO.getUuid())); + } + return hostId; + } + + @Override + @ActionEvent(eventType = EventTypes.EVENT_VM_UNMANAGE, eventDescription = "unmanaging VM", async = true) + public Pair unmanageVMInstance(long vmId, Long paramHostId, boolean isForced) { + VMInstanceVO vmVO = vmDao.findById(vmId); + if (vmVO == null || vmVO.getRemoved() != null) { + throw new InvalidParameterValueException("Could not find VM to unmanage, it is either removed or not existing VM"); + } else if (vmVO.getState() != VirtualMachine.State.Running && vmVO.getState() != VirtualMachine.State.Stopped) { + throw new InvalidParameterValueException("VM with id = " + vmVO.getUuid() + " must be running or stopped to be unmanaged"); + } else if (!UnmanagedVMsManager.isSupported(vmVO.getHypervisorType())) { + throw new UnsupportedServiceException("Unmanage VM is currently not allowed for hypervisor " + + vmVO.getHypervisorType().toString()); + } else if (vmVO.getType() != VirtualMachine.Type.User) { + throw new UnsupportedServiceException("Unmanage VM is currently allowed for guest VMs only"); + } else if (paramHostId != null && + (vmVO.getHypervisorType() != Hypervisor.HypervisorType.KVM || vmVO.getState() != VirtualMachine.State.Stopped)) { + throw new UnsupportedServiceException("Param hostid is only supported for KVM hypervisor for stopped Instances."); + } else if (!isForced && vmVO.getHypervisorType() == Hypervisor.HypervisorType.KVM + && vmInstanceDetailsDao.findDetail(vmId, VmDetailConstants.CONFIG_DRIVE_LOCATION) != null) { + throw new UnsupportedServiceException("Config drive is attached to Instance, use forced param true from API to unmanage it."); + } + + if (vmVO.getType().equals(VirtualMachine.Type.User)) { + UserVmVO userVm = userVmDao.findById(vmId); + if (UserVmManager.SHAREDFSVM.equals(userVm.getUserVmType())) { + throw new InvalidParameterValueException("Operation not supported on Shared FileSystem Instance"); + } + } + + performUnmanageVMInstancePrechecks(vmVO); + + boolean isKvmVmStopped = VirtualMachine.State.Stopped.equals(vmVO.getState()) && vmVO.getHypervisorType() == Hypervisor.HypervisorType.KVM; + Long hostId = isKvmVmStopped ? vmVO.getLastHostId() : findSuitableHostId(vmVO); + String instanceName = vmVO.getInstanceName(); + + if (!isKvmVmStopped && !existsVMToUnmanage(instanceName, hostId)) { + throw new CloudRuntimeException(String.format("VM %s is not found in the hypervisor", vmVO)); + } + + return userVmManager.unmanageUserVM(vmId, paramHostId); + } + + /** + * Verify the VM to unmanage exists on the hypervisor + */ + private boolean existsVMToUnmanage(String instanceName, Long hostId) { + PrepareUnmanageVMInstanceCommand command = new PrepareUnmanageVMInstanceCommand(); + command.setInstanceName(instanceName); + Answer ans = agentManager.easySend(hostId, command); + if (!(ans instanceof PrepareUnmanageVMInstanceAnswer)) { + throw new CloudRuntimeException(String.format("Error communicating with host %s", hostDao.findById(hostId))); + } + PrepareUnmanageVMInstanceAnswer answer = (PrepareUnmanageVMInstanceAnswer) ans; + if (!answer.getResult()) { + logger.error("Error verifying VM {} exists on host {}: {}", instanceName::toString, () -> hostDao.findById(hostId), answer::getDetails); + } + return answer.getResult(); + } + + private UserVmResponse importKvmInstance(ImportVmCmd cmd) { + final Account caller = CallContext.current().getCallingAccount(); + if (caller.getType() != Account.Type.ADMIN) { + throw new PermissionDeniedException(String.format("Cannot perform this operation, Calling account is not root admin: %s", caller.getUuid())); + } + final Long zoneId = cmd.getZoneId(); + final DataCenterVO zone = dataCenterDao.findById(zoneId); + if (zone == null) { + throw new InvalidParameterValueException("Please specify a valid zone."); + } + final String hypervisorType = cmd.getHypervisor(); + if (!Hypervisor.HypervisorType.KVM.toString().equalsIgnoreCase(hypervisorType)) { + throw new InvalidParameterValueException(String.format("VM import is currently not supported for hypervisor: %s", hypervisorType)); + } + + final String instanceName = cmd.getName(); + if (StringUtils.isEmpty(instanceName)) { + throw new InvalidParameterValueException(String.format("Instance name cannot be empty")); + } + if (cmd.getDomainId() != null && StringUtils.isEmpty(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()); + if (CollectionUtils.isNotEmpty(userVOs)) { + userId = userVOs.get(0).getId(); + } + VMTemplateVO template = getTemplateForImportInstance(cmd.getTemplateId(), Hypervisor.HypervisorType.KVM); + 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); + String displayName = cmd.getDisplayName(); + if (StringUtils.isEmpty(displayName)) { + displayName = instanceName; + } + String hostName = cmd.getHostName(); + if (StringUtils.isEmpty(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 = mergeNicMacAddresses(cmd.getNicIpAddressList(), cmd.getNicMacAddressList()); + final Map dataDiskOfferingMap = cmd.getDataDiskToDiskOfferingList(); + final Map details = cmd.getDetails(); + + String remoteUrl = cmd.getHost(); + String source = cmd.getImportSource().toUpperCase(); + String diskPath = cmd.getDiskPath(); + ImportSource importSource = Enum.valueOf(ImportSource.class, source); + Long hostId = cmd.getHostId(); + Long poolId = cmd.getStoragePoolId(); + Long networkId = cmd.getNetworkId(); + + UnmanagedInstanceTO unmanagedInstanceTO = null; + if (ImportSource.EXTERNAL == importSource) { + if (StringUtils.isBlank(cmd.getUsername())) { + throw new InvalidParameterValueException("Username need to be provided."); + } + + HashMap instancesMap = getRemoteVmsOnKVMHost(zoneId, remoteUrl, cmd.getUsername(), cmd.getPassword()); + unmanagedInstanceTO = instancesMap.get(cmd.getName()); + if (unmanagedInstanceTO == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM with name: %s not found on remote host %s", instanceName, remoteUrl)); + } + } + + if (ImportSource.SHARED == importSource || ImportSource.LOCAL == importSource) { + if (diskPath == null) { + throw new InvalidParameterValueException("Disk Path is required for Import from shared/local storage"); + } + + if (networkId == null) { + throw new InvalidParameterValueException("Network is required for Import from shared/local storage"); + } + + if (poolId == null) { + throw new InvalidParameterValueException("Storage Pool is required for Import from shared/local storage"); + } + + StoragePool storagePool = primaryDataStoreDao.findById(poolId); + if (storagePool == null) { + throw new InvalidParameterValueException("Storage Pool not found"); + } + + if (volumeDao.findByPoolIdAndPath(poolId, diskPath) != null) { + throw new InvalidParameterValueException("Disk image is already in use"); + } + + DiskOffering diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); + + if (diskOffering != null && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) { + throw new InvalidParameterValueException(String.format("Service offering: %s storage tags are not compatible with selected storage pool: %s", serviceOffering.getUuid(), storagePool.getUuid())); + } + } + + if (ImportSource.LOCAL == importSource) { + if (hostId == null) { + throw new InvalidParameterValueException("Host is required for Import from local storage"); + } + + if (hostDao.findById(hostId) == null) { + throw new InvalidParameterValueException("Host not found"); + } + + if(storagePoolHostDao.findByPoolHost(poolId, hostId) == null) { + throw new InvalidParameterValueException("Specified Local Storage Pool not found on Host"); + } + } + + UserVm userVm = null; + + try { + + if (ImportSource.EXTERNAL == importSource) { + String username = cmd.getUsername(); + String password = cmd.getPassword(); + String tmpPath = cmd.getTmpPath(); + userVm = importExternalKvmVirtualMachine(unmanagedInstanceTO, instanceName, zone, + template, displayName, hostName, caller, owner, userId, + serviceOffering, dataDiskOfferingMap, + nicNetworkMap, nicIpAddressMap, remoteUrl, username, password, tmpPath, details); + } else if (ImportSource.SHARED == importSource || ImportSource.LOCAL == importSource) { + try { + userVm = importKvmVirtualMachineFromDisk(importSource, instanceName, zone, + template, displayName, hostName, caller, owner, userId, + serviceOffering, dataDiskOfferingMap, networkId, hostId, poolId, diskPath, + details); + } catch (InsufficientCapacityException e) { + throw new RuntimeException(e); + } catch (ResourceAllocationException e) { + throw new RuntimeException(e); + } + } + + } 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(), StringUtils.defaultString(e.getMessage()))); + } + + if (userVm == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import Vm with name: %s ", instanceName)); + } + + CallContext.current().setEventResourceId(userVm.getId()); + CallContext.current().setEventResourceType(ApiCommandResourceType.VirtualMachine); + return responseGenerator.createUserVmResponse(ResponseObject.ResponseView.Full, "virtualmachine", userVm).get(0); + } + + private UserVm importExternalKvmVirtualMachine(final UnmanagedInstanceTO unmanagedInstance, final String instanceName, final DataCenter zone, + final VirtualMachineTemplate template, final String displayName, final String hostName, final Account caller, final Account owner, final Long userId, + final ServiceOfferingVO serviceOffering, final Map dataDiskOfferingMap, + final Map nicNetworkMap, final Map callerNicIpAddressMap, + final String remoteUrl, String username, String password, String tmpPath, final Map details) throws ResourceAllocationException { + UserVm userVm = null; + + Map allDetails = new HashMap<>(details); + // 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)); + } + + DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); + Pair> rootAndDataDisksPair = getRootAndDataDisks(unmanagedInstanceDisks, dataDiskOfferingMap); + final UnmanagedInstanceTO.Disk rootDisk = rootAndDataDisksPair.first(); + final List dataDisks = rootAndDataDisksPair.second(); + if (rootDisk == null || StringUtils.isEmpty(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 reservations = new ArrayList<>(); + try { + checkVmResourceLimitsForExternalKvmVmImport(owner, serviceOffering, (VMTemplateVO) template, details, reservations); + checkVolumeResourceLimitsForExternalKvmVmImport(owner, rootDisk, dataDisks, diskOffering, dataDiskOfferingMap, reservations); + + // Check NICs and supplied networks + Map nicIpAddressMap = getNicIpAddresses(unmanagedInstance.getNics(), callerNicIpAddressMap); + Map allNicNetworkMap = getUnmanagedNicNetworkMap(unmanagedInstance.getName(), unmanagedInstance.getNics(), nicNetworkMap, nicIpAddressMap, zone, hostName, owner, Hypervisor.HypervisorType.KVM); + if (!CollectionUtils.isEmpty(unmanagedInstance.getNics())) { + allDetails.put(VmDetailConstants.NIC_ADAPTER, unmanagedInstance.getNics().get(0).getAdapterType()); + } + VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff; + + try { + userVm = userVmManager.importVM(zone, null, template, null, displayName, owner, + null, caller, true, null, owner.getAccountId(), userId, + serviceOffering, null, null, hostName, + Hypervisor.HypervisorType.KVM, allDetails, powerState, null); + } 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)); + } + String rootVolumeName = String.format("ROOT-%s", userVm.getId()); + DiskProfile diskProfile = volumeManager.allocateRawVolume(Volume.Type.ROOT, rootVolumeName, diskOffering, null, null, null, userVm, template, owner, null, false); + + DiskProfile[] dataDiskProfiles = new DiskProfile[dataDisks.size()]; + int diskSeq = 0; + for (UnmanagedInstanceTO.Disk disk : dataDisks) { + DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId())); + DiskProfile dataDiskProfile = volumeManager.allocateRawVolume(Volume.Type.DATADISK, String.format("DATA-%d-%s", userVm.getId(), disk.getDiskId()), offering, null, null, null, userVm, template, owner, null, false); + dataDiskProfiles[diskSeq++] = dataDiskProfile; + } + + final VirtualMachineProfile profile = new VirtualMachineProfileImpl(userVm, template, serviceOffering, owner, null); + ServiceOfferingVO dummyOffering = serviceOfferingDao.findById(userVm.getId(), serviceOffering.getId()); + profile.setServiceOffering(dummyOffering); + DeploymentPlanner.ExcludeList excludeList = new DeploymentPlanner.ExcludeList(); + final DataCenterDeployment plan = new DataCenterDeployment(zone.getId(), null, null, null, null, null); + DeployDestination dest = null; + try { + dest = deploymentPlanningManager.planDeployment(profile, plan, excludeList, null); + } catch (Exception e) { + logger.warn("Import failed for Vm: {} while finding deployment destination", userVm, e); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s while finding deployment destination", userVm.getInstanceName())); + } + if(dest == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s. Suitable deployment destination not found", userVm.getInstanceName())); + } + + List> diskProfileStoragePoolList = new ArrayList<>(); + try { + diskProfileStoragePoolList.add(importExternalDisk(rootDisk, userVm, dest, diskOffering, Volume.Type.ROOT, + template, null, remoteUrl, username, password, tmpPath, diskProfile)); + + long deviceId = 1L; + diskSeq = 0; + for (UnmanagedInstanceTO.Disk disk : dataDisks) { + DiskProfile dataDiskProfile = dataDiskProfiles[diskSeq++]; + DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId())); + + diskProfileStoragePoolList.add(importExternalDisk(disk, userVm, dest, offering, Volume.Type.DATADISK, + template, deviceId, remoteUrl, username, password, tmpPath, dataDiskProfile)); + deviceId++; + } + } catch (Exception e) { + logger.error(String.format("Failed to import volumes while importing vm: %s", instanceName), e); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", instanceName, StringUtils.defaultString(e.getMessage()))); + } + try { + int nicIndex = 0; + 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, nicIndex, nicIndex==0, true); + nicIndex++; + } + } catch (Exception e) { + logger.error(String.format("Failed to import NICs while importing vm: %s", instanceName), e); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import NICs while importing vm: %s. %s", instanceName, StringUtils.defaultString(e.getMessage()))); + } + publishVMUsageUpdateResourceCount(userVm, dummyOffering, template); + return userVm; + + } finally { + ReservationHelper.closeAll(reservations); + } + } + + protected void checkVolumeResourceLimitsForExternalKvmVmImport(Account owner, UnmanagedInstanceTO.Disk rootDisk, + List dataDisks, DiskOfferingVO rootDiskOffering, + Map dataDiskOfferingMap, List reservations) throws ResourceAllocationException { + if (rootDisk.getCapacity() == null || rootDisk.getCapacity() == 0) { + throw new InvalidParameterValueException(String.format("Root disk ID: %s size is invalid", rootDisk.getDiskId())); + } + resourceLimitService.checkVolumeResourceLimit(owner, true, rootDisk.getCapacity(), rootDiskOffering, reservations); + + if (CollectionUtils.isEmpty(dataDisks)) { + return; + } + for (UnmanagedInstanceTO.Disk disk : dataDisks) { + if (disk.getCapacity() == null || disk.getCapacity() == 0) { + throw new InvalidParameterValueException(String.format("Data disk ID: %s size is invalid", disk.getDiskId())); + } + DiskOffering offering = diskOfferingDao.findById(dataDiskOfferingMap.get(disk.getDiskId())); + resourceLimitService.checkVolumeResourceLimit(owner, true, disk.getCapacity(), offering, reservations); + } + } + + private UserVm importKvmVirtualMachineFromDisk(final ImportSource importSource, final String instanceName, final DataCenter zone, + final VirtualMachineTemplate template, final String displayName, final String hostName, final Account caller, final Account owner, final Long userId, + final ServiceOfferingVO serviceOffering, final Map dataDiskOfferingMap, final Long networkId, + final Long hostId, final Long poolId, final String diskPath, final Map details) throws InsufficientCapacityException, ResourceAllocationException { + + UserVm userVm = null; + + Map allDetails = new HashMap<>(details); + + VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff; + + NetworkVO network = networkDao.findById(networkId); + if (network == null) { + throw new InvalidParameterValueException("Unable to find network by id " + networkId); + } + + networkModel.checkNetworkPermissions(owner, network); + + // don't allow to use system networks + NetworkOffering networkOffering = entityMgr.findById(NetworkOffering.class, network.getNetworkOfferingId()); + if (networkOffering.isSystemOnly()) { + throw new InvalidParameterValueException("Network id=" + networkId + " is system only and can't be used for vm deployment"); + } + + LinkedHashMap> networkNicMap = new LinkedHashMap<>(); + + if ((network.getDataCenterId() != zone.getId())) { + if (!network.isStrechedL2Network()) { + throw new InvalidParameterValueException("Network id=" + network.getId() + + " doesn't belong to zone " + zone.getId()); + } + } + + String macAddress = networkModel.getNextAvailableMacAddressInNetwork(networkId); + + String ipAddress = network.getGuestType() != Network.GuestType.L2 ? "auto" : null; + + Network.IpAddresses requestedIpPair = new Network.IpAddresses(ipAddress, null, macAddress); + + NicProfile nicProfile = new NicProfile(requestedIpPair.getIp4Address(), requestedIpPair.getIp6Address(), requestedIpPair.getMacAddress()); + nicProfile.setOrderIndex(0); + + boolean securityGroupEnabled = false; + if (networkModel.isSecurityGroupSupportedInNetwork(network)) { + securityGroupEnabled = true; + } + List profiles = networkNicMap.get(network.getUuid()); + if (CollectionUtils.isEmpty(profiles)) { + profiles = new ArrayList<>(); + } + profiles.add(nicProfile); + networkNicMap.put(network.getUuid(), profiles); + + List reservations = new ArrayList<>(); + try { + checkVmResourceLimitsForExternalKvmVmImport(owner, serviceOffering, (VMTemplateVO) template, details, reservations); + userVm = userVmManager.importVM(zone, null, template, null, displayName, owner, + null, caller, true, null, owner.getAccountId(), userId, + serviceOffering, null, null, hostName, + Hypervisor.HypervisorType.KVM, allDetails, powerState, networkNicMap); + + if (userVm == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import vm name: %s", instanceName)); + } + + DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); + List resourceLimitStorageTags = resourceLimitService.getResourceLimitStorageTagsForResourceCountOperation(true, diskOffering); + CheckedReservation volumeReservation = new CheckedReservation(owner, Resource.ResourceType.volume, resourceLimitStorageTags, + CollectionUtils.isNotEmpty(resourceLimitStorageTags) ? 1L : 0L, reservationDao, resourceLimitService); + reservations.add(volumeReservation); + + String rootVolumeName = String.format("ROOT-%s", userVm.getId()); + DiskProfile diskProfile = volumeManager.allocateRawVolume(Volume.Type.ROOT, rootVolumeName, diskOffering, null, null, null, userVm, template, owner, null, false); + + final VirtualMachineProfile profile = new VirtualMachineProfileImpl(userVm, template, serviceOffering, owner, null); + ServiceOfferingVO dummyOffering = serviceOfferingDao.findById(userVm.getId(), serviceOffering.getId()); + profile.setServiceOffering(dummyOffering); + DeploymentPlanner.ExcludeList excludeList = new DeploymentPlanner.ExcludeList(); + final DataCenterDeployment plan = new DataCenterDeployment(zone.getId(), null, null, hostId, poolId, null); + DeployDestination dest = null; + try { + dest = deploymentPlanningManager.planDeployment(profile, plan, excludeList, null); + } catch (Exception e) { + logger.warn("Import failed for Vm: {} while finding deployment destination", userVm, e); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s while finding deployment destination", userVm.getInstanceName())); + } + if(dest == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Import failed for Vm: %s. Suitable deployment destination not found", userVm.getInstanceName())); + } + + Map storage = dest.getStorageForDisks(); + Volume volume = volumeDao.findById(diskProfile.getVolumeId()); + StoragePool storagePool = storage.get(volume); + CheckVolumeCommand checkVolumeCommand = new CheckVolumeCommand(); + checkVolumeCommand.setSrcFile(diskPath); + StorageFilerTO storageTO = new StorageFilerTO(storagePool); + checkVolumeCommand.setStorageFilerTO(storageTO); + Answer answer = agentManager.easySend(dest.getHost().getId(), checkVolumeCommand); + if (!(answer instanceof CheckVolumeAnswer)) { + cleanupFailedImportVM(userVm); + throw new CloudRuntimeException("Disk not found or is invalid"); + } + CheckVolumeAnswer checkVolumeAnswer = (CheckVolumeAnswer) answer; + try { + checkVolume(checkVolumeAnswer.getVolumeDetails()); + } catch (CloudRuntimeException e) { + cleanupFailedImportVM(userVm); + throw e; + } + if (!checkVolumeAnswer.getResult()) { + cleanupFailedImportVM(userVm); + throw new CloudRuntimeException("Disk not found or is invalid"); + } + diskProfile.setSize(checkVolumeAnswer.getSize()); + + CheckedReservation primaryStorageReservation = new CheckedReservation(owner, Resource.ResourceType.primary_storage, resourceLimitStorageTags, + CollectionUtils.isNotEmpty(resourceLimitStorageTags) ? diskProfile.getSize() : 0L, reservationDao, resourceLimitService); + reservations.add(primaryStorageReservation); + + List> diskProfileStoragePoolList = new ArrayList<>(); + try { + long deviceId = 1L; + if(ImportSource.SHARED == importSource) { + diskProfileStoragePoolList.add(importKVMSharedDisk(userVm, diskOffering, Volume.Type.ROOT, + template, deviceId, poolId, diskPath, diskProfile)); + } else if(ImportSource.LOCAL == importSource) { + diskProfileStoragePoolList.add(importKVMLocalDisk(userVm, diskOffering, Volume.Type.ROOT, + template, deviceId, hostId, diskPath, diskProfile)); + } + } catch (Exception e) { + logger.error(String.format("Failed to import volumes while importing vm: %s", instanceName), e); + cleanupFailedImportVM(userVm); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", instanceName, StringUtils.defaultString(e.getMessage()))); + } + networkOrchestrationService.importNic(macAddress, 0, network, true, userVm, requestedIpPair, zone, true); + publishVMUsageUpdateResourceCount(userVm, dummyOffering, template); + return userVm; + + } catch (InsufficientCapacityException ice) { // This will be thrown by com.cloud.vm.UserVmService.importVM + logger.error(String.format("Failed to import vm name: %s", instanceName), ice); + throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ice.getMessage()); + } catch (ResourceAllocationException e) { + cleanupFailedImportVM(userVm); + throw e; + } finally { + ReservationHelper.closeAll(reservations); + } + } + + protected void checkVmResourceLimitsForExternalKvmVmImport(Account owner, ServiceOfferingVO serviceOffering, VMTemplateVO template, Map details, List reservations) throws ResourceAllocationException { + // When importing an external VM, the amount of CPUs and memory is always obtained from the compute offering, + // unlike the unmanaged instance import that obtains it from the hypervisor unless the VM is powered off and the offering is fixed + Integer cpu = serviceOffering.getCpu(); + Integer memory = serviceOffering.getRamSize(); + + if (serviceOffering.isDynamic()) { + cpu = getDetailAsInteger(VmDetailConstants.CPU_NUMBER, details); + memory = getDetailAsInteger(VmDetailConstants.MEMORY, details); + } + + List resourceLimitHostTags = resourceLimitService.getResourceLimitHostTags(serviceOffering, template); + + CheckedReservation vmReservation = new CheckedReservation(owner, Resource.ResourceType.user_vm, resourceLimitHostTags, 1L, reservationDao, resourceLimitService); + reservations.add(vmReservation); + + CheckedReservation cpuReservation = new CheckedReservation(owner, Resource.ResourceType.cpu, resourceLimitHostTags, cpu.longValue(), reservationDao, resourceLimitService); + reservations.add(cpuReservation); + + CheckedReservation memReservation = new CheckedReservation(owner, Resource.ResourceType.memory, resourceLimitHostTags, memory.longValue(), reservationDao, resourceLimitService); + reservations.add(memReservation); + } + + protected Integer getDetailAsInteger(String key, Map details) { + String detail = details.get(key); + if (detail == null) { + throw new InvalidParameterValueException(String.format("Detail '%s' must be provided.", key)); + } + try { + return Integer.valueOf(detail); + } catch (NumberFormatException e) { + throw new InvalidParameterValueException(String.format("Please provide a valid integer value for detail '%s'.", key)); + } + } + + private void checkVolume(Map volumeDetails) { + if (MapUtils.isEmpty(volumeDetails)) { + return; + } + + if (volumeDetails.containsKey(VolumeOnStorageTO.Detail.IS_LOCKED)) { + String isLocked = volumeDetails.get(VolumeOnStorageTO.Detail.IS_LOCKED); + if (Boolean.parseBoolean(isLocked)) { + logFailureAndThrowException("Locked volume cannot be imported or unmanaged."); + } + } + if (volumeDetails.containsKey(VolumeOnStorageTO.Detail.IS_ENCRYPTED)) { + String isEncrypted = volumeDetails.get(VolumeOnStorageTO.Detail.IS_ENCRYPTED); + if (Boolean.parseBoolean(isEncrypted)) { + logFailureAndThrowException("Encrypted volume cannot be imported or unmanaged."); + } + } + if (volumeDetails.containsKey(VolumeOnStorageTO.Detail.BACKING_FILE)) { + String backingFile = volumeDetails.get(VolumeOnStorageTO.Detail.BACKING_FILE); + if (StringUtils.isNotBlank(backingFile) && !AllowImportVolumeWithBackingFile.value()) { + logFailureAndThrowException("Volume with backing file cannot be imported or unmanaged."); + } + } + } + + private NetworkVO getDefaultNetwork(DataCenter zone, Account owner, boolean selectAny) throws InsufficientCapacityException, ResourceAllocationException { + NetworkVO defaultNetwork = null; + + // if no network is passed in + // Check if default virtual network offering has + // Availability=Required. If it's true, search for corresponding + // network + // * if network is found, use it. If more than 1 virtual network is + // found, throw an error + // * if network is not found, create a new one and use it + + List requiredOfferings = networkOfferingDao.listByAvailability(NetworkOffering.Availability.Required, false); + if (requiredOfferings.size() < 1) { + throw new InvalidParameterValueException("Unable to find network offering with availability=" + NetworkOffering.Availability.Required + + " to automatically create the network as a part of vm creation"); + } + + if (requiredOfferings.get(0).getState() == NetworkOffering.State.Enabled) { + // get Virtual networks + List virtualNetworks = networkModel.listNetworksForAccount(owner.getId(), zone.getId(), Network.GuestType.Isolated); + if (virtualNetworks == null) { + throw new InvalidParameterValueException("No (virtual) networks are found for account " + owner); + } + if (virtualNetworks.isEmpty()) { + defaultNetwork = createDefaultNetworkForAccount(zone, owner, requiredOfferings); + } else if (virtualNetworks.size() > 1 && !selectAny) { + throw new InvalidParameterValueException("More than 1 default Isolated networks are found for account " + owner + "; please specify networkIds"); + } else { + defaultNetwork = networkDao.findById(virtualNetworks.get(0).getId()); + } + } else { + throw new InvalidParameterValueException("Required network offering id=" + requiredOfferings.get(0).getId() + " is not in " + NetworkOffering.State.Enabled); + } + + return defaultNetwork; + } + + private NetworkVO createDefaultNetworkForAccount(DataCenter zone, Account owner, List requiredOfferings) + throws InsufficientCapacityException, ResourceAllocationException { + NetworkVO defaultNetwork = null; + long physicalNetworkId = networkModel.findPhysicalNetworkId(zone.getId(), requiredOfferings.get(0).getTags(), requiredOfferings.get(0).getTrafficType()); + // Validate physical network + PhysicalNetwork physicalNetwork = physicalNetworkDao.findById(physicalNetworkId); + if (physicalNetwork == null) { + throw new InvalidParameterValueException("Unable to find physical network with id: " + physicalNetworkId + " and tag: " + + requiredOfferings.get(0).getTags()); + } + logger.debug("Creating network for account {} from the network offering {} as a part of deployVM process", owner, requiredOfferings.get(0)); + Network newNetwork = networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName() + "-network", + null, null, null, false, null, owner, null, physicalNetwork, zone.getId(), ControlledEntity.ACLType.Account, null, null, null, null, true, null, null, + null, null, null, null, null, null, null, null, null); + if (newNetwork != null) { + defaultNetwork = networkDao.findById(newNetwork.getId()); + } + return defaultNetwork; + } + + public ListResponse listVmsForImport(ListVmsForImportCmd cmd) { + final Account caller = CallContext.current().getCallingAccount(); + if (caller.getType() != Account.Type.ADMIN) { + throw new PermissionDeniedException(String.format("Cannot perform this operation, Calling account is not root admin: %s", caller.getUuid())); + } + final Long zoneId = cmd.getZoneId(); + final DataCenterVO zone = dataCenterDao.findById(zoneId); + if (zone == null) { + throw new InvalidParameterValueException("Please specify a valid zone."); + } + final String hypervisorType = cmd.getHypervisor(); + if (!Hypervisor.HypervisorType.KVM.toString().equalsIgnoreCase(hypervisorType)) { + throw new InvalidParameterValueException(String.format("VM Import is currently not supported for hypervisor: %s", hypervisorType)); + } + + String keyword = cmd.getKeyword(); + if (StringUtils.isNotEmpty(keyword)) { + keyword = keyword.toLowerCase(); + } + + List responses = new ArrayList<>(); + HashMap vmMap = getRemoteVmsOnKVMHost(zoneId, cmd.getHost(), cmd.getUsername(), cmd.getPassword()); + for (String key : vmMap.keySet()) { + UnmanagedInstanceTO instance = vmMap.get(key); + if (StringUtils.isNotEmpty(keyword) && + !instance.getName().toLowerCase().contains(keyword)) { + continue; + } + responses.add(responseGenerator.createUnmanagedInstanceResp diff --git a/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java index 4cb665449346..ac4c9c43a38a 100644 --- a/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java @@ -1,1749 +1,1749 @@ -// 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.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyMap; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.net.URI; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.apache.cloudstack.api.ApiConstants; -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.ImportVmCmd; -import org.apache.cloudstack.api.command.admin.vm.ListUnmanagedInstancesCmd; -import org.apache.cloudstack.api.command.admin.vm.ListVmsForImportCmd; -import org.apache.cloudstack.api.response.ListResponse; -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.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; -import org.apache.cloudstack.framework.config.ConfigKey; -import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.cloudstack.resourcelimit.Reserver; -import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; -import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.jetbrains.annotations.NotNull; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.BDDMockito; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockedConstruction; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; -import org.mockito.junit.MockitoJUnitRunner; - -import com.cloud.agent.AgentManager; -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.CheckConvertInstanceAnswer; -import com.cloud.agent.api.CheckConvertInstanceCommand; -import com.cloud.agent.api.CheckVolumeAnswer; -import com.cloud.agent.api.CheckVolumeCommand; -import com.cloud.agent.api.ConvertInstanceAnswer; -import com.cloud.agent.api.ConvertInstanceCommand; -import com.cloud.agent.api.CopyRemoteVolumeAnswer; -import com.cloud.agent.api.CopyRemoteVolumeCommand; -import com.cloud.agent.api.GetRemoteVmsAnswer; -import com.cloud.agent.api.GetRemoteVmsCommand; -import com.cloud.agent.api.GetUnmanagedInstancesAnswer; -import com.cloud.agent.api.GetUnmanagedInstancesCommand; -import com.cloud.agent.api.ImportConvertedInstanceAnswer; -import com.cloud.agent.api.ImportConvertedInstanceCommand; -import com.cloud.agent.api.to.DataStoreTO; -import com.cloud.dc.ClusterVO; -import com.cloud.dc.DataCenter; -import com.cloud.dc.DataCenterVO; -import com.cloud.dc.VmwareDatacenterVO; -import com.cloud.dc.dao.ClusterDao; -import com.cloud.dc.dao.DataCenterDao; -import com.cloud.dc.dao.VmwareDatacenterDao; -import com.cloud.deploy.DeployDestination; -import com.cloud.deploy.DeploymentPlanningManager; -import com.cloud.event.ActionEventUtils; -import com.cloud.event.UsageEventUtils; -import com.cloud.exception.AgentUnavailableException; -import com.cloud.exception.InsufficientServerCapacityException; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.OperationTimedoutException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.PermissionDeniedException; -import com.cloud.exception.UnsupportedServiceException; -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.hypervisor.HypervisorGuru; -import com.cloud.hypervisor.HypervisorGuruManager; -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; -import com.cloud.offering.NetworkOffering; -import com.cloud.offering.ServiceOffering; -import com.cloud.org.Grouping; -import com.cloud.resource.ResourceManager; -import com.cloud.resource.ResourceState; -import com.cloud.resourcelimit.CheckedReservation; -import com.cloud.service.ServiceOfferingVO; -import com.cloud.service.dao.ServiceOfferingDao; -import com.cloud.storage.DataStoreRole; -import com.cloud.storage.DiskOfferingVO; -import com.cloud.storage.ScopeType; -import com.cloud.storage.Snapshot; -import com.cloud.storage.SnapshotVO; -import com.cloud.storage.Storage; -import com.cloud.storage.StoragePool; -import com.cloud.storage.StoragePoolHostVO; -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.SnapshotDao; -import com.cloud.storage.dao.StoragePoolHostDao; -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.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.utils.db.EntityManager; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.vm.DiskProfile; -import com.cloud.vm.ImportVMTaskVO; -import com.cloud.vm.NicProfile; -import com.cloud.vm.UserVmManager; -import com.cloud.vm.UserVmVO; -import com.cloud.vm.VmDetailConstants; -import com.cloud.vm.VMInstanceDetailVO; -import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.VirtualMachine; -import com.cloud.vm.dao.NicDao; -import com.cloud.vm.dao.UserVmDao; -import com.cloud.vm.dao.VMInstanceDao; -import com.cloud.vm.dao.VMInstanceDetailsDao; - -@RunWith(MockitoJUnitRunner.class) -public class UnmanagedVMsManagerImplTest { - - @Spy - @InjectMocks - private UnmanagedVMsManagerImpl unmanagedVMsManager; - - @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 VolumeDao volumeDao; - @Mock - private ResourceLimitService resourceLimitService; - @Mock - private PrimaryDataStoreDao primaryDataStoreDao; - @Mock - private VolumeApiService volumeApiService; - @Mock - private NetworkModel networkModel; - @Mock - private ConfigurationDao configurationDao; - @Mock - private UserVmDao userVmDao; - @Mock - private NicDao nicDao; - @Mock - private HostDao hostDao; - @Mock - private VmwareDatacenterDao vmwareDatacenterDao; - @Mock - private HypervisorGuruManager hypervisorGuruManager; - @Mock - private ImageStoreDao imageStoreDao; - @Mock - private DataStoreManager dataStoreManager; - @Mock - private StoragePoolHostDao storagePoolHostDao; - @Mock - private ImportVmTasksManager importVmTasksManager; - @Mock - private SnapshotDao snapshotDao; - - @Mock - private VMInstanceVO virtualMachine; - @Mock - EntityManager entityMgr; - @Mock - DeploymentPlanningManager deploymentPlanningManager; - @Mock - ImportVMTaskVO importVMTaskVO; - @Mock - private VMInstanceDetailsDao vmInstanceDetailsDao; - @Mock - private ConfigKey configKeyMockParamsAllowed; - @Mock - private ConfigKey configKeyMockParamsAllowedList; - @Mock - private Account accountMock; - @Mock - private ServiceOfferingVO serviceOfferingMock; - @Mock - private VMTemplateVO templateMock; - @Mock - private UnmanagedInstanceTO unmanagedInstanceMock; - - private static final long virtualMachineId = 1L; - - private AutoCloseable closeable; - - private MockedStatic actionEventUtilsMocked; - - private UnmanagedInstanceTO instance; - - @Before - public void setUp() throws Exception { - closeable = MockitoAnnotations.openMocks(this); - actionEventUtilsMocked = Mockito.mockStatic(ActionEventUtils.class); - BDDMockito.given(ActionEventUtils.onStartedActionEvent(anyLong(), anyLong(), anyString(), anyString(), anyLong(), anyString(), anyBoolean(), anyLong())) - .willReturn(1L); - BDDMockito.given(ActionEventUtils.onCompletedActionEvent(anyLong(), anyLong(), anyString(), anyString(), anyString(), anyLong(), anyString(), anyLong())) - .willReturn(1L); - - AccountVO account = new AccountVO("admin", 1L, "", 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); - - instance = new UnmanagedInstanceTO(); - instance.setName("TestInstance"); - instance.setCpuCores(2); - instance.setCpuCoresPerSocket(1); - instance.setCpuSpeed(1000); - instance.setMemory(1024); - instance.setOperatingSystem("CentOS 7"); - List instanceDisks = getDisks(); - instance.setDisks(instanceDisks); - 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(UnmanagedInstanceTO.PowerState.PowerOn); - - ClusterVO clusterVO = new ClusterVO(1L, 1L, "Cluster"); - clusterVO.setHypervisorType(Hypervisor.HypervisorType.VMware.toString()); - when(clusterDao.findById(anyLong())).thenReturn(clusterVO); - when(configurationDao.getValue(Mockito.anyString())).thenReturn(null); - List hosts = new ArrayList<>(); - HostVO hostVO = Mockito.mock(HostVO.class); - when(hostVO.isInMaintenanceStates()).thenReturn(false); - hosts.add(hostVO); - when(resourceManager.listHostsInClusterByStatus(anyLong(), any(Status.class))).thenReturn(hosts); - when(resourceManager.listAllUpAndEnabledHostsInOneZoneByHypervisor(any(Hypervisor.HypervisorType.class), anyLong())).thenReturn(hosts); - List templates = new ArrayList<>(); - when(templatePoolDao.listAll()).thenReturn(templates); - List volumes = new ArrayList<>(); - when(volumeDao.findIncludingRemovedByZone(anyLong())).thenReturn(volumes); - GetUnmanagedInstancesCommand cmd = Mockito.mock(GetUnmanagedInstancesCommand.class); - HashMap map = new HashMap<>(); - map.put(instance.getName(), instance); - Answer answer = new GetUnmanagedInstancesAnswer(cmd, "", map); - when(agentManager.easySend(anyLong(), any(GetUnmanagedInstancesCommand.class))).thenReturn(answer); - GetRemoteVmsCommand remoteVmListcmd = Mockito.mock(GetRemoteVmsCommand.class); - Answer remoteVmListAnswer = new GetRemoteVmsAnswer(remoteVmListcmd, "", map); - when(agentManager.easySend(anyLong(), any(GetRemoteVmsCommand.class))).thenReturn(remoteVmListAnswer); - DataCenterVO zone = Mockito.mock(DataCenterVO.class); - when(zone.getId()).thenReturn(1L); - when(dataCenterDao.findById(anyLong())).thenReturn(zone); - when(accountService.getActiveAccountById(anyLong())).thenReturn(Mockito.mock(Account.class)); - List users = new ArrayList<>(); - users.add(Mockito.mock(UserVO.class)); - when(userDao.listByAccount(anyLong())).thenReturn(users); - VMTemplateVO template = Mockito.mock(VMTemplateVO.class); - when(template.getName()).thenReturn("Template"); - when(templateDao.findById(anyLong())).thenReturn(template); - ServiceOfferingVO serviceOffering = Mockito.mock(ServiceOfferingVO.class); - when(serviceOffering.getId()).thenReturn(1L); - 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(anyLong())).thenReturn(serviceOffering); - when(serviceOfferingDao.findById(anyLong(), anyLong())).thenReturn(Mockito.mock(ServiceOfferingVO.class)); - DiskOfferingVO diskOfferingVO = Mockito.mock(DiskOfferingVO.class); - when(diskOfferingDao.findById(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 - userVm.setInstanceName(instance.getName()); - userVm.setHostName(instance.getName()); - StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); - when(poolVO.getDataCenterId()).thenReturn(1L); - when(poolVO.getClusterId()).thenReturn(clusterVO.getId()); - List pools = new ArrayList<>(); - pools.add(poolVO); - when(primaryDataStoreDao.listPoolByHostPath(Mockito.anyString(), Mockito.anyString())).thenReturn(pools); - when(userVmManager.importVM(nullable(DataCenter.class), nullable(Host.class), nullable(VirtualMachineTemplate.class), nullable(String.class), nullable(String.class), - nullable(Account.class), nullable(String.class), nullable(Account.class), nullable(Boolean.class), nullable(String.class), - nullable(Long.class), nullable(Long.class), nullable(ServiceOffering.class), nullable(String.class), nullable(Long.class), - nullable(String.class), nullable(Hypervisor.HypervisorType.class), nullable(Map.class), nullable(VirtualMachine.PowerState.class), nullable(LinkedHashMap.class))).thenReturn(userVm); - 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(anyLong())).thenReturn(networkVO); - List networks = new ArrayList<>(); - networks.add(networkVO); - when(networkDao.listByZone(anyLong())).thenReturn(networks); - doNothing().when(networkModel).checkNetworkPermissions(any(Account.class), any(Network.class)); - NicProfile profile = Mockito.mock(NicProfile.class); - Integer deviceId = 100; - Pair pair = new Pair<>(profile, deviceId); - when(networkOrchestrationService.importNic(nullable(String.class), nullable(Integer.class), nullable(Network.class), nullable(Boolean.class), nullable(VirtualMachine.class), nullable(Network.IpAddresses.class), nullable(DataCenter.class), Mockito.anyBoolean())).thenReturn(pair); - when(volumeDao.findByInstance(Mockito.anyLong())).thenReturn(volumes); - List userVmResponses = new ArrayList<>(); - UserVmResponse userVmResponse = new UserVmResponse(); - userVmResponse.setInstanceName(instance.getName()); - userVmResponses.add(userVmResponse); - when(responseGenerator.createUserVmResponse(any(ResponseObject.ResponseView.class), Mockito.anyString(), any(UserVm.class))).thenReturn(userVmResponses); - - when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Running); - - when(unmanagedInstanceMock.getCpuCores()).thenReturn(8); - when(unmanagedInstanceMock.getMemory()).thenReturn(4096); - when(serviceOfferingMock.getCpu()).thenReturn(4); - when(serviceOfferingMock.getRamSize()).thenReturn(2048); - } - - @NotNull - private static List getDisks() { - List instanceDisks = new ArrayList<>(); - UnmanagedInstanceTO.Disk instanceDisk = new UnmanagedInstanceTO.Disk(); - instanceDisk.setDiskId("1000-1"); - instanceDisk.setPosition(0); - instanceDisk.setLabel("DiskLabel"); - instanceDisk.setController("scsi"); - instanceDisk.setImagePath("[b6ccf44a1fa13e29b3667b4954fa10ee] TestInstance/ROOT-1.vmdk"); - instanceDisk.setCapacity(5242880L); - instanceDisk.setDatastoreName("Test"); - instanceDisk.setDatastoreHost("Test"); - instanceDisk.setDatastorePath("Test"); - instanceDisk.setDatastoreType("NFS"); - instanceDisks.add(instanceDisk); - return instanceDisks; - } - - @After - public void tearDown() throws Exception { - closeable.close(); - actionEventUtilsMocked.close(); - CallContext.unregister(); - } - - @Test - public void listUnmanagedInstancesTest() { - ListUnmanagedInstancesCmd cmd = Mockito.mock(ListUnmanagedInstancesCmd.class); - unmanagedVMsManager.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.XenServer.toString()); - when(clusterDao.findById(anyLong())).thenReturn(cluster); - unmanagedVMsManager.listUnmanagedInstances(cmd); - } - - @Test(expected = PermissionDeniedException.class) - public void listUnmanagedInstancesInvalidCallerTest() { - CallContext.unregister(); - AccountVO account = new AccountVO("user", 1L, "", 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); - unmanagedVMsManager.listUnmanagedInstances(cmd); - } - - @Test - public void importUnmanagedInstanceTest() { - ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class); - when(importUnmanageInstanceCmd.getName()).thenReturn("TestInstance"); - when(importUnmanageInstanceCmd.getDomainId()).thenReturn(null); - when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true); - try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class); - MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.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"); - unmanagedVMsManager.importUnmanagedInstance(importUnmanageInstanceCmd); - } - - @Test(expected = ServerApiException.class) - public void importUnmanagedInstanceMissingInstanceTest() { - ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class); - when(importUnmanageInstanceCmd.getName()).thenReturn("SomeInstance"); - when(importUnmanageInstanceCmd.getDomainId()).thenReturn(null); - try (MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.importUnmanagedInstance(importUnmanageInstanceCmd); - } - } - - @Test(expected = InvalidParameterValueException.class) - public void unmanageVMInstanceMissingInstanceTest() { - when(vmDao.findById(anyLong())).thenReturn(null); - unmanagedVMsManager.unmanageVMInstance(1L, null, false); - } - - @Test(expected = InvalidParameterValueException.class) - public void unmanageVMInstanceRemovedInstanceTest() { - VMInstanceVO userVmVO = mock(VMInstanceVO.class); - when(vmDao.findById(anyLong())).thenReturn(userVmVO); - when(userVmVO.getRemoved()).thenReturn(new Date()); - unmanagedVMsManager.unmanageVMInstance(1L, null, false); - } - - @Test(expected = InvalidParameterValueException.class) - public void unmanageVMInstanceDestroyedInstanceTest() { - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Destroyed); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = InvalidParameterValueException.class) - public void unmanageVMInstanceExpungedInstanceTest() { - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Expunging); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void unmanageVMInstanceExistingVMSnapshotsTest() { - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.None); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void unmanageVMInstanceInvalidHyperVisor() { - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.None); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void unmanageVMInstanceInvalidVmType() { - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.VMware); - when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.ConsoleProxy); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void unmanageVMInstanceExistingVolumeSnapshotsTest() { - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.None); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void unmanageVMInstanceExistingISOAttachedTest() { - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.None); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void unmanageVMInstanceVmwareHostIdParamTest() { - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.VMware); - when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, 1L, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void unmanageVMInstanceRunningHostIdParamTest() { - when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Running); - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, 1L, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void unmanageVMInstanceRunningForceParamTest() { - when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Running); - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); - VMInstanceDetailVO vmInstanceDetailVO = mock(VMInstanceDetailVO.class); - when(vmInstanceDetailsDao.findDetail(virtualMachineId, VmDetailConstants.CONFIG_DRIVE_LOCATION)).thenReturn(vmInstanceDetailVO); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test - public void unmanageVMInstanceVMwareHostId() { - when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); - UserVmVO userVmVO = mock(UserVmVO.class); - when(userVmVO.getIsoId()).thenReturn(null); - when(userVmDao.findById(anyLong())).thenReturn(userVmVO); - when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, 1L, false); - } - - @Test - public void unmanageVMInstanceStoppedInstanceTest() { - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); - when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); - UserVmVO userVmVO = mock(UserVmVO.class); - when(userVmDao.findById(anyLong())).thenReturn(userVmVO); - Mockito.doNothing().when(unmanagedVMsManager).performUnmanageVMInstancePrechecks(any()); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void testUnmanageVMInstanceWithVolumeSnapshotsFail() { - when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); - when(virtualMachine.getId()).thenReturn(virtualMachineId); - UserVmVO userVmVO = mock(UserVmVO.class); - when(userVmDao.findById(anyLong())).thenReturn(userVmVO); - when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); - VolumeVO volumeVO = mock(VolumeVO.class); - long volumeId = 20L; - when(volumeVO.getId()).thenReturn(volumeId); - SnapshotVO snapshotVO = mock(SnapshotVO.class); - when(snapshotVO.getState()).thenReturn(Snapshot.State.BackedUp); - when(snapshotDao.listByVolumeId(volumeId)).thenReturn(Collections.singletonList(snapshotVO)); - when(volumeDao.findByInstance(virtualMachineId)).thenReturn(Collections.singletonList(volumeVO)); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void testUnmanageVMInstanceWithAssociatedIsoFail() { - when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); - when(virtualMachine.getId()).thenReturn(virtualMachineId); - UserVmVO userVmVO = mock(UserVmVO.class); - when(userVmVO.getIsoId()).thenReturn(null); - when(userVmDao.findById(anyLong())).thenReturn(userVmVO); - when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); - when(userVmVO.getIsoId()).thenReturn(1L); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test(expected = UnsupportedServiceException.class) - public void testUnmanageVMInstanceBelongingToCksClusterFail() { - when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); - when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); - when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); - when(virtualMachine.getId()).thenReturn(virtualMachineId); - UserVmVO userVmVO = mock(UserVmVO.class); - when(userVmVO.getIsoId()).thenReturn(null); - when(userVmDao.findById(anyLong())).thenReturn(userVmVO); - when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); - when(userVmManager.isVMPartOfAnyCKSCluster(virtualMachine)).thenReturn(true); - unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); - } - - @Test - public void testListRemoteInstancesTest() { - ListVmsForImportCmd cmd = Mockito.mock(ListVmsForImportCmd.class); - when(cmd.getHypervisor()).thenReturn(Hypervisor.HypervisorType.KVM.toString()); - when(cmd.getUsername()).thenReturn("user"); - when(cmd.getPassword()).thenReturn("pass"); - ListResponse response = unmanagedVMsManager.listVmsForImport(cmd); - Assert.assertEquals(1, response.getCount().intValue()); - } - - @Test(expected = InvalidParameterValueException.class) - public void testListRemoteInstancesTestNonKVM() { - ListVmsForImportCmd cmd = Mockito.mock(ListVmsForImportCmd.class); - unmanagedVMsManager.listVmsForImport(cmd); - } - @Test - public void testImportFromExternalTest() throws InsufficientServerCapacityException { - String vmname = "TestInstance"; - ImportVmCmd cmd = Mockito.mock(ImportVmCmd.class); - when(cmd.getHypervisor()).thenReturn(Hypervisor.HypervisorType.KVM.toString()); - when(cmd.getName()).thenReturn(vmname); - when(cmd.getUsername()).thenReturn("user"); - when(cmd.getPassword()).thenReturn("pass"); - when(cmd.getImportSource()).thenReturn("external"); - when(cmd.getDomainId()).thenReturn(null); - HostVO host = Mockito.mock(HostVO.class); - DeployDestination mockDest = Mockito.mock(DeployDestination.class); - when(deploymentPlanningManager.planDeployment(any(), any(), any(), any())).thenReturn(mockDest); - DiskProfile diskProfile = Mockito.mock(DiskProfile.class); - when(volumeManager.allocateRawVolume(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), anyBoolean())) - .thenReturn(diskProfile); - Map storage = new HashMap<>(); - VolumeVO volume = Mockito.mock(VolumeVO.class); - StoragePoolVO storagePool = Mockito.mock(StoragePoolVO.class); - storage.put(volume, storagePool); - when(mockDest.getStorageForDisks()).thenReturn(storage); - when(mockDest.getHost()).thenReturn(host); - when(volumeDao.findById(anyLong())).thenReturn(volume); - CopyRemoteVolumeAnswer copyAnswer = Mockito.mock(CopyRemoteVolumeAnswer.class); - when(copyAnswer.getResult()).thenReturn(true); - when(agentManager.easySend(anyLong(), any(CopyRemoteVolumeCommand.class))).thenReturn(copyAnswer); - try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class); - MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.importVm(cmd); - } - } - - private void baseBasicParametersCheckForImportInstance(String name, Long domainId, String accountName) { - unmanagedVMsManager.basicParametersCheckForImportInstance(name, domainId, accountName); - } - - @Test(expected = InvalidParameterValueException.class) - public void testBasicParametersCheckForImportInstanceMissingName() { - baseBasicParametersCheckForImportInstance(null, 1L, "test"); - } - - @Test(expected = InvalidParameterValueException.class) - public void testBasicParametersCheckForImportInstanceMissingDomainAndAccount() { - baseBasicParametersCheckForImportInstance("vm", 1L, ""); - } - - @Test(expected = InvalidParameterValueException.class) - public void testBasicAccessChecksMissingClusterId() { - unmanagedVMsManager.basicAccessChecks(null); - } - - @Test(expected = PermissionDeniedException.class) - public void testBasicAccessChecksNotAdminCaller() { - CallContext.unregister(); - AccountVO account = new AccountVO("user", 1L, "", 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); - unmanagedVMsManager.basicAccessChecks(1L); - } - - @Test(expected = InvalidParameterValueException.class) - public void testBasicAccessChecksUnsupportedHypervisorType() { - ClusterVO clusterVO = new ClusterVO(1L, 1L, "Cluster"); - clusterVO.setHypervisorType(Hypervisor.HypervisorType.XenServer.toString()); - when(clusterDao.findById(anyLong())).thenReturn(clusterVO); - unmanagedVMsManager.basicAccessChecks(1L); - } - - @Test - public void testGetTemplateForImportInstanceDefaultTemplate() { - String defaultTemplateName = "DefaultTemplate"; - VMTemplateVO template = Mockito.mock(VMTemplateVO.class); - when(template.getName()).thenReturn(defaultTemplateName); - when(templateDao.findByName(anyString())).thenReturn(template); - VMTemplateVO templateForImportInstance = unmanagedVMsManager.getTemplateForImportInstance(null, Hypervisor.HypervisorType.KVM); - Assert.assertEquals(defaultTemplateName, templateForImportInstance.getName()); - } - - private enum VcenterParameter { - EXISTING, - EXTERNAL, - BOTH, - NONE, - EXISTING_INVALID, - AGENT_UNAVAILABLE, - CONVERT_FAILURE, - FORCE_MS_AND_USE_VDDK, - USE_VDDK_OVF_UNSUPPORTED, - USE_VDDK_OVF_SUPPORTED, - USE_VDDK_DETAILS_OVERRIDES - } - - private void baseTestImportVmFromVmwareToKvm(VcenterParameter vcenterParameter, boolean selectConvertHost, - boolean selectTemporaryStorage) throws OperationTimedoutException, AgentUnavailableException { - long clusterId = 1L; - long zoneId = 1L; - long existingDatacenterId = 1L; - String vcenterHost = "192.168.1.2"; - String datacenter = "Datacenter"; - String username = "administrator@vsphere.local"; - String password = "password"; - String host = "192.168.1.10"; - String vmName = "TestInstanceFromVmware"; - instance.setName(vmName); - String tmplFileName = "5b8d689a-e61a-4ac3-9b76-e121ff90fbd3"; - long newVmId = 2L; - long networkId = 1L; - - ClusterVO cluster = mock(ClusterVO.class); - when(cluster.getId()).thenReturn(clusterId); - when(cluster.getAllocationState()).thenReturn(Grouping.AllocationState.Enabled); - when(cluster.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); - when(cluster.getDataCenterId()).thenReturn(zoneId); - when(clusterDao.findById(clusterId)).thenReturn(cluster); - - ImportVmCmd importVmCmd = Mockito.mock(ImportVmCmd.class); - - when(importVmCmd.getName()).thenReturn(vmName); - when(importVmCmd.getClusterId()).thenReturn(clusterId); - when(importVmCmd.getDomainId()).thenReturn(null); - when(importVmCmd.getImportSource()).thenReturn(VmImportService.ImportSource.VMWARE.toString()); - when(importVmCmd.getHostIp()).thenReturn(host); - when(importVmCmd.getNicNetworkList()).thenReturn(Map.of("NIC 1", networkId)); - when(importVmCmd.getConvertInstanceHostId()).thenReturn(null); - when(importVmCmd.getImportInstanceHostId()).thenReturn(null); - when(importVmCmd.getConvertStoragePoolId()).thenReturn(null); - when(importVmCmd.getExistingVcenterId()).thenReturn(null); - when(importVmCmd.getVcenter()).thenReturn(null); - when(importVmCmd.getDatacenterName()).thenReturn(null); - when(importVmCmd.getUsername()).thenReturn(null); - when(importVmCmd.getPassword()).thenReturn(null); - when(importVmCmd.getDetails()).thenReturn(new HashMap<>()); - - boolean forceMsToImportVmFiles = false; - boolean useVddk = false; - boolean ovfExportSupported = false; - if (VcenterParameter.FORCE_MS_AND_USE_VDDK == vcenterParameter) { - forceMsToImportVmFiles = true; - useVddk = true; - } else if (VcenterParameter.USE_VDDK_OVF_UNSUPPORTED == vcenterParameter) { - useVddk = true; - } else if (VcenterParameter.USE_VDDK_OVF_SUPPORTED == vcenterParameter) { - useVddk = true; - ovfExportSupported = true; - } else if (VcenterParameter.USE_VDDK_DETAILS_OVERRIDES == vcenterParameter) { - useVddk = true; - ovfExportSupported = true; - when(importVmCmd.getDetails()).thenReturn(Map.of( - "vddk.lib.dir", "/opt/vmware-vddk/override", - "vddk.transports", "nbd:nbdssl", - "vddk.thumbprint", "AA:BB:CC:DD:EE")); - } - when(importVmCmd.getForceMsToImportVmFiles()).thenReturn(forceMsToImportVmFiles); - when(importVmCmd.getUseVddk()).thenReturn(useVddk); - - NetworkVO networkVO = Mockito.mock(NetworkVO.class); - when(networkVO.getGuestType()).thenReturn(Network.GuestType.L2); - when(networkVO.getDataCenterId()).thenReturn(zoneId); - when(networkDao.findById(networkId)).thenReturn(networkVO); - - HypervisorGuru vmwareGuru = mock(HypervisorGuru.class); - when(hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware)).thenReturn(vmwareGuru); - when(vmwareGuru.getHypervisorVMOutOfBandAndCloneIfRequired(anyString(), anyString(), anyMap())).thenReturn(new Pair<>(instance, true)); - when(vmwareGuru.removeClonedHypervisorVMOutOfBand(anyString(), anyString(), anyMap())).thenReturn(true); - when(vmwareGuru.createVMTemplateOutOfBand(anyString(), anyString(), anyMap(), any(DataStoreTO.class), anyInt())).thenReturn(tmplFileName); - when(vmwareGuru.removeVMTemplateOutOfBand(any(DataStoreTO.class), anyString())).thenReturn(true); - - HostVO convertHost = mock(HostVO.class); - long convertHostId = 1L; - when(convertHost.getStatus()).thenReturn(Status.Up); - when(convertHost.getResourceState()).thenReturn(ResourceState.Enabled); - when(convertHost.getId()).thenReturn(convertHostId); - when(convertHost.getType()).thenReturn(Host.Type.Routing); - when(convertHost.getDataCenterId()).thenReturn(zoneId); - when(convertHost.getClusterId()).thenReturn(clusterId); - if (selectConvertHost) { - when(importVmCmd.getConvertInstanceHostId()).thenReturn(convertHostId); - when(importVmCmd.getImportInstanceHostId()).thenReturn(convertHostId); - when(hostDao.findById(convertHostId)).thenReturn(convertHost); - } else { - when(hostDao.listByClusterAndHypervisorType(clusterId, Hypervisor.HypervisorType.KVM)).thenReturn(List.of(convertHost)); - } - - DataStoreTO dataStoreTO = mock(DataStoreTO.class); - DataStore dataStore = mock(DataStore.class); - when(dataStore.getTO()).thenReturn(dataStoreTO); - - StoragePoolVO destPool = mock(StoragePoolVO.class); - when(destPool.getDataCenterId()).thenReturn(zoneId); - when(destPool.getClusterId()).thenReturn(null); - when(destPool.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem); - StoragePoolVO zoneDestPool = mock(StoragePoolVO.class); - if (selectTemporaryStorage) { - long temporaryStoragePoolId = 1L; - when(importVmCmd.getConvertStoragePoolId()).thenReturn(temporaryStoragePoolId); - when(primaryDataStoreDao.findById(temporaryStoragePoolId)).thenReturn(destPool); - when(dataStoreManager.getPrimaryDataStore(temporaryStoragePoolId)).thenReturn(dataStore); - } else { - ImageStoreVO imageStoreVO = mock(ImageStoreVO.class); - when(imageStoreVO.getId()).thenReturn(1L); - when(imageStoreDao.findOneByZoneAndProtocol(zoneId, "nfs")).thenReturn(imageStoreVO); - when(dataStoreManager.getDataStore(1L, DataStoreRole.Image)).thenReturn(dataStore); - } - when(primaryDataStoreDao.listPoolByHostPath(Mockito.anyString(), Mockito.anyString())).thenReturn(List.of(destPool)); - when(primaryDataStoreDao.findClusterWideStoragePoolsByHypervisorAndPoolType(clusterId, Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)).thenReturn(List.of(destPool)); - when(primaryDataStoreDao.findZoneWideStoragePoolsByHypervisorAndPoolType(zoneId, Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)).thenReturn(List.of(zoneDestPool)); - - if (VcenterParameter.EXISTING == vcenterParameter) { - VmwareDatacenterVO datacenterVO = mock(VmwareDatacenterVO.class); - when(datacenterVO.getVcenterHost()).thenReturn(vcenterHost); - when(datacenterVO.getVmwareDatacenterName()).thenReturn(datacenter); - when(datacenterVO.getUser()).thenReturn(username); - when(datacenterVO.getPassword()).thenReturn(password); - when(importVmCmd.getExistingVcenterId()).thenReturn(existingDatacenterId); - when(vmwareDatacenterDao.findById(existingDatacenterId)).thenReturn(datacenterVO); - } - - if (VcenterParameter.BOTH == vcenterParameter) { - when(importVmCmd.getExistingVcenterId()).thenReturn(existingDatacenterId); - when(importVmCmd.getVcenter()).thenReturn(vcenterHost); - } else if (VcenterParameter.NONE == vcenterParameter) { - when(importVmCmd.getExistingVcenterId()).thenReturn(null); - when(importVmCmd.getVcenter()).thenReturn(null); - } else if (VcenterParameter.EXISTING_INVALID == vcenterParameter) { - when(importVmCmd.getExistingVcenterId()).thenReturn(existingDatacenterId); - when(vmwareDatacenterDao.findById(existingDatacenterId)).thenReturn(null); - } - - if (VcenterParameter.FORCE_MS_AND_USE_VDDK == vcenterParameter - || VcenterParameter.USE_VDDK_OVF_UNSUPPORTED == vcenterParameter - || VcenterParameter.USE_VDDK_OVF_SUPPORTED == vcenterParameter - || VcenterParameter.USE_VDDK_DETAILS_OVERRIDES == vcenterParameter) { - Mockito.doReturn((Long) null).when(importVmCmd).getExistingVcenterId(); - Mockito.doReturn(vcenterHost).when(importVmCmd).getVcenter(); - Mockito.doReturn(datacenter).when(importVmCmd).getDatacenterName(); - Mockito.doReturn(username).when(importVmCmd).getUsername(); - Mockito.doReturn(password).when(importVmCmd).getPassword(); - } - - CheckConvertInstanceAnswer checkConvertInstanceAnswer = mock(CheckConvertInstanceAnswer.class); - when(checkConvertInstanceAnswer.getResult()).thenReturn(vcenterParameter != VcenterParameter.CONVERT_FAILURE); - when(checkConvertInstanceAnswer.isOvfExportSupported()).thenReturn(ovfExportSupported); - if (VcenterParameter.AGENT_UNAVAILABLE != vcenterParameter) { - when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(CheckConvertInstanceCommand.class))).thenReturn(checkConvertInstanceAnswer); - } - - when(importVmTasksManager.createImportVMTaskRecord(any(DataCenter.class), any(Account.class), anyLong(), anyString(), - anyString(), anyString(), anyString(), any(Host.class), any(Host.class))).thenReturn(importVMTaskVO); - when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any(DiskOffering.class))).thenReturn(true); - - ConvertInstanceAnswer convertInstanceAnswer = mock(ConvertInstanceAnswer.class); - ImportConvertedInstanceAnswer convertImportedInstanceAnswer = mock(ImportConvertedInstanceAnswer.class); - when(convertInstanceAnswer.getResult()).thenReturn(vcenterParameter != VcenterParameter.CONVERT_FAILURE); - Mockito.lenient().when(convertImportedInstanceAnswer.getConvertedInstance()).thenReturn(instance); - Mockito.lenient().when(convertImportedInstanceAnswer.getResult()).thenReturn(vcenterParameter != VcenterParameter.CONVERT_FAILURE); - if (VcenterParameter.AGENT_UNAVAILABLE != vcenterParameter) { - when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(ConvertInstanceCommand.class))).thenReturn(convertInstanceAnswer); - Mockito.lenient().when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(ImportConvertedInstanceCommand.class))).thenReturn(convertImportedInstanceAnswer); - } - - try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class); - MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.importVm(importVmCmd); - verify(vmwareGuru).getHypervisorVMOutOfBandAndCloneIfRequired(Mockito.eq(host), Mockito.eq(vmName), anyMap()); - if (VcenterParameter.USE_VDDK_OVF_SUPPORTED == vcenterParameter) { - verify(vmwareGuru, Mockito.never()).createVMTemplateOutOfBand(anyString(), anyString(), anyMap(), any(DataStoreTO.class), anyInt()); - verify(agentManager).send(Mockito.eq(convertHostId), Mockito.argThat(command -> - command instanceof ConvertInstanceCommand && ((ConvertInstanceCommand) command).isUseVddk())); - verify(vmwareGuru, Mockito.never()).removeVMTemplateOutOfBand(any(DataStoreTO.class), anyString()); - } else if (VcenterParameter.USE_VDDK_DETAILS_OVERRIDES == vcenterParameter) { - verify(vmwareGuru, Mockito.never()).createVMTemplateOutOfBand(anyString(), anyString(), anyMap(), any(DataStoreTO.class), anyInt()); - verify(agentManager).send(Mockito.eq(convertHostId), Mockito.argThat(command -> { - if (!(command instanceof ConvertInstanceCommand)) { - return false; - } - ConvertInstanceCommand convertCmd = (ConvertInstanceCommand) command; - return convertCmd.isUseVddk() - && "/opt/vmware-vddk/override".equals(convertCmd.getVddkLibDir()) - && "nbd:nbdssl".equals(convertCmd.getVddkTransports()) - && "AA:BB:CC:DD:EE".equals(convertCmd.getVddkThumbprint()); - })); - verify(vmwareGuru, Mockito.never()).removeVMTemplateOutOfBand(any(DataStoreTO.class), anyString()); - } else { - verify(vmwareGuru).createVMTemplateOutOfBand(Mockito.eq(host), Mockito.eq(vmName), anyMap(), any(DataStoreTO.class), anyInt()); - verify(vmwareGuru).removeVMTemplateOutOfBand(any(DataStoreTO.class), anyString()); - } - verify(vmwareGuru).removeClonedHypervisorVMOutOfBand(Mockito.eq(host), Mockito.eq(vmName), anyMap()); - } - } - - @Test - public void importFromLocalDisk() throws InsufficientServerCapacityException { - importFromDisk("local"); - } - - @Test - public void importFromsharedStorage() throws InsufficientServerCapacityException { - importFromDisk("shared"); - } - - private void importFromDisk(String source) throws InsufficientServerCapacityException { - String vmname = "testVm"; - ImportVmCmd cmd = Mockito.mock(ImportVmCmd.class); - when(cmd.getHypervisor()).thenReturn(Hypervisor.HypervisorType.KVM.toString()); - when(cmd.getName()).thenReturn(vmname); - when(cmd.getImportSource()).thenReturn(source); - when(cmd.getDiskPath()).thenReturn("/var/lib/libvirt/images/test.qcow2"); - when(cmd.getDomainId()).thenReturn(null); - HostVO host = Mockito.mock(HostVO.class); - when(hostDao.findById(anyLong())).thenReturn(host); - NetworkOffering netOffering = Mockito.mock(NetworkOffering.class); - when(entityMgr.findById(NetworkOffering.class, 0L)).thenReturn(netOffering); - DeployDestination mockDest = Mockito.mock(DeployDestination.class); - when(deploymentPlanningManager.planDeployment(any(), any(), any(), any())).thenReturn(mockDest); - DiskProfile diskProfile = Mockito.mock(DiskProfile.class); - when(volumeManager.allocateRawVolume(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), anyBoolean())) - .thenReturn(diskProfile); - Map storage = new HashMap<>(); - VolumeVO volume = Mockito.mock(VolumeVO.class); - StoragePoolVO storagePool = Mockito.mock(StoragePoolVO.class); - storage.put(volume, storagePool); - when(mockDest.getStorageForDisks()).thenReturn(storage); - when(mockDest.getHost()).thenReturn(host); - when(volumeDao.findById(anyLong())).thenReturn(volume); - CheckVolumeAnswer answer = Mockito.mock(CheckVolumeAnswer.class); - when(answer.getResult()).thenReturn(true); - when(agentManager.easySend(anyLong(), any(CheckVolumeCommand.class))).thenReturn(answer); - List storagePools = new ArrayList<>(); - storagePools.add(storagePool); - when(primaryDataStoreDao.findLocalStoragePoolsByHostAndTags(anyLong(), any())).thenReturn(storagePools); - when(primaryDataStoreDao.findById(anyLong())).thenReturn(storagePool); - when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true); - StoragePoolHostVO storagePoolHost = Mockito.mock(StoragePoolHostVO.class); - when(storagePoolHostDao.findByPoolHost(anyLong(), anyLong())).thenReturn(storagePoolHost); - try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class); - MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.importVm(cmd); - } - } - - @Test - public void testImportVmFromVmwareToKvmExistingVcenter() throws OperationTimedoutException, AgentUnavailableException { - baseTestImportVmFromVmwareToKvm(VcenterParameter.EXISTING, false, false); - } - - @Test - public void testImportVmFromVmwareToKvmExistingVcenterSetConvertHost() throws OperationTimedoutException, AgentUnavailableException { - baseTestImportVmFromVmwareToKvm(VcenterParameter.EXISTING, true, false); - } - - @Test - public void testImportVmFromVmwareToKvmExistingVcenterSetConvertHostAndTemporaryStorage() throws OperationTimedoutException, AgentUnavailableException { - baseTestImportVmFromVmwareToKvm(VcenterParameter.EXISTING, true, true); - } - - @Test(expected = ServerApiException.class) - public void testImportVmFromVmwareToKvmExistingVcenterExclusiveParameters() throws OperationTimedoutException, AgentUnavailableException { - baseTestImportVmFromVmwareToKvm(VcenterParameter.BOTH, false, false); - } - - @Test(expected = ServerApiException.class) - public void testImportVmFromVmwareToKvmExistingVcenterMissingParameters() throws OperationTimedoutException, AgentUnavailableException { - baseTestImportVmFromVmwareToKvm(VcenterParameter.NONE, false, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testImportVmFromVmwareToKvmExistingVcenterInvalid() throws OperationTimedoutException, AgentUnavailableException { - baseTestImportVmFromVmwareToKvm(VcenterParameter.EXISTING_INVALID, false, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testImportVmFromVmwareToKvmExistingVcenterAgentUnavailable() throws OperationTimedoutException, AgentUnavailableException { - baseTestImportVmFromVmwareToKvm(VcenterParameter.AGENT_UNAVAILABLE, false, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testImportVmFromVmwareToKvmExistingVcenterConvertFailure() throws OperationTimedoutException, AgentUnavailableException { - baseTestImportVmFromVmwareToKvm(VcenterParameter.CONVERT_FAILURE, false, false); - } - - @Test(expected = ServerApiException.class) - public void testImportVmFromVmwareToKvmForceMsMutuallyExclusiveWithUseVddk() throws OperationTimedoutException, AgentUnavailableException { - baseTestImportVmFromVmwareToKvm(VcenterParameter.FORCE_MS_AND_USE_VDDK, false, false); - } - - @Test(expected = InvalidParameterValueException.class) - public void testValidateSelectedConversionStoragePoolForVddkFailsWhenPoolDoesNotSupportDiskOfferings() { - long poolId = 11L; - StoragePoolVO selectedPool = mock(StoragePoolVO.class); - ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class); - DiskOfferingVO rootDiskOffering = mock(DiskOfferingVO.class); - DiskOfferingVO dataDiskOffering = mock(DiskOfferingVO.class); - - when(serviceOffering.getDiskOfferingId()).thenReturn(21L); - when(primaryDataStoreDao.findById(poolId)).thenReturn(selectedPool); - when(diskOfferingDao.findById(21L)).thenReturn(rootDiskOffering); - when(diskOfferingDao.findById(22L)).thenReturn(dataDiskOffering); - when(volumeApiService.doesStoragePoolSupportDiskOffering(selectedPool, rootDiskOffering)).thenReturn(true); - when(volumeApiService.doesStoragePoolSupportDiskOffering(selectedPool, dataDiskOffering)).thenReturn(false); - - unmanagedVMsManager.validateSelectedConversionStoragePoolForVddk(true, poolId, - serviceOffering, Map.of("1000-2", 22L)); - } - - @Test - public void testValidateSelectedConversionStoragePoolForVddkPassesWhenPoolSupportsAllDiskOfferings() { - long poolId = 12L; - StoragePoolVO selectedPool = mock(StoragePoolVO.class); - ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class); - DiskOfferingVO rootDiskOffering = mock(DiskOfferingVO.class); - DiskOfferingVO dataDiskOffering = mock(DiskOfferingVO.class); - - when(serviceOffering.getDiskOfferingId()).thenReturn(31L); - when(primaryDataStoreDao.findById(poolId)).thenReturn(selectedPool); - when(diskOfferingDao.findById(31L)).thenReturn(rootDiskOffering); - when(diskOfferingDao.findById(32L)).thenReturn(dataDiskOffering); - when(volumeApiService.doesStoragePoolSupportDiskOffering(selectedPool, rootDiskOffering)).thenReturn(true); - when(volumeApiService.doesStoragePoolSupportDiskOffering(selectedPool, dataDiskOffering)).thenReturn(true); - - unmanagedVMsManager.validateSelectedConversionStoragePoolForVddk(true, poolId, - serviceOffering, Map.of("1000-2", 32L)); - } - - private ClusterVO getClusterForTests() { - ClusterVO cluster = mock(ClusterVO.class); - when(cluster.getId()).thenReturn(1L); - when(cluster.getDataCenterId()).thenReturn(1L); - return cluster; - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectInstanceConversionTemporaryLocationInvalidStorage() { - ClusterVO cluster = getClusterForTests(); - - long poolId = 1L; - when(primaryDataStoreDao.findById(poolId)).thenReturn(null); - unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, poolId, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectInstanceConversionTemporaryLocationPoolInvalidScope() { - ClusterVO cluster = getClusterForTests(); - long poolId = 1L; - StoragePoolVO pool = mock(StoragePoolVO.class); - when(pool.getScope()).thenReturn(ScopeType.CLUSTER); - when(pool.getClusterId()).thenReturn(100L); - when(primaryDataStoreDao.findById(poolId)).thenReturn(pool); - unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, poolId, false); - } - - - @Test(expected = CloudRuntimeException.class) - public void testSelectInstanceConversionTemporaryLocationPoolConvertHostDifferentCluster() { - ClusterVO cluster = getClusterForTests(); - long poolId = 1L; - StoragePoolVO pool = mock(StoragePoolVO.class); - when(pool.getScope()).thenReturn(ScopeType.CLUSTER); - when(pool.getClusterId()).thenReturn(1L); - HostVO host = mock(HostVO.class); - when(primaryDataStoreDao.findById(poolId)).thenReturn(pool); - when(host.getClusterId()).thenReturn(2L); - unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, host, null, poolId, false); - } - - - @Test(expected = CloudRuntimeException.class) - public void testSelectInstanceConversionTemporaryLocationLocalStoragePoolInvalid() { - ClusterVO cluster = getClusterForTests(); - long poolId = 1L; - StoragePoolVO pool = mock(StoragePoolVO.class); - when(pool.getScope()).thenReturn(ScopeType.HOST); - when(primaryDataStoreDao.findById(poolId)).thenReturn(pool); - unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, poolId, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectInstanceConversionTemporaryLocationStoragePoolInvalidType() { - ClusterVO cluster = getClusterForTests(); - long poolId = 1L; - StoragePoolVO pool = mock(StoragePoolVO.class); - when(pool.getScope()).thenReturn(ScopeType.CLUSTER); - when(pool.getClusterId()).thenReturn(1L); - when(primaryDataStoreDao.findById(poolId)).thenReturn(pool); - when(pool.getPoolType()).thenReturn(Storage.StoragePoolType.RBD); - unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, poolId, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectInstanceConversionTemporaryLocationNoPoolAvailable() { - ClusterVO cluster = getClusterForTests(); - when(imageStoreDao.findOneByZoneAndProtocol(anyLong(), anyString())).thenReturn(null); - unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, null, false); - } - - @Test - public void testSelectKVMHostForImportingInClusterWithImportInstanceIdSuccess() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Enabled); - when(host.getStatus()).thenReturn(Status.Up); - when(host.getType()).thenReturn(Host.Type.Routing); - when(host.getClusterId()).thenReturn(1L); - - when(hostDao.findById(hostId)).thenReturn(host); - - HostVO returnedHost = unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); - Assert.assertEquals(host, returnedHost); - } - - @Test - public void testSelectKVMHostForImportingInClusterWithNullImportInstanceIdSuccess() { - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(hostDao.listByClusterAndHypervisorType(cluster.getId(), cluster.getHypervisorType())).thenReturn(List.of(host)); - - HostVO returnedHost = unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, null); - Assert.assertEquals(host, returnedHost); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForImportingInClusterFailure() { - ClusterVO cluster = getClusterForTests(); - when(hostDao.listByClusterAndHypervisorType(cluster.getId(), cluster.getHypervisorType())).thenReturn(List.of()); - - unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, null); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidCluster() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Enabled); - when(host.getStatus()).thenReturn(Status.Up); - when(host.getType()).thenReturn(Host.Type.Routing); - when(host.getClusterId()).thenReturn(2L); - - when(hostDao.findById(hostId)).thenReturn(host); - - unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidType() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Enabled); - when(host.getStatus()).thenReturn(Status.Up); - when(host.getType()).thenReturn(Host.Type.Storage); - - when(hostDao.findById(hostId)).thenReturn(host); - - unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidStatus() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Enabled); - when(host.getStatus()).thenReturn(Status.Alert); - - when(hostDao.findById(hostId)).thenReturn(host); - - unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidResourceState() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Disabled); - - when(hostDao.findById(hostId)).thenReturn(host); - - unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidHostId() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - - when(hostDao.findById(hostId)).thenReturn(null); - - unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); - } - - @Test - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdEnabledHost() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Enabled); - when(host.getStatus()).thenReturn(Status.Up); - when(host.getType()).thenReturn(Host.Type.Routing); - when(host.getDataCenterId()).thenReturn(1L); - - when(hostDao.findById(hostId)).thenReturn(host); - - HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); - Assert.assertEquals(host, returnedHost); - } - - @Test - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdDisabledHost() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Disabled); - when(host.getStatus()).thenReturn(Status.Up); - when(host.getType()).thenReturn(Host.Type.Routing); - when(host.getDataCenterId()).thenReturn(1L); - - when(hostDao.findById(hostId)).thenReturn(host); - - HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); - Assert.assertEquals(host, returnedHost); - } - - @Test - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdSuccessCompatible() { - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - - when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(), - cluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION)).thenReturn(List.of(host)); - - HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, null, false); - Assert.assertEquals(host, returnedHost); - } - - @Test - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdSuccessNonCompatible() { - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - - when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(), - cluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION)).thenReturn(List.of()); - - when(hostDao.listByClusterAndHypervisorType(cluster.getId(), cluster.getHypervisorType())).thenReturn(List.of(host)); - - HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, null, false); - Assert.assertEquals(host, returnedHost); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdFailure() { - ClusterVO cluster = getClusterForTests(); - - when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(), - cluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION)).thenReturn(List.of()); - - when(hostDao.listByClusterAndHypervisorType(cluster.getId(), cluster.getHypervisorType())).thenReturn(List.of()); - - unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, null, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidZone() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Enabled); - when(host.getStatus()).thenReturn(Status.Up); - when(host.getType()).thenReturn(Host.Type.Routing); - when(host.getDataCenterId()).thenReturn(2L); - - when(hostDao.findById(hostId)).thenReturn(host); - - unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidType() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Enabled); - when(host.getStatus()).thenReturn(Status.Up); - when(host.getType()).thenReturn(Host.Type.SecondaryStorage); - - when(hostDao.findById(hostId)).thenReturn(host); - - unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidStatus() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Enabled); - when(host.getStatus()).thenReturn(Status.Down); - - when(hostDao.findById(hostId)).thenReturn(host); - - unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidResourceState() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - HostVO host = Mockito.mock(HostVO.class); - when(host.getResourceState()).thenReturn(ResourceState.Maintenance); - - when(hostDao.findById(hostId)).thenReturn(host); - - unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); - } - - @Test(expected = CloudRuntimeException.class) - public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidHostId() { - Long hostId = 1L; - ClusterVO cluster = getClusterForTests(); - - when(hostDao.findById(hostId)).thenReturn(null); - - unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); - } - - @Test - public void testSelectKVMHostForConversionInClusterVddkAutoSelectsHostWithVddkSupport() { - ClusterVO cluster = getClusterForTests(); - HostVO hostWithVddk = Mockito.mock(HostVO.class); - HostVO hostWithoutVddk = Mockito.mock(HostVO.class); - when(hostWithVddk.getDetail(Host.HOST_VDDK_SUPPORT)).thenReturn("true"); - when(hostWithoutVddk.getDetail(Host.HOST_VDDK_SUPPORT)).thenReturn(null); - - when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(), - cluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION)) - .thenReturn(List.of(hostWithoutVddk, hostWithVddk)); - - HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, null, true); - Assert.assertEquals(hostWithVddk, returnedHost); - } - - @Test - public void testCheckConversionStoragePoolSecondaryStorageStaging() { - unmanagedVMsManager.checkConversionStoragePool(null, false); - Mockito.verifyNoInteractions(primaryDataStoreDao); - } - - @Test(expected = CloudRuntimeException.class) - public void testCheckConversionStoragePoolTemporarySecondaryStorageForceConvertToPool() { - unmanagedVMsManager.checkConversionStoragePool(null, true); - } - - @Test - public void testCheckConversionStoragePoolPrimaryStagingPool() { - StoragePoolVO destPool = mock(StoragePoolVO.class); - long destPoolId = 1L; - Mockito.when(primaryDataStoreDao.findById(destPoolId)).thenReturn(destPool); - unmanagedVMsManager.checkConversionStoragePool(destPoolId, false); - } - - @Test - public void testCheckConversionStoragePoolPrimaryStagingPoolTypeAllowedForce() { - StoragePoolVO destPool = mock(StoragePoolVO.class); - Mockito.when(destPool.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem); - long destPoolId = 1L; - Mockito.when(primaryDataStoreDao.findById(destPoolId)).thenReturn(destPool); - unmanagedVMsManager.checkConversionStoragePool(destPoolId, true); - } - - @Test(expected = CloudRuntimeException.class) - public void testCheckConversionStoragePoolPrimaryStagingPoolTypeNotAllowedForce() { - StoragePoolVO destPool = mock(StoragePoolVO.class); - Mockito.when(destPool.getPoolType()).thenReturn(Storage.StoragePoolType.RBD); - long destPoolId = 1L; - Mockito.when(primaryDataStoreDao.findById(destPoolId)).thenReturn(destPool); - unmanagedVMsManager.checkConversionStoragePool(destPoolId, true); - } - - @Test - public void testCheckExtraParamsAllowedEmptyParams() { - unmanagedVMsManager.checkExtraParamsAllowed(null); - Mockito.verifyNoInteractions(configKeyMockParamsAllowed); - } - - @Test(expected = ServerApiException.class) - public void testCheckExtraParamsAllowedDisabledByAdministrator() { - unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowed = configKeyMockParamsAllowed; - Mockito.when(configKeyMockParamsAllowed.value()).thenReturn(false); - unmanagedVMsManager.checkExtraParamsAllowed("--mac 00:0c:29:e6:3d:9d:ip:192.168.0.89,192.168.0.1,24,192.168.0.254 -x"); - } - - @Test(expected = ServerApiException.class) - public void testCheckExtraParamsAllowedEnabledButEmptyAllowedList() { - unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowed = configKeyMockParamsAllowed; - unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowedList = configKeyMockParamsAllowedList; - Mockito.when(configKeyMockParamsAllowed.value()).thenReturn(true); - Mockito.when(configKeyMockParamsAllowedList.value()).thenReturn(null); - unmanagedVMsManager.checkExtraParamsAllowed("--mac 00:0c:29:e6:3d:9d:ip:192.168.0.89,192.168.0.1,24,192.168.0.254 -x"); - } - - @Test - public void testCheckExtraParamsAllowedEnabledAndAllowedList() { - unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowed = configKeyMockParamsAllowed; - unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowedList = configKeyMockParamsAllowedList; - Mockito.when(configKeyMockParamsAllowed.value()).thenReturn(true); - Mockito.when(configKeyMockParamsAllowedList.value()).thenReturn("mac,network,x"); - unmanagedVMsManager.checkExtraParamsAllowed("--mac 00:0c:29:e6:3d:9d:ip:192.168.0.89,192.168.0.1,24,192.168.0.254 -x"); - } - - @Test(expected = ServerApiException.class) - public void testCheckExtraParamsAllowedEnabledParamNotInTheAllowedList() { - unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowed = configKeyMockParamsAllowed; - unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowedList = configKeyMockParamsAllowedList; - Mockito.when(configKeyMockParamsAllowed.value()).thenReturn(true); - Mockito.when(configKeyMockParamsAllowedList.value()).thenReturn("network,x"); - unmanagedVMsManager.checkExtraParamsAllowed("--mac 00:0c:29:e6:3d:9d:ip:192.168.0.89,192.168.0.1,24,192.168.0.254 -x"); - } - - @Test - public void testAddServiceOfferingDetailsToParamsFixedOffering() { - Map params = new HashMap<>(); - ServiceOfferingVO serviceOfferingVO = mock(ServiceOfferingVO.class); - Mockito.when(serviceOfferingVO.getCpu()).thenReturn(2); - Mockito.when(serviceOfferingVO.getRamSize()).thenReturn(2048); - unmanagedVMsManager.addServiceOfferingDetailsToParams(params, serviceOfferingVO); - Assert.assertEquals("2", params.get(VmDetailConstants.CPU_NUMBER)); - Assert.assertEquals("2048", params.get(VmDetailConstants.MEMORY)); - } - - @Test - public void testAddServiceOfferingDetailsToParamsCustomConstrainedOffering() { - Map params = new HashMap<>(); - ServiceOfferingVO serviceOfferingVO = mock(ServiceOfferingVO.class); - Map details = new HashMap<>(); - details.put(ApiConstants.MIN_CPU_NUMBER, "1"); - details.put(ApiConstants.MIN_MEMORY, "1024"); - Mockito.when(serviceOfferingVO.getDetails()).thenReturn(details); - Mockito.when(serviceOfferingVO.getCpu()).thenReturn(null); - Mockito.when(serviceOfferingVO.getSpeed()).thenReturn(1500); - Mockito.when(serviceOfferingVO.getRamSize()).thenReturn(null); - unmanagedVMsManager.addServiceOfferingDetailsToParams(params, serviceOfferingVO); - Assert.assertEquals("1", params.get(VmDetailConstants.CPU_NUMBER)); - Assert.assertEquals("1500", params.get(VmDetailConstants.CPU_SPEED)); - Assert.assertEquals("1024", params.get(VmDetailConstants.MEMORY)); - } - - @Test - public void testAddServiceOfferingDetailsToParamsCustomUnconstrainedOffering() { - Map params = new HashMap<>(); - ServiceOfferingVO serviceOfferingVO = mock(ServiceOfferingVO.class); - Mockito.when(serviceOfferingVO.getCpu()).thenReturn(null); - Mockito.when(serviceOfferingVO.getSpeed()).thenReturn(null); - Mockito.when(serviceOfferingVO.getRamSize()).thenReturn(null); - unmanagedVMsManager.addServiceOfferingDetailsToParams(params, serviceOfferingVO); - Assert.assertFalse(params.containsKey(VmDetailConstants.CPU_NUMBER)); - Assert.assertFalse(params.containsKey(VmDetailConstants.CPU_SPEED)); - Assert.assertFalse(params.containsKey(VmDetailConstants.MEMORY)); - } - - @Test - public void checkVmResourceLimitsForUnmanagedInstanceImportTestUsesInformationFromHypervisorWhenOfferingIsDynamic() throws Exception { - when(serviceOfferingMock.isDynamic()).thenReturn(true); - List reservations = new ArrayList<>(); - - try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.checkVmResourceLimitsForUnmanagedInstanceImport(accountMock, unmanagedInstanceMock, serviceOfferingMock, templateMock, reservations); - - Assert.assertEquals(3, mockedConstruction.constructed().size()); - Assert.assertEquals(3, reservations.size()); - verify(unmanagedInstanceMock).getCpuCores(); - verify(unmanagedInstanceMock).getMemory(); - } - } - - @Test - public void checkVmResourceLimitsForUnmanagedInstanceImportTestUsesInformationFromHypervisorWhenVmIsPoweredOn() throws Exception { - when(unmanagedInstanceMock.getPowerState()).thenReturn(UnmanagedInstanceTO.PowerState.PowerOn); - when(serviceOfferingMock.isDynamic()).thenReturn(false); - List reservations = new ArrayList<>(); - - try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.checkVmResourceLimitsForUnmanagedInstanceImport(accountMock, unmanagedInstanceMock, serviceOfferingMock, templateMock, reservations); - - Assert.assertEquals(3, mockedConstruction.constructed().size()); - Assert.assertEquals(3, reservations.size()); - verify(unmanagedInstanceMock).getCpuCores(); - verify(unmanagedInstanceMock).getMemory(); - } - } - - @Test - public void checkVmResourceLimitsForUnmanagedInstanceImportTestUsesInformationFromOfferingWhenOfferingIsNotDynamicAndVmIsPoweredOff() throws Exception { - when(unmanagedInstanceMock.getPowerState()).thenReturn(UnmanagedInstanceTO.PowerState.PowerOff); - when(serviceOfferingMock.isDynamic()).thenReturn(false); - List reservations = new ArrayList<>(); - - try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.checkVmResourceLimitsForUnmanagedInstanceImport(accountMock, unmanagedInstanceMock, serviceOfferingMock, templateMock, reservations); - - Assert.assertEquals(3, mockedConstruction.constructed().size()); - Assert.assertEquals(3, reservations.size()); - verify(serviceOfferingMock).getCpu(); - verify(serviceOfferingMock).getRamSize(); - verify(unmanagedInstanceMock, Mockito.never()).getCpuCores(); - verify(unmanagedInstanceMock, Mockito.never()).getMemory(); - } - } - - @Test - public void checkVmResourceLimitsForExternalKvmVmImportTestUsesInformationFromOfferingWhenOfferingIsNotDynamic() throws ResourceAllocationException { - when(serviceOfferingMock.isDynamic()).thenReturn(false); - Map details = new HashMap<>(); - List reservations = new ArrayList<>(); - - try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.checkVmResourceLimitsForExternalKvmVmImport(accountMock, serviceOfferingMock, templateMock, details, reservations); - - Assert.assertEquals(3, mockedConstruction.constructed().size()); - Assert.assertEquals(3, reservations.size()); - verify(serviceOfferingMock).getCpu(); - verify(serviceOfferingMock).getRamSize(); - verify(unmanagedVMsManager, Mockito.never()).getDetailAsInteger(VmDetailConstants.CPU_NUMBER, details); - verify(unmanagedVMsManager, Mockito.never()).getDetailAsInteger(VmDetailConstants.MEMORY, details); - } - } - - @Test - public void checkVmResourceLimitsForExternalKvmVmImportTestUsesInformationFromDetailsWhenOfferingIsDynamic() throws ResourceAllocationException { - when(serviceOfferingMock.isDynamic()).thenReturn(true); - Map details = new HashMap<>(); - details.put(VmDetailConstants.CPU_NUMBER, "8"); - details.put(VmDetailConstants.MEMORY, "4096"); - List reservations = new ArrayList<>(); - - try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { - unmanagedVMsManager.checkVmResourceLimitsForExternalKvmVmImport(accountMock, serviceOfferingMock, templateMock, details, reservations); - - Assert.assertEquals(3, mockedConstruction.constructed().size()); - Assert.assertEquals(3, reservations.size()); - verify(unmanagedVMsManager).getDetailAsInteger(VmDetailConstants.CPU_NUMBER, details); - verify(unmanagedVMsManager).getDetailAsInteger(VmDetailConstants.MEMORY, details); - } - } - - @Test(expected = InvalidParameterValueException.class) - public void getDetailAsIntegerTestThrowsInvalidParameterValueExceptionWhenDetailIsNull() { - Map details = new HashMap<>(); - unmanagedVMsManager.getDetailAsInteger("non-existent", details); - } - - @Test(expected = InvalidParameterValueException.class) - public void getDetailAsIntegerTestThrowsInvalidParameterValueExceptionWhenValueIsInvalid() { - Map details = new HashMap<>(); - details.put("key", "not-a-number"); - unmanagedVMsManager.getDetailAsInteger("key", details); - } - - // ------------------------------------------------------------------------- - // mergeNicMacAddresses tests - // ------------------------------------------------------------------------- - - @Test - public void mergeNicMacAddressesEmptyMacMapReturnsOriginal() { - Map ipMap = new HashMap<>(); - ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); - - Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, new HashMap<>()); - - Assert.assertSame(ipMap, result); - Assert.assertNull(result.get("nic1").getMacAddress()); - } - - @Test - public void mergeNicMacAddressesNullMacMapReturnsOriginal() { - Map ipMap = new HashMap<>(); - ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); - - Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, null); - - Assert.assertSame(ipMap, result); - } - - @Test - public void mergeNicMacAddressesMacMergedIntoExistingEntry() { - Map ipMap = new HashMap<>(); - ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); - - Map macMap = new HashMap<>(); - macMap.put("nic1", "aa:bb:cc:dd:ee:ff"); - - Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, macMap); - - Assert.assertEquals("aa:bb:cc:dd:ee:ff", result.get("nic1").getMacAddress()); - Assert.assertEquals("10.0.0.1", result.get("nic1").getIp4Address()); - } - - @Test - public void mergeNicMacAddressesNewEntryCreatedWhenNicNotInIpMap() { - Map ipMap = new HashMap<>(); - - Map macMap = new HashMap<>(); - macMap.put("nic1", "aa:bb:cc:dd:ee:ff"); - - Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, macMap); - - Assert.assertNotNull(result.get("nic1")); - Assert.assertEquals("aa:bb:cc:dd:ee:ff", result.get("nic1").getMacAddress()); - Assert.assertNull(result.get("nic1").getIp4Address()); - } - - @Test - public void mergeNicMacAddressesMultipleNicsMergedCorrectly() { - Map ipMap = new HashMap<>(); - ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); - ipMap.put("nic2", new Network.IpAddresses("10.0.0.2", null)); - - Map macMap = new HashMap<>(); - macMap.put("nic1", "aa:bb:cc:dd:ee:01"); - macMap.put("nic2", "aa:bb:cc:dd:ee:02"); - - Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, macMap); - - Assert.assertEquals("aa:bb:cc:dd:ee:01", result.get("nic1").getMacAddress()); - Assert.assertEquals("10.0.0.1", result.get("nic1").getIp4Address()); - Assert.assertEquals("aa:bb:cc:dd:ee:02", result.get("nic2").getMacAddress()); - Assert.assertEquals("10.0.0.2", result.get("nic2").getIp4Address()); - } - - // ------------------------------------------------------------------------- - // importNic: caller MAC vs hypervisor MAC selection - // ------------------------------------------------------------------------- - - @Test - public void importNicUsesCallerSuppliedMacWhenPresent() throws Exception { - UnmanagedInstanceTO.Nic nic = new UnmanagedInstanceTO.Nic(); - nic.setNicId("nic1"); - nic.setMacAddress("11:22:33:44:55:66"); - - Network.IpAddresses ipAddresses = new Network.IpAddresses(null, null, "aa:bb:cc:dd:ee:ff"); - - NetworkVO networkVO = Mockito.mock(NetworkVO.class); - when(networkVO.getDataCenterId()).thenReturn(1L); - - UserVmVO vm = Mockito.mock(UserVmVO.class); - NicProfile result = unmanagedVMsManager.importNic(nic, vm, networkVO, ipAddresses, 0, true, false); - - Assert.assertNotNull(result); - Mockito.verify(networkOrchestrationService).importNic( - Mockito.eq("aa:bb:cc:dd:ee:ff"), - Mockito.anyInt(), Mockito.any(), Mockito.anyBoolean(), - Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyBoolean()); - } - - @Test - public void importNicFallsBackToHypervisorMacWhenIpAddressesHasNoMac() throws Exception { - UnmanagedInstanceTO.Nic nic = new UnmanagedInstanceTO.Nic(); - nic.setNicId("nic1"); - nic.setMacAddress("11:22:33:44:55:66"); - - Network.IpAddresses ipAddresses = new Network.IpAddresses("10.0.0.1", null); // no MAC - - NetworkVO networkVO = Mockito.mock(NetworkVO.class); - when(networkVO.getDataCenterId()).thenReturn(1L); - - UserVmVO vm = Mockito.mock(UserVmVO.class); - NicProfile result = unmanagedVMsManager.importNic(nic, vm, networkVO, ipAddresses, 0, true, false); - - Assert.assertNotNull(result); - Mockito.verify(networkOrchestrationService).importNic( - Mockito.eq("11:22:33:44:55:66"), - Mockito.anyInt(), Mockito.any(), Mockito.anyBoolean(), - Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyBoolean()); - } - - @Test - public void importNicFallsBackToHypervisorMacWhenIpAddressesIsNull() throws Exception { - UnmanagedInstanceTO.Nic nic = new UnmanagedInstanceTO.Nic(); - nic.setNicId("nic1"); - nic.setMacAddress("11:22:33:44:55:66"); - - NetworkVO networkVO = Mockito.mock(NetworkVO.class); - when(networkVO.getDataCenterId()).thenReturn(1L); - - UserVmVO vm = Mockito.mock(UserVmVO.class); - NicProfile result = unmanagedVMsManager.importNic(nic, vm, networkVO, null, 0, true, false); - - Assert.assertNotNull(result); - Mockito.verify(networkOrchestrationService).importNic( - Mockito.eq("11:22:33:44:55:66"), - Mockito.anyInt(), Mockito.any(), Mockito.anyBoolean(), - Mockito.any(), Mockito.isNull(), Mockito.any(), Mockito.anyBoolean()); - } -} - \ No newline at end of file +// 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.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.apache.cloudstack.api.ApiConstants; +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.ImportVmCmd; +import org.apache.cloudstack.api.command.admin.vm.ListUnmanagedInstancesCmd; +import org.apache.cloudstack.api.command.admin.vm.ListVmsForImportCmd; +import org.apache.cloudstack.api.response.ListResponse; +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.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.framework.config.ConfigKey; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.resourcelimit.Reserver; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.jetbrains.annotations.NotNull; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.BDDMockito; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedConstruction; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CheckConvertInstanceAnswer; +import com.cloud.agent.api.CheckConvertInstanceCommand; +import com.cloud.agent.api.CheckVolumeAnswer; +import com.cloud.agent.api.CheckVolumeCommand; +import com.cloud.agent.api.ConvertInstanceAnswer; +import com.cloud.agent.api.ConvertInstanceCommand; +import com.cloud.agent.api.CopyRemoteVolumeAnswer; +import com.cloud.agent.api.CopyRemoteVolumeCommand; +import com.cloud.agent.api.GetRemoteVmsAnswer; +import com.cloud.agent.api.GetRemoteVmsCommand; +import com.cloud.agent.api.GetUnmanagedInstancesAnswer; +import com.cloud.agent.api.GetUnmanagedInstancesCommand; +import com.cloud.agent.api.ImportConvertedInstanceAnswer; +import com.cloud.agent.api.ImportConvertedInstanceCommand; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.dc.ClusterVO; +import com.cloud.dc.DataCenter; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.VmwareDatacenterVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.VmwareDatacenterDao; +import com.cloud.deploy.DeployDestination; +import com.cloud.deploy.DeploymentPlanningManager; +import com.cloud.event.ActionEventUtils; +import com.cloud.event.UsageEventUtils; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.InsufficientServerCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.OperationTimedoutException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.exception.UnsupportedServiceException; +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.hypervisor.HypervisorGuru; +import com.cloud.hypervisor.HypervisorGuruManager; +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; +import com.cloud.offering.NetworkOffering; +import com.cloud.offering.ServiceOffering; +import com.cloud.org.Grouping; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceState; +import com.cloud.resourcelimit.CheckedReservation; +import com.cloud.service.ServiceOfferingVO; +import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.DiskOfferingVO; +import com.cloud.storage.ScopeType; +import com.cloud.storage.Snapshot; +import com.cloud.storage.SnapshotVO; +import com.cloud.storage.Storage; +import com.cloud.storage.StoragePool; +import com.cloud.storage.StoragePoolHostVO; +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.SnapshotDao; +import com.cloud.storage.dao.StoragePoolHostDao; +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.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.utils.db.EntityManager; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.DiskProfile; +import com.cloud.vm.ImportVMTaskVO; +import com.cloud.vm.NicProfile; +import com.cloud.vm.UserVmManager; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.VmDetailConstants; +import com.cloud.vm.VMInstanceDetailVO; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.dao.NicDao; +import com.cloud.vm.dao.UserVmDao; +import com.cloud.vm.dao.VMInstanceDao; +import com.cloud.vm.dao.VMInstanceDetailsDao; + +@RunWith(MockitoJUnitRunner.class) +public class UnmanagedVMsManagerImplTest { + + @Spy + @InjectMocks + private UnmanagedVMsManagerImpl unmanagedVMsManager; + + @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 VolumeDao volumeDao; + @Mock + private ResourceLimitService resourceLimitService; + @Mock + private PrimaryDataStoreDao primaryDataStoreDao; + @Mock + private VolumeApiService volumeApiService; + @Mock + private NetworkModel networkModel; + @Mock + private ConfigurationDao configurationDao; + @Mock + private UserVmDao userVmDao; + @Mock + private NicDao nicDao; + @Mock + private HostDao hostDao; + @Mock + private VmwareDatacenterDao vmwareDatacenterDao; + @Mock + private HypervisorGuruManager hypervisorGuruManager; + @Mock + private ImageStoreDao imageStoreDao; + @Mock + private DataStoreManager dataStoreManager; + @Mock + private StoragePoolHostDao storagePoolHostDao; + @Mock + private ImportVmTasksManager importVmTasksManager; + @Mock + private SnapshotDao snapshotDao; + + @Mock + private VMInstanceVO virtualMachine; + @Mock + EntityManager entityMgr; + @Mock + DeploymentPlanningManager deploymentPlanningManager; + @Mock + ImportVMTaskVO importVMTaskVO; + @Mock + private VMInstanceDetailsDao vmInstanceDetailsDao; + @Mock + private ConfigKey configKeyMockParamsAllowed; + @Mock + private ConfigKey configKeyMockParamsAllowedList; + @Mock + private Account accountMock; + @Mock + private ServiceOfferingVO serviceOfferingMock; + @Mock + private VMTemplateVO templateMock; + @Mock + private UnmanagedInstanceTO unmanagedInstanceMock; + + private static final long virtualMachineId = 1L; + + private AutoCloseable closeable; + + private MockedStatic actionEventUtilsMocked; + + private UnmanagedInstanceTO instance; + + @Before + public void setUp() throws Exception { + closeable = MockitoAnnotations.openMocks(this); + actionEventUtilsMocked = Mockito.mockStatic(ActionEventUtils.class); + BDDMockito.given(ActionEventUtils.onStartedActionEvent(anyLong(), anyLong(), anyString(), anyString(), anyLong(), anyString(), anyBoolean(), anyLong())) + .willReturn(1L); + BDDMockito.given(ActionEventUtils.onCompletedActionEvent(anyLong(), anyLong(), anyString(), anyString(), anyString(), anyLong(), anyString(), anyLong())) + .willReturn(1L); + + AccountVO account = new AccountVO("admin", 1L, "", 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); + + instance = new UnmanagedInstanceTO(); + instance.setName("TestInstance"); + instance.setCpuCores(2); + instance.setCpuCoresPerSocket(1); + instance.setCpuSpeed(1000); + instance.setMemory(1024); + instance.setOperatingSystem("CentOS 7"); + List instanceDisks = getDisks(); + instance.setDisks(instanceDisks); + 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(UnmanagedInstanceTO.PowerState.PowerOn); + + ClusterVO clusterVO = new ClusterVO(1L, 1L, "Cluster"); + clusterVO.setHypervisorType(Hypervisor.HypervisorType.VMware.toString()); + when(clusterDao.findById(anyLong())).thenReturn(clusterVO); + when(configurationDao.getValue(Mockito.anyString())).thenReturn(null); + List hosts = new ArrayList<>(); + HostVO hostVO = Mockito.mock(HostVO.class); + when(hostVO.isInMaintenanceStates()).thenReturn(false); + hosts.add(hostVO); + when(resourceManager.listHostsInClusterByStatus(anyLong(), any(Status.class))).thenReturn(hosts); + when(resourceManager.listAllUpAndEnabledHostsInOneZoneByHypervisor(any(Hypervisor.HypervisorType.class), anyLong())).thenReturn(hosts); + List templates = new ArrayList<>(); + when(templatePoolDao.listAll()).thenReturn(templates); + List volumes = new ArrayList<>(); + when(volumeDao.findIncludingRemovedByZone(anyLong())).thenReturn(volumes); + GetUnmanagedInstancesCommand cmd = Mockito.mock(GetUnmanagedInstancesCommand.class); + HashMap map = new HashMap<>(); + map.put(instance.getName(), instance); + Answer answer = new GetUnmanagedInstancesAnswer(cmd, "", map); + when(agentManager.easySend(anyLong(), any(GetUnmanagedInstancesCommand.class))).thenReturn(answer); + GetRemoteVmsCommand remoteVmListcmd = Mockito.mock(GetRemoteVmsCommand.class); + Answer remoteVmListAnswer = new GetRemoteVmsAnswer(remoteVmListcmd, "", map); + when(agentManager.easySend(anyLong(), any(GetRemoteVmsCommand.class))).thenReturn(remoteVmListAnswer); + DataCenterVO zone = Mockito.mock(DataCenterVO.class); + when(zone.getId()).thenReturn(1L); + when(dataCenterDao.findById(anyLong())).thenReturn(zone); + when(accountService.getActiveAccountById(anyLong())).thenReturn(Mockito.mock(Account.class)); + List users = new ArrayList<>(); + users.add(Mockito.mock(UserVO.class)); + when(userDao.listByAccount(anyLong())).thenReturn(users); + VMTemplateVO template = Mockito.mock(VMTemplateVO.class); + when(template.getName()).thenReturn("Template"); + when(templateDao.findById(anyLong())).thenReturn(template); + ServiceOfferingVO serviceOffering = Mockito.mock(ServiceOfferingVO.class); + when(serviceOffering.getId()).thenReturn(1L); + 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(anyLong())).thenReturn(serviceOffering); + when(serviceOfferingDao.findById(anyLong(), anyLong())).thenReturn(Mockito.mock(ServiceOfferingVO.class)); + DiskOfferingVO diskOfferingVO = Mockito.mock(DiskOfferingVO.class); + when(diskOfferingDao.findById(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 + userVm.setInstanceName(instance.getName()); + userVm.setHostName(instance.getName()); + StoragePoolVO poolVO = Mockito.mock(StoragePoolVO.class); + when(poolVO.getDataCenterId()).thenReturn(1L); + when(poolVO.getClusterId()).thenReturn(clusterVO.getId()); + List pools = new ArrayList<>(); + pools.add(poolVO); + when(primaryDataStoreDao.listPoolByHostPath(Mockito.anyString(), Mockito.anyString())).thenReturn(pools); + when(userVmManager.importVM(nullable(DataCenter.class), nullable(Host.class), nullable(VirtualMachineTemplate.class), nullable(String.class), nullable(String.class), + nullable(Account.class), nullable(String.class), nullable(Account.class), nullable(Boolean.class), nullable(String.class), + nullable(Long.class), nullable(Long.class), nullable(ServiceOffering.class), nullable(String.class), nullable(Long.class), + nullable(String.class), nullable(Hypervisor.HypervisorType.class), nullable(Map.class), nullable(VirtualMachine.PowerState.class), nullable(LinkedHashMap.class))).thenReturn(userVm); + 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(anyLong())).thenReturn(networkVO); + List networks = new ArrayList<>(); + networks.add(networkVO); + when(networkDao.listByZone(anyLong())).thenReturn(networks); + doNothing().when(networkModel).checkNetworkPermissions(any(Account.class), any(Network.class)); + NicProfile profile = Mockito.mock(NicProfile.class); + Integer deviceId = 100; + Pair pair = new Pair<>(profile, deviceId); + when(networkOrchestrationService.importNic(nullable(String.class), nullable(Integer.class), nullable(Network.class), nullable(Boolean.class), nullable(VirtualMachine.class), nullable(Network.IpAddresses.class), nullable(DataCenter.class), Mockito.anyBoolean())).thenReturn(pair); + when(volumeDao.findByInstance(Mockito.anyLong())).thenReturn(volumes); + List userVmResponses = new ArrayList<>(); + UserVmResponse userVmResponse = new UserVmResponse(); + userVmResponse.setInstanceName(instance.getName()); + userVmResponses.add(userVmResponse); + when(responseGenerator.createUserVmResponse(any(ResponseObject.ResponseView.class), Mockito.anyString(), any(UserVm.class))).thenReturn(userVmResponses); + + when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Running); + + when(unmanagedInstanceMock.getCpuCores()).thenReturn(8); + when(unmanagedInstanceMock.getMemory()).thenReturn(4096); + when(serviceOfferingMock.getCpu()).thenReturn(4); + when(serviceOfferingMock.getRamSize()).thenReturn(2048); + } + + @NotNull + private static List getDisks() { + List instanceDisks = new ArrayList<>(); + UnmanagedInstanceTO.Disk instanceDisk = new UnmanagedInstanceTO.Disk(); + instanceDisk.setDiskId("1000-1"); + instanceDisk.setPosition(0); + instanceDisk.setLabel("DiskLabel"); + instanceDisk.setController("scsi"); + instanceDisk.setImagePath("[b6ccf44a1fa13e29b3667b4954fa10ee] TestInstance/ROOT-1.vmdk"); + instanceDisk.setCapacity(5242880L); + instanceDisk.setDatastoreName("Test"); + instanceDisk.setDatastoreHost("Test"); + instanceDisk.setDatastorePath("Test"); + instanceDisk.setDatastoreType("NFS"); + instanceDisks.add(instanceDisk); + return instanceDisks; + } + + @After + public void tearDown() throws Exception { + closeable.close(); + actionEventUtilsMocked.close(); + CallContext.unregister(); + } + + @Test + public void listUnmanagedInstancesTest() { + ListUnmanagedInstancesCmd cmd = Mockito.mock(ListUnmanagedInstancesCmd.class); + unmanagedVMsManager.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.XenServer.toString()); + when(clusterDao.findById(anyLong())).thenReturn(cluster); + unmanagedVMsManager.listUnmanagedInstances(cmd); + } + + @Test(expected = PermissionDeniedException.class) + public void listUnmanagedInstancesInvalidCallerTest() { + CallContext.unregister(); + AccountVO account = new AccountVO("user", 1L, "", 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); + unmanagedVMsManager.listUnmanagedInstances(cmd); + } + + @Test + public void importUnmanagedInstanceTest() { + ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class); + when(importUnmanageInstanceCmd.getName()).thenReturn("TestInstance"); + when(importUnmanageInstanceCmd.getDomainId()).thenReturn(null); + when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true); + try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class); + MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.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"); + unmanagedVMsManager.importUnmanagedInstance(importUnmanageInstanceCmd); + } + + @Test(expected = ServerApiException.class) + public void importUnmanagedInstanceMissingInstanceTest() { + ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class); + when(importUnmanageInstanceCmd.getName()).thenReturn("SomeInstance"); + when(importUnmanageInstanceCmd.getDomainId()).thenReturn(null); + try (MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.importUnmanagedInstance(importUnmanageInstanceCmd); + } + } + + @Test(expected = InvalidParameterValueException.class) + public void unmanageVMInstanceMissingInstanceTest() { + when(vmDao.findById(anyLong())).thenReturn(null); + unmanagedVMsManager.unmanageVMInstance(1L, null, false); + } + + @Test(expected = InvalidParameterValueException.class) + public void unmanageVMInstanceRemovedInstanceTest() { + VMInstanceVO userVmVO = mock(VMInstanceVO.class); + when(vmDao.findById(anyLong())).thenReturn(userVmVO); + when(userVmVO.getRemoved()).thenReturn(new Date()); + unmanagedVMsManager.unmanageVMInstance(1L, null, false); + } + + @Test(expected = InvalidParameterValueException.class) + public void unmanageVMInstanceDestroyedInstanceTest() { + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Destroyed); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = InvalidParameterValueException.class) + public void unmanageVMInstanceExpungedInstanceTest() { + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Expunging); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void unmanageVMInstanceExistingVMSnapshotsTest() { + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.None); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void unmanageVMInstanceInvalidHyperVisor() { + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.None); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void unmanageVMInstanceInvalidVmType() { + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.VMware); + when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.ConsoleProxy); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void unmanageVMInstanceExistingVolumeSnapshotsTest() { + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.None); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void unmanageVMInstanceExistingISOAttachedTest() { + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.None); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void unmanageVMInstanceVmwareHostIdParamTest() { + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.VMware); + when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, 1L, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void unmanageVMInstanceRunningHostIdParamTest() { + when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Running); + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, 1L, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void unmanageVMInstanceRunningForceParamTest() { + when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Running); + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + VMInstanceDetailVO vmInstanceDetailVO = mock(VMInstanceDetailVO.class); + when(vmInstanceDetailsDao.findDetail(virtualMachineId, VmDetailConstants.CONFIG_DRIVE_LOCATION)).thenReturn(vmInstanceDetailVO); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test + public void unmanageVMInstanceVMwareHostId() { + when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); + UserVmVO userVmVO = mock(UserVmVO.class); + when(userVmVO.getIsoId()).thenReturn(null); + when(userVmDao.findById(anyLong())).thenReturn(userVmVO); + when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, 1L, false); + } + + @Test + public void unmanageVMInstanceStoppedInstanceTest() { + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); + UserVmVO userVmVO = mock(UserVmVO.class); + when(userVmDao.findById(anyLong())).thenReturn(userVmVO); + Mockito.doNothing().when(unmanagedVMsManager).performUnmanageVMInstancePrechecks(any()); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void testUnmanageVMInstanceWithVolumeSnapshotsFail() { + when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); + when(virtualMachine.getId()).thenReturn(virtualMachineId); + UserVmVO userVmVO = mock(UserVmVO.class); + when(userVmDao.findById(anyLong())).thenReturn(userVmVO); + when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); + VolumeVO volumeVO = mock(VolumeVO.class); + long volumeId = 20L; + when(volumeVO.getId()).thenReturn(volumeId); + SnapshotVO snapshotVO = mock(SnapshotVO.class); + when(snapshotVO.getState()).thenReturn(Snapshot.State.BackedUp); + when(snapshotDao.listByVolumeId(volumeId)).thenReturn(Collections.singletonList(snapshotVO)); + when(volumeDao.findByInstance(virtualMachineId)).thenReturn(Collections.singletonList(volumeVO)); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void testUnmanageVMInstanceWithAssociatedIsoFail() { + when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); + when(virtualMachine.getId()).thenReturn(virtualMachineId); + UserVmVO userVmVO = mock(UserVmVO.class); + when(userVmVO.getIsoId()).thenReturn(null); + when(userVmDao.findById(anyLong())).thenReturn(userVmVO); + when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); + when(userVmVO.getIsoId()).thenReturn(1L); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test(expected = UnsupportedServiceException.class) + public void testUnmanageVMInstanceBelongingToCksClusterFail() { + when(virtualMachine.getType()).thenReturn(VirtualMachine.Type.User); + when(virtualMachine.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped); + when(virtualMachine.getId()).thenReturn(virtualMachineId); + UserVmVO userVmVO = mock(UserVmVO.class); + when(userVmVO.getIsoId()).thenReturn(null); + when(userVmDao.findById(anyLong())).thenReturn(userVmVO); + when(vmDao.findById(virtualMachineId)).thenReturn(virtualMachine); + when(userVmManager.isVMPartOfAnyCKSCluster(virtualMachine)).thenReturn(true); + unmanagedVMsManager.unmanageVMInstance(virtualMachineId, null, false); + } + + @Test + public void testListRemoteInstancesTest() { + ListVmsForImportCmd cmd = Mockito.mock(ListVmsForImportCmd.class); + when(cmd.getHypervisor()).thenReturn(Hypervisor.HypervisorType.KVM.toString()); + when(cmd.getUsername()).thenReturn("user"); + when(cmd.getPassword()).thenReturn("pass"); + ListResponse response = unmanagedVMsManager.listVmsForImport(cmd); + Assert.assertEquals(1, response.getCount().intValue()); + } + + @Test(expected = InvalidParameterValueException.class) + public void testListRemoteInstancesTestNonKVM() { + ListVmsForImportCmd cmd = Mockito.mock(ListVmsForImportCmd.class); + unmanagedVMsManager.listVmsForImport(cmd); + } + @Test + public void testImportFromExternalTest() throws InsufficientServerCapacityException { + String vmname = "TestInstance"; + ImportVmCmd cmd = Mockito.mock(ImportVmCmd.class); + when(cmd.getHypervisor()).thenReturn(Hypervisor.HypervisorType.KVM.toString()); + when(cmd.getName()).thenReturn(vmname); + when(cmd.getUsername()).thenReturn("user"); + when(cmd.getPassword()).thenReturn("pass"); + when(cmd.getImportSource()).thenReturn("external"); + when(cmd.getDomainId()).thenReturn(null); + HostVO host = Mockito.mock(HostVO.class); + DeployDestination mockDest = Mockito.mock(DeployDestination.class); + when(deploymentPlanningManager.planDeployment(any(), any(), any(), any())).thenReturn(mockDest); + DiskProfile diskProfile = Mockito.mock(DiskProfile.class); + when(volumeManager.allocateRawVolume(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), anyBoolean())) + .thenReturn(diskProfile); + Map storage = new HashMap<>(); + VolumeVO volume = Mockito.mock(VolumeVO.class); + StoragePoolVO storagePool = Mockito.mock(StoragePoolVO.class); + storage.put(volume, storagePool); + when(mockDest.getStorageForDisks()).thenReturn(storage); + when(mockDest.getHost()).thenReturn(host); + when(volumeDao.findById(anyLong())).thenReturn(volume); + CopyRemoteVolumeAnswer copyAnswer = Mockito.mock(CopyRemoteVolumeAnswer.class); + when(copyAnswer.getResult()).thenReturn(true); + when(agentManager.easySend(anyLong(), any(CopyRemoteVolumeCommand.class))).thenReturn(copyAnswer); + try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class); + MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.importVm(cmd); + } + } + + private void baseBasicParametersCheckForImportInstance(String name, Long domainId, String accountName) { + unmanagedVMsManager.basicParametersCheckForImportInstance(name, domainId, accountName); + } + + @Test(expected = InvalidParameterValueException.class) + public void testBasicParametersCheckForImportInstanceMissingName() { + baseBasicParametersCheckForImportInstance(null, 1L, "test"); + } + + @Test(expected = InvalidParameterValueException.class) + public void testBasicParametersCheckForImportInstanceMissingDomainAndAccount() { + baseBasicParametersCheckForImportInstance("vm", 1L, ""); + } + + @Test(expected = InvalidParameterValueException.class) + public void testBasicAccessChecksMissingClusterId() { + unmanagedVMsManager.basicAccessChecks(null); + } + + @Test(expected = PermissionDeniedException.class) + public void testBasicAccessChecksNotAdminCaller() { + CallContext.unregister(); + AccountVO account = new AccountVO("user", 1L, "", 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); + unmanagedVMsManager.basicAccessChecks(1L); + } + + @Test(expected = InvalidParameterValueException.class) + public void testBasicAccessChecksUnsupportedHypervisorType() { + ClusterVO clusterVO = new ClusterVO(1L, 1L, "Cluster"); + clusterVO.setHypervisorType(Hypervisor.HypervisorType.XenServer.toString()); + when(clusterDao.findById(anyLong())).thenReturn(clusterVO); + unmanagedVMsManager.basicAccessChecks(1L); + } + + @Test + public void testGetTemplateForImportInstanceDefaultTemplate() { + String defaultTemplateName = "DefaultTemplate"; + VMTemplateVO template = Mockito.mock(VMTemplateVO.class); + when(template.getName()).thenReturn(defaultTemplateName); + when(templateDao.findByName(anyString())).thenReturn(template); + VMTemplateVO templateForImportInstance = unmanagedVMsManager.getTemplateForImportInstance(null, Hypervisor.HypervisorType.KVM); + Assert.assertEquals(defaultTemplateName, templateForImportInstance.getName()); + } + + private enum VcenterParameter { + EXISTING, + EXTERNAL, + BOTH, + NONE, + EXISTING_INVALID, + AGENT_UNAVAILABLE, + CONVERT_FAILURE, + FORCE_MS_AND_USE_VDDK, + USE_VDDK_OVF_UNSUPPORTED, + USE_VDDK_OVF_SUPPORTED, + USE_VDDK_DETAILS_OVERRIDES + } + + private void baseTestImportVmFromVmwareToKvm(VcenterParameter vcenterParameter, boolean selectConvertHost, + boolean selectTemporaryStorage) throws OperationTimedoutException, AgentUnavailableException { + long clusterId = 1L; + long zoneId = 1L; + long existingDatacenterId = 1L; + String vcenterHost = "192.168.1.2"; + String datacenter = "Datacenter"; + String username = "administrator@vsphere.local"; + String password = "password"; + String host = "192.168.1.10"; + String vmName = "TestInstanceFromVmware"; + instance.setName(vmName); + String tmplFileName = "5b8d689a-e61a-4ac3-9b76-e121ff90fbd3"; + long newVmId = 2L; + long networkId = 1L; + + ClusterVO cluster = mock(ClusterVO.class); + when(cluster.getId()).thenReturn(clusterId); + when(cluster.getAllocationState()).thenReturn(Grouping.AllocationState.Enabled); + when(cluster.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM); + when(cluster.getDataCenterId()).thenReturn(zoneId); + when(clusterDao.findById(clusterId)).thenReturn(cluster); + + ImportVmCmd importVmCmd = Mockito.mock(ImportVmCmd.class); + + when(importVmCmd.getName()).thenReturn(vmName); + when(importVmCmd.getClusterId()).thenReturn(clusterId); + when(importVmCmd.getDomainId()).thenReturn(null); + when(importVmCmd.getImportSource()).thenReturn(VmImportService.ImportSource.VMWARE.toString()); + when(importVmCmd.getHostIp()).thenReturn(host); + when(importVmCmd.getNicNetworkList()).thenReturn(Map.of("NIC 1", networkId)); + when(importVmCmd.getConvertInstanceHostId()).thenReturn(null); + when(importVmCmd.getImportInstanceHostId()).thenReturn(null); + when(importVmCmd.getConvertStoragePoolId()).thenReturn(null); + when(importVmCmd.getExistingVcenterId()).thenReturn(null); + when(importVmCmd.getVcenter()).thenReturn(null); + when(importVmCmd.getDatacenterName()).thenReturn(null); + when(importVmCmd.getUsername()).thenReturn(null); + when(importVmCmd.getPassword()).thenReturn(null); + when(importVmCmd.getDetails()).thenReturn(new HashMap<>()); + + boolean forceMsToImportVmFiles = false; + boolean useVddk = false; + boolean ovfExportSupported = false; + if (VcenterParameter.FORCE_MS_AND_USE_VDDK == vcenterParameter) { + forceMsToImportVmFiles = true; + useVddk = true; + } else if (VcenterParameter.USE_VDDK_OVF_UNSUPPORTED == vcenterParameter) { + useVddk = true; + } else if (VcenterParameter.USE_VDDK_OVF_SUPPORTED == vcenterParameter) { + useVddk = true; + ovfExportSupported = true; + } else if (VcenterParameter.USE_VDDK_DETAILS_OVERRIDES == vcenterParameter) { + useVddk = true; + ovfExportSupported = true; + when(importVmCmd.getDetails()).thenReturn(Map.of( + "vddk.lib.dir", "/opt/vmware-vddk/override", + "vddk.transports", "nbd:nbdssl", + "vddk.thumbprint", "AA:BB:CC:DD:EE")); + } + when(importVmCmd.getForceMsToImportVmFiles()).thenReturn(forceMsToImportVmFiles); + when(importVmCmd.getUseVddk()).thenReturn(useVddk); + + NetworkVO networkVO = Mockito.mock(NetworkVO.class); + when(networkVO.getGuestType()).thenReturn(Network.GuestType.L2); + when(networkVO.getDataCenterId()).thenReturn(zoneId); + when(networkDao.findById(networkId)).thenReturn(networkVO); + + HypervisorGuru vmwareGuru = mock(HypervisorGuru.class); + when(hypervisorGuruManager.getGuru(Hypervisor.HypervisorType.VMware)).thenReturn(vmwareGuru); + when(vmwareGuru.getHypervisorVMOutOfBandAndCloneIfRequired(anyString(), anyString(), anyMap())).thenReturn(new Pair<>(instance, true)); + when(vmwareGuru.removeClonedHypervisorVMOutOfBand(anyString(), anyString(), anyMap())).thenReturn(true); + when(vmwareGuru.createVMTemplateOutOfBand(anyString(), anyString(), anyMap(), any(DataStoreTO.class), anyInt())).thenReturn(tmplFileName); + when(vmwareGuru.removeVMTemplateOutOfBand(any(DataStoreTO.class), anyString())).thenReturn(true); + + HostVO convertHost = mock(HostVO.class); + long convertHostId = 1L; + when(convertHost.getStatus()).thenReturn(Status.Up); + when(convertHost.getResourceState()).thenReturn(ResourceState.Enabled); + when(convertHost.getId()).thenReturn(convertHostId); + when(convertHost.getType()).thenReturn(Host.Type.Routing); + when(convertHost.getDataCenterId()).thenReturn(zoneId); + when(convertHost.getClusterId()).thenReturn(clusterId); + if (selectConvertHost) { + when(importVmCmd.getConvertInstanceHostId()).thenReturn(convertHostId); + when(importVmCmd.getImportInstanceHostId()).thenReturn(convertHostId); + when(hostDao.findById(convertHostId)).thenReturn(convertHost); + } else { + when(hostDao.listByClusterAndHypervisorType(clusterId, Hypervisor.HypervisorType.KVM)).thenReturn(List.of(convertHost)); + } + + DataStoreTO dataStoreTO = mock(DataStoreTO.class); + DataStore dataStore = mock(DataStore.class); + when(dataStore.getTO()).thenReturn(dataStoreTO); + + StoragePoolVO destPool = mock(StoragePoolVO.class); + when(destPool.getDataCenterId()).thenReturn(zoneId); + when(destPool.getClusterId()).thenReturn(null); + when(destPool.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem); + StoragePoolVO zoneDestPool = mock(StoragePoolVO.class); + if (selectTemporaryStorage) { + long temporaryStoragePoolId = 1L; + when(importVmCmd.getConvertStoragePoolId()).thenReturn(temporaryStoragePoolId); + when(primaryDataStoreDao.findById(temporaryStoragePoolId)).thenReturn(destPool); + when(dataStoreManager.getPrimaryDataStore(temporaryStoragePoolId)).thenReturn(dataStore); + } else { + ImageStoreVO imageStoreVO = mock(ImageStoreVO.class); + when(imageStoreVO.getId()).thenReturn(1L); + when(imageStoreDao.findOneByZoneAndProtocol(zoneId, "nfs")).thenReturn(imageStoreVO); + when(dataStoreManager.getDataStore(1L, DataStoreRole.Image)).thenReturn(dataStore); + } + when(primaryDataStoreDao.listPoolByHostPath(Mockito.anyString(), Mockito.anyString())).thenReturn(List.of(destPool)); + when(primaryDataStoreDao.findClusterWideStoragePoolsByHypervisorAndPoolType(clusterId, Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)).thenReturn(List.of(destPool)); + when(primaryDataStoreDao.findZoneWideStoragePoolsByHypervisorAndPoolType(zoneId, Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)).thenReturn(List.of(zoneDestPool)); + + if (VcenterParameter.EXISTING == vcenterParameter) { + VmwareDatacenterVO datacenterVO = mock(VmwareDatacenterVO.class); + when(datacenterVO.getVcenterHost()).thenReturn(vcenterHost); + when(datacenterVO.getVmwareDatacenterName()).thenReturn(datacenter); + when(datacenterVO.getUser()).thenReturn(username); + when(datacenterVO.getPassword()).thenReturn(password); + when(importVmCmd.getExistingVcenterId()).thenReturn(existingDatacenterId); + when(vmwareDatacenterDao.findById(existingDatacenterId)).thenReturn(datacenterVO); + } + + if (VcenterParameter.BOTH == vcenterParameter) { + when(importVmCmd.getExistingVcenterId()).thenReturn(existingDatacenterId); + when(importVmCmd.getVcenter()).thenReturn(vcenterHost); + } else if (VcenterParameter.NONE == vcenterParameter) { + when(importVmCmd.getExistingVcenterId()).thenReturn(null); + when(importVmCmd.getVcenter()).thenReturn(null); + } else if (VcenterParameter.EXISTING_INVALID == vcenterParameter) { + when(importVmCmd.getExistingVcenterId()).thenReturn(existingDatacenterId); + when(vmwareDatacenterDao.findById(existingDatacenterId)).thenReturn(null); + } + + if (VcenterParameter.FORCE_MS_AND_USE_VDDK == vcenterParameter + || VcenterParameter.USE_VDDK_OVF_UNSUPPORTED == vcenterParameter + || VcenterParameter.USE_VDDK_OVF_SUPPORTED == vcenterParameter + || VcenterParameter.USE_VDDK_DETAILS_OVERRIDES == vcenterParameter) { + Mockito.doReturn((Long) null).when(importVmCmd).getExistingVcenterId(); + Mockito.doReturn(vcenterHost).when(importVmCmd).getVcenter(); + Mockito.doReturn(datacenter).when(importVmCmd).getDatacenterName(); + Mockito.doReturn(username).when(importVmCmd).getUsername(); + Mockito.doReturn(password).when(importVmCmd).getPassword(); + } + + CheckConvertInstanceAnswer checkConvertInstanceAnswer = mock(CheckConvertInstanceAnswer.class); + when(checkConvertInstanceAnswer.getResult()).thenReturn(vcenterParameter != VcenterParameter.CONVERT_FAILURE); + when(checkConvertInstanceAnswer.isOvfExportSupported()).thenReturn(ovfExportSupported); + if (VcenterParameter.AGENT_UNAVAILABLE != vcenterParameter) { + when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(CheckConvertInstanceCommand.class))).thenReturn(checkConvertInstanceAnswer); + } + + when(importVmTasksManager.createImportVMTaskRecord(any(DataCenter.class), any(Account.class), anyLong(), anyString(), + anyString(), anyString(), anyString(), any(Host.class), any(Host.class))).thenReturn(importVMTaskVO); + when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any(DiskOffering.class))).thenReturn(true); + + ConvertInstanceAnswer convertInstanceAnswer = mock(ConvertInstanceAnswer.class); + ImportConvertedInstanceAnswer convertImportedInstanceAnswer = mock(ImportConvertedInstanceAnswer.class); + when(convertInstanceAnswer.getResult()).thenReturn(vcenterParameter != VcenterParameter.CONVERT_FAILURE); + Mockito.lenient().when(convertImportedInstanceAnswer.getConvertedInstance()).thenReturn(instance); + Mockito.lenient().when(convertImportedInstanceAnswer.getResult()).thenReturn(vcenterParameter != VcenterParameter.CONVERT_FAILURE); + if (VcenterParameter.AGENT_UNAVAILABLE != vcenterParameter) { + when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(ConvertInstanceCommand.class))).thenReturn(convertInstanceAnswer); + Mockito.lenient().when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(ImportConvertedInstanceCommand.class))).thenReturn(convertImportedInstanceAnswer); + } + + try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class); + MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.importVm(importVmCmd); + verify(vmwareGuru).getHypervisorVMOutOfBandAndCloneIfRequired(Mockito.eq(host), Mockito.eq(vmName), anyMap()); + if (VcenterParameter.USE_VDDK_OVF_SUPPORTED == vcenterParameter) { + verify(vmwareGuru, Mockito.never()).createVMTemplateOutOfBand(anyString(), anyString(), anyMap(), any(DataStoreTO.class), anyInt()); + verify(agentManager).send(Mockito.eq(convertHostId), Mockito.argThat(command -> + command instanceof ConvertInstanceCommand && ((ConvertInstanceCommand) command).isUseVddk())); + verify(vmwareGuru, Mockito.never()).removeVMTemplateOutOfBand(any(DataStoreTO.class), anyString()); + } else if (VcenterParameter.USE_VDDK_DETAILS_OVERRIDES == vcenterParameter) { + verify(vmwareGuru, Mockito.never()).createVMTemplateOutOfBand(anyString(), anyString(), anyMap(), any(DataStoreTO.class), anyInt()); + verify(agentManager).send(Mockito.eq(convertHostId), Mockito.argThat(command -> { + if (!(command instanceof ConvertInstanceCommand)) { + return false; + } + ConvertInstanceCommand convertCmd = (ConvertInstanceCommand) command; + return convertCmd.isUseVddk() + && "/opt/vmware-vddk/override".equals(convertCmd.getVddkLibDir()) + && "nbd:nbdssl".equals(convertCmd.getVddkTransports()) + && "AA:BB:CC:DD:EE".equals(convertCmd.getVddkThumbprint()); + })); + verify(vmwareGuru, Mockito.never()).removeVMTemplateOutOfBand(any(DataStoreTO.class), anyString()); + } else { + verify(vmwareGuru).createVMTemplateOutOfBand(Mockito.eq(host), Mockito.eq(vmName), anyMap(), any(DataStoreTO.class), anyInt()); + verify(vmwareGuru).removeVMTemplateOutOfBand(any(DataStoreTO.class), anyString()); + } + verify(vmwareGuru).removeClonedHypervisorVMOutOfBand(Mockito.eq(host), Mockito.eq(vmName), anyMap()); + } + } + + @Test + public void importFromLocalDisk() throws InsufficientServerCapacityException { + importFromDisk("local"); + } + + @Test + public void importFromsharedStorage() throws InsufficientServerCapacityException { + importFromDisk("shared"); + } + + private void importFromDisk(String source) throws InsufficientServerCapacityException { + String vmname = "testVm"; + ImportVmCmd cmd = Mockito.mock(ImportVmCmd.class); + when(cmd.getHypervisor()).thenReturn(Hypervisor.HypervisorType.KVM.toString()); + when(cmd.getName()).thenReturn(vmname); + when(cmd.getImportSource()).thenReturn(source); + when(cmd.getDiskPath()).thenReturn("/var/lib/libvirt/images/test.qcow2"); + when(cmd.getDomainId()).thenReturn(null); + HostVO host = Mockito.mock(HostVO.class); + when(hostDao.findById(anyLong())).thenReturn(host); + NetworkOffering netOffering = Mockito.mock(NetworkOffering.class); + when(entityMgr.findById(NetworkOffering.class, 0L)).thenReturn(netOffering); + DeployDestination mockDest = Mockito.mock(DeployDestination.class); + when(deploymentPlanningManager.planDeployment(any(), any(), any(), any())).thenReturn(mockDest); + DiskProfile diskProfile = Mockito.mock(DiskProfile.class); + when(volumeManager.allocateRawVolume(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), anyBoolean())) + .thenReturn(diskProfile); + Map storage = new HashMap<>(); + VolumeVO volume = Mockito.mock(VolumeVO.class); + StoragePoolVO storagePool = Mockito.mock(StoragePoolVO.class); + storage.put(volume, storagePool); + when(mockDest.getStorageForDisks()).thenReturn(storage); + when(mockDest.getHost()).thenReturn(host); + when(volumeDao.findById(anyLong())).thenReturn(volume); + CheckVolumeAnswer answer = Mockito.mock(CheckVolumeAnswer.class); + when(answer.getResult()).thenReturn(true); + when(agentManager.easySend(anyLong(), any(CheckVolumeCommand.class))).thenReturn(answer); + List storagePools = new ArrayList<>(); + storagePools.add(storagePool); + when(primaryDataStoreDao.findLocalStoragePoolsByHostAndTags(anyLong(), any())).thenReturn(storagePools); + when(primaryDataStoreDao.findById(anyLong())).thenReturn(storagePool); + when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true); + StoragePoolHostVO storagePoolHost = Mockito.mock(StoragePoolHostVO.class); + when(storagePoolHostDao.findByPoolHost(anyLong(), anyLong())).thenReturn(storagePoolHost); + try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class); + MockedConstruction mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.importVm(cmd); + } + } + + @Test + public void testImportVmFromVmwareToKvmExistingVcenter() throws OperationTimedoutException, AgentUnavailableException { + baseTestImportVmFromVmwareToKvm(VcenterParameter.EXISTING, false, false); + } + + @Test + public void testImportVmFromVmwareToKvmExistingVcenterSetConvertHost() throws OperationTimedoutException, AgentUnavailableException { + baseTestImportVmFromVmwareToKvm(VcenterParameter.EXISTING, true, false); + } + + @Test + public void testImportVmFromVmwareToKvmExistingVcenterSetConvertHostAndTemporaryStorage() throws OperationTimedoutException, AgentUnavailableException { + baseTestImportVmFromVmwareToKvm(VcenterParameter.EXISTING, true, true); + } + + @Test(expected = ServerApiException.class) + public void testImportVmFromVmwareToKvmExistingVcenterExclusiveParameters() throws OperationTimedoutException, AgentUnavailableException { + baseTestImportVmFromVmwareToKvm(VcenterParameter.BOTH, false, false); + } + + @Test(expected = ServerApiException.class) + public void testImportVmFromVmwareToKvmExistingVcenterMissingParameters() throws OperationTimedoutException, AgentUnavailableException { + baseTestImportVmFromVmwareToKvm(VcenterParameter.NONE, false, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testImportVmFromVmwareToKvmExistingVcenterInvalid() throws OperationTimedoutException, AgentUnavailableException { + baseTestImportVmFromVmwareToKvm(VcenterParameter.EXISTING_INVALID, false, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testImportVmFromVmwareToKvmExistingVcenterAgentUnavailable() throws OperationTimedoutException, AgentUnavailableException { + baseTestImportVmFromVmwareToKvm(VcenterParameter.AGENT_UNAVAILABLE, false, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testImportVmFromVmwareToKvmExistingVcenterConvertFailure() throws OperationTimedoutException, AgentUnavailableException { + baseTestImportVmFromVmwareToKvm(VcenterParameter.CONVERT_FAILURE, false, false); + } + + @Test(expected = ServerApiException.class) + public void testImportVmFromVmwareToKvmForceMsMutuallyExclusiveWithUseVddk() throws OperationTimedoutException, AgentUnavailableException { + baseTestImportVmFromVmwareToKvm(VcenterParameter.FORCE_MS_AND_USE_VDDK, false, false); + } + + @Test(expected = InvalidParameterValueException.class) + public void testValidateSelectedConversionStoragePoolForVddkFailsWhenPoolDoesNotSupportDiskOfferings() { + long poolId = 11L; + StoragePoolVO selectedPool = mock(StoragePoolVO.class); + ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class); + DiskOfferingVO rootDiskOffering = mock(DiskOfferingVO.class); + DiskOfferingVO dataDiskOffering = mock(DiskOfferingVO.class); + + when(serviceOffering.getDiskOfferingId()).thenReturn(21L); + when(primaryDataStoreDao.findById(poolId)).thenReturn(selectedPool); + when(diskOfferingDao.findById(21L)).thenReturn(rootDiskOffering); + when(diskOfferingDao.findById(22L)).thenReturn(dataDiskOffering); + when(volumeApiService.doesStoragePoolSupportDiskOffering(selectedPool, rootDiskOffering)).thenReturn(true); + when(volumeApiService.doesStoragePoolSupportDiskOffering(selectedPool, dataDiskOffering)).thenReturn(false); + + unmanagedVMsManager.validateSelectedConversionStoragePoolForVddk(true, poolId, + serviceOffering, Map.of("1000-2", 22L)); + } + + @Test + public void testValidateSelectedConversionStoragePoolForVddkPassesWhenPoolSupportsAllDiskOfferings() { + long poolId = 12L; + StoragePoolVO selectedPool = mock(StoragePoolVO.class); + ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class); + DiskOfferingVO rootDiskOffering = mock(DiskOfferingVO.class); + DiskOfferingVO dataDiskOffering = mock(DiskOfferingVO.class); + + when(serviceOffering.getDiskOfferingId()).thenReturn(31L); + when(primaryDataStoreDao.findById(poolId)).thenReturn(selectedPool); + when(diskOfferingDao.findById(31L)).thenReturn(rootDiskOffering); + when(diskOfferingDao.findById(32L)).thenReturn(dataDiskOffering); + when(volumeApiService.doesStoragePoolSupportDiskOffering(selectedPool, rootDiskOffering)).thenReturn(true); + when(volumeApiService.doesStoragePoolSupportDiskOffering(selectedPool, dataDiskOffering)).thenReturn(true); + + unmanagedVMsManager.validateSelectedConversionStoragePoolForVddk(true, poolId, + serviceOffering, Map.of("1000-2", 32L)); + } + + private ClusterVO getClusterForTests() { + ClusterVO cluster = mock(ClusterVO.class); + when(cluster.getId()).thenReturn(1L); + when(cluster.getDataCenterId()).thenReturn(1L); + return cluster; + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectInstanceConversionTemporaryLocationInvalidStorage() { + ClusterVO cluster = getClusterForTests(); + + long poolId = 1L; + when(primaryDataStoreDao.findById(poolId)).thenReturn(null); + unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, poolId, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectInstanceConversionTemporaryLocationPoolInvalidScope() { + ClusterVO cluster = getClusterForTests(); + long poolId = 1L; + StoragePoolVO pool = mock(StoragePoolVO.class); + when(pool.getScope()).thenReturn(ScopeType.CLUSTER); + when(pool.getClusterId()).thenReturn(100L); + when(primaryDataStoreDao.findById(poolId)).thenReturn(pool); + unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, poolId, false); + } + + + @Test(expected = CloudRuntimeException.class) + public void testSelectInstanceConversionTemporaryLocationPoolConvertHostDifferentCluster() { + ClusterVO cluster = getClusterForTests(); + long poolId = 1L; + StoragePoolVO pool = mock(StoragePoolVO.class); + when(pool.getScope()).thenReturn(ScopeType.CLUSTER); + when(pool.getClusterId()).thenReturn(1L); + HostVO host = mock(HostVO.class); + when(primaryDataStoreDao.findById(poolId)).thenReturn(pool); + when(host.getClusterId()).thenReturn(2L); + unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, host, null, poolId, false); + } + + + @Test(expected = CloudRuntimeException.class) + public void testSelectInstanceConversionTemporaryLocationLocalStoragePoolInvalid() { + ClusterVO cluster = getClusterForTests(); + long poolId = 1L; + StoragePoolVO pool = mock(StoragePoolVO.class); + when(pool.getScope()).thenReturn(ScopeType.HOST); + when(primaryDataStoreDao.findById(poolId)).thenReturn(pool); + unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, poolId, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectInstanceConversionTemporaryLocationStoragePoolInvalidType() { + ClusterVO cluster = getClusterForTests(); + long poolId = 1L; + StoragePoolVO pool = mock(StoragePoolVO.class); + when(pool.getScope()).thenReturn(ScopeType.CLUSTER); + when(pool.getClusterId()).thenReturn(1L); + when(primaryDataStoreDao.findById(poolId)).thenReturn(pool); + when(pool.getPoolType()).thenReturn(Storage.StoragePoolType.RBD); + unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, poolId, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectInstanceConversionTemporaryLocationNoPoolAvailable() { + ClusterVO cluster = getClusterForTests(); + when(imageStoreDao.findOneByZoneAndProtocol(anyLong(), anyString())).thenReturn(null); + unmanagedVMsManager.selectInstanceConversionTemporaryLocation(cluster, null, null, null, false); + } + + @Test + public void testSelectKVMHostForImportingInClusterWithImportInstanceIdSuccess() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Enabled); + when(host.getStatus()).thenReturn(Status.Up); + when(host.getType()).thenReturn(Host.Type.Routing); + when(host.getClusterId()).thenReturn(1L); + + when(hostDao.findById(hostId)).thenReturn(host); + + HostVO returnedHost = unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); + Assert.assertEquals(host, returnedHost); + } + + @Test + public void testSelectKVMHostForImportingInClusterWithNullImportInstanceIdSuccess() { + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(hostDao.listByClusterAndHypervisorType(cluster.getId(), cluster.getHypervisorType())).thenReturn(List.of(host)); + + HostVO returnedHost = unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, null); + Assert.assertEquals(host, returnedHost); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForImportingInClusterFailure() { + ClusterVO cluster = getClusterForTests(); + when(hostDao.listByClusterAndHypervisorType(cluster.getId(), cluster.getHypervisorType())).thenReturn(List.of()); + + unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, null); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidCluster() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Enabled); + when(host.getStatus()).thenReturn(Status.Up); + when(host.getType()).thenReturn(Host.Type.Routing); + when(host.getClusterId()).thenReturn(2L); + + when(hostDao.findById(hostId)).thenReturn(host); + + unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidType() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Enabled); + when(host.getStatus()).thenReturn(Status.Up); + when(host.getType()).thenReturn(Host.Type.Storage); + + when(hostDao.findById(hostId)).thenReturn(host); + + unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidStatus() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Enabled); + when(host.getStatus()).thenReturn(Status.Alert); + + when(hostDao.findById(hostId)).thenReturn(host); + + unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidResourceState() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Disabled); + + when(hostDao.findById(hostId)).thenReturn(host); + + unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForImportingInClusterWithImportInstanceIdInvalidHostId() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + + when(hostDao.findById(hostId)).thenReturn(null); + + unmanagedVMsManager.selectKVMHostForImportingInCluster(cluster, hostId); + } + + @Test + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdEnabledHost() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Enabled); + when(host.getStatus()).thenReturn(Status.Up); + when(host.getType()).thenReturn(Host.Type.Routing); + when(host.getDataCenterId()).thenReturn(1L); + + when(hostDao.findById(hostId)).thenReturn(host); + + HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); + Assert.assertEquals(host, returnedHost); + } + + @Test + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdDisabledHost() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Disabled); + when(host.getStatus()).thenReturn(Status.Up); + when(host.getType()).thenReturn(Host.Type.Routing); + when(host.getDataCenterId()).thenReturn(1L); + + when(hostDao.findById(hostId)).thenReturn(host); + + HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); + Assert.assertEquals(host, returnedHost); + } + + @Test + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdSuccessCompatible() { + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + + when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(), + cluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION)).thenReturn(List.of(host)); + + HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, null, false); + Assert.assertEquals(host, returnedHost); + } + + @Test + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdSuccessNonCompatible() { + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + + when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(), + cluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION)).thenReturn(List.of()); + + when(hostDao.listByClusterAndHypervisorType(cluster.getId(), cluster.getHypervisorType())).thenReturn(List.of(host)); + + HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, null, false); + Assert.assertEquals(host, returnedHost); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdFailure() { + ClusterVO cluster = getClusterForTests(); + + when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(), + cluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION)).thenReturn(List.of()); + + when(hostDao.listByClusterAndHypervisorType(cluster.getId(), cluster.getHypervisorType())).thenReturn(List.of()); + + unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, null, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidZone() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Enabled); + when(host.getStatus()).thenReturn(Status.Up); + when(host.getType()).thenReturn(Host.Type.Routing); + when(host.getDataCenterId()).thenReturn(2L); + + when(hostDao.findById(hostId)).thenReturn(host); + + unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidType() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Enabled); + when(host.getStatus()).thenReturn(Status.Up); + when(host.getType()).thenReturn(Host.Type.SecondaryStorage); + + when(hostDao.findById(hostId)).thenReturn(host); + + unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidStatus() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Enabled); + when(host.getStatus()).thenReturn(Status.Down); + + when(hostDao.findById(hostId)).thenReturn(host); + + unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidResourceState() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + HostVO host = Mockito.mock(HostVO.class); + when(host.getResourceState()).thenReturn(ResourceState.Maintenance); + + when(hostDao.findById(hostId)).thenReturn(host); + + unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); + } + + @Test(expected = CloudRuntimeException.class) + public void testSelectKVMHostForConversionInClusterWithImportInstanceIdInvalidHostId() { + Long hostId = 1L; + ClusterVO cluster = getClusterForTests(); + + when(hostDao.findById(hostId)).thenReturn(null); + + unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, hostId, false); + } + + @Test + public void testSelectKVMHostForConversionInClusterVddkAutoSelectsHostWithVddkSupport() { + ClusterVO cluster = getClusterForTests(); + HostVO hostWithVddk = Mockito.mock(HostVO.class); + HostVO hostWithoutVddk = Mockito.mock(HostVO.class); + when(hostWithVddk.getDetail(Host.HOST_VDDK_SUPPORT)).thenReturn("true"); + when(hostWithoutVddk.getDetail(Host.HOST_VDDK_SUPPORT)).thenReturn(null); + + when(hostDao.listByClusterHypervisorTypeAndHostCapability(cluster.getId(), + cluster.getHypervisorType(), Host.HOST_INSTANCE_CONVERSION)) + .thenReturn(List.of(hostWithoutVddk, hostWithVddk)); + + HostVO returnedHost = unmanagedVMsManager.selectKVMHostForConversionInCluster(cluster, null, true); + Assert.assertEquals(hostWithVddk, returnedHost); + } + + @Test + public void testCheckConversionStoragePoolSecondaryStorageStaging() { + unmanagedVMsManager.checkConversionStoragePool(null, false); + Mockito.verifyNoInteractions(primaryDataStoreDao); + } + + @Test(expected = CloudRuntimeException.class) + public void testCheckConversionStoragePoolTemporarySecondaryStorageForceConvertToPool() { + unmanagedVMsManager.checkConversionStoragePool(null, true); + } + + @Test + public void testCheckConversionStoragePoolPrimaryStagingPool() { + StoragePoolVO destPool = mock(StoragePoolVO.class); + long destPoolId = 1L; + Mockito.when(primaryDataStoreDao.findById(destPoolId)).thenReturn(destPool); + unmanagedVMsManager.checkConversionStoragePool(destPoolId, false); + } + + @Test + public void testCheckConversionStoragePoolPrimaryStagingPoolTypeAllowedForce() { + StoragePoolVO destPool = mock(StoragePoolVO.class); + Mockito.when(destPool.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem); + long destPoolId = 1L; + Mockito.when(primaryDataStoreDao.findById(destPoolId)).thenReturn(destPool); + unmanagedVMsManager.checkConversionStoragePool(destPoolId, true); + } + + @Test(expected = CloudRuntimeException.class) + public void testCheckConversionStoragePoolPrimaryStagingPoolTypeNotAllowedForce() { + StoragePoolVO destPool = mock(StoragePoolVO.class); + Mockito.when(destPool.getPoolType()).thenReturn(Storage.StoragePoolType.RBD); + long destPoolId = 1L; + Mockito.when(primaryDataStoreDao.findById(destPoolId)).thenReturn(destPool); + unmanagedVMsManager.checkConversionStoragePool(destPoolId, true); + } + + @Test + public void testCheckExtraParamsAllowedEmptyParams() { + unmanagedVMsManager.checkExtraParamsAllowed(null); + Mockito.verifyNoInteractions(configKeyMockParamsAllowed); + } + + @Test(expected = ServerApiException.class) + public void testCheckExtraParamsAllowedDisabledByAdministrator() { + unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowed = configKeyMockParamsAllowed; + Mockito.when(configKeyMockParamsAllowed.value()).thenReturn(false); + unmanagedVMsManager.checkExtraParamsAllowed("--mac 00:0c:29:e6:3d:9d:ip:192.168.0.89,192.168.0.1,24,192.168.0.254 -x"); + } + + @Test(expected = ServerApiException.class) + public void testCheckExtraParamsAllowedEnabledButEmptyAllowedList() { + unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowed = configKeyMockParamsAllowed; + unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowedList = configKeyMockParamsAllowedList; + Mockito.when(configKeyMockParamsAllowed.value()).thenReturn(true); + Mockito.when(configKeyMockParamsAllowedList.value()).thenReturn(null); + unmanagedVMsManager.checkExtraParamsAllowed("--mac 00:0c:29:e6:3d:9d:ip:192.168.0.89,192.168.0.1,24,192.168.0.254 -x"); + } + + @Test + public void testCheckExtraParamsAllowedEnabledAndAllowedList() { + unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowed = configKeyMockParamsAllowed; + unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowedList = configKeyMockParamsAllowedList; + Mockito.when(configKeyMockParamsAllowed.value()).thenReturn(true); + Mockito.when(configKeyMockParamsAllowedList.value()).thenReturn("mac,network,x"); + unmanagedVMsManager.checkExtraParamsAllowed("--mac 00:0c:29:e6:3d:9d:ip:192.168.0.89,192.168.0.1,24,192.168.0.254 -x"); + } + + @Test(expected = ServerApiException.class) + public void testCheckExtraParamsAllowedEnabledParamNotInTheAllowedList() { + unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowed = configKeyMockParamsAllowed; + unmanagedVMsManager.ConvertVmwareInstanceToKvmExtraParamsAllowedList = configKeyMockParamsAllowedList; + Mockito.when(configKeyMockParamsAllowed.value()).thenReturn(true); + Mockito.when(configKeyMockParamsAllowedList.value()).thenReturn("network,x"); + unmanagedVMsManager.checkExtraParamsAllowed("--mac 00:0c:29:e6:3d:9d:ip:192.168.0.89,192.168.0.1,24,192.168.0.254 -x"); + } + + @Test + public void testAddServiceOfferingDetailsToParamsFixedOffering() { + Map params = new HashMap<>(); + ServiceOfferingVO serviceOfferingVO = mock(ServiceOfferingVO.class); + Mockito.when(serviceOfferingVO.getCpu()).thenReturn(2); + Mockito.when(serviceOfferingVO.getRamSize()).thenReturn(2048); + unmanagedVMsManager.addServiceOfferingDetailsToParams(params, serviceOfferingVO); + Assert.assertEquals("2", params.get(VmDetailConstants.CPU_NUMBER)); + Assert.assertEquals("2048", params.get(VmDetailConstants.MEMORY)); + } + + @Test + public void testAddServiceOfferingDetailsToParamsCustomConstrainedOffering() { + Map params = new HashMap<>(); + ServiceOfferingVO serviceOfferingVO = mock(ServiceOfferingVO.class); + Map details = new HashMap<>(); + details.put(ApiConstants.MIN_CPU_NUMBER, "1"); + details.put(ApiConstants.MIN_MEMORY, "1024"); + Mockito.when(serviceOfferingVO.getDetails()).thenReturn(details); + Mockito.when(serviceOfferingVO.getCpu()).thenReturn(null); + Mockito.when(serviceOfferingVO.getSpeed()).thenReturn(1500); + Mockito.when(serviceOfferingVO.getRamSize()).thenReturn(null); + unmanagedVMsManager.addServiceOfferingDetailsToParams(params, serviceOfferingVO); + Assert.assertEquals("1", params.get(VmDetailConstants.CPU_NUMBER)); + Assert.assertEquals("1500", params.get(VmDetailConstants.CPU_SPEED)); + Assert.assertEquals("1024", params.get(VmDetailConstants.MEMORY)); + } + + @Test + public void testAddServiceOfferingDetailsToParamsCustomUnconstrainedOffering() { + Map params = new HashMap<>(); + ServiceOfferingVO serviceOfferingVO = mock(ServiceOfferingVO.class); + Mockito.when(serviceOfferingVO.getCpu()).thenReturn(null); + Mockito.when(serviceOfferingVO.getSpeed()).thenReturn(null); + Mockito.when(serviceOfferingVO.getRamSize()).thenReturn(null); + unmanagedVMsManager.addServiceOfferingDetailsToParams(params, serviceOfferingVO); + Assert.assertFalse(params.containsKey(VmDetailConstants.CPU_NUMBER)); + Assert.assertFalse(params.containsKey(VmDetailConstants.CPU_SPEED)); + Assert.assertFalse(params.containsKey(VmDetailConstants.MEMORY)); + } + + @Test + public void checkVmResourceLimitsForUnmanagedInstanceImportTestUsesInformationFromHypervisorWhenOfferingIsDynamic() throws Exception { + when(serviceOfferingMock.isDynamic()).thenReturn(true); + List reservations = new ArrayList<>(); + + try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.checkVmResourceLimitsForUnmanagedInstanceImport(accountMock, unmanagedInstanceMock, serviceOfferingMock, templateMock, reservations); + + Assert.assertEquals(3, mockedConstruction.constructed().size()); + Assert.assertEquals(3, reservations.size()); + verify(unmanagedInstanceMock).getCpuCores(); + verify(unmanagedInstanceMock).getMemory(); + } + } + + @Test + public void checkVmResourceLimitsForUnmanagedInstanceImportTestUsesInformationFromHypervisorWhenVmIsPoweredOn() throws Exception { + when(unmanagedInstanceMock.getPowerState()).thenReturn(UnmanagedInstanceTO.PowerState.PowerOn); + when(serviceOfferingMock.isDynamic()).thenReturn(false); + List reservations = new ArrayList<>(); + + try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.checkVmResourceLimitsForUnmanagedInstanceImport(accountMock, unmanagedInstanceMock, serviceOfferingMock, templateMock, reservations); + + Assert.assertEquals(3, mockedConstruction.constructed().size()); + Assert.assertEquals(3, reservations.size()); + verify(unmanagedInstanceMock).getCpuCores(); + verify(unmanagedInstanceMock).getMemory(); + } + } + + @Test + public void checkVmResourceLimitsForUnmanagedInstanceImportTestUsesInformationFromOfferingWhenOfferingIsNotDynamicAndVmIsPoweredOff() throws Exception { + when(unmanagedInstanceMock.getPowerState()).thenReturn(UnmanagedInstanceTO.PowerState.PowerOff); + when(serviceOfferingMock.isDynamic()).thenReturn(false); + List reservations = new ArrayList<>(); + + try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.checkVmResourceLimitsForUnmanagedInstanceImport(accountMock, unmanagedInstanceMock, serviceOfferingMock, templateMock, reservations); + + Assert.assertEquals(3, mockedConstruction.constructed().size()); + Assert.assertEquals(3, reservations.size()); + verify(serviceOfferingMock).getCpu(); + verify(serviceOfferingMock).getRamSize(); + verify(unmanagedInstanceMock, Mockito.never()).getCpuCores(); + verify(unmanagedInstanceMock, Mockito.never()).getMemory(); + } + } + + @Test + public void checkVmResourceLimitsForExternalKvmVmImportTestUsesInformationFromOfferingWhenOfferingIsNotDynamic() throws ResourceAllocationException { + when(serviceOfferingMock.isDynamic()).thenReturn(false); + Map details = new HashMap<>(); + List reservations = new ArrayList<>(); + + try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.checkVmResourceLimitsForExternalKvmVmImport(accountMock, serviceOfferingMock, templateMock, details, reservations); + + Assert.assertEquals(3, mockedConstruction.constructed().size()); + Assert.assertEquals(3, reservations.size()); + verify(serviceOfferingMock).getCpu(); + verify(serviceOfferingMock).getRamSize(); + verify(unmanagedVMsManager, Mockito.never()).getDetailAsInteger(VmDetailConstants.CPU_NUMBER, details); + verify(unmanagedVMsManager, Mockito.never()).getDetailAsInteger(VmDetailConstants.MEMORY, details); + } + } + + @Test + public void checkVmResourceLimitsForExternalKvmVmImportTestUsesInformationFromDetailsWhenOfferingIsDynamic() throws ResourceAllocationException { + when(serviceOfferingMock.isDynamic()).thenReturn(true); + Map details = new HashMap<>(); + details.put(VmDetailConstants.CPU_NUMBER, "8"); + details.put(VmDetailConstants.MEMORY, "4096"); + List reservations = new ArrayList<>(); + + try (MockedConstruction mockedConstruction = Mockito.mockConstruction(CheckedReservation.class)) { + unmanagedVMsManager.checkVmResourceLimitsForExternalKvmVmImport(accountMock, serviceOfferingMock, templateMock, details, reservations); + + Assert.assertEquals(3, mockedConstruction.constructed().size()); + Assert.assertEquals(3, reservations.size()); + verify(unmanagedVMsManager).getDetailAsInteger(VmDetailConstants.CPU_NUMBER, details); + verify(unmanagedVMsManager).getDetailAsInteger(VmDetailConstants.MEMORY, details); + } + } + + @Test(expected = InvalidParameterValueException.class) + public void getDetailAsIntegerTestThrowsInvalidParameterValueExceptionWhenDetailIsNull() { + Map details = new HashMap<>(); + unmanagedVMsManager.getDetailAsInteger("non-existent", details); + } + + @Test(expected = InvalidParameterValueException.class) + public void getDetailAsIntegerTestThrowsInvalidParameterValueExceptionWhenValueIsInvalid() { + Map details = new HashMap<>(); + details.put("key", "not-a-number"); + unmanagedVMsManager.getDetailAsInteger("key", details); + } + + // ------------------------------------------------------------------------- + // mergeNicMacAddresses tests + // ------------------------------------------------------------------------- + + @Test + public void mergeNicMacAddressesEmptyMacMapReturnsOriginal() { + Map ipMap = new HashMap<>(); + ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); + + Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, new HashMap<>()); + + Assert.assertSame(ipMap, result); + Assert.assertNull(result.get("nic1").getMacAddress()); + } + + @Test + public void mergeNicMacAddressesNullMacMapReturnsOriginal() { + Map ipMap = new HashMap<>(); + ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); + + Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, null); + + Assert.assertSame(ipMap, result); + } + + @Test + public void mergeNicMacAddressesMacMergedIntoExistingEntry() { + Map ipMap = new HashMap<>(); + ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); + + Map macMap = new HashMap<>(); + macMap.put("nic1", "aa:bb:cc:dd:ee:ff"); + + Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, macMap); + + Assert.assertEquals("aa:bb:cc:dd:ee:ff", result.get("nic1").getMacAddress()); + Assert.assertEquals("10.0.0.1", result.get("nic1").getIp4Address()); + } + + @Test + public void mergeNicMacAddressesNewEntryCreatedWhenNicNotInIpMap() { + Map ipMap = new HashMap<>(); + + Map macMap = new HashMap<>(); + macMap.put("nic1", "aa:bb:cc:dd:ee:ff"); + + Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, macMap); + + Assert.assertNotNull(result.get("nic1")); + Assert.assertEquals("aa:bb:cc:dd:ee:ff", result.get("nic1").getMacAddress()); + Assert.assertNull(result.get("nic1").getIp4Address()); + } + + @Test + public void mergeNicMacAddressesMultipleNicsMergedCorrectly() { + Map ipMap = new HashMap<>(); + ipMap.put("nic1", new Network.IpAddresses("10.0.0.1", null)); + ipMap.put("nic2", new Network.IpAddresses("10.0.0.2", null)); + + Map macMap = new HashMap<>(); + macMap.put("nic1", "aa:bb:cc:dd:ee:01"); + macMap.put("nic2", "aa:bb:cc:dd:ee:02"); + + Map result = unmanagedVMsManager.mergeNicMacAddresses(ipMap, macMap); + + Assert.assertEquals("aa:bb:cc:dd:ee:01", result.get("nic1").getMacAddress()); + Assert.assertEquals("10.0.0.1", result.get("nic1").getIp4Address()); + Assert.assertEquals("aa:bb:cc:dd:ee:02", result.get("nic2").getMacAddress()); + Assert.assertEquals("10.0.0.2", result.get("nic2").getIp4Address()); + } + + // ------------------------------------------------------------------------- + // importNic: caller MAC vs hypervisor MAC selection + // ------------------------------------------------------------------------- + + @Test + public void importNicUsesCallerSuppliedMacWhenPresent() throws Exception { + UnmanagedInstanceTO.Nic nic = new UnmanagedInstanceTO.Nic(); + nic.setNicId("nic1"); + nic.setMacAddress("11:22:33:44:55:66"); + + Network.IpAddresses ipAddresses = new Network.IpAddresses(null, null, "aa:bb:cc:dd:ee:ff"); + + NetworkVO networkVO = Mockito.mock(NetworkVO.class); + when(networkVO.getDataCenterId()).thenReturn(1L); + + UserVmVO vm = Mockito.mock(UserVmVO.class); + NicProfile result = unmanagedVMsManager.importNic(nic, vm, networkVO, ipAddresses, 0, true, false); + + Assert.assertNotNull(result); + Mockito.verify(networkOrchestrationService).importNic( + Mockito.eq("aa:bb:cc:dd:ee:ff"), + Mockito.anyInt(), Mockito.any(), Mockito.anyBoolean(), + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyBoolean()); + } + + @Test + public void importNicFallsBackToHypervisorMacWhenIpAddressesHasNoMac() throws Exception { + UnmanagedInstanceTO.Nic nic = new UnmanagedInstanceTO.Nic(); + nic.setNicId("nic1"); + nic.setMacAddress("11:22:33:44:55:66"); + + Network.IpAddresses ipAddresses = new Network.IpAddresses("10.0.0.1", null); // no MAC + + NetworkVO networkVO = Mockito.mock(NetworkVO.class); + when(networkVO.getDataCenterId()).thenReturn(1L); + + UserVmVO vm = Mockito.mock(UserVmVO.class); + NicProfile result = unmanagedVMsManager.importNic(nic, vm, networkVO, ipAddresses, 0, true, false); + + Assert.assertNotNull(result); + Mockito.verify(networkOrchestrationService).importNic( + Mockito.eq("11:22:33:44:55:66"), + Mockito.anyInt(), Mockito.any(), Mockito.anyBoolean(), + Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyBoolean()); + } + + @Test + public void importNicFallsBackToHypervisorMacWhenIpAddressesIsNull() throws Exception { + UnmanagedInstanceTO.Nic nic = new UnmanagedInstanceTO.Nic(); + nic.setNicId("nic1"); + nic.setMacAddress("11:22:33:44:55:66"); + + NetworkVO networkVO = Mockito.mock(NetworkVO.class); + when(networkVO.getDataCenterId()).thenReturn(1L); + + UserVmVO vm = Mockito.mock(UserVmVO.class); + NicProfile result = unmanagedVMsManager.importNic(nic, vm, networkVO, null, 0, true, false); + + Assert.assertNotNull(result); + Mockito.verify(networkOrchestrationService).importNic( + Mockito.eq("11:22:33:44:55:66"), + Mockito.anyInt(), Mockito.any(), Mockito.anyBoolean(), + Mockito.any(), Mockito.isNull(), Mockito.any(), Mockito.anyBoolean()); + } +} + From 603b9dc1947190baeac045e28f6915ad079190c2 Mon Sep 17 00:00:00 2001 From: Prashanth Reddy Date: Thu, 11 Jun 2026 21:50:48 +0000 Subject: [PATCH 04/10] Fix truncated ImportUnmanagedInstanceCmd.java - restore complete class body --- .../admin/vm/ImportUnmanagedInstanceCmd.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) 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 380c34528c40..3c01d61a3cc5 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 @@ -279,3 +279,61 @@ public Map getDataDiskToDiskOfferingList() { throw new InvalidParameterValueException(String.format("Disk offering ID: %s for disk ID: %s is invalid", offeringUuid, disk)); } dataDiskToDiskOfferingMap.put(disk, _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 Instance: " + name; + } + + public boolean isForced() { + return BooleanUtils.isTrue(forced); + } + + ///////////////////////////////////////////////////// + /////////////// 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 long getEntityOwnerId() { + Long accountId = _accountService.finalizeAccountId(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; + } +} From de223ef93f4dc6b716371d46e79912477ed4ea40 Mon Sep 17 00:00:00 2001 From: Prashanth Reddy Date: Thu, 11 Jun 2026 22:03:03 +0000 Subject: [PATCH 05/10] Fix null bytes in UnmanagedVMsManagerImplTest.java from normalization --- .../org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java index ac4c9c43a38a..2ef43495109e 100644 --- a/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java @@ -1746,4 +1746,3 @@ public void importNicFallsBackToHypervisorMacWhenIpAddressesIsNull() throws Exce Mockito.any(), Mockito.isNull(), Mockito.any(), Mockito.anyBoolean()); } } - From e0eeb16218a693a65012579768c3b3f024f2abd4 Mon Sep 17 00:00:00 2001 From: Prashanth Reddy Date: Thu, 11 Jun 2026 22:26:46 +0000 Subject: [PATCH 06/10] Fix truncated UnmanagedVMsManagerImpl.java - restore complete class body with MAC address changes --- .../vm/UnmanagedVMsManagerImpl.java | 102 ++++++++++++------ 1 file changed, 71 insertions(+), 31 deletions(-) diff --git a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java index 577bf14f0838..ade40e92cb30 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java @@ -489,36 +489,6 @@ private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedIns return serviceOffering; } - /** - * Merges caller-supplied MAC addresses into the NIC IP address map. - * For each NIC entry in {@code nicMacAddressMap}, the MAC address is set on the corresponding - * {@link Network.IpAddresses} object. If no IP address entry exists for a given NIC, a new - * {@link Network.IpAddresses} object is created to carry the MAC. - * - * @param nicIpAddressMap map of NIC ID to IP addresses (may be empty, never null after cmd getter) - * @param nicMacAddressMap map of NIC ID to validated/standardized MAC address strings - * @return merged map with MAC addresses populated where supplied by the caller - */ - protected Map mergeNicMacAddresses( - final Map nicIpAddressMap, - final Map nicMacAddressMap) { - if (MapUtils.isEmpty(nicMacAddressMap)) { - return nicIpAddressMap; - } - Map merged = new HashMap<>(nicIpAddressMap); - for (Map.Entry entry : nicMacAddressMap.entrySet()) { - String nicId = entry.getKey(); - String mac = entry.getValue(); - Network.IpAddresses existing = merged.get(nicId); - if (existing != null) { - existing.setMacAddress(mac); - } else { - merged.put(nicId, new Network.IpAddresses(null, null, mac)); - } - } - return merged; - } - private Map getNicIpAddresses(final List nics, final Map callerNicIpAddressMap) { Map nicIpAddresses = new HashMap<>(); for (UnmanagedInstanceTO.Nic nic : nics) { @@ -890,6 +860,36 @@ protected NicProfile importNic(UnmanagedInstanceTO.Nic nic, VirtualMachine vm, N return result.first(); } + + /** + * Merges caller-supplied MAC addresses into the NIC IP address map. + * For each NIC entry in {@code nicMacAddressMap}, the MAC address is set on the corresponding + * {@link Network.IpAddresses} object. If no IP address entry exists for a given NIC, a new + * {@link Network.IpAddresses} object is created to carry the MAC. + * + * @param nicIpAddressMap map of NIC ID to IP addresses (may be empty, never null after cmd getter) + * @param nicMacAddressMap map of NIC ID to validated/standardized MAC address strings + * @return merged map with MAC addresses populated where supplied by the caller + */ + protected Map mergeNicMacAddresses( + final Map nicIpAddressMap, + final Map nicMacAddressMap) { + if (MapUtils.isEmpty(nicMacAddressMap)) { + return nicIpAddressMap; + } + Map merged = new HashMap<>(nicIpAddressMap); + for (Map.Entry entry : nicMacAddressMap.entrySet()) { + String nicId = entry.getKey(); + String mac = entry.getValue(); + Network.IpAddresses existing = merged.get(nicId); + if (existing != null) { + existing.setMacAddress(mac); + } else { + merged.put(nicId, new Network.IpAddresses(null, null, mac)); + } + } + return merged; + } private void cleanupFailedImportVM(final UserVm userVm) { if (userVm == null) { return; @@ -3174,4 +3174,44 @@ public ListResponse listVmsForImport(ListVmsForImport !instance.getName().toLowerCase().contains(keyword)) { continue; } - responses.add(responseGenerator.createUnmanagedInstanceResp + responses.add(responseGenerator.createUnmanagedInstanceResponse(instance, null, null)); + } + ListResponse listResponses = new ListResponse<>(); + listResponses.setResponses(responses, responses.size()); + return listResponses; + } + + private HashMap getRemoteVmsOnKVMHost(long zoneId, String remoteHostUrl, String username, String password) { + //ToDo: add option to list one Vm by name + List hosts = resourceManager.listAllUpAndEnabledHostsInOneZoneByHypervisor(Hypervisor.HypervisorType.KVM, zoneId); + if (hosts.size() < 1) { + throw new CloudRuntimeException("No hosts available to list VMs on remote host " + remoteHostUrl); + } + HostVO host = hosts.get(0); + GetRemoteVmsCommand getRemoteVmsCommand = new GetRemoteVmsCommand(remoteHostUrl, username, password); + Answer answer = agentManager.easySend(host.getId(), getRemoteVmsCommand); + if (!(answer instanceof GetRemoteVmsAnswer)) { + throw new CloudRuntimeException("Failed to list VMs, due to: " + answer.getDetails()); + } + GetRemoteVmsAnswer getRemoteVmsAnswer = (GetRemoteVmsAnswer) answer; + return getRemoteVmsAnswer.getUnmanagedInstances(); + } + + @Override + public String getConfigComponentName() { + return UnmanagedVMsManagerImpl.class.getSimpleName(); + } + + @Override + public ConfigKey[] getConfigKeys() { + return new ConfigKey[]{ + UnmanageVMPreserveNic, + RemoteKvmInstanceDisksCopyTimeout, + ConvertVmwareInstanceToKvmTimeout, + ThreadsOnMSToImportVMwareVMFiles, + ThreadsOnKVMHostToImportVMwareVMFiles, + ConvertVmwareInstanceToKvmExtraParamsAllowed, + ConvertVmwareInstanceToKvmExtraParamsAllowedList + }; + } +} From 88846285a9c8c7991e879e32974688af0620d778 Mon Sep 17 00:00:00 2001 From: Prashanth Reddy Date: Fri, 12 Jun 2026 09:10:42 +0000 Subject: [PATCH 07/10] style: rename NIC_MAC_ADDRESS key from 'mac' to 'macAddress' for consistency with ip4Address --- api/src/main/java/com/cloud/vm/VmDetailConstants.java | 5 ++--- .../api/command/admin/vm/ImportUnmanagedInstanceCmd.java | 8 +++----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/api/src/main/java/com/cloud/vm/VmDetailConstants.java b/api/src/main/java/com/cloud/vm/VmDetailConstants.java index c3754ab7c424..9ca013646d0b 100644 --- a/api/src/main/java/com/cloud/vm/VmDetailConstants.java +++ b/api/src/main/java/com/cloud/vm/VmDetailConstants.java @@ -87,7 +87,7 @@ public interface VmDetailConstants { String NETWORK = "network"; String IP4_ADDRESS = "ip4Address"; String IP6_ADDRESS = "ip6Address"; - String NIC_MAC_ADDRESS = "mac"; + String NIC_MAC_ADDRESS = "macAddress"; String DISK = "disk"; String DISK_OFFERING = "diskOffering"; @@ -136,5 +136,4 @@ public interface VmDetailConstants { String ACTIVE_CHECKPOINT_ID = "active.checkpoint.id"; String ACTIVE_CHECKPOINT_CREATE_TIME = "active.checkpoint.create.time"; String LAST_CHECKPOINT_ID = "last.checkpoint.id"; - String LAST_CHECKPOINT_CREATE_TIME = "last.checkpoint.create.time"; -} + String LAST_CHECKPOINT_CREATE_TIME = "last.checkpoint.create.ti \ No newline at end of file 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 3c01d61a3cc5..37f956bdc9af 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 @@ -137,8 +137,8 @@ public class ImportUnmanagedInstanceCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.NIC_MAC_ADDRESS_LIST, type = CommandType.MAP, - description = "VM NIC to MAC address mapping using keys nic and mac. " + - "Example: nicmacaddresslist[0].nic=nic1&nicmacaddresslist[0].mac=aa:bb:cc:dd:ee:ff. " + + description = "VM NIC to MAC address mapping using keys nic and macAddress. " + + "Example: nicmacaddresslist[0].nic=nic1&nicmacaddresslist[0].macAddress=aa:bb:cc:dd:ee:ff. " + "Overrides the MAC address reported by the hypervisor for the given NIC.", since = "4.21.0") private Map nicMacAddressList; @@ -334,6 +334,4 @@ public long getEntityOwnerId() { accountId = Account.ACCOUNT_ID_SYSTEM; } } - return accountId; - } -} + return accou \ No newline at end of file From 9d791445d2e91edc5ff373280d2c2cbc33ff807b Mon Sep 17 00:00:00 2001 From: Prashanth Reddy Date: Fri, 12 Jun 2026 09:12:55 +0000 Subject: [PATCH 08/10] style: fix EOF newlines after macAddress rename --- api/src/main/java/com/cloud/vm/VmDetailConstants.java | 2 +- .../api/command/admin/vm/ImportUnmanagedInstanceCmd.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/com/cloud/vm/VmDetailConstants.java b/api/src/main/java/com/cloud/vm/VmDetailConstants.java index 9ca013646d0b..1740eb17442b 100644 --- a/api/src/main/java/com/cloud/vm/VmDetailConstants.java +++ b/api/src/main/java/com/cloud/vm/VmDetailConstants.java @@ -136,4 +136,4 @@ public interface VmDetailConstants { String ACTIVE_CHECKPOINT_ID = "active.checkpoint.id"; String ACTIVE_CHECKPOINT_CREATE_TIME = "active.checkpoint.create.time"; String LAST_CHECKPOINT_ID = "last.checkpoint.id"; - String LAST_CHECKPOINT_CREATE_TIME = "last.checkpoint.create.ti \ No newline at end of file + String LAST_CHECKPOINT_CREATE_TIME = "last.checkpoint.create.ti 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 37f956bdc9af..c83011263180 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 @@ -334,4 +334,4 @@ public long getEntityOwnerId() { accountId = Account.ACCOUNT_ID_SYSTEM; } } - return accou \ No newline at end of file + return accou From f9125efcfcce5ce7efd9de2536df757856f78bdc Mon Sep 17 00:00:00 2001 From: Prashanth Reddy Date: Fri, 12 Jun 2026 09:22:39 +0000 Subject: [PATCH 09/10] fix: restore NIC_MAC_ADDRESS constant in VmDetailConstants with correct macAddress value --- api/src/main/java/com/cloud/vm/VmDetailConstants.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/src/main/java/com/cloud/vm/VmDetailConstants.java b/api/src/main/java/com/cloud/vm/VmDetailConstants.java index 1740eb17442b..b1b70a6a1587 100644 --- a/api/src/main/java/com/cloud/vm/VmDetailConstants.java +++ b/api/src/main/java/com/cloud/vm/VmDetailConstants.java @@ -136,4 +136,5 @@ public interface VmDetailConstants { String ACTIVE_CHECKPOINT_ID = "active.checkpoint.id"; String ACTIVE_CHECKPOINT_CREATE_TIME = "active.checkpoint.create.time"; String LAST_CHECKPOINT_ID = "last.checkpoint.id"; - String LAST_CHECKPOINT_CREATE_TIME = "last.checkpoint.create.ti + String LAST_CHECKPOINT_CREATE_TIME = "last.checkpoint.create.time"; +} From 44a88530062dba290dc089a69b2092e2eed587f2 Mon Sep 17 00:00:00 2001 From: Prashanth Reddy Date: Fri, 12 Jun 2026 09:39:27 +0000 Subject: [PATCH 10/10] style: rename NIC map key mac->macAddress, use stdin hashing to avoid filesystem truncation --- .../api/command/admin/vm/ImportUnmanagedInstanceCmd.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 c83011263180..1d0267750f79 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 @@ -334,4 +334,6 @@ public long getEntityOwnerId() { accountId = Account.ACCOUNT_ID_SYSTEM; } } - return accou + return accountId; + } +}