1818
1919import static com .cloud .utils .NumbersUtil .toHumanReadableSize ;
2020
21+ import java .net .URI ;
2122import java .util .ArrayList ;
2223import java .util .Date ;
2324import java .util .HashMap ;
149150import com .cloud .vm .dao .UserVmDao ;
150151import com .cloud .vm .dao .VMInstanceDao ;
151152import com .google .gson .Gson ;
153+ import com .vmware .vim25 .DistributedVirtualPort ;
154+ import com .vmware .vim25 .DistributedVirtualSwitchPortConnection ;
155+ import com .vmware .vim25 .DistributedVirtualSwitchPortCriteria ;
152156import com .vmware .vim25 .ManagedObjectReference ;
157+ import com .vmware .vim25 .VMwareDVSPortSetting ;
153158import com .vmware .vim25 .VirtualDevice ;
154159import com .vmware .vim25 .VirtualDeviceBackingInfo ;
155160import com .vmware .vim25 .VirtualDeviceConnectInfo ;
156161import com .vmware .vim25 .VirtualDisk ;
157162import com .vmware .vim25 .VirtualDiskFlatVer2BackingInfo ;
158163import com .vmware .vim25 .VirtualEthernetCard ;
164+ import com .vmware .vim25 .VirtualEthernetCardDistributedVirtualPortBackingInfo ;
159165import com .vmware .vim25 .VirtualEthernetCardNetworkBackingInfo ;
160166import com .vmware .vim25 .VirtualMachineConfigSummary ;
161167import com .vmware .vim25 .VirtualMachineRuntimeInfo ;
168+ import com .vmware .vim25 .VmwareDistributedVirtualSwitchVlanIdSpec ;
162169
163170public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru , Configurable {
164171 private static final Logger s_logger = Logger .getLogger (VMwareGuru .class );
@@ -533,25 +540,43 @@ private void checkBackingInfo(VirtualDeviceBackingInfo backingInfo) {
533540 /**
534541 * Get pool ID from datastore UUID
535542 */
536- private Long getPoolIdFromDatastoreUuid (String datastoreUuid ) {
537- String poolUuid = UuidUtils .normalize (datastoreUuid );
538- StoragePoolVO pool = _storagePoolDao .findByUuid (poolUuid );
543+ private Long getPoolIdFromDatastoreUuid (long zoneId , String datastoreUuid ) {
544+ StoragePoolVO pool = null ;
545+ try {
546+ String poolUuid = UuidUtils .normalize (datastoreUuid );
547+ s_logger .info ("Trying to find pool by UUID: " + poolUuid );
548+ pool = _storagePoolDao .findByUuid (poolUuid );
549+ } catch (CloudRuntimeException ex ) {
550+ s_logger .warn ("Unable to get pool by datastore UUID: " + ex .getMessage ());
551+ }
539552 if (pool == null ) {
540- throw new CloudRuntimeException ("Couldn't find storage pool " + poolUuid );
553+ s_logger .info ("Trying to find pool by path: " + datastoreUuid );
554+ pool = _storagePoolDao .findPoolByZoneAndPath (zoneId , datastoreUuid );
555+ }
556+ if (pool == null && datastoreUuid .startsWith ("-iqn" ) && datastoreUuid .endsWith ("-0" )) {
557+ String iScsiName = "/iqn" + datastoreUuid .substring (4 , datastoreUuid .length () - 2 ) + "/0" ;
558+ s_logger .info ("Trying to find volume by iScsi name: " + iScsiName );
559+ VolumeVO volumeVO = _volumeDao .findOneByIScsiName (iScsiName );
560+ if (volumeVO != null ) {
561+ pool = _storagePoolDao .findById (volumeVO .getPoolId ());
562+ }
563+ }
564+ if (pool == null ) {
565+ throw new CloudRuntimeException ("Couldn't find storage pool " + datastoreUuid );
541566 }
542567 return pool .getId ();
543568 }
544569
545570 /**
546571 * Get pool ID for disk
547572 */
548- private Long getPoolId (VirtualDisk disk ) {
573+ private Long getPoolId (long zoneId , VirtualDisk disk ) {
549574 VirtualDeviceBackingInfo backing = disk .getBacking ();
550575 checkBackingInfo (backing );
551576 VirtualDiskFlatVer2BackingInfo info = (VirtualDiskFlatVer2BackingInfo )backing ;
552577 String [] fileNameParts = info .getFileName ().split (" " );
553578 String datastoreUuid = StringUtils .substringBetween (fileNameParts [0 ], "[" , "]" );
554- return getPoolIdFromDatastoreUuid (datastoreUuid );
579+ return getPoolIdFromDatastoreUuid (zoneId , datastoreUuid );
555580 }
556581
557582 /**
@@ -588,12 +613,12 @@ private VirtualMachineMO getTemplate(DatacenterMO dcMo, String templatePath) thr
588613 /**
589614 * Get template pool ID
590615 */
591- private Long getTemplatePoolId (VirtualMachineMO template ) throws Exception {
616+ private Long getTemplatePoolId (long zoneId , VirtualMachineMO template ) throws Exception {
592617 VirtualMachineConfigSummary configSummary = template .getConfigSummary ();
593618 String vmPathName = configSummary .getVmPathName ();
594619 String [] pathParts = vmPathName .split (" " );
595620 String dataStoreUuid = pathParts [0 ].replace ("[" , "" ).replace ("]" , "" );
596- return getPoolIdFromDatastoreUuid (dataStoreUuid );
621+ return getPoolIdFromDatastoreUuid (zoneId , dataStoreUuid );
597622 }
598623
599624 /**
@@ -643,14 +668,14 @@ private void updateTemplateRef(long templateId, Long poolId, String templatePath
643668 /**
644669 * Get template ID for VM being imported. If it is not found, it is created
645670 */
646- private Long getImportingVMTemplate (List <VirtualDisk > virtualDisks , DatacenterMO dcMo , String vmInternalName , Long guestOsId , long accountId , Map <VirtualDisk , VolumeVO > disksMapping , Backup backup ) throws Exception {
671+ private Long getImportingVMTemplate (List <VirtualDisk > virtualDisks , long zoneId , DatacenterMO dcMo , String vmInternalName , Long guestOsId , long accountId , Map <VirtualDisk , VolumeVO > disksMapping , Backup backup ) throws Exception {
647672 for (VirtualDisk disk : virtualDisks ) {
648673 if (isRootDisk (disk , disksMapping , backup )) {
649674 VolumeVO volumeVO = disksMapping .get (disk );
650675 if (volumeVO == null ) {
651676 String templatePath = getRootDiskTemplatePath (disk );
652677 VirtualMachineMO template = getTemplate (dcMo , templatePath );
653- Long poolId = getTemplatePoolId (template );
678+ Long poolId = getTemplatePoolId (zoneId , template );
654679 Long templateSize = getTemplateSize (template , vmInternalName , disksMapping , backup );
655680 long templateId = getTemplateId (templatePath , vmInternalName , guestOsId , accountId );
656681 updateTemplateRef (templateId , poolId , templatePath , templateSize );
@@ -744,7 +769,11 @@ private long getDiskOfferingId(long size, Storage.ProvisioningType provisioningT
744769 protected VolumeVO updateVolume (VirtualDisk disk , Map <VirtualDisk , VolumeVO > disksMapping , VirtualMachineMO vmToImport , Long poolId , VirtualMachine vm ) throws Exception {
745770 VolumeVO volume = disksMapping .get (disk );
746771 String volumeName = getVolumeName (disk , vmToImport );
747- volume .setPath (volumeName );
772+ if (volume .get_iScsiName () != null ) {
773+ volume .setPath (String .format ("[%s] %s.vmdk" , volumeName , volumeName ));
774+ } else {
775+ volume .setPath (volumeName );
776+ }
748777 volume .setPoolId (poolId );
749778 VirtualMachineDiskInfo diskInfo = getDiskInfo (vmToImport , poolId , volumeName );
750779 volume .setChainInfo (GSON .toJson (diskInfo ));
@@ -779,7 +808,7 @@ private void syncVMVolumes(VMInstanceVO vmInstanceVO, List<VirtualDisk> virtualD
779808
780809 String operation = "" ;
781810 for (VirtualDisk disk : virtualDisks ) {
782- Long poolId = getPoolId (disk );
811+ Long poolId = getPoolId (zoneId , disk );
783812 Volume volume = null ;
784813 if (disksMapping .containsKey (disk ) && disksMapping .get (disk ) != null ) {
785814 volume = updateVolume (disk , disksMapping , vmToImport , poolId , vmInstanceVO );
@@ -903,8 +932,13 @@ private Map<String, NetworkVO> getNetworksMapping(String[] vmNetworkNames, long
903932 Map <String , NetworkVO > mapping = new HashMap <>();
904933 for (String networkName : vmNetworkNames ) {
905934 NetworkVO networkVO = getGuestNetworkFromNetworkMorName (networkName , accountId , zoneId , domainId );
906- s_logger .debug (String .format ("Mapping network name [%s] to networkVO [id: %s]." , networkName , networkVO .getUuid ()));
907- mapping .put (networkName , networkVO );
935+ URI broadcastUri = networkVO .getBroadcastUri ();
936+ if (broadcastUri == null ) {
937+ continue ;
938+ }
939+ String vlan = broadcastUri .getHost ();
940+ s_logger .debug (String .format ("Mapping network vlan [%s] to networkVO [id: %s]." , vlan , networkVO .getUuid ()));
941+ mapping .put (vlan , networkVO );
908942 }
909943 return mapping ;
910944 }
@@ -914,30 +948,88 @@ private Map<String, NetworkVO> getNetworksMapping(String[] vmNetworkNames, long
914948 */
915949 private NetworkMO getNetworkMO (VirtualEthernetCard nic , VmwareContext context ) {
916950 VirtualDeviceConnectInfo connectable = nic .getConnectable ();
917- VirtualEthernetCardNetworkBackingInfo info = (VirtualEthernetCardNetworkBackingInfo )nic .getBacking ();
951+ VirtualEthernetCardNetworkBackingInfo info = (VirtualEthernetCardNetworkBackingInfo ) nic .getBacking ();
918952 ManagedObjectReference networkMor = info .getNetwork ();
919953 if (networkMor == null ) {
920954 throw new CloudRuntimeException ("Could not find network for NIC on: " + nic .getMacAddress ());
921955 }
922956 return new NetworkMO (context , networkMor );
923957 }
924958
925- private Pair <String , String > getNicMacAddressAndNetworkName (VirtualDevice nicDevice , VmwareContext context ) throws Exception {
959+ private Pair <String , String > getNicMacAddressAndVlan (VirtualDevice nicDevice , VmwareContext context ) throws Exception {
926960 VirtualEthernetCard nic = (VirtualEthernetCard )nicDevice ;
927961 String macAddress = nic .getMacAddress ();
928- NetworkMO networkMO = getNetworkMO (nic , context );
929- String networkName = networkMO .getName ();
930- return new Pair <>(macAddress , networkName );
962+ VirtualDeviceBackingInfo backing = nic .getBacking ();
963+ if (backing instanceof VirtualEthernetCardNetworkBackingInfo ) {
964+ VirtualEthernetCardNetworkBackingInfo backingInfo = (VirtualEthernetCardNetworkBackingInfo ) backing ;
965+ String deviceName = backingInfo .getDeviceName ();
966+ String vlan = getVlanFromDeviceName (deviceName );
967+ return new Pair <>(macAddress , vlan );
968+ } else if (backing instanceof VirtualEthernetCardDistributedVirtualPortBackingInfo ) {
969+ VirtualEthernetCardDistributedVirtualPortBackingInfo portInfo = (VirtualEthernetCardDistributedVirtualPortBackingInfo ) backing ;
970+ DistributedVirtualSwitchPortConnection port = portInfo .getPort ();
971+ String portKey = port .getPortKey ();
972+ String portGroupKey = port .getPortgroupKey ();
973+ String dvSwitchUuid = port .getSwitchUuid ();
974+ String vlan = getVlanFromDvsPort (context , dvSwitchUuid , portGroupKey , portKey );
975+ return new Pair <>(macAddress , vlan );
976+ }
977+ return new Pair <>(macAddress , null );
978+ }
979+
980+ private String getVlanFromDeviceName (String networkName ) {
981+ String prefix = "cloud.guest." ;
982+ if (!networkName .startsWith (prefix )) {
983+ return null ;
984+ }
985+ String nameWithoutPrefix = networkName .replace (prefix , "" );
986+ String [] parts = nameWithoutPrefix .split ("\\ ." );
987+ String vlan = parts [0 ];
988+ return vlan ;
989+ }
990+
991+ private String getVlanFromDvsPort (VmwareContext context , String dvSwitchUuid , String portGroupKey , String portKey ) {
992+ try {
993+ ManagedObjectReference dvSwitchManager = context .getVimClient ().getServiceContent ().getDvSwitchManager ();
994+ ManagedObjectReference dvSwitch = context .getVimClient ().getService ().queryDvsByUuid (dvSwitchManager , dvSwitchUuid );
995+
996+ // Get all ports
997+ DistributedVirtualSwitchPortCriteria criteria = new DistributedVirtualSwitchPortCriteria ();
998+ criteria .setInside (true );
999+ criteria .getPortgroupKey ().add (portGroupKey );
1000+ List <DistributedVirtualPort > dvPorts = context .getVimClient ().getService ().fetchDVPorts (dvSwitch , criteria );
1001+
1002+ for (DistributedVirtualPort dvPort : dvPorts ) {
1003+ if (!portKey .equals (dvPort .getKey ())) {
1004+ continue ;
1005+ }
1006+ VMwareDVSPortSetting settings = (VMwareDVSPortSetting ) dvPort .getConfig ().getSetting ();
1007+ VmwareDistributedVirtualSwitchVlanIdSpec vlanId = (VmwareDistributedVirtualSwitchVlanIdSpec ) settings .getVlan ();
1008+ s_logger .debug ("Found port " + dvPort .getKey () + " with vlan " + vlanId .getVlanId ());
1009+ return String .valueOf (vlanId .getVlanId ());
1010+ }
1011+ } catch (Exception ex ) {
1012+ s_logger .error ("Got exception while get vlan from DVS port: " + ex .getMessage ());
1013+ }
1014+ return null ;
9311015 }
9321016
9331017 private void syncVMNics (VirtualDevice [] nicDevices , DatacenterMO dcMo , Map <String , NetworkVO > networksMapping , VMInstanceVO vm ) throws Exception {
9341018 VmwareContext context = dcMo .getContext ();
9351019 List <NicVO > allNics = nicDao .listByVmId (vm .getId ());
9361020 for (VirtualDevice nicDevice : nicDevices ) {
937- Pair <String , String > pair = getNicMacAddressAndNetworkName (nicDevice , context );
1021+ Pair <String , String > pair = getNicMacAddressAndVlan (nicDevice , context );
9381022 String macAddress = pair .first ();
939- String networkName = pair .second ();
940- NetworkVO networkVO = networksMapping .get (networkName );
1023+ String vlanId = pair .second ();
1024+ if (vlanId == null ) {
1025+ s_logger .warn (String .format ("vlanId for MAC address [%s] is null" , macAddress ));
1026+ continue ;
1027+ }
1028+ NetworkVO networkVO = networksMapping .get (vlanId );
1029+ if (networkVO == null ) {
1030+ s_logger .warn (String .format ("Cannot find network for MAC address [%s] and vlanId [%s]" , macAddress , vlanId ));
1031+ continue ;
1032+ }
9411033 NicVO nicVO = nicDao .findByNetworkIdAndMacAddressIncludingRemoved (networkVO .getId (), macAddress );
9421034 if (nicVO != null ) {
9431035 s_logger .warn (String .format ("Find NIC in DB with networkId [%s] and MAC Address [%s], so this NIC will be removed from list of unmapped NICs of VM [id: %s, name: %s]." ,
@@ -1068,7 +1160,7 @@ public VirtualMachine importVirtualMachineFromBackup(long zoneId, long domainId,
10681160
10691161 long guestOsId = getImportingVMGuestOs (configSummary );
10701162 long serviceOfferingId = getImportingVMServiceOffering (configSummary , runtimeInfo );
1071- long templateId = getImportingVMTemplate (virtualDisks , dcMo , vmInternalName , guestOsId , accountId , disksMapping , backup );
1163+ long templateId = getImportingVMTemplate (virtualDisks , zoneId , dcMo , vmInternalName , guestOsId , accountId , disksMapping , backup );
10721164
10731165 VMInstanceVO vm = getVM (vmInternalName , templateId , guestOsId , serviceOfferingId , zoneId , accountId , userId , domainId );
10741166 syncVMVolumes (vm , virtualDisks , disksMapping , vmToImport , backup );
0 commit comments