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')
def _add_extra_prop(template, stack_id): temp_res = template.get('resources') for key, value in temp_res.items(): res_type = value.get('type') if res_type == 'OS::Cinder::Volume': # v_prop = value.get('properties') v_exra_prop = value.get('extra_properties', {}) d_copy = copy_data and v_exra_prop['copy_data'] v_exra_prop['copy_data'] = d_copy if not d_copy: continue if not v_exra_prop or not v_exra_prop.get('gw_url'): phy_id = v_exra_prop.get('id') res_info = self.volume_api.get(context, phy_id) az = res_info.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) v_exra_prop.update({"gw_url": gw_url, "gw_id": gw_id}) volume_status = res_info['status'] v_exra_prop['status'] = volume_status value['extra_properties'] = v_exra_prop value['id'] = phy_id self._handle_volume_for_stack(context, value, gw_id, gw_ip, undo_mgr) elif res_type == 'OS::Nova::Server': v_exra_prop = value.get('extra_properties', {}) phy_id = v_exra_prop.get('id') server_info = self.compute_api.get_server(context, phy_id) vm_state = server_info.get('OS-EXT-STS:vm_state', None) v_exra_prop['vm_state'] = vm_state value['extra_properties'] = v_exra_prop
def convert_version_to_int(version): try: if isinstance(version, six.string_types): version = convert_version_to_tuple(version) if isinstance(version, tuple): return reduce(lambda x, y: (x * 1000) + y, version) except Exception: msg = _("Version %s is invalid.") % version raise exception.V2vException(msg)
def start_template_clone(self, context, resource_name, template): if not template: LOG.error("Resources in template is null") raise exception.V2vException(message='Template is null') try: trans_data_wait_fun = \ self.resource_common._await_data_trans_status self.clone_driver.start_volume_clone( context, resource_name, template, volume_wait_fun=self.resource_common._await_volume_status, trans_data_wait_fun=trans_data_wait_fun, set_plan_state=self._set_plan_statu) except Exception as e: LOG.error(_LW("Clone volume error: %s"), e) _msg = 'Volume clone error: %s' % e raise exception.V2vException(message=_msg)
def _add_extra_properties_for_dep_volume(self, context, resource, copy_data, undo_mgr): gw_url = resource.extra_properties.get('gw_url') 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 }) resource.extra_properties['is_deacidized'] = True self._handle_dep_volume(context, resource, gw_id, gw_ip, undo_mgr)
def __get_backend(self): if not self.__backend: if self.__config_group is None: backend_name = CONF[self.__pivot] else: backend_name = CONF[self.__config_group][self.__pivot] if backend_name not in self.__backends: msg = _('Invalid backend: %s') % backend_name raise exception.V2vException(msg) backend = self.__backends[backend_name] if isinstance(backend, tuple): name = backend[0] fromlist = backend[1] else: name = backend fromlist = backend self.__backend = __import__(name, None, None, fromlist) return self.__backend
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
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')
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