예제 #1
0
    def _handle_dv_for_svm(self, context, vol_res, server_id, dev_name,
                           gw_id, gw_ip, undo_mgr):
        volume_id = vol_res.id
        LOG.debug('detach the volume %s form server %s', volume_id, server_id)
        self.compute_api.detach_volume(context, server_id,
                                       volume_id)
        undo_mgr.undo_with(functools.partial(self._attach_volume,
                                             context,
                                             server_id,
                                             volume_id,
                                             dev_name))
        self._wait_for_volume_status(context, volume_id, server_id,
                                     'available')

        client = birdiegatewayclient.get_birdiegateway_client(
            gw_ip,
            str(CONF.v2vgateway_api_listen_port)
        )
        disks = set(client.vservices.get_disk_name().get('dev_name'))

        self.compute_api.attach_volume(context,
                                       gw_id,
                                       volume_id,
                                       None)
        LOG.debug('attach volume %s to gw host %s', volume_id, gw_id)
        undo_mgr.undo_with(functools.partial(self._detach_volume,
                                             context,
                                             gw_id,
                                             volume_id))
        self._wait_for_volume_status(context, volume_id, gw_id,
                                     'in-use')
        n_disks = set(client.vservices.get_disk_name().get('dev_name'))

        diff_disk = n_disks - disks
        LOG.debug('begin get info for volume,the vgw ip %s' % gw_ip)
        client = birdiegatewayclient.get_birdiegateway_client(
            gw_ip, str(CONF.v2vgateway_api_listen_port))
        #         sys_dev_name = client.vservices.get_disk_name(volume_id).get(
        #             'dev_name')
        #         sys_dev_name = device_name
        # sys_dev_name = attach_resp._info.get('device')
        sys_dev_name = list(diff_disk)[0] if len(diff_disk) >= 1 else None
        LOG.debug("dev_name = %s", sys_dev_name)

        vol_res.extra_properties['sys_dev_name'] = sys_dev_name
        guest_format = client.vservices.get_disk_format(sys_dev_name) \
            .get('disk_format')
        if guest_format:
            vol_res.extra_properties['guest_format'] = guest_format
            mount_point = client.vservices.force_mount_disk(
                sys_dev_name, "/opt/" + volume_id)
            vol_res.extra_properties['mount_point'] = mount_point.get(
                'mount_disk')
예제 #2
0
    def _handle_sv_for_svm(self, context, vol_res,
                           gw_id, gw_ip, undo_mgr):
        volume_id = vol_res.id
        LOG.debug('Set the volume %s shareable', volume_id)
        self.volume_api.set_volume_shareable(context, volume_id, True)
        undo_mgr.undo_with(functools.partial(self._set_volume_shareable,
                                             context,
                                             volume_id,
                                             False))

        client = birdiegatewayclient.get_birdiegateway_client(
            gw_ip,
            str(CONF.v2vgateway_api_listen_port)
        )
        disks = set(client.vservices.get_disk_name().get('dev_name'))

        self.compute_api.attach_volume(context,
                                       gw_id,
                                       volume_id,
                                       None)
        LOG.debug('Attach the volume %s to gw host %s ', volume_id, gw_id)
        undo_mgr.undo_with(functools.partial(self._detach_volume,
                                             context,
                                             gw_id,
                                             volume_id))
        self._wait_for_volume_status(context, volume_id, gw_id,
                                     'in-use')
        n_disks = set(client.vservices.get_disk_name().get('dev_name'))

        diff_disk = n_disks - disks
        LOG.debug('Begin get info for volume,the vgw ip %s' % gw_ip)
        client = birdiegatewayclient.get_birdiegateway_client(
            gw_ip, str(CONF.v2vgateway_api_listen_port))
        #         sys_dev_name = client.vservices.get_disk_name(volume_id).get(
        #             'dev_name')
        #         sys_dev_name = device_name
        #        sys_dev_name = attach_resp._info.get('device')
        sys_dev_name = list(diff_disk)[0] if len(diff_disk) >= 1 else None
        LOG.debug("dev_name = %s", sys_dev_name)
        vol_res.extra_properties['sys_dev_name'] = sys_dev_name
        guest_format = client.vservices.get_disk_format(sys_dev_name) \
            .get('disk_format')
        if guest_format:
            vol_res.extra_properties['guest_format'] = guest_format
            mount_point = client.vservices.force_mount_disk(
                sys_dev_name, "/opt/" + volume_id)
            vol_res.extra_properties['mount_point'] = mount_point.get(
                'mount_disk')
예제 #3
0
 def _handle_volume_for_vm_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')
     sys_clone = server_resource.get('extra_properties', {}) \
                                .get('sys_clone')
     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)
         volume_id = volume_res.get('extra_properties', {}) \
                               .get('id')
         vgw_url = volume_res.get('extra_properties', {}) \
                             .get('gw_url')
         vgw_ip = vgw_url.split(':')[0]
         if not sys_clone and boot_index in ['0', 0]:
             continue
         try:
             client = birdiegatewayclient.get_birdiegateway_client(
                 vgw_ip, str(CONF.v2vgateway_api_listen_port))
             client.vservices._force_umount_disk("/opt/" + volume_id)
             self.nova_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.nova_api.attach_volume(context, server_id, volume_id,
                                         device_name)
             self._wait_for_volume_status(context, volume_id, server_id,
                                          'in-use')
         except Exception as e:
             LOG.error(
                 _LE('Error from handle volume of vm after clone. '
                     'Error=%(e)s'), {'e': e})
예제 #4
0
 def _add_extra_prop_for_dep_in_use_volume(self, context, resource,
                                           copy_data, undo_mgr):
     volume_id = resource.extra_properties.get('id')
     volume = self.volume_api.get(context, volume_id)
     v_shareable = volume['shareable']
     gw_url = resource.extra_properties.get('gw_url')
     gw_id = None
     gw_ip = None
     if not gw_url:
         az = resource.properties.get('availability_zone')
         gw_id, gw_ip = utils.get_next_vgw(az)
         if not gw_id or not gw_ip:
             raise exception.V2vException(message='no vgw host found')
         gw_url = gw_ip + ':' + str(CONF.v2vgateway_api_listen_port)
         resource.extra_properties.update({
             "gw_url": gw_url,
             "gw_id": gw_id
         })
     if not v_shareable:
         v_attachments = volume.get('attachments', [])
         resource.extra_properties['attachments'] = v_attachments
         for attachment in v_attachments:
             server_id = attachment.get('server_id')
             server_info = self.compute_api.get_server(context, server_id)
             vm_state = server_info.get('OS-EXT-STS:vm_state', None)
             if vm_state != 'stopped':
                 _msg = 'the server %s not stopped' % server_id
                 raise exception.V2vException(message=_msg)
             device = attachment.get('device')
             self.compute_api.detach_volume(context, server_id, volume_id)
             self._wait_for_volume_status(context, volume_id, server_id,
                                          'available')
             undo_mgr.undo_with(
                 functools.partial(self._attach_volume, context, server_id,
                                   volume_id, device))
     client = birdiegatewayclient.get_birdiegateway_client(
         gw_ip, str(CONF.v2vgateway_api_listen_port))
     disks = set(client.vservices.get_disk_name().get('dev_name'))
     LOG.debug('Attach volume %s to gw host %s', volume_id, gw_id)
     attach_resp = self.compute_api.attach_volume(context, gw_id, volume_id,
                                                  None)
     LOG.debug('The volume attachment info is %s ' % str(attach_resp))
     undo_mgr.undo_with(
         functools.partial(self._detach_volume, context, gw_id, volume_id))
     self._wait_for_volume_status(context, volume_id, gw_id, 'in-use')
     n_disks = set(client.vservices.get_disk_name().get('dev_name'))
     diff_disk = n_disks - disks
     LOG.debug('Begin get info for volume,the vgw ip %s' % gw_ip)
     sys_dev_name = list(diff_disk)[0] if len(diff_disk) >= 1 else None
     LOG.debug("dev_name = %s", sys_dev_name)
     resource.extra_properties['sys_dev_name'] = sys_dev_name
     guest_format = client.vservices.get_disk_format(sys_dev_name) \
         .get('disk_format')
     if guest_format:
         resource.extra_properties['guest_format'] = guest_format
         mount_point = client.vservices.force_mount_disk(
             sys_dev_name, "/opt/" + volume_id)
         resource.extra_properties['mount_point'] = mount_point.get(
             'mount_disk')
예제 #5
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})
예제 #6
0
    def _handle_dep_volume(self, context, resource, gw_id, gw_ip, undo_mgr):
        volume_id = resource.id
        LOG.debug('Attach volume %s to gw host %s', volume_id, gw_id)
        # query disk list before attaching (add wanggang)
        client = birdiegatewayclient.get_birdiegateway_client(
            gw_ip,
            str(CONF.v2vgateway_api_listen_port)
        )
        disks = set(client.vservices.get_disk_name().get('dev_name'))

        self.compute_api.attach_volume(context,
                                       gw_id,
                                       volume_id,
                                       None)
        undo_mgr.undo_with(functools.partial(self._detach_volume,
                                             gw_id,
                                             volume_id))
        self._wait_for_volume_status(context, volume_id,
                                     gw_id,
                                     'in-use')

        n_disks = set(client.vservices.get_disk_name().get('dev_name'))

        diff_disk = n_disks - disks
        resource.extra_properties['status'] = 'in-use'
        LOG.debug('Begin get info for volume,the vgw ip %s' % gw_ip)
        # client = birdiegatewayclient.get_birdiegateway_client(
        #     gw_ip,
        #     str(CONF.v2vgateway_api_listen_port)
        # )
        # sys_dev_name = client.vservices.get_disk_name(volume_id).get(
        #                 'dev_name')
        # sys_dev_name = device_name
        # sys_dev_name = attach_resp._info.get('device')
        sys_dev_name = list(diff_disk)[0] if len(diff_disk) >= 1 else None
        LOG.debug("in _handle_dep_volume dev_name = %s", sys_dev_name)
        resource.extra_properties['sys_dev_name'] = sys_dev_name
        guest_format = client.vservices.get_disk_format(sys_dev_name) \
            .get('disk_format')
        if guest_format:
            resource.extra_properties['guest_format'] = guest_format
            mount_point = client.vservices.force_mount_disk(
                sys_dev_name, "/opt/" + volume_id)
            resource.extra_properties['mount_point'] = mount_point.get(
                'mount_disk'
            )
예제 #7
0
    def _handle_dep_volume_after_clone(self, context, resource):
        volume_id = resource.get('extra_properties', {}).get('id')
        extra_properties = resource.get('extra_properties', {})
        vgw_id = extra_properties.get('gw_id')
        if not extra_properties.get('copy_data', True):
            return
        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
                resouce_common = common.ResourceCommon()
                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})
예제 #8
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})
예제 #9
0
    def _handle_dep_volume(self, context, resource, gw_id, gw_ip, undo_mgr):
        volume_id = resource.id
        LOG.debug('Attach volume %s to gw host %s', volume_id, gw_id)
        # query disk list before attaching (add wanggang)
        client = birdiegatewayclient.get_birdiegateway_client(
            gw_ip, str(CONF.v2vgateway_api_listen_port))
        disks = set(client.vservices.get_disk_name().get('dev_name'))

        self.compute_api.attach_volume(context, gw_id, volume_id, None)
        undo_mgr.undo_with(
            functools.partial(self._detach_volume, gw_id, volume_id))
        self._wait_for_volume_status(context, volume_id, gw_id, 'in-use')

        n_disks = set(client.vservices.get_disk_name().get('dev_name'))

        diff_disk = n_disks - disks
        resource.extra_properties['status'] = 'in-use'
        LOG.debug('Begin get info for volume,the vgw ip %s' % gw_ip)
        # client = birdiegatewayclient.get_birdiegateway_client(
        #     gw_ip,
        #     str(CONF.v2vgateway_api_listen_port)
        # )
        # sys_dev_name = client.vservices.get_disk_name(volume_id).get(
        #                 'dev_name')
        # sys_dev_name = device_name
        # sys_dev_name = attach_resp._info.get('device')
        sys_dev_name = list(diff_disk)[0] if len(diff_disk) >= 1 else None
        LOG.debug("in _handle_dep_volume dev_name = %s", sys_dev_name)
        resource.extra_properties['sys_dev_name'] = sys_dev_name
        guest_format = client.vservices.get_disk_format(sys_dev_name) \
            .get('disk_format')
        if guest_format:
            resource.extra_properties['guest_format'] = guest_format
            mount_point = client.vservices.force_mount_disk(
                sys_dev_name, "/opt/" + volume_id)
            resource.extra_properties['mount_point'] = mount_point.get(
                'mount_disk')
예제 #10
0
 def _handle_volume_for_vm_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')
     sys_clone = server_resource.get('extra_properties', {}) \
                                .get('sys_clone')
     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)
         volume_id = volume_res.get('extra_properties', {}) \
                               .get('id')
         vgw_url = volume_res.get('extra_properties', {}) \
                             .get('gw_url')
         vgw_ip = vgw_url.split(':')[0]
         if not sys_clone and boot_index in ['0', 0]:
             continue
         try:
             client = birdiegatewayclient.get_birdiegateway_client(
                 vgw_ip, str(CONF.v2vgateway_api_listen_port))
             client.vservices._force_umount_disk("/opt/" + volume_id)
             self.nova_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.nova_api.attach_volume(context, server_id,
                                         volume_id,
                                         device_name)
             self._wait_for_volume_status(context, volume_id,
                                          server_id, 'in-use')
         except Exception as e:
             LOG.error(_LE('Error from handle volume of vm after clone. '
                           'Error=%(e)s'), {'e': e})
예제 #11
0
    def _copy_volume_data(self, context, resource_name,
                          des_gw_ip, vgw_id, template, dev_name):

        LOG.debug('Clone volume driver copy data start for %s', resource_name)
        resources = template.get('resources')
        volume_res = resources.get(resource_name)
        volume_id = volume_res.get('id')
        volume_ext_properties = volume_res.get('extra_properties')
        # 1. get gateway vm conveyor agent service ip and port
        des_gw_port = str(CONF.v2vgateway_api_listen_port)
        des_gw_url = des_gw_ip + ':' + des_gw_port
        # data transformer procotol(ftp/fillp)
        data_trans_protocol = CONF.data_transformer_procotol
        # data_trans_ports = CONF.trans_ports
        # trans_port = data_trans_ports[0]
        trans_port = utils.get_next_port_for_vgw(vgw_id)
        # 2. get source cloud gateway vm conveyor agent service ip and port
        src_gw_url = volume_ext_properties.get('gw_url')

        src_urls = src_gw_url.split(':')

        if len(src_urls) != 2:
            LOG.error("Input source gw url error: %s", src_gw_url)
            msg = "Input source gw url error: " + src_gw_url
            raise exception.InvalidInput(reason=msg)

        src_gw_ip = src_urls[0]
        src_gw_port = src_urls[1]

        # 3. get volme mount point and disk format info

        boot_index = 1
        src_mount_point = "/opt/" + volume_id

        if volume_ext_properties:
            src_dev_format = volume_ext_properties.get('guest_format')
            # volume dev name in system
            src_vol_sys_dev = volume_ext_properties.get('sys_dev_name')
            boot_index = volume_ext_properties.get('boot_index', 1)

            if dev_name:
                des_dev_name = dev_name
            else:
                des_dev_name = src_vol_sys_dev

        if not src_dev_format:
            client = birdiegatewayclient.get_birdiegateway_client(src_gw_ip,
                                                                  src_gw_port)
            d_fromat = client.vservices.get_disk_format(src_vol_sys_dev)
            src_dev_format = d_fromat.get('disk_format')

        # if disk does not format, then no data to copy
        if not src_dev_format and data_trans_protocol == 'ftp':
            rsp = {'volume_id': volume_id,
                   'des_ip': None,
                   'des_port': None,
                   'copy_tasks': None}
            return rsp

        mount_point = []
        task_ids = []

        if boot_index not in[0, '0'] and data_trans_protocol == 'ftp':
            mount_point.append(src_mount_point)

        # 4. copy data
        client = birdiegatewayclient.get_birdiegateway_client(des_gw_ip,
                                                              des_gw_port)
        clone_rsp = client.vservices.clone_volume(
                                        src_vol_sys_dev,
                                        des_dev_name,
                                        src_dev_format,
                                        mount_point,
                                        src_gw_url,
                                        des_gw_url,
                                        trans_protocol=data_trans_protocol,
                                        trans_port=trans_port)
        task_id = clone_rsp.get('body').get('task_id')
        task_ids.append(task_id)

        rsp = {'volume_id': volume_id,
               'des_ip': des_gw_ip,
               'des_port': des_gw_port,
               'copy_tasks': task_ids}

        LOG.debug('Clone volume driver copy data end for %s', resource_name)
        return rsp
예제 #12
0
 def _handle_volume_for_stack(self, context, vol_res,
                              gw_id, gw_ip, undo_mgr):
     volume_id = vol_res.get('id')
     volume_info = self.volume_api.get(context, volume_id)
     volume_status = volume_info['status']
     v_shareable = volume_info['shareable']
     if not v_shareable and volume_status == 'in-use':
         volume_attachments = volume_info.get('attachments', [])
         vol_res.get('extra_properties')['attachments'] = volume_attachments
         for attachment in volume_attachments:
             server_id = attachment.get('server_id')
             server_info = self.compute_api.get_server(context, server_id)
             vm_state = server_info.get('OS-EXT-STS:vm_state', None)
             if vm_state != 'stopped':
                 _msg = 'the server %s not stopped' % server_id
                 raise exception.V2vException(message=_msg)
             device = attachment.get('device')
             self.compute_api.detach_volume(context, server_id,
                                            volume_id)
             self._wait_for_volume_status(context, volume_id, server_id,
                                          'available')
             undo_mgr.undo_with(functools.partial(self._attach_volume,
                                                  context,
                                                  server_id,
                                                  volume_id,
                                                  device))
     client = birdiegatewayclient.get_birdiegateway_client(
         gw_ip,
         str(CONF.v2vgateway_api_listen_port)
     )
     disks = set(client.vservices.get_disk_name().get('dev_name'))
     LOG.debug('Attach volume %s to gw host %s', volume_id, gw_id)
     attach_resp = self.compute_api.attach_volume(context,
                                                  gw_id,
                                                  volume_id,
                                                  None)
     LOG.debug('The volume attachment info is %s '
               % str(attach_resp))
     undo_mgr.undo_with(functools.partial(self._detach_volume,
                                          context,
                                          gw_id,
                                          volume_id))
     self._wait_for_volume_status(context, volume_id, gw_id,
                                  'in-use')
     n_disks = set(client.vservices.get_disk_name().get('dev_name'))
     diff_disk = n_disks - disks
     vol_res.get('extra_properties')['status'] = 'in-use'
     LOG.debug('Begin get info for volume,the vgw ip %s' % gw_ip)
     sys_dev_name = list(diff_disk)[0] if len(diff_disk) >= 1 else None
     LOG.debug("dev_name = %s", sys_dev_name)
     #         device_name = attach_resp._info.get('device')
     #         sys_dev_name = client.vservices.get_disk_name(volume_id).get(
     #             'dev_name')
     #        sys_dev_name = device_name
     vol_res.get('extra_properties')['sys_dev_name'] = sys_dev_name
     guest_format = client.vservices.get_disk_format(sys_dev_name) \
         .get('disk_format')
     if guest_format:
         vol_res.get('extra_properties')['guest_format'] = guest_format
         mount_point = client.vservices.force_mount_disk(
             sys_dev_name, "/opt/" + volume_id)
         vol_res.get('extra_properties')['mount_point'] = mount_point.get(
             'mount_disk')
예제 #13
0
 def add_extra_properties_for_server(self, context, resource, resource_map,
                                     sys_clone, copy_data,
                                     undo_mgr):
     migrate_net_map = CONF.migrate_net_map
     server_properties = resource.properties
     server_id = resource.id
     server_extra_properties = resource.extra_properties
     server_az = server_properties.get('availability_zone')
     vm_state = server_extra_properties.get('vm_state')
     gw_url = server_extra_properties.get('gw_url')
     if not gw_url:
         if vm_state == 'stopped':
             gw_id, gw_ip = utils.get_next_vgw(server_az)
             if not gw_id or not gw_ip:
                 raise exception.V2vException(message='no vgw host found')
             gw_url = gw_ip + ':' + str(CONF.v2vgateway_api_listen_port)
             resource.extra_properties.update({"gw_url": gw_url,
                                               "gw_id": gw_id})
             resource.extra_properties['sys_clone'] = sys_clone
             resource.extra_properties['is_deacidized'] = True
             block_device_mapping = server_properties.get(
                 'block_device_mapping_v2')
             if block_device_mapping:
                 for block_device in block_device_mapping:
                     volume_name = block_device.get('volume_id').get(
                         'get_resource')
                     volume_resource = resource_map.get(volume_name)
                     volume_resource.extra_properties['gw_url'] = gw_url
                     volume_resource.extra_properties['is_deacidized'] = \
                         True
                     boot_index = block_device.get('boot_index')
                     dev_name = block_device.get('device_name')
                     if boot_index == 0 or boot_index == '0':
                         volume_resource.extra_properties['sys_clone'] = \
                             sys_clone
                         if sys_clone:
                             self._handle_dv_for_svm(context,
                                                     volume_resource,
                                                     server_id, dev_name,
                                                     gw_id, gw_ip, undo_mgr)
                     else:
                         d_copy = copy_data and volume_resource. \
                             extra_properties['copy_data']
                         volume_resource.extra_properties['copy_data'] = \
                             d_copy
                         if not d_copy:
                             continue
                         self._handle_dv_for_svm(context, volume_resource,
                                                 server_id, dev_name,
                                                 gw_id, gw_ip, undo_mgr)
         else:
             if migrate_net_map:
                 # get the availability_zone of server
                 server_az = server_properties.get('availability_zone')
                 if not server_az:
                     LOG.error(_LE('Not get the availability_zone'
                                   'of server %s') % resource.id)
                     raise exception.AvailabilityZoneNotFound(
                         server_uuid=resource.id)
                 migrate_net_id = migrate_net_map.get(server_az)
                 if not migrate_net_id:
                     LOG.error(_LE('Not get the migrate net of server %s')
                               % resource.id)
                     raise exception.NoMigrateNetProvided(
                         server_uuid=resource.id)
                 # attach interface
                 LOG.debug('Attach a port of net %s to server %s',
                           migrate_net_id,
                           server_id)
                 obj = self.compute_api.interface_attach(context, server_id,
                                                         migrate_net_id,
                                                         None,
                                                         None)
                 interface_attachment = obj._info
                 if interface_attachment:
                     LOG.debug('The interface attachment info is %s '
                               % str(interface_attachment))
                     migrate_fix_ip = interface_attachment.get('fixed_ips')[0] \
                         .get('ip_address')
                     migrate_port_id = interface_attachment.get('port_id')
                     undo_mgr.undo_with(functools.partial
                                        (self.compute_api.interface_detach,
                                         context,
                                         server_id,
                                         migrate_port_id))
                     gw_url = migrate_fix_ip + ':' + str(
                         CONF.v2vgateway_api_listen_port)
                     extra_properties = {}
                     extra_properties['gw_url'] = gw_url
                     extra_properties['is_deacidized'] = True
                     extra_properties['migrate_port_id'] = migrate_port_id
                     extra_properties['sys_clone'] = sys_clone
                     resource.extra_properties.update(extra_properties)
                     # waiting port attach finished, and can ping this vm
                     self._await_port_status(context, migrate_port_id,
                                             migrate_fix_ip)
             # else:
             #     interfaces = self.neutron_api.port_list(
             #         context, device_id=server_id)
             #     host_ip = None
             #     for infa in interfaces:
             #         if host_ip:
             #             break
             #         binding_profile = infa.get("binding:profile", [])
             #         if binding_profile:
             #             host_ip = binding_profile.get('host_ip')
             #     if not host_ip:
             #         LOG.error(_LE('Not find the clone data
             # ip for server'))
             #         raise exception.NoMigrateNetProvided(
             #             server_uuid=resource.id
             #         )
             #     gw_url = host_ip + ':' + str(
             #         CONF.v2vgateway_api_listen_port)
             #     extra_properties = {}
             #     extra_properties['gw_url'] = gw_url
             #     extra_properties['sys_clone'] = sys_clone
             #     resource.extra_properties.update(extra_properties)
             block_device_mapping = server_properties.get(
                 'block_device_mapping_v2')
             if block_device_mapping:
                 client = None
                 if gw_url:
                     gw_urls = gw_url.split(':')
                     client = birdiegatewayclient.get_birdiegateway_client(
                         gw_urls[0], gw_urls[1])
                 for block_device in block_device_mapping:
                     device_name = block_device.get('device_name')
                     volume_name = block_device.get('volume_id').get(
                         'get_resource')
                     volume_resource = resource_map.get(volume_name)
                     boot_index = block_device.get('boot_index')
                     if boot_index == 0 or boot_index == '0':
                         volume_resource.extra_properties['sys_clone'] = \
                             sys_clone
                         if not sys_clone:
                             continue
                     else:
                         d_copy = copy_data and volume_resource. \
                             extra_properties['copy_data']
                         volume_resource.extra_properties['copy_data'] = \
                             d_copy
                         if not d_copy:
                             continue
                     # need to check the vm disk name
                     if not client:
                         continue
                     src_dev_format = client.vservices. \
                         get_disk_format(device_name).get('disk_format')
                     src_mount_point = client. \
                         vservices.get_disk_mount_point(device_name). \
                         get('mount_point')
                     volume_resource.extra_properties['guest_format'] = \
                         src_dev_format
                     volume_resource.extra_properties['mount_point'] = \
                         src_mount_point
                     volume_resource.extra_properties['gw_url'] = gw_url
                     volume_resource.extra_properties['is_deacidized'] = \
                         True
                     sys_dev_name = client. \
                         vservices.get_disk_name(volume_resource.id). \
                         get('dev_name')
                     if not sys_dev_name:
                         sys_dev_name = device_name
                     volume_resource.extra_properties['sys_dev_name'] = \
                         sys_dev_name
예제 #14
0
 def _add_extra_prop_for_dep_in_use_volume(self, context, resource,
                                           copy_data, undo_mgr):
     volume_id = resource.extra_properties.get('id')
     volume = self.volume_api.get(context, volume_id)
     v_shareable = volume['shareable']
     gw_url = resource.extra_properties.get('gw_url')
     gw_id = None
     gw_ip = None
     if not gw_url:
         az = resource.properties.get('availability_zone')
         gw_id, gw_ip = utils.get_next_vgw(az)
         if not gw_id or not gw_ip:
             raise exception.V2vException(message='no vgw host found')
         gw_url = gw_ip + ':' + str(CONF.v2vgateway_api_listen_port)
         resource.extra_properties.update({"gw_url": gw_url,
                                           "gw_id": gw_id})
     if not v_shareable:
         v_attachments = volume.get('attachments', [])
         resource.extra_properties['attachments'] = v_attachments
         for attachment in v_attachments:
             server_id = attachment.get('server_id')
             server_info = self.compute_api.get_server(context,
                                                       server_id)
             vm_state = server_info.get('OS-EXT-STS:vm_state', None)
             if vm_state != 'stopped':
                 _msg = 'the server %s not stopped' % server_id
                 raise exception.V2vException(message=_msg)
             device = attachment.get('device')
             self.compute_api.detach_volume(context, server_id,
                                            volume_id)
             self._wait_for_volume_status(context, volume_id,
                                          server_id,
                                          'available')
             undo_mgr.undo_with(functools.partial(self._attach_volume,
                                                  context,
                                                  server_id,
                                                  volume_id,
                                                  device))
     client = birdiegatewayclient.get_birdiegateway_client(
         gw_ip,
         str(CONF.v2vgateway_api_listen_port)
     )
     disks = set(client.vservices.get_disk_name().get('dev_name'))
     LOG.debug('Attach volume %s to gw host %s', volume_id, gw_id)
     attach_resp = self.compute_api.attach_volume(context,
                                                  gw_id,
                                                  volume_id,
                                                  None)
     LOG.debug('The volume attachment info is %s '
               % str(attach_resp))
     undo_mgr.undo_with(functools.partial(self._detach_volume,
                                          context,
                                          gw_id,
                                          volume_id))
     self._wait_for_volume_status(context, volume_id, gw_id,
                                  'in-use')
     n_disks = set(client.vservices.get_disk_name().get('dev_name'))
     diff_disk = n_disks - disks
     LOG.debug('Begin get info for volume,the vgw ip %s' % gw_ip)
     sys_dev_name = list(diff_disk)[0] if len(diff_disk) >= 1 else None
     LOG.debug("dev_name = %s", sys_dev_name)
     resource.extra_properties['sys_dev_name'] = sys_dev_name
     guest_format = client.vservices.get_disk_format(sys_dev_name) \
         .get('disk_format')
     if guest_format:
         resource.extra_properties['guest_format'] = guest_format
         mount_point = client.vservices.force_mount_disk(
             sys_dev_name, "/opt/" + volume_id)
         resource.extra_properties['mount_point'] = mount_point.get(
             'mount_disk')
예제 #15
0
    def _await_data_trans_status(self,
                                 context,
                                 host,
                                 port,
                                 task_ids,
                                 state_map,
                                 plan_id=None):

        start = time.time()
        retries = CONF.data_transformer_state_retries
        if retries < 0:
            LOG.warn(
                _LW("Treating negative config value (%(retries)s) for "
                    "'datat_transformer_retries' as 0."), {'retries': retries})
        # (1) treat  negative config value as 0
        # (2) the configured value is 0, one attempt should be made
        # (3) the configured value is > 0, then the total number attempts
        #      is (retries + 1)

        # if not volume data to copy
        if not host:
            plan_state = state_map.get('DATA_TRANS_FINISHED')
            values = {}
            values['plan_status'] = plan_state
            values['task_status'] = 'DATA_TRANS_FINISHED'
            self.plan_api.update_plan(context, plan_id, values)
            return 0

        attempts = 1
        if retries >= 1:
            attempts = retries + 1
        for attempt in range(1, attempts + 1):
            # record all volume data transformer task state
            task_states = []
            for task_id in task_ids:
                cls = conveyorclient.get_birdiegateway_client(host, port)
                status = cls.vservices.get_data_trans_status(task_id)
                task_status = status.get('body').get('task_state')
                # if one volume data transformer failed, this clone failed
                if 'DATA_TRANS_FAILED' == task_status:
                    plan_state = state_map.get(task_status)
                    values = {}
                    values['plan_status'] = plan_state
                    values['task_status'] = task_status
                    self.plan_api.update_plan(context, plan_id, values)
                    return attempt
                task_states.append(task_status)
            # as long as one volume data does not transformer finished,
            # clone plan state is cloning
            if 'DATA_TRANSFORMING' in task_states:
                plan_state = state_map.get('DATA_TRANSFORMING')
                values = {}
                values['plan_status'] = plan_state
                values['task_status'] = 'DATA_TRANSFORMING'
                self.plan_api.update_plan(context, plan_id, values)
            # otherwise, plan state is finished
            else:
                LOG.debug(_("Data transformer finished!"))
                plan_state = state_map.get('DATA_TRANS_FINISHED')
                values = {}
                values['plan_status'] = plan_state
                values['task_status'] = 'DATA_TRANS_FINISHED'
                self.plan_api.update_plan(context, plan_id, values)
                return attempt

            greenthread.sleep(CONF.data_transformer_state_retries_interval)

        # NOTE(harlowja): Should only happen if we ran out of attempts
        raise exception.InstanceNotCreated(instance_id=task_id,
                                           seconds=int(time.time() - start),
                                           attempts=attempts)
예제 #16
0
    def _await_data_trans_status(self, context, host, port, task_ids,
                                 state_map, plan_id=None):

        start = time.time()
        retries = CONF.data_transformer_state_retries
        if retries < 0:
            LOG.warn(_LW("Treating negative config value (%(retries)s) for "
                         "'datat_transformer_retries' as 0."),
                     {'retries': retries})
        # (1) treat  negative config value as 0
        # (2) the configured value is 0, one attempt should be made
        # (3) the configured value is > 0, then the total number attempts
        #      is (retries + 1)

        # if not volume data to copy
        if not host:
            plan_state = state_map.get('DATA_TRANS_FINISHED')
            values = {}
            values['plan_status'] = plan_state
            values['task_status'] = 'DATA_TRANS_FINISHED'
            self.plan_api.update_plan(context, plan_id, values)
            return 0

        attempts = 1
        if retries >= 1:
            attempts = retries + 1
        for attempt in range(1, attempts + 1):
            # record all volume data transformer task state
            task_states = []
            for task_id in task_ids:
                cls = conveyorclient.get_birdiegateway_client(host, port)
                status = cls.vservices.get_data_trans_status(task_id)
                task_status = status.get('body').get('task_state')
                # if one volume data transformer failed, this clone failed
                if 'DATA_TRANS_FAILED' == task_status:
                    plan_state = state_map.get(task_status)
                    values = {}
                    values['plan_status'] = plan_state
                    values['task_status'] = task_status
                    self.plan_api.update_plan(context, plan_id, values)
                    return attempt
                task_states.append(task_status)
            # as long as one volume data does not transformer finished,
            # clone plan state is cloning
            if 'DATA_TRANSFORMING' in task_states:
                    plan_state = state_map.get('DATA_TRANSFORMING')
                    values = {}
                    values['plan_status'] = plan_state
                    values['task_status'] = 'DATA_TRANSFORMING'
                    self.plan_api.update_plan(context, plan_id, values)
            # otherwise, plan state is finished
            else:
                LOG.debug(_("Data transformer finished!"))
                plan_state = state_map.get('DATA_TRANS_FINISHED')
                values = {}
                values['plan_status'] = plan_state
                values['task_status'] = 'DATA_TRANS_FINISHED'
                self.plan_api.update_plan(context, plan_id, values)
                return attempt

            greenthread.sleep(CONF.data_transformer_state_retries_interval)

        # NOTE(harlowja): Should only happen if we ran out of attempts
        raise exception.InstanceNotCreated(instance_id=task_id,
                                           seconds=int(time.time() - start),
                                           attempts=attempts)
예제 #17
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})
예제 #18
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})
예제 #19
0
    def _copy_volume_data(self, context, resource_name, template,
                          trans_data_wait_fun=None, port_wait_fun=None):
        '''copy volumes in template data'''
        resources = template.get('resources')
        instance = resources.get(resource_name)
        # 2. get server info
        server_id = instance.get('id')
        stack_id = template.get('stack_id')

        try:
            server = self.nova_api.get_server(context, server_id)
        except Exception as e:
            LOG.error("Query server %(server_id)s error: %(error)s",
                      {'server_id': server_id, 'error': e})
            raise exception.ServerNotFound(server_id=server_id)

        # 3. get volumes attached to this server
        properties = instance.get('properties')
        ext_properties = instance.get('extra_properties')
        volumes = properties.get('block_device_mapping_v2')
        if not volumes:
            LOG.warn("Clone instance warning: instance does not have volume.")
            rsp = {'server_id': server_id,
                   'port_id': None,
                   'des_ip': None,
                   'des_port': None,
                   'copy_tasks': []}
            return rsp
        bdms = []

        for v_volume in volumes:
            # if volume id is string, this volume is using exist volume,
            # so does not copy data
            vol_res_id = v_volume.get('volume_id')
            if isinstance(vol_res_id, str) or vol_res_id.get('get_param'):
                _msg = "Instance clone warning: volume does not copy data: %s" \
                     % vol_res_id
                LOG.debug(_msg)
                continue
            vol_res_name = v_volume.get('volume_id').get('get_resource')
            sys_clone = ext_properties.get('sys_clone')
            boot_index = v_volume.get('boot_index')
            # 3.1 if do not clone system volume,
            # don't add system volume to bdms
            if not sys_clone and boot_index in [0, '0']:
                continue
            volume_ext_properties = \
                resources.get(vol_res_name).get('extra_properties')
            if not volume_ext_properties.get('copy_data'):
                continue
            # 3.2 get volume id
            volume_id = self._get_resource_id(context, vol_res_name, stack_id)
            v_volume['id'] = volume_id
            if volume_ext_properties:
                v_volume['guest_format'] = \
                    volume_ext_properties.get('guest_format')
                v_volume['mount_point'] = \
                    volume_ext_properties.get('mount_point')
                # volume dev name in system
                vol_sys_dev = volume_ext_properties.get('sys_dev_name')
                # if not None, use it,otherwise use default name
                if vol_sys_dev:
                    v_volume['device_name'] = vol_sys_dev
            bdms.append(v_volume)

        if not bdms:
            return {}
        # 4. create transform data port to new instances
        server_az = server.get('OS-EXT-AZ:availability_zone', None)
        id = server.get('id', None)
        if not server_az:
            LOG.error('Can not get the availability_zone of server %s', id)
            raise exception.AvailabilityZoneNotFound(server_uuid=id)

        migrate_net_map = CONF.migrate_net_map
        migrate_net_id = migrate_net_map.get(server_az, None)

        if migrate_net_id:
            # 4.1 call neutron api create port
            LOG.debug("Instance template driver attach port to instance start")
            net_info = self.nova_api.interface_attach(context, id,
                                                      migrate_net_id,
                                                      port_id=None,
                                                      fixed_ip=None)

            interface_attachment = net_info._info
            if interface_attachment:
                LOG.debug('The interface attachment info is %s ' %
                          str(interface_attachment))
                des_gw_ip = \
                    interface_attachment.get('fixed_ips')[0].get('ip_address')
                port_id = interface_attachment.get('port_id')
            else:
                LOG.error("Instance template driver attach port failed")
                raise exception.NoMigrateNetProvided(server_uuid=id)
        else:
            retrying = 1
            while retrying < 300:
                des_gw_ip = self._get_server_ip(context, server_id)
                if des_gw_ip:
                    break
                retrying += 1
                time.sleep(2)
            port_id = None

        LOG.debug("Instance template driver attach port end: %s", des_gw_ip)
        if not des_gw_ip:
            _msg = "New clone or migrate VM data transformer IP is None"
            raise exception.V2vException(message=_msg)
        des_port = str(CONF.v2vgateway_api_listen_port)
        des_gw_url = des_gw_ip + ":" + des_port

        # data transformer procotol(ftp/fillp)
        data_trans_protocol = CONF.data_transformer_procotol
        data_trans_ports = CONF.trans_ports
        trans_port = data_trans_ports[0]
        src_gw_url = ext_properties.get('gw_url')

        src_urls = src_gw_url.split(':')

        if len(src_urls) != 2:
            LOG.error("Input source gw url error: %s", src_gw_url)
            msg = "Input source gw url error: " + src_gw_url
            raise exception.InvalidInput(reason=msg)
        # 5. request birdiegateway service to clone each volume data
        # record all volume data copy task id
        task_ids = []
        for bdm in bdms:
            # 6.1 query cloned new VM volume name
            # src_dev_name = "/dev/sdc"
            src_dev_name = bdm.get('device_name')
            client = birdiegatewayclient.get_birdiegateway_client(des_gw_ip,
                                                                  des_port)
            des_dev_name = \
                client.vservices.get_disk_name(bdm.get('id')).get('dev_name')
            if not des_dev_name:
                des_dev_name = src_dev_name

            src_dev_format = bdm.get('guest_format')
            # if template does not hava disk format and mount point info
            # query them from conveyor-agent
            if not src_dev_format:
                client = \
                    birdiegatewayclient.get_birdiegateway_client(src_urls[0],
                                                                 src_urls[1])
                d_format = client.vservices.get_disk_format(src_dev_name)
                src_dev_format = d_format.get('disk_format')
            # if volume does not format, this volume not data to transformer
            if not src_dev_format and CONF.data_transformer_procotol == 'ftp':
                continue

            src_mount_point = bdm.get('mount_point')

            if not src_mount_point:
                client = \
                    birdiegatewayclient.get_birdiegateway_client(src_urls[0],
                                                                 src_urls[1])
                m_info = client.vservices.get_disk_mount_point(src_dev_name)
                src_mount_point = m_info.get('mount_point')

            if not src_mount_point and CONF.data_transformer_procotol == 'ftp':
                continue

            mount_point = []
            mount_point.append(src_mount_point)
            LOG.debug('Volume %(dev_name)s disk format is %(disk_format)s'
                      ' and mount point is %(point)s',
                      {'dev_name': src_dev_name,
                       'disk_format': src_dev_format,
                       'point': src_mount_point})

            # get conveyor gateway client to call birdiegateway api
            LOG.debug("Instance template driver transform data start")
            client = birdiegatewayclient.get_birdiegateway_client(des_gw_ip,
                                                                  des_port)
            clone_rsp = client.vservices.clone_volume(
                            src_dev_name,
                            des_dev_name,
                            src_dev_format,
                            mount_point,
                            src_gw_url,
                            des_gw_url,
                            trans_protocol=data_trans_protocol,
                            trans_port=trans_port)
            task_id = clone_rsp.get('body').get('task_id')
            if not task_id:
                LOG.warn("Clone volume %(dev_name)s response is %(rsp)s",
                         {'dev_name': des_dev_name, 'rsp': clone_rsp})
                continue
            task_ids.append(task_id)

        rsp = {'server_id': server_id,
               'port_id': port_id,
               'des_ip': des_gw_ip,
               'des_port': des_port,
               'copy_tasks': task_ids}
        LOG.debug("Instance template driver transform data end")
        return rsp