Esempio n. 1
0
    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)