Esempio n. 1
0
    def _copy_volume_to_volume(self, dest_volume_name, 
                                        dest_volume_size,
                                        dest_volume_id,
                                        source_volume_name, 
                                        source_volume_size,
                                        source_volume_id,
                                        created = False, 
                                        source_attached = False,
                                        dest_attached = False):
        """
        """

        def _attach_disks_to_vm():
            for detached_disk in detached_disks:
                self._vcloud_client.attach_disk_to_vm(detached_disk['vapp_name'], detached_disk['disk_ref'])

        def _delete_volumes():
            for created_volume in created_volumes:
                self._vcloud_client.delete_volume(created_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)

        LOG.debug('copy volume to volume: dest: %s ID %s %s GB source: %s id: %s %s GB',
                    dest_volume_name, dest_volume_id, dest_volume_size,
                    source_volume_name, source_volume_id, source_volume_size)

        detached_disks = []
        created_volumes = []
        attached_disk_names =[]
        undo_mgr = util.UndoManager()

        try:

            if not created and dest_attached:
                msg = _('only created destination volume can be attached')
                LOG.error(msg)
                raise exception.CinderException(msg)

            result, source_disk_ref = self._vcloud_client.get_disk_ref(source_volume_name)
            if not result:
                msg = _('source volume %s cannot found') % source_volume_name
                LOG.error(msg)
                raise exception.CinderException(msg)

            if source_attached:
                source_vapp_name = self._vcloud_client.get_disk_attached_vapp(source_volume_name)
                source_vapp = self._vcloud_client._get_vcloud_vapp(source_vapp_name)
                if self._vcloud_client._get_status_first_vm(source_vapp) != constants.VM_POWER_OFF_STATUS:
                    msg = "when source volume is attached, the vm must be in power off state"
                    LOG.info(msg)
                    raise exception.CinderException(msg)

                self._vcloud_client.detach_disk_from_vm(source_vapp_name, source_disk_ref)

                source_detached_disk = {}
                source_detached_disk['vapp_name'] = source_vapp_name
                source_detached_disk['disk_ref'] = source_disk_ref
                detached_disks.append(source_detached_disk)
                undo_mgr.undo_with(_attach_disks_to_vm)
                LOG.debug("source volume %s has been detached from vapp %s", source_volume_name, source_vapp_name)

            if not created:
                self._vcloud_client.create_volume(dest_volume_name, dest_volume_size)
                created_volumes.append(dest_volume_name)
                undo_mgr.undo_with(_delete_volumes)
                LOG.debug("dst volume %s(%s GB) has been created", dest_volume_name, dest_volume_size)

            result, dest_disk_ref = self._vcloud_client.get_disk_ref(dest_volume_name)
            if not result:
                msg = _('dest volume %s cannot found') % dest_volume_name
                LOG.error(msg)
                raise exception.CinderException(msg)

            if dest_attached:
                dest_vapp_name = self._vcloud_client.get_disk_attached_vapp(dest_volume_name)
                dest_vapp = self._vcloud_client._get_vcloud_vapp(dest_vapp_name)
                if self._vcloud_client._get_status_first_vm(dest_vapp) != constants.VM_POWER_OFF_STATUS:
                    msg = "when dest volume is attached, the vm must be in power off state"
                    LOG.info(msg)
                    raise exception.CinderException(msg)

                self._vcloud_client.detach_disk_from_vm(dest_vapp_name, dest_disk_ref)

                dest_detached_disk = {}
                dest_detached_disk['vapp_name'] = dest_vapp_name
                dest_detached_disk['disk_ref'] = dest_disk_ref
                detached_disks.append(dest_detached_disk)
                if undo_mgr.count_func(_attach_disks_to_vm) == 0:
                    undo_mgr.undo_with(_attach_disks_to_vm)
                LOG.debug("dst volume %s has been detached from vapp %s", dest_volume_name, dest_vapp_name)

            #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' % dest_volume_name
            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)

            local_disk_name = 'Local@%s' % clone_vapp_name[len('server@'):]

            self._vcloud_client.create_volume(local_disk_name, 1)
            created_volumes.append(local_disk_name)
            if undo_mgr.count_func(_delete_volumes) == 0:
                undo_mgr.undo_with(_delete_volumes)
            LOG.debug("Create Local disk %s for vapp %s successful", local_disk_name, clone_vapp_name)

            result, local_disk_ref = self._vcloud_client.get_disk_ref(local_disk_name)
            self._vcloud_client.attach_disk_to_vm(clone_vapp_name, local_disk_ref)
            attached_disk_names.append(local_disk_name)
            undo_mgr.undo_with(_detach_disks_to_vm)
            LOG.debug("attach local disk %s to vapp %s successful", local_disk_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)

            odevs = set(client.list_volume()['devices'])
            if self._vcloud_client.attach_disk_to_vm(clone_vapp_name, source_disk_ref):
                attached_disk_names.append(source_volume_name)
                LOG.debug("Volume %s attached to: %s",source_volume_name, clone_vapp_name)

            ndevs = set(client.list_volume()['devices'])
            devs = ndevs - odevs
            for dev in devs:
                client.attach_volume(source_volume_id, dev, constants.DEV1)

            odevs = set(client.list_volume()['devices'])
            if self._vcloud_client.attach_disk_to_vm(clone_vapp_name, dest_disk_ref):
                attached_disk_names.append(dest_volume_name)
                LOG.debug("Volume %s attached to: %s", dest_volume_name, clone_vapp_name)

            ndevs = set(client.list_volume()['devices'])
            devs = ndevs - odevs
            for dev in devs:
                client.attach_volume(dest_volume_id, dev, constants.DEV2)

            LOG.debug('begin time of copy vloume(size %s GB) is %s', source_volume_size, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

            dest_volume = {}
            dest_volume['id'] = dest_volume_id
            dest_volume['size'] = dest_volume_size
            src_volume = {}
            src_volume['id'] = source_volume_id
            src_volume['size'] = source_volume_size

            task = client.clone_volume(dest_volume, src_volume)
            while task['code'] == client_constants.TASK_DOING:
                eventlet.greenthread.sleep(30)
                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 copy vloume is %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(source_volume_name)
            self._vcloud_client.detach_disk_from_vm(clone_vapp_name, source_disk_ref)
            if source_attached:
                detached_disks.remove(source_detached_disk)
                self._vcloud_client.attach_disk_to_vm(source_vapp_name, source_disk_ref)

            attached_disk_names.remove(local_disk_name)
            self._vcloud_client.detach_disk_from_vm(clone_vapp_name, local_disk_ref)

            attached_disk_names.remove(dest_volume_name)
            self._vcloud_client.detach_disk_from_vm(clone_vapp_name, dest_disk_ref)
            if dest_attached:
                detached_disks.remove(dest_detached_disk)
                self._vcloud_client.attach_disk_to_vm(dest_vapp_name, dest_disk_ref)

            undo_mgr.cancel_undo(_delete_vapp)
            self._vcloud_client.delete_vapp(clone_vapp_name)

            created_volumes.remove(local_disk_name)
            self._vcloud_client.delete_volume(local_disk_name)

            return True
        except Exception as e:
            msg = _("Failed to copy volume to volume reason %s, rolling back") % e
            LOG.error(msg)
            undo_mgr.rollback_and_reraise(msg=msg)
            return False
Esempio n. 2
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)
Esempio n. 3
0
 def _wait_hybrid_service_up(self, server_ip, port = '7127'):
     client = Client(server_ip, port = port)
     return client.get_version()