Beispiel #1
0
 def _create_target_volume(self,volume_dict_for_image_id):
     """ create the target volume and return the mapping of source_volume and target_volume"""
     LOG.info('begin create target volume')
     source_target_vol_mapping={}
     if volume_dict_for_image_id:
         for volume_id in volume_dict_for_image_id.keys():
             image_id_of_volume = volume_dict_for_image_id.get(volume_id)
             image = self.image_api.get(self.context,image_id_of_volume)
             query_image_status_count=1800
             LOG.info('query the image %s status of the voluem %s' %(image_id_of_volume,volume_id))
             while image['status'] != 'active':
                 time.sleep(2)
                 image = self.image_api.get(self.context,image_id_of_volume)
                 if image['status'] == 'error':
                     msg = _("migrate vm failed.")
                     raise exc.HTTPBadRequest(explanation=msg)
                 query_cascaded_image_status_count = query_image_status_count-1
                 if query_cascaded_image_status_count == 0 and image['status'] != 'active':
                     msg = _("migrate vm failed.")
                     raise exc.HTTPBadRequest(explanation=msg)
             
             LOG.info('create target volume using the image %s' %image_id_of_volume)
             volume = self.volume_api.get(self.context, volume_id)
             size= volume.get('size')
             volume_type = self._convert_volume_type(self.context,self.availability_zone)
             volume_name = volume.get('display_name')
             metadata ={'readonly':'False','attached_mode':'rw'}
             target_volume = self.volume_api.create(self.context,size,volume_name,None,image_id=image['id'],volume_type=volume_type, 
                                                            metadata=metadata,availability_zone=self.availability_zone)
             source_target_vol_mapping[volume_id]=target_volume
     return source_target_vol_mapping
Beispiel #2
0
 def _check_volume_status(self,source_target_vol_mapping):
     if source_target_vol_mapping:
         for target_volume in source_target_vol_mapping.values():
             query_volume_status_count=1800
             volume_id = target_volume['id']
             volume = self.volume_api.get(self.context, volume_id)
             while volume.get('status') != 'available':
                 time.sleep(2)
                 volume = self.volume_api.get(self.context, volume_id)  
                 if volume.get('status') == 'error':
                     msg = _("migrate vm failed.")
                     raise exc.HTTPBadRequest(explanation=msg)
                 query_volume_status_count = query_volume_status_count-1
                 if query_volume_status_count==0 and  volume.get('status') != 'available':
                     msg = _("migrate vm failed.")
                     raise exc.HTTPBadRequest(explanation=msg)
Beispiel #3
0
    def _format_volume(self, context, volume):
        instance_ec2_id = None
        instance_data = None
        if volume.get('instance', None):
            instance_id = volume['instance']['id']
            instance_ec2_id = ec2utils.id_to_ec2_id(instance_id)
            instance_data = '%s[%s]' % (instance_ec2_id,
                                        volume['instance']['host'])
        v = {}
        v['volumeId'] = ec2utils.id_to_ec2_id(volume['id'], 'vol-%08x')
        v['status'] = volume['status']
        v['size'] = volume['size']
        v['availabilityZone'] = volume['availability_zone']
        v['createTime'] = volume['created_at']
        if context.is_admin:
            v['status'] = '%s (%s, %s, %s, %s)' % (
                volume['status'], volume['project_id'], volume['host'],
                instance_data, volume['mountpoint'])
        if volume['attach_status'] == 'attached':
            v['attachmentSet'] = [{
                'attachTime': volume['attach_time'],
                'deleteOnTermination': False,
                'device': volume['mountpoint'],
                'instanceId': instance_ec2_id,
                'status': 'attached',
                'volumeId': v['volumeId']
            }]
        else:
            v['attachmentSet'] = [{}]

        v['display_name'] = volume['display_name']
        v['display_description'] = volume['display_description']
        return v
Beispiel #4
0
 def _check_volume_status(self,source_target_vol_mapping):
     if source_target_vol_mapping:
         for target_volume in source_target_vol_mapping.values():
             query_volume_status_count=1800
             volume_id = target_volume['id']
             volume = self.volume_api.get(self.context, volume_id)
             while volume.get('status') != 'available':
                 time.sleep(2)
                 volume = self.volume_api.get(self.context, volume_id)  
                 if volume.get('status') == 'error':
                     msg = _("migrate vm failed.")
                     raise exc.HTTPBadRequest(explanation=msg)
                 query_volume_status_count = query_volume_status_count-1
                 if query_volume_status_count==0 and  volume.get('status') != 'available':
                     msg = _("migrate vm failed.")
                     raise exc.HTTPBadRequest(explanation=msg)
Beispiel #5
0
    def _format_volume(self, context, volume):
        instance_ec2_id = None
        instance_data = None
        if volume.get('instance', None):
            instance_id = volume['instance']['id']
            instance_ec2_id = id_to_ec2_id(instance_id)
            instance_data = '%s[%s]' % (instance_ec2_id,
                                        volume['instance']['host'])
        v = {}
        v['volumeId'] = id_to_ec2_id(volume['id'], 'vol-%08x')
        v['status'] = volume['status']
        v['size'] = volume['size']
        v['availabilityZone'] = volume['availability_zone']
        v['createTime'] = volume['created_at']
        if context.is_admin:
            v['status'] = '%s (%s, %s, %s, %s)' % (
                volume['status'],
                volume['user_id'],
                volume['host'],
                instance_data,
                volume['mountpoint'])
        if volume['attach_status'] == 'attached':
            v['attachmentSet'] = [{'attachTime': volume['attach_time'],
                                   'deleteOnTermination': False,
                                   'device': volume['mountpoint'],
                                   'instanceId': instance_ec2_id,
                                   'status': 'attached',
                                   'volumeId': id_to_ec2_id(volume['id'],
                                                            'vol-%08x')}]
        else:
            v['attachmentSet'] = [{}]

        v['display_name'] = volume['display_name']
        v['display_description'] = volume['display_description']
        return v
Beispiel #6
0
 def  _delete_volume_after_migrate(self,data_volume_info_dict):
     for volume_id in data_volume_info_dict.keys():
         volume = self.volume_api.get(self.context, volume_id)
         query_volume_status=1800
         if  volume:
             volume_status=volume.get('status')
             if volume_status=='error' \
                 or volume_status=='deleting' \
                 or volume_status=='error_deleting':
                 return
             while volume_status != 'available':
                 time.sleep(1)
                 volume = self.volume_api.get(self.context, volume_id) 
                 if volume:
                     volume_status=volume.get('status')
                     query_volume_status = query_volume_status-1
                     if query_volume_status==0 and volume_status !='available':
                         return
             self.volume_api.delete(self.context, volume_id)
Beispiel #7
0
 def  _delete_volume_after_migrate(self,volume_ids):
     for volume_id in volume_ids:
         volume = self.volume_api.get(self.context, volume_id)
         query_volume_status=1800
         if  volume:
             volume_status=volume.get('status')
             if volume_status=='error' \
                 or volume_status=='deleting' \
                 or volume_status=='error_deleting':
                 return
             while volume_status != 'available':
                 time.sleep(1)
                 volume = self.volume_api.get(self.context, volume_id) 
                 if volume:
                     volume_status=volume.get('status')
                     query_volume_status = query_volume_status-1
                     if query_volume_status==0 and volume_status !='available':
                         return
             self.volume_api.delete(self.context, volume_id)
Beispiel #8
0
    def create(self, req, body):
        """Creates a new volume."""
        context = req.environ['nova.context']

        if not body:
            raise exc.HTTPUnprocessableEntity()

        volume = body['volume']
        size = volume['size']
        LOG.audit(_("Create volume of %s GB"), size, context=context)

        kwargs = {}

        req_volume_type = volume.get('volume_type', None)
        if req_volume_type:
            try:
                kwargs['volume_type'] = volume_types.get_volume_type_by_name(
                        context, req_volume_type)
            except exception.NotFound:
                raise exc.HTTPNotFound()

        kwargs['metadata'] = volume.get('metadata', None)

        snapshot_id = volume.get('snapshot_id')
        if snapshot_id is not None:
            snapshot = self.volume_api.get_snapshot(context, snapshot_id)
        else:
            snapshot = None

        new_volume = self.volume_api.create(context,
                                            size,
                                            snapshot,
                                            volume.get('display_name'),
                                            volume.get('display_description'),
                                            **kwargs)

        # Work around problem that instance is lazy-loaded...
        new_volume = self.volume_api.get(context, new_volume['id'])

        retval = _translate_volume_detail_view(context, new_volume)

        return {'volume': retval}
Beispiel #9
0
 def _mount_data_volume(self,instance,source_target_vol_mapping,data_volume_info_dict):     
     if source_target_vol_mapping:
         for source_vol_id in source_target_vol_mapping.keys():
             target_volume= source_target_vol_mapping.get(source_vol_id)
             device_name =data_volume_info_dict.get(source_vol_id)['mount_point']
             self.compute_api.attach_volume(self.context,instance,target_volume['id'],device=device_name)
         
         for target_volume in source_target_vol_mapping.values():
             query_volume_status_count=1800
             volume_id = target_volume['id']
             volume = self.volume_api.get(self.context, volume_id)
             while volume.get('status') != 'in-use':
                 time.sleep(2)
                 volume = self.volume_api.get(self.context, volume_id)  
                 if volume.get('status') == 'error':
                     msg = _("migrate vm failed.")
                     raise exc.HTTPBadRequest(explanation=msg)
                 query_volume_status_count = query_volume_status_count-1
                 if query_volume_status_count==0 and  volume.get('status') != 'in-use':
                     msg = _("migrate vm failed.")
                     raise exc.HTTPBadRequest(explanation=msg)
Beispiel #10
0
    def create(self, req, body):
        """Creates a new volume."""
        context = req.environ['nova.context']

        if not body:
            raise exc.HTTPUnprocessableEntity()

        volume = body['volume']

        def as_int(s):
            try:
                return int(s)
            except ValueError:
                return s

        # NOTE(eglynn): we're tolerant of non-int sizes here, as type
        # integrity is enforced later in the creation codepath
        size = as_int(volume['size'])

        LOG.audit(_("Create volume of %s GB"), size, context=context)

        kwargs = {}

        req_volume_type = volume.get('volume_type', None)
        if req_volume_type:
            try:
                kwargs['volume_type'] = volume_types.get_volume_type_by_name(
                        context, req_volume_type)
            except exception.NotFound:
                raise exc.HTTPNotFound()

        kwargs['metadata'] = volume.get('metadata', None)

        snapshot_id = volume.get('snapshot_id')
        if snapshot_id is not None:
            kwargs['snapshot'] = self.volume_api.get_snapshot(context,
                                                              snapshot_id)
        else:
            kwargs['snapshot'] = None

        kwargs['availability_zone'] = volume.get('availability_zone', None)

        new_volume = self.volume_api.create(context,
                                            size,
                                            volume.get('display_name'),
                                            volume.get('display_description'),
                                            **kwargs)

        # TODO(vish): Instance should be None at db layer instead of
        #             trying to lazy load, but for now we turn it into
        #             a dict to avoid an error.
        retval = _translate_volume_detail_view(context, dict(new_volume))

        result = {'volume': retval}

        location = '%s/%s' % (req.url, new_volume['id'])

        return wsgi.ResponseObject(result, headers=dict(location=location))
Beispiel #11
0
    def create(self, req, body):
        """Creates a new volume."""
        context = req.environ['nova.context']

        if not body:
            raise exc.HTTPUnprocessableEntity()

        volume = body['volume']

        def as_int(s):
            try:
                return int(s)
            except ValueError:
                return s

        # NOTE(eglynn): we're tolerant of non-int sizes here, as type
        # integrity is enforced later in the creation codepath
        size = as_int(volume['size'])

        LOG.audit(_("Create volume of %s GB"), size, context=context)

        kwargs = {}

        req_volume_type = volume.get('volume_type', None)
        if req_volume_type:
            try:
                kwargs['volume_type'] = volume_types.get_volume_type_by_name(
                    context, req_volume_type)
            except exception.NotFound:
                raise exc.HTTPNotFound()

        kwargs['metadata'] = volume.get('metadata', None)

        snapshot_id = volume.get('snapshot_id')
        if snapshot_id is not None:
            kwargs['snapshot'] = self.volume_api.get_snapshot(
                context, snapshot_id)
        else:
            kwargs['snapshot'] = None

        kwargs['availability_zone'] = volume.get('availability_zone', None)

        new_volume = self.volume_api.create(context, size,
                                            volume.get('display_name'),
                                            volume.get('display_description'),
                                            **kwargs)

        # TODO(vish): Instance should be None at db layer instead of
        #             trying to lazy load, but for now we turn it into
        #             a dict to avoid an error.
        retval = _translate_volume_detail_view(context, dict(new_volume))

        result = {'volume': retval}

        location = '%s/%s' % (req.url, new_volume['id'])

        return wsgi.ResponseObject(result, headers=dict(location=location))
Beispiel #12
0
    def create(self, req, body):
        """Creates a new volume."""
        if not self.is_valid_body(body, 'volume'):
            raise exc.HTTPUnprocessableEntity()

        context = req.environ['nova.context']
        volume = body['volume']

        kwargs = {}

        req_volume_type = volume.get('volume_type', None)
        if req_volume_type:
            try:
                kwargs['volume_type'] = volume_types.get_volume_type_by_name(
                        context, req_volume_type)
            except exception.NotFound:
                raise exc.HTTPNotFound()

        kwargs['metadata'] = volume.get('metadata', None)

        snapshot_id = volume.get('snapshot_id')
        if snapshot_id is not None:
            kwargs['snapshot'] = self.volume_api.get_snapshot(context,
                                                              snapshot_id)
        else:
            kwargs['snapshot'] = None

        size = volume.get('size', None)
        if size is None and kwargs['snapshot'] is not None:
            size = kwargs['snapshot']['volume_size']

        LOG.audit(_("Create volume of %s GB"), size, context=context)

        kwargs['availability_zone'] = volume.get('availability_zone', None)

        new_volume = self.volume_api.create(context,
                                            size,
                                            volume.get('display_name'),
                                            volume.get('display_description'),
                                            **kwargs)

        # TODO(vish): Instance should be None at db layer instead of
        #             trying to lazy load, but for now we turn it into
        #             a dict to avoid an error.
        retval = _translate_volume_detail_view(context, dict(new_volume))

        result = {'volume': retval}

        location = '%s/%s' % (req.url, new_volume['id'])

        return wsgi.ResponseObject(result, headers=dict(location=location))
Beispiel #13
0
    def create(self, req, body):
        """Creates a new volume."""
        context = req.environ['nova.context']

        if not body:
            raise exc.HTTPUnprocessableEntity()

        volume = body['volume']
        size = volume['size']
        LOG.audit(_("Create volume of %s GB"), size, context=context)

        kwargs = {}

        req_volume_type = volume.get('volume_type', None)
        if req_volume_type:
            try:
                kwargs['volume_type'] = volume_types.get_volume_type_by_name(
                        context, req_volume_type)
            except exception.NotFound:
                raise exc.HTTPNotFound()

        kwargs['metadata'] = volume.get('metadata', None)

        snapshot_id = volume.get('snapshot_id')
        if snapshot_id is not None:
            kwargs['snapshot'] = self.volume_api.get_snapshot(context,
                                                              snapshot_id)
        else:
            kwargs['snapshot'] = None

        kwargs['availability_zone'] = volume.get('availability_zone', None)

        new_volume = self.volume_api.create(context,
                                            size,
                                            volume.get('display_name'),
                                            volume.get('display_description'),
                                            **kwargs)

        # TODO(vish): Instance should be None at db layer instead of
        #             trying to lazy load, but for now we turn it into
        #             a dict to avoid an error.
        retval = _translate_volume_detail_view(context, dict(new_volume))

        return {'volume': retval}
Beispiel #14
0
   def run(self):
       LOG.error('begin time of migrate is %s' %(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
       bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
               self.context, self.instance['uuid'])
       is_boot_from_image = False
       volume_dict_for_image_id ={}
       #add system_volume
       system_volume=None
       
       data_volume_info_dict={}
       
       
       block_device_mapping = None
       volume_ids = []
       system_volume_image_id = None
       #step1 get the source instance info
       instance = common.get_instance(self.compute_api, self.context, self.instance.uuid, want_objects=True) 
       
       #get the interface-port info
       search_opts = {'device_id': instance['uuid']}
       try:
           data = self.network_api.list_ports(self.context, **search_opts)
       except exception.NotFound as e:
           raise exc.HTTPNotFound(explanation=e.format_message())
       except NotImplementedError:
           msg = _("Network driver does not support this function.")
           raise webob.exc.HTTPNotImplemented(explanation=msg)
       ports = data.get('ports', []) 
       access_ip_v4 = instance.access_ip_v4  
       access_ip_v6 = instance.access_ip_v6
       min_count = 1
       max_count = 1
       
       name=instance.display_name
       key_name = None
       metadata = instance.metadata
       injected_files = []
       security_group=instance.security_groups
       user_data=instance.user_data
       
       flavor_id = instance.system_metadata['instance_type_flavorid']
       
       scheduler_hints = {}
       #check_server_group_quota = \
       #    self.ext_mgr.is_loaded('os-server-group-quotas')
       check_server_group_quota=True
       
       requested_networks = []
       nw_info = compute_utils.get_nw_info_for_instance(instance)
       for vif in nw_info:
           net_uuid = vif['network']['id']
           net_ip = vif['network']['subnets'][0]['ips'][0]['address']
           requested_networks.append({'fixed_ip':net_ip, 'uuid':net_uuid})
       
       requested_networks = self._get_requested_networks(requested_networks)
       
       for port in ports:
           LOG.debug('begin detach the port %s of instance %s' %(port['id'],instance.uuid))
           self.compute_api.detach_interface(self.context,instance, port_id=port['id'])
           time.sleep(2)
           LOG.debug('end detach the port %s of instance %s' %(port['id'],instance.uuid))
       
       for bdm in bdms:
           if bdm.image_id is not None and bdm.boot_index == 0 and bdm.destination_type =='local':
               is_boot_from_image =True
               system_volume_image_id = bdm.image_id
           if bdm.volume_id is not None:
               if bdm.boot_index == 0:
                   volume = self.volume_api.get(self.context, bdm.volume_id)
                   system_volume = volume
                   volume_image_metadata = volume.get('volume_metadata')
                   system_volume_image_id = volume_image_metadata['image_id'] 
               else:
                   volume_info={'boot_index':bdm.boot_index,'mount_point':bdm.device_name}
                   data_volume_info_dict[bdm.volume_id]=volume_info
       #step2 stop the instance
       LOG.error('begin time of stop instance is %s' %(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
       self._stop_instance(instance)
       LOG.error('end time of stop instance is %s' %(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
       
       #get the image of target vm
       boot_image_uuid = None       
       if is_boot_from_image:
           if self.migrate_system_volume is False:
               boot_image_uuid = system_volume_image_id
           else:
               tmp_image_name = "%s@%s" % (uuid.uuid1(), self.instance.uuid)
               instance = common.get_instance(self.compute_api, self.context, self.instance.uuid, want_objects=True) 
               image_meta = self.compute_api.snapshot(self.context, instance, name=tmp_image_name, extra_properties=None)
               query_image_status_count=1800
               filters = {'name':tmp_image_name}
               imagelist = self.image_api.get_all(self.context,filters=filters)
               image = imagelist[0]
               while image['status'] != 'active':
                   time.sleep(1)
                   imagelist = self.image_api.get_all(self.context,filters=filters)
                   image = imagelist[0]
                   #image_uuid = image['id']
                   #image = self.image_api.get(self.context,image_uuid )
                   if image['status'] =='error':
                       msg = _("migrate vm failed.")
                       raise exc.HTTPBadRequest(explanation=msg)
                   query_image_status_count = query_image_status_count-1
                   if query_image_status_count == 0 and image['status'] != 'active':
                       msg = _("migrate vm failed.")
                       raise exc.HTTPBadRequest(explanation=msg)
               boot_image_uuid =image['id'] 
       else:
           if self.migrate_system_volume is False:
               boot_image_uuid = system_volume_image_id 
           else :
               response = self.volume_api.upload_to_image(self.context,
                                                       system_volume['id'],
                                                       True,
                                                       system_volume['id'],
                                                       'bare',
                                                       'qcow2')
               image_id_of_volume = response[1]['os-volume_upload_image']['image_id']
               image = self.image_api.get(self.context,image_id_of_volume)
               query_image_status_count=1800
               LOG.info('query the image %s status of the voluem %s' %(image_id_of_volume,system_volume['id']))
               while image['status'] != 'active':
                   time.sleep(2)
                   image = self.image_api.get(self.context,image_id_of_volume)
                   if image['status'] == 'error':
                       msg = _("migrate vm failed.")
                       raise exc.HTTPBadRequest(explanation=msg)
                   query_cascaded_image_status_count = query_image_status_count-1
                   if query_cascaded_image_status_count == 0 and image['status'] != 'active':
                       msg = _("migrate vm failed.")
                       raise exc.HTTPBadRequest(explanation=msg)
               boot_image_uuid = image_id_of_volume
       
       
       _get_inst_type = flavors.get_flavor_by_flavor_id
       inst_type = _get_inst_type(flavor_id, ctxt=self.context,
                                          read_deleted="no") 
       instances=self._create_instance(inst_type,boot_image_uuid, display_name=name, 
                          display_description=name,key_name=key_name,metadata=metadata,
                          access_ip_v4=access_ip_v4,access_ip_v6=access_ip_v6,injected_files=injected_files,
                          admin_password=None, min_count=min_count,max_count=max_count, requested_networks=requested_networks,
                          security_group=security_group,  user_data=user_data,availability_zone=self.availability_zone,
                          config_drive=None, block_device_mapping=block_device_mapping, auto_disk_config=None,
                          scheduler_hints=scheduler_hints, legacy_bdm=True,check_server_group_quota=check_server_group_quota) 
          
       volume_dict_for_image_id = self._upload_data_volume_to_image(data_volume_info_dict)
       source_target_vol_mapping = self._create_target_volume(volume_dict_for_image_id) 
        #update the instance metadata the metadata use for vcloud delete vm
       self.compute_api.update_instance_metadata(self.context,instance,{'quick_delete_once': 'True'},delete=False) 
       #step7 delete the vm
       LOG.error('begin time of delete instance is %s' %(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
       self.compute_api.delete(self.context,instance)
       LOG.error('end time of delete instance is %s' %(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
       
       #mount volume and reboot
       instance_new =None
       if instances is not None and len(instances) == 1:
           instance_new = instances[0]
           query_new_vm_status_count=1200
           while instance_new.vm_state != 'active':
               time.sleep(2)
               instance_new = common.get_instance(self.compute_api, self.context, instance_new.uuid,
                                      want_objects=True)
               if instance_new.vm_state == 'error' : 
                   LOG.error("bulid instance failed")
                   msg = _("migrate vm failed.")
                   raise exc.HTTPBadRequest(explanation=msg)
               query_new_vm_status_count =query_new_vm_status_count-1
               if query_new_vm_status_count ==0 and instance_new.vm_state != 'active':
                   msg = _("migrate vm failed.")
                   raise exc.HTTPBadRequest(explanation=msg)  
       self._mount_data_volume(instance_new, source_target_vol_mapping, data_volume_info_dict)
       self.compute_api.reboot(self.context, instance_new, 'SOFT')
 
       #step 9 delete the image
       LOG.debug('begin clear the image and volume')
       self._delete_tmp_image(boot_image_uuid, volume_dict_for_image_id)
       #step 10 delete the volume
       self._delete_volume_after_migrate(data_volume_info_dict) 
       
       
       time.sleep(2)
       instance_new = common.get_instance(self.compute_api, self.context, instance_new.uuid,
                                      want_objects=True)
       while instance_new.vm_state != 'active':
           time.sleep(2)
           instance_new = common.get_instance(self.compute_api, self.context, instance_new.uuid,
                                  want_objects=True)
           if instance_new.vm_state == 'error' : 
               LOG.error("bulid instance failed")
               msg = _("migrate vm failed.")
               raise exc.HTTPBadRequest(explanation=msg)
           query_new_vm_status_count =query_new_vm_status_count-1
           if query_new_vm_status_count ==0 and instance_new.vm_state != 'active':
               msg = _("migrate vm failed.")
               raise exc.HTTPBadRequest(explanation=msg) 
       LOG.error('end time of migrate is %s' %(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
Beispiel #15
0
    def run(self):
        bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
                self.context, self.instance['uuid'])
        is_boot_from_image = False
        
        #save the volume
        volume_dict_for_boot_index = {}
        volume_dict_for_image_id ={}
        volume_dict_for_mountpoint ={}
        block_device_mapping = None
        volume_ids = []
        system_volume_image_id = None
        #step1 get the source instance info
        instance = common.get_instance(self.compute_api, self.context, self.instance.uuid, want_objects=True) 
        for bdm in bdms:
            if bdm.image_id is not None and bdm.boot_index == 0 and bdm.destination_type =='local':
                is_boot_from_image =True
                system_volume_image_id = bdm.image_id
            if bdm.volume_id is not None:
                if bdm.boot_index == 0:
                    volume = self.volume_api.get(self.context, bdm.volume_id)
                    volume_image_metadata = volume.get('volume_metadata')
                    system_volume_image_id = volume_image_metadata['image_id'] 
                volume_dict_for_boot_index[bdm.volume_id]=bdm.boot_index
                volume_ids.append(bdm.volume_id)
                volume_dict_for_mountpoint[bdm.volume_id] =bdm.device_name
        #step2 stop the instance        
        self._stop_instance(instance)
        
        
        #step3 create image of vm and volume
        boot_image_uuid = None       
        if is_boot_from_image:
            if self.migrate_system_volume is False:
                boot_image_uuid = system_volume_image_id
            else:
                tmp_image_name = "%s@%s" % (uuid.uuid1(), self.instance.uuid)
                instance = common.get_instance(self.compute_api, self.context, self.instance.uuid, want_objects=True) 
                image_meta = self.compute_api.snapshot(self.context, instance, name=tmp_image_name, extra_properties=None)
                query_image_status_count=1800
                filters = {'name':tmp_image_name}
                imagelist = self.image_api.get_all(self.context,filters=filters)
                image = imagelist[0]
                while image['status'] != 'active':
                    time.sleep(1)
                    imagelist = self.image_api.get_all(self.context,filters=filters)
                    image = imagelist[0]
                    #image_uuid = image['id']
                    #image = self.image_api.get(self.context,image_uuid )
                    if image['status'] =='error':
                        msg = _("migrate vm failed.")
                        raise exc.HTTPBadRequest(explanation=msg)
                    query_image_status_count = query_image_status_count-1
                    if query_image_status_count == 0 and image['status'] != 'active':
                        msg = _("migrate vm failed.")
                        raise exc.HTTPBadRequest(explanation=msg)
                boot_image_uuid =image['id']

            #data_volume upload to glance
            #import pdb
            #pdb.set_trace()
            volume_dict_for_image_id= self._upload_volume_to_image(volume_ids,
                                                                    volume_dict_for_boot_index)
        else : 
            instance.task_state = task_states.IMAGE_SNAPSHOT
            instance.save() 
            if self.migrate_system_volume is False:
                boot_image_uuid = system_volume_image_id  
            volume_dict_for_image_id = self._upload_volume_to_image(volume_ids,
                                                                    volume_dict_for_boot_index)
           
          
        try:
            #step4 create the target volume
            source_target_vol_mapping = self._create_target_volume(volume_dict_for_image_id)  
            #step5 check the volume status
            self._check_volume_status(source_target_vol_mapping)
        except exc.HTTPBadRequest as e:
            #exception occurred,reset the instance task_state
            LOG.error('error occur when create target volume')
            instance.task_state = None
            instance.save()
            raise e
        #reset the instance task_state
        instance.task_state = None
        instance.save() 
        #step6 prepare the params of create vm
        block_device_mapping=self._create_bdm(source_target_vol_mapping, volume_dict_for_boot_index, volume_dict_for_mountpoint)  
        
        access_ip_v4 = instance.access_ip_v4
        if access_ip_v4 is not None:
            self._validate_access_ipv4(access_ip_v4)
            
        access_ip_v6 = instance.access_ip_v6
        if access_ip_v6 is not None:
            self._validate_access_ipv6(access_ip_v6)
            
        #networks = common.get_networks_for_instance(context, instance)
        min_count = 1
        max_count = 1
        
        name=instance.display_name
        key_name = None
        metadata = instance.metadata
        injected_files = []
        security_group=instance.security_groups
        user_data=instance.user_data
        
        flavor_id = instance.system_metadata['instance_type_flavorid']
        
        scheduler_hints = {}
         
        #check_server_group_quota = \
        #    self.ext_mgr.is_loaded('os-server-group-quotas')
        check_server_group_quota=True
        
        requested_networks = []
        nw_info = compute_utils.get_nw_info_for_instance(instance)
        for vif in nw_info:
            net_uuid = vif['network']['id']
            net_ip = vif['network']['subnets'][0]['ips'][0]['address']
            requested_networks.append({'fixed_ip':net_ip, 'uuid':net_uuid})
        
        requested_networks = self._get_requested_networks(requested_networks)
        #update the instance metadata the metadata use for vcloud delete vm
        self.compute_api.update_instance_metadata(self.context,instance,{'quick_delete_once': 'True'},delete=False) 
        #TODO detach port delete
        
        
        #step7 delete the vm
        self.compute_api.delete(self.context,instance)
        #import pdb
        #pdb.set_trace()
        #step8 create vm
        while True:
            time.sleep(3)
            try:
                _get_inst_type = flavors.get_flavor_by_flavor_id
                inst_type = _get_inst_type(flavor_id, ctxt=self.context,
                                           read_deleted="no")
                (instances, resv_id) = self.compute_api.create(self.context,
                            inst_type,
                            boot_image_uuid,
                            display_name=name,
                            display_description=name,
                            key_name=key_name,
                            metadata=metadata,
                            access_ip_v4=access_ip_v4,
                            access_ip_v6=access_ip_v6,
                            injected_files=injected_files,
                            admin_password=None,
                            min_count=min_count,
                            max_count=max_count,
                            requested_networks=requested_networks,
                            security_group=security_group,
                            user_data=user_data,
                            availability_zone=self.availability_zone,
                            config_drive=None,
                            block_device_mapping=block_device_mapping,
                            auto_disk_config=None,
                            scheduler_hints=scheduler_hints,
                            legacy_bdm=True,
                            check_server_group_quota=check_server_group_quota)
            except (exception.PortInUse,
                    exception.NoUniqueMatch) as error:
                readable = traceback.format_exc()
                LOG.exception('migrate exception10:%s', readable)
                continue
                raise exc.HTTPConflict(explanation=error.format_message())
            except exception.FixedIpAlreadyInUse as error:
                readable = traceback.format_exc()
                LOG.exception('migrate exception11:%s', readable)
                continue
                raise exc.HTTPBadRequest(explanation=error.format_message())
            break
        
        if instances is not None and len(instances) == 1:
            instance_new = instances[0]
            query_new_vm_status_count=1200
            while instance_new.vm_state != 'active':
                time.sleep(2)
                instance_new = common.get_instance(self.compute_api, self.context, instance_new.uuid,
                                       want_objects=True)
                if instance_new.vm_state == 'error' : 
                    LOG.error("bulid instance failed")
                    msg = _("migrate vm failed.")
                    raise exc.HTTPBadRequest(explanation=msg)
                query_new_vm_status_count =query_new_vm_status_count-1
                if query_new_vm_status_count ==0 and instance_new.vm_state != 'active':
                    msg = _("migrate vm failed.")
                    raise exc.HTTPBadRequest(explanation=msg)    
        #step 9 delete the image
        LOG.debug('begin clear the image and volume')
        self._delete_tmp_image(boot_image_uuid, volume_dict_for_image_id)
        #step 10 delete the volume
        self._delete_volume_after_migrate(volume_ids) 
Beispiel #16
0
    def create(self, req, body):
        """Creates a new volume."""
        if not self.is_valid_body(body, 'volume'):
            msg = _("Invalid request body. 'volume' not found")
            raise exc.HTTPUnprocessableEntity(explanation=msg)

        context = req.environ['nova.context']
        volume = body['volume']

        kwargs = {}

        req_volume_type = volume.get('volume_type', None)
        if req_volume_type:
            try:
                kwargs['volume_type'] = volume_types.get_volume_type_by_name(
                        context, req_volume_type)
            except exception.NotFound:
                raise exc.HTTPNotFound()

        kwargs['metadata'] = volume.get('metadata', None)

        snapshot_id = volume.get('snapshot_id')
        if snapshot_id is not None:
            kwargs['snapshot'] = self.volume_api.get_snapshot(context,
                                                              snapshot_id)
        else:
            kwargs['snapshot'] = None

        size = volume.get('size', None)
        if size is None and kwargs['snapshot'] is not None:
            size = kwargs['snapshot']['volume_size']

        if size is None:
            msg = _("Invalid request body. 'size' not found")
            raise exc.HTTPUnprocessableEntity(explanation=msg)

        LOG.audit(_("Create volume of %s GB"), size, context=context)

        image_href = None
        image_uuid = None
        if self.ext_mgr.is_loaded('os-image-create'):
            image_href = volume.get('imageRef')
            if snapshot_id and image_href:
                msg = _("Snapshot and image cannot be specified together.")
                raise exc.HTTPBadRequest(explanation=msg)
            if image_href:
                image_uuid = self._image_uuid_from_href(image_href)
                kwargs['image_id'] = image_uuid

        kwargs['availability_zone'] = volume.get('availability_zone', None)

        new_volume = self.volume_api.create(context,
                                            size,
                                            volume.get('display_name'),
                                            volume.get('display_description'),
                                            **kwargs)

        # TODO(vish): Instance should be None at db layer instead of
        #             trying to lazy load, but for now we turn it into
        #             a dict to avoid an error.
        retval = _translate_volume_detail_view(context, dict(new_volume),
                                               image_uuid)

        result = {'volume': retval}

        location = '%s/%s' % (req.url, new_volume['id'])

        return wsgi.ResponseObject(result, headers=dict(location=location))
Beispiel #17
0
    def create(self, req, body):
        """Creates a new volume."""
        if not self.is_valid_body(body, 'volume'):
            raise exc.HTTPUnprocessableEntity()

        context = req.environ['nova.context']
        volume = body['volume']

        kwargs = {}

        req_volume_type = volume.get('volume_type', None)
        if req_volume_type:
            try:
                kwargs['volume_type'] = volume_types.get_volume_type_by_name(
                    context, req_volume_type)
            except exception.NotFound:
                raise exc.HTTPNotFound()

        kwargs['metadata'] = volume.get('metadata', None)

        snapshot_id = volume.get('snapshot_id')
        if snapshot_id is not None:
            kwargs['snapshot'] = self.volume_api.get_snapshot(
                context, snapshot_id)
        else:
            kwargs['snapshot'] = None

        size = volume.get('size', None)
        if size is None and kwargs['snapshot'] is not None:
            size = kwargs['snapshot']['volume_size']

        LOG.audit(_("Create volume of %s GB"), size, context=context)

        image_href = None
        image_uuid = None
        if self.ext_mgr.is_loaded('os-image-create'):
            image_href = volume.get('imageRef')
            if snapshot_id and image_href:
                msg = _("Snapshot and image cannot be specified together.")
                raise exc.HTTPBadRequest(explanation=msg)
            if image_href:
                image_uuid = self._image_uuid_from_href(image_href)
                kwargs['image_id'] = image_uuid

        kwargs['availability_zone'] = volume.get('availability_zone', None)

        new_volume = self.volume_api.create(context, size,
                                            volume.get('display_name'),
                                            volume.get('display_description'),
                                            **kwargs)

        # TODO(vish): Instance should be None at db layer instead of
        #             trying to lazy load, but for now we turn it into
        #             a dict to avoid an error.
        retval = _translate_volume_detail_view(context, dict(new_volume),
                                               image_uuid)

        result = {'volume': retval}

        location = '%s/%s' % (req.url, new_volume['id'])

        return wsgi.ResponseObject(result, headers=dict(location=location))