Пример #1
0
    def _handle_volume_for_svm_after_clone(self, context,
                                           server_resource, resources):
        bdms = server_resource['properties'].get('block_device_mapping_v2', [])
        vgw_id = server_resource.get('extra_properties', {}).get('gw_id')
        for bdm in bdms:
            volume_key = bdm.get('volume_id', {}).get('get_resource')
            boot_index = bdm.get('boot_index')
            device_name = bdm.get('device_name')
            volume_res = resources.get(volume_key)
            try:
                if volume_res.get('extra_properties', {}).get('is_deacidized'):
                    volume_id = volume_res.get('extra_properties', {}) \
                        .get('id')
                    vgw_url = volume_res.get('extra_properties', {}) \
                        .get('gw_url')
                    sys_clone = volume_res.get('extra_properties', {}) \
                        .get('sys_clone')
                    copy_data = volume_res.get('extra_properties', {}). \
                        get('copy_data')
                    if (boot_index in ['0', 0] and not sys_clone) or \
                            not copy_data:
                        continue
                    vgw_ip = vgw_url.split(':')[0]
                    client = birdiegatewayclient.get_birdiegateway_client(
                        vgw_ip, str(CONF.v2vgateway_api_listen_port))

                    if boot_index not in ['0', 0] or sys_clone:
                        client.vservices._force_umount_disk(
                            "/opt/" + volume_id)

                    # if provider cloud can not detcah volume in active status
                    if not CONF.is_active_detach_volume:
                        resouce_common = common.ResourceCommon()
                        self.compute_api.stop_server(context, vgw_id)
                        resouce_common._await_instance_status(context,
                                                              vgw_id,
                                                              'SHUTOFF')
                    self.compute_api.detach_volume(context, vgw_id,
                                                   volume_id)
                    self._wait_for_volume_status(context, volume_id,
                                                 vgw_id, 'available')
                    server_id = server_resource.get('extra_properties', {}) \
                        .get('id')
                    self.compute_api.attach_volume(context, server_id,
                                                   volume_id,
                                                   device_name)
                    self._wait_for_volume_status(context, volume_id,
                                                 server_id, 'in-use')

                    if not CONF.is_active_detach_volume:
                        self.compute_api.start_server(context, vgw_id)
                        resouce_common._await_instance_status(context,
                                                              vgw_id,
                                                              'ACTIVE')
            except Exception as e:
                LOG.error(_LE('Error from handle volume of vm after'
                              ' clone.'
                              'Error=%(e)s'), {'e': e})
Пример #2
0
    def _handle_dep_volume_after_clone(self, context, resource):
        volume_id = resource.get('extra_properties', {}).get('id')
        if not resource.get('extra_properties', {}).get('copy_data'):
            return
        if resource.get('extra_properties', {}).get('is_deacidized'):
            extra_properties = resource.get('extra_properties', {})
            vgw_id = extra_properties.get('gw_id')
            if vgw_id:
                try:
                    mount_point = resource.get('extra_properties', {}) \
                                          .get('mount_point')
                    if mount_point:
                        vgw_url = resource.get('extra_properties', {}) \
                                          .get('gw_url')
                        vgw_ip = vgw_url.split(':')[0]
                        client = birdiegatewayclient.get_birdiegateway_client(
                            vgw_ip, str(CONF.v2vgateway_api_listen_port))
                        client.vservices._force_umount_disk("/opt/" +
                                                            volume_id)

                    # if provider cloud can not detach volume in active status
                    if not CONF.is_active_detach_volume:
                        resouce_common = common.ResourceCommon()
                        self.compute_api.stop_server(context, vgw_id)
                        resouce_common._await_instance_status(
                            context, vgw_id, 'SHUTOFF')
                    self.compute_api.detach_volume(context, vgw_id, volume_id)
                    self._wait_for_volume_status(context, volume_id, vgw_id,
                                                 'available')

                    if not CONF.is_active_detach_volume:
                        self.compute_api.start_server(context, vgw_id)
                        resouce_common._await_instance_status(
                            context, vgw_id, 'ACTIVE')
                except Exception as e:
                    LOG.error(
                        _LE('Error from handle volume of '
                            'vm after clone. Error=%(e)s'), {'e': e})
Пример #3
0
 def __init__(self, *args, **kwargs):
     """Load configuration options and connect to the hypervisor."""
     self.clone_driver = importutils.import_object(CONF.volume_clone_driver)
     self.resource_common = common.ResourceCommon()
     self.plan_api = plan_api.PlanAPI()
Пример #4
0
    def start_volume_clone(self, context, resource_name, template,
                           trans_data_wait_fun=None,
                           volume_wait_fun=None,
                           set_plan_state=None):
        resources = template.get('resources')
        volume_res = resources.get(resource_name)
        volume_id = volume_res.get('id')
        plan_id = template.get('plan_id', None)
        ext_properties = volume_res.get('extra_properties', None)

        d_copy = ext_properties.get('copy_data', True) if ext_properties \
            else True
        if not d_copy:
            plan_state = 'DATA_TRANS_FINISHED'
            set_plan_state(context, plan_id, plan_state,
                           plan_status.STATE_MAP)
            return
        resource_names = resource_name.split('.')
        if len(resource_names) >= 1:
            if resource_names[0].startswith('stack'):
                self._copy_stack_volume(context, resource_name, template,
                                        plan_id, trans_data_wait_fun,
                                        volume_wait_fun, set_plan_state)
                return
        # 1. check instance which dependences this volume in template or not
        # if instance exists in template do not execute copy data step
        is_attached = self._check_volume_attach_instance(resource_name,
                                                         template)
        if is_attached:
            LOG.debug('Volume clone driver: volume %(id)s, name %(name)s',
                      {'id': volume_id, 'name': resource_name})
            # update plan status
            plan_state = 'DATA_TRANS_FINISHED'
            set_plan_state(context, plan_id, plan_state,
                           plan_status.STATE_MAP)
            return

        # 2. if volume is system volume and does not clone, skip copy data step
        if ext_properties:
            sys_clone = ext_properties.get('sys_clone', False)
            boot_index = ext_properties.get('boot_index', 1)
        else:
            sys_clone = False
            boot_index = 1
        if not sys_clone and boot_index in ['0', 0]:
            plan_state = 'DATA_TRANS_FINISHED'
            set_plan_state(context, plan_id, plan_state,
                           plan_status.STATE_MAP)
            return

        # 3. get volume info
        try:
            volume_info = self.cinder_api.get(context, volume_id)
        except Exception as e:
            LOG.error("Clone volume driver get volume %(id)s error: %(error)s",
                      {'id': volume_id, 'error': e})
            raise exception.VolumeNotFound()
        volume_status = volume_info['status']
        v_shareable = volume_info.get('shareable', False)
        volume_az = volume_info.get('availability_zone')
        need_set_shareable = False
        if volume_status == 'in-use' and not v_shareable:
            need_set_shareable = True

        # 3. attach volume to gateway vm
        vgw_id, vgw_ip = utils.get_next_vgw(volume_az)
        LOG.debug('Clone volume driver vgw info: id: %(id)s,ip: %(ip)s',
                  {'id': vgw_id, 'ip': vgw_ip})

        des_dev_name = None
        try:
            client = birdiegatewayclient.get_birdiegateway_client(
                vgw_ip,
                str(CONF.v2vgateway_api_listen_port)
            )
            disks = set(client.vservices.get_disk_name().get('dev_name'))
            if CONF.is_provide_device_name:
                if need_set_shareable:
                    self.cinder_api.set_volume_shareable(context, volume_id,
                                                         True)
                    self.compute_api.attach_volume(context, vgw_id,
                                                   volume_id, None)
                    # des_dev_name = attach_resp._info.get('device')
                    self._wait_for_shareable_volume_status(context, volume_id,
                                                           vgw_id, 'in-use')
                else:
                    self.compute_api.attach_volume(context, vgw_id,
                                                   volume_id, None)
                    if volume_wait_fun:
                        volume_wait_fun(context, volume_id, 'in-use')
                # des_dev_name = attach_resp._info.get('device')
                n_disks = set(client.vservices.get_disk_name().get('dev_name'))
                diff_disk = n_disks - disks
                des_dev_name = list(diff_disk)[0] if len(diff_disk) >= 1 \
                    else None
                LOG.debug("dev_name = %s", des_dev_name)
            else:
                des_dev_name = self._attach_volume_for_device_name(
                    context, need_set_shareable, vgw_id, volume_id,
                    volume_wait_fun, client)
                LOG.debug("dev_name = %s", des_dev_name)
        except Exception as e:
            LOG.error('Volume clone error: attach volume failed:%(id)s,%(e)s',
                      {'id': volume_id, 'e': e})
            raise exception.VolumeNotAttach(volume_id=volume_id,
                                            seconds=120,
                                            attempts=5)

        # 5. copy data
        try:
            result = self._copy_volume_data(context, resource_name,
                                            vgw_ip, vgw_id, template,
                                            des_dev_name)

            des_gw_ip = result.get('des_ip')
            des_port = result.get('des_port')
            task_ids = result.get('copy_tasks')
            if trans_data_wait_fun:
                trans_data_wait_fun(context, des_gw_ip,
                                    des_port, task_ids,
                                    plan_status.STATE_MAP,
                                    plan_id)
        except Exception as e:
            LOG.error('Volume clone error: copy data failed:%(id)s,%(e)s',
                      {'id': volume_id, 'e': e})
            raise
        finally:
            try:
                # if protocol is ftp, we should unmount volume in gateway vm
                data_trans_protocol = CONF.data_transformer_procotol
                if 'ftp' == data_trans_protocol:
                    client = birdiegatewayclient.get_birdiegateway_client(
                        vgw_ip,
                        str(CONF.v2vgateway_api_listen_port)
                    )
                    client.vservices._force_umount_disk("/opt/" + volume_id)

                # if provider cloud can not detach volume in active status
                if not CONF.is_active_detach_volume:
                    resouce_common = common.ResourceCommon()
                    self.compute_api.stop_server(context, vgw_id)
                    resouce_common._await_instance_status(context,
                                                          vgw_id,
                                                          'SHUTOFF')
                # 5. detach volume
                self.compute_api.detach_volume(context, vgw_id, volume_id)
                if need_set_shareable:
                    self._wait_for_shareable_volume_status(context,
                                                           volume_id,
                                                           vgw_id,
                                                           'available')
                    self.cinder_api.set_volume_shareable(context,
                                                         volume_id,
                                                         False)
                else:
                    if volume_wait_fun:
                        volume_wait_fun(context, volume_id, 'available')

                if not CONF.is_active_detach_volume:
                    self.compute_api.start_server(context, vgw_id)
                    resouce_common._await_instance_status(context,
                                                          vgw_id,
                                                          'ACTIVE')
            except Exception as e:
                LOG.error('Volume clone error: detach failed:%(id)s,%(e)s',
                          {'id': volume_id, 'e': e})
Пример #5
0
    def _copy_stack_volume(self, context, resource_name, template, plan_id,
                           trans_data_wait_fun=None, volume_wait_fun=None,
                           set_plan_state=None):
        resources = template.get('resources')
        volume_res = resources.get(resource_name)
        ext_properties = volume_res.get('extra_properties', None)
        if ext_properties:
            sys_clone = ext_properties.get('sys_clone', False)
            boot_index = ext_properties.get('boot_index', 1)
        else:
            sys_clone = False
            boot_index = 1
        if not sys_clone and boot_index in ['0', 0]:
            plan_state = 'DATA_TRANS_FINISHED'
            set_plan_state(context, plan_id, plan_state,
                           plan_status.STATE_MAP)
            return
        volume_id = volume_res.get('id')
        try:
            volume_info = self.cinder_api.get(context, volume_id)
        except Exception as e:
            LOG.error("Clone volume driver get volume %(id)s error: %(error)s",
                      {'id': volume_id, 'error': e})
            raise exception.VolumeNotFound()
        volume_status = volume_info['status']
        v_shareable = volume_info.get('shareable', False)
        volume_az = volume_info.get('availability_zone')
        volume_attachments = volume_info.get('attachments', [])
        if volume_status == 'in-use' and not v_shareable:
            for attachment in volume_attachments:
                server_id = attachment.get('server_id')
                if not CONF.is_active_detach_volume:
                    resouce_common = common.ResourceCommon()
                    self.compute_api.stop_server(context, server_id)
                    resouce_common._await_instance_status(context,
                                                          server_id,
                                                          'SHUTOFF')
                self.compute_api.detach_volume(context, server_id,
                                               volume_id)
                if volume_wait_fun:
                    volume_wait_fun(context, volume_id, 'available')
        vgw_id, vgw_ip = utils.get_next_vgw(volume_az)
        LOG.debug('Clone volume driver vgw info: id: %(id)s,ip: %(ip)s',
                  {'id': vgw_id, 'ip': vgw_ip})
        des_dev_name = None
        try:
            client = birdiegatewayclient.get_birdiegateway_client(
                vgw_ip,
                str(CONF.v2vgateway_api_listen_port)
            )
            disks = set(client.vservices.get_disk_name().get('dev_name'))
            self.compute_api.attach_volume(context, vgw_id,
                                           volume_id, None)
            if volume_wait_fun:
                volume_wait_fun(context, volume_id, 'in-use')
            n_disks = set(client.vservices.get_disk_name().get('dev_name'))
            diff_disk = n_disks - disks
            des_dev_name = list(diff_disk)[0] if len(diff_disk) >= 1 else None
            LOG.debug("dev_name = %s", des_dev_name)
        except Exception as e:
            LOG.error('Volume clone error: attach volume failed:%(id)s,%(e)s',
                      {'id': volume_id, 'e': e})
            raise exception.VolumeNotAttach(volume_id=volume_id,
                                            seconds=120,
                                            attempts=5)
        # 5. copy data
        try:
            result = self._copy_volume_data(context, resource_name,
                                            vgw_ip, vgw_id, template,
                                            des_dev_name)

            des_gw_ip = result.get('des_ip')
            des_port = result.get('des_port')
            task_ids = result.get('copy_tasks')
            if trans_data_wait_fun:
                trans_data_wait_fun(context, des_gw_ip,
                                    des_port, task_ids,
                                    plan_status.STATE_MAP,
                                    plan_id)
        except Exception as e:
            LOG.error('Volume clone error: copy data failed:%(id)s,%(e)s',
                      {'id': volume_id, 'e': e})
            raise
        finally:
            try:
                # if protocol is ftp, we should unmount volume in gateway vm
                data_trans_protocol = CONF.data_transformer_procotol
                if 'ftp' == data_trans_protocol:
                    client = birdiegatewayclient.get_birdiegateway_client(
                        vgw_ip,
                        str(CONF.v2vgateway_api_listen_port)
                    )
                    client.vservices._force_umount_disk("/opt/" + volume_id)

                # if provider cloud can not detach volume in active status
                if not CONF.is_active_detach_volume:
                    resouce_common = common.ResourceCommon()
                    self.compute_api.stop_server(context, vgw_id)
                    resouce_common._await_instance_status(context,
                                                          vgw_id,
                                                          'SHUTOFF')
                # 5. detach volume
                self.compute_api.detach_volume(context, vgw_id, volume_id)
                if volume_wait_fun:
                    volume_wait_fun(context, volume_id, 'available')

                if not CONF.is_active_detach_volume:
                    self.compute_api.start_server(context, vgw_id)
                    resouce_common._await_instance_status(context,
                                                          vgw_id,
                                                          'ACTIVE')
                for attachment in volume_attachments:
                    server_id = attachment.get('server_id')
                    self.compute_api.attach_volume(context, server_id,
                                                   volume_id, None)
                    if volume_wait_fun:
                        volume_wait_fun(context, volume_id, 'in-use')
            except Exception as e:
                LOG.error('Volume clone error: detach failed:%(id)s,%(e)s',
                          {'id': volume_id, 'e': e})
Пример #6
0
 def setUp(self):
     super(ResourceCommonTestCase, self).setUp()
     self.context = context.RequestContext('fake', 'fake', is_admin=False)
     self.manager = resource_comm.ResourceCommon()