def copy_volume_to_image(self, context, volume, image_service, image_meta): """Creates glance image from volume.""" def _delete_vapp(): self._vcloud_client.delete_vapp(clone_vapp_name) def _detach_disks_to_vm(): for attached_disk_name in attached_disk_names: result, disk_ref = self._vcloud_client.get_disk_ref(attached_disk_name) if result: self._vcloud_client.detach_disk_from_vm(clone_vapp_name, disk_ref) def _power_off_vapp(): self._vcloud_client.power_off_vapp(clone_vapp_name) undo_mgr = util.UndoManager() attached_disk_names = [] try: LOG.info('begin time of copy_volume_to_image is %s' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))) container_format = image_meta.get('container_format') if container_format in VGW_URLS: # attach the volume to vgw vm disk_ref, vapp_name = self._attach_volume_to_vgw(volume) try: # use ssh client connect to vgw_host and copy image file to volume self._copy_volume_to_file_to_vgw(image_meta) finally: self._vcloud_client.detach_disk_from_vm(vapp_name, disk_ref) # create an empty file to glance with image_utils.temporary_file() as tmp: image_utils.upload_volume(context, image_service, image_meta, tmp) elif container_format == constants.HYBRID_VM: volume_name = volume['display_name'] vcloud_volume_name = self._get_vcloud_volume_name(volume['id'], volume_name) result,disk_ref = self._vcloud_client.get_disk_ref(vcloud_volume_name) if not result: msg = 'can not find volume %s in vcloud!' % vcloud_volume_name LOG.error(msg) raise exception.CinderException(msg) if volume['volume_attachment']: msg = 'copy volume to image not support attached volume!' LOG.error(msg) raise exception.CinderException(msg) #NOTE(nkapotoxin): create vapp with vapptemplate network_names = [CONF.vcloud.provider_tunnel_network_name, CONF.vcloud.provider_base_network_name] network_configs = self._vcloud_client.get_network_configs(network_names) # create vapp clone_vapp_name = 'server@%s' % image_meta['id'] clone_vapp = self._vcloud_client.create_vapp(clone_vapp_name, CONF.vcloud.base_image_id, network_configs) undo_mgr.undo_with(_delete_vapp) LOG.debug("Create clone vapp %s successful" % clone_vapp_name) # generate the network_connection network_connections = self._vcloud_client.get_network_connections(clone_vapp, network_names) # update network self._vcloud_client.update_vms_connections(clone_vapp, network_connections) # update vm specification #self._vcloud_client.modify_vm_cpu(clone_vapp, instance.get_flavor().vcpus) #self._vcloud_client.modify_vm_memory(clone_vapp, instance.get_flavor().memory_mb) LOG.debug("Config vapp %s successful" % clone_vapp_name) if self._vcloud_client.attach_disk_to_vm(clone_vapp_name, disk_ref): attached_disk_names.append(vcloud_volume_name) undo_mgr.undo_with(_detach_disks_to_vm) LOG.debug("Volume %s attached to: %s", vcloud_volume_name, clone_vapp_name) # power on it self._vcloud_client.power_on_vapp(clone_vapp_name) undo_mgr.undo_with(_power_off_vapp) vapp_ip = self.get_vapp_ip(clone_vapp_name) client = Client(vapp_ip, CONF.vcloud.hybrid_service_port) self._wait_hybrid_service_up(vapp_ip, CONF.vcloud.hybrid_service_port) LOG.debug("vapp %s(ip: %s) hybrid service has been up", clone_vapp_name, vapp_ip) LOG.debug('begin time of create image is %s' % time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) task = client.create_image(image_meta['name'], image_meta['id']) while task['code'] == client_constants.TASK_DOING: eventlet.greenthread.sleep(10) task = client.query_task(task) if task['code'] != client_constants.TASK_SUCCESS: LOG.error(task['message']) raise exception.CinderException(task['message']) else: LOG.debug('end time of create image is %s' % time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) image_info = client.image_info(image_meta['name'], image_meta['id']) if not image_info: LOG.error('cannot get image info') raise exception.CinderException('cannot get image info') LOG.debug('begin time of image_utils upload_volume %s' % time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) with image_utils.temporary_file() as tmp: with fileutils.file_open(tmp, 'wb+') as f: f.truncate(image_info['size']) image_utils.upload_volume(context, image_service, image_meta, tmp, volume_format=image_meta['disk_format']) LOG.debug('end time of image_utils upload_volume %s' % time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) undo_mgr.cancel_undo(_power_off_vapp) self._vcloud_client.power_off_vapp(clone_vapp_name) attached_disk_names.remove(vcloud_volume_name) self._vcloud_client.detach_disk_from_vm(clone_vapp_name, disk_ref) undo_mgr.cancel_undo(_delete_vapp) self._vcloud_client.delete_vapp(clone_vapp_name) LOG.info('end time of copy_volume_to_image is %s' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))) except Exception as e: msg = _("Failed to copy volume to image reason %s, rolling back") % e LOG.error(msg) undo_mgr.rollback_and_reraise(msg=msg)