+ def _create_vm(self, account, vduinfo, pci_assignement=None, server_group=None, port_list=None, network_list=None, imageinfo_list=None):
+ """Create a new virtual machine.
+
+ Arguments:
+ account - a cloud account
+ vminfo - information that defines the type of VM to create
+
+ Returns:
+ The image id
+ """
+ kwargs = {}
+ kwargs['name'] = vduinfo.name
+ kwargs['flavor_id'] = vduinfo.flavor_id
+ if vduinfo.has_field('image_id'):
+ kwargs['image_id'] = vduinfo.image_id
+ else:
+ kwargs['image_id'] = ""
+
+ with self._use_driver(account) as drv:
+ ### If floating_ip is required and we don't have one, better fail before any further allocation
+ if vduinfo.has_field('allocate_public_address') and vduinfo.allocate_public_address:
+ if account.openstack.has_field('floating_ip_pool'):
+ pool_name = account.openstack.floating_ip_pool
+ else:
+ pool_name = None
+ floating_ip = self._allocate_floating_ip(drv, pool_name)
+ else:
+ floating_ip = None
+
+ if vduinfo.has_field('vdu_init') and vduinfo.vdu_init.has_field('userdata'):
+ kwargs['userdata'] = vduinfo.vdu_init.userdata
+ else:
+ kwargs['userdata'] = ''
+
+ if account.openstack.security_groups:
+ kwargs['security_groups'] = account.openstack.security_groups
+
+ kwargs['port_list'] = port_list
+ kwargs['network_list'] = network_list
+
+ metadata = {}
+ # Add all metadata related fields
+ if vduinfo.has_field('node_id'):
+ metadata['node_id'] = vduinfo.node_id
+ if pci_assignement is not None:
+ metadata['pci_assignement'] = pci_assignement
+ kwargs['metadata'] = metadata
+
+ if vduinfo.has_field('availability_zone') and vduinfo.availability_zone.has_field('name'):
+ kwargs['availability_zone'] = vduinfo.availability_zone
+ else:
+ kwargs['availability_zone'] = None
+
+ if server_group is not None:
+ kwargs['scheduler_hints'] = {'group': server_group}
+ else:
+ kwargs['scheduler_hints'] = None
+
+ kwargs['block_device_mapping_v2'] = None
+ if vduinfo.has_field('volumes') :
+ kwargs['block_device_mapping_v2'] = []
+ with self._use_driver(account) as drv:
+ # Only support image->volume
+ for volume in vduinfo.volumes:
+ block_map = dict()
+ block_map['boot_index'] = volume.boot_params.boot_priority
+ if "image" in volume:
+ # Support image->volume
+ # Match retrived image info with volume based image name and checksum
+ if volume.image is not None:
+ matching_images = [img for img in imageinfo_list if img['name'] == volume.image]
+ if volume.image_checksum is not None:
+ matching_images = [img for img in matching_images if img['checksum'] == volume.image_checksum]
+ img_id = matching_images[0]['id']
+ if img_id is None:
+ raise OpenstackCALOperationFailure("Create-vdu operation failed. Volume image not found for name {} checksum {}".format(volume.name, volume.checksum))
+ block_map['uuid'] = img_id
+ block_map['source_type'] = "image"
+ else:
+ block_map['source_type'] = "blank"
+
+ block_map['device_name'] = volume.name
+ block_map['destination_type'] = "volume"
+ block_map['volume_size'] = volume.size
+ block_map['delete_on_termination'] = True
+ if volume.guest_params.has_field('device_type') and volume.guest_params.device_type == 'cdrom':
+ block_map['device_type'] = 'cdrom'
+ if volume.guest_params.has_field('device_bus') and volume.guest_params.device_bus == 'ide':
+ block_map['disk_bus'] = 'ide'
+ kwargs['block_device_mapping_v2'].append(block_map)
+
+
+ with self._use_driver(account) as drv:
+ vm_id = drv.nova_server_create(**kwargs)
+ if floating_ip:
+ self.prepare_vdu_on_boot(account, vm_id, floating_ip)
+
+ return vm_id
+
+ def get_openstack_image_info(self, account, image_name, image_checksum=None):
+ self.log.debug("Looking up image id for image name %s and checksum %s on cloud account: %s",
+ image_name, image_checksum, account.name
+ )
+
+ image_list = []
+ with self._use_driver(account) as drv:
+ image_list = drv.glance_image_list()
+ matching_images = [img for img in image_list if img['name'] == image_name]
+
+ # If the image checksum was filled in then further filter the images by the checksum
+ if image_checksum is not None:
+ matching_images = [img for img in matching_images if img['checksum'] == image_checksum]
+ else:
+ self.log.warning("Image checksum not provided. Lookup using image name (%s) only.",
+ image_name)
+
+ if len(matching_images) == 0:
+ raise ResMgrCALOperationFailure("Could not find image name {} (using checksum: {}) for cloud account: {}".format(
+ image_name, image_checksum, account.name
+ ))
+
+ elif len(matching_images) > 1:
+ unique_checksums = {i.checksum for i in matching_images}
+ if len(unique_checksums) > 1:
+ msg = ("Too many images with different checksums matched "
+ "image name of %s for cloud account: %s" % (image_name, account.name))
+ raise ResMgrCALOperationFailure(msg)
+
+ return matching_images[0]
+