Beispiel #1
0
def get_list(args):
    '''获取镜像列表'''
    ret_list = []
    storage_api = StorageAPI()
    image_api = ImageAPI()
    cephpool = storage_api.get_pool_by_id(args['ceph_id'])

    if not cephpool.managed_by(args['req_user']):
        return {'res': False, 'err': ERR_AUTH_PERM}
    # if 'enable' in args:
    #     enable = args['enable']
    # else:
    #     enable = None
    # 非得改接口……
    enable = True
    image_list = image_api.get_image_list_by_pool_id(args['ceph_id'], enable)
    for image in image_list:
        ret_list.append({
            'id': image.id,
            'ceph_id': image.cephpool_id,
            'name': image.name,
            'version': image.version,
            'type': image.type_name,
            'order': image.order
        })
    return {'res': True, 'list': ret_list}
Beispiel #2
0
 def __init__(self,
              manager=None,
              user_api=None,
              network_api=None,
              image_api=None,
              group_api=None,
              host_api=None):
     if not manager:
         self.manager = VMManager()
     else:
         self.manager = manager
     if not user_api:
         self.user_api = UserAPI()
     else:
         self.user_api = user_api
     if not network_api:
         self.network_api = NetworkAPI()
     else:
         self.network_api = network_api
     if not image_api:
         self.image_api = ImageAPI()
     else:
         self.image_api = image_api
     if not group_api:
         self.group_api = GroupAPI()
     else:
         self.group_api = group_api
     if not host_api:
         self.host_api = HostAPI()
     else:
         self.host_api = host_api
Beispiel #3
0
 def __init__(self, manager=None, user_api=None, network_api=None, image_api=None, group_api=None, host_api=None):
     if not manager:
         self.manager = VMManager()
     else:
         self.manager = manager
     if not user_api:
         self.user_api = UserAPI()
     else:
         self.user_api = user_api
     if not network_api:
         self.network_api = NetworkAPI()
     else:
         self.network_api = network_api
     if not image_api:
         self.image_api = ImageAPI()
     else:
         self.image_api = image_api
     if not group_api:
         self.group_api = GroupAPI()
     else:
         self.group_api = group_api
     if not host_api:
         self.host_api = HostAPI()
     else:
         self.host_api = host_api
Beispiel #4
0
def get(args):
    '''获取镜像信息'''
    info = {}
    image_api = ImageAPI()
    image = image_api.get_image_by_id(args['image_id'])
    
    if not image.managed_by(args['req_user']):
        return {'res': False, 'err': ERR_AUTH_PERM}
    
    info = {
        'id':       image.id,
        'ceph_id':  image.cephpool_id,
        'name':     image.name,
        'version':  image.version,
        'snap':     image.snap,
        'type':     image.type_name,
        'desc':     image.desc
    }
    return {'res': True, 'info': info}    
Beispiel #5
0
def get(args):
    '''获取镜像信息'''
    info = {}
    image_api = ImageAPI()
    image = image_api.get_image_by_id(args['image_id'])

    if not image.managed_by(args['req_user']):
        return {'res': False, 'err': ERR_AUTH_PERM}

    info = {
        'id': image.id,
        'ceph_id': image.cephpool_id,
        'name': image.name,
        'version': image.version,
        'snap': image.snap,
        'type': image.type_name,
        'desc': image.desc
    }
    return {'res': True, 'info': info}
Beispiel #6
0
def get_list(args):
    '''获取镜像列表'''
    ret_list = []
    storage_api = CephStorageAPI()
    image_api = ImageAPI()
    cephpool = storage_api.get_pool_by_id(args['ceph_id'])

    if not cephpool.managed_by(args['req_user']):
        return {'res': False, 'err': ERR_AUTH_PERM}
    
    image_list = image_api.get_image_list_by_pool_id(args['ceph_id'])
    for image in image_list:
        ret_list.append({
            'id':   image.id,
            'ceph_id': image.cephpool_id,
            'name': image.name,
            'version': image.version,
            'type': image.type_name,
            'order': image.order
            })
    return {'res': True, 'list': ret_list}
Beispiel #7
0
class VmAPI(object):
    def __init__(self,
                 manager=None,
                 user_api=None,
                 network_api=None,
                 image_api=None,
                 group_api=None,
                 host_api=None):
        if not manager:
            self.manager = VMManager()
        else:
            self.manager = manager
        if not user_api:
            self.user_api = UserAPI()
        else:
            self.user_api = user_api
        if not network_api:
            self.network_api = NetworkAPI()
        else:
            self.network_api = network_api
        if not image_api:
            self.image_api = ImageAPI()
        else:
            self.image_api = image_api
        if not group_api:
            self.group_api = GroupAPI()
        else:
            self.group_api = group_api
        if not host_api:
            self.host_api = HostAPI()
        else:
            self.host_api = host_api

    def get_vm_by_uuid(self, vm_uuid):
        return self.manager.get_vm_by_uuid(vm_uuid)

    def get_vm_list_by_group_id(self,
                                group_id,
                                host_id=None,
                                order=None,
                                ha_monitored=None):
        return self.manager.get_vm_list_by_group_id(group_id, host_id, order,
                                                    ha_monitored)

    def vm_uuid_exists(self, vm_uuid):
        return self.manager.vm_uuid_exists(vm_uuid)

    def attach_device(self, vm_uuid, xml):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        return vm.attach_device(xml)

    def detach_device(self, vm_uuid, xml):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        return vm.detach_device(xml)

    def set_creator(self, vm_uuid, username):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        return vm.set_creator(str(username))

    def set_ha_monitored(self, vm_uuid, ha_monitored=True):
        '''设置虚拟机的[高可用]属性'''
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        return vm.set_ha_monitored(ha_monitored)

    def create_vm(self,
                  image_id,
                  vcpu,
                  mem,
                  group_id=None,
                  host_id=None,
                  net_type_id=None,
                  vlan_id=None,
                  diskname=None,
                  vm_uuid=None,
                  remarks=None,
                  ipv4=None):
        '''
        参数说明:
            image_id, vcpu, mem 为必要参数。
            group_id, host_id 两者至少必须有其一, host_id存在时指定相应宿主机,
            无host_id但有group_id时在指定集群筛选宿主机。
            net_type_id, vlan_id 两者至少必须有其一,有vlan_id时使用指定的网段,
            无vlan_id但有net_type_id时在指定网络类型中筛选网段。
            其他参数都是可选参数。
        '''
        vcpu = int(vcpu)
        mem = int(mem)

        if not vm_uuid:
            vm_uuid = self.manager.create_vm_uuid()
        if not diskname:
            diskname = vm_uuid

        image = self.image_api.get_image_by_id(image_id)
        if not image.enable:
            raise Error(ERR_IMAGE_ID)

        image_info = self.image_api.get_image_info_by_id(image_id)

        if host_id:
            host_list = [self.host_api.get_host_by_id(host_id)]
        elif group_id:
            host_list = self.host_api.get_host_list_by_group_id(group_id)
        else:
            raise Error(ERR_VM_CREATE_ARGS_HOST)

        available_host_list = []
        for host in host_list:
            if host.enable and not host.exceed_vm_limit(
            ) and not host.exceed_mem_limit(mem):
                available_host_list.append(host)

        if not available_host_list:
            raise Error(ERR_HOST_FILTER_NONE)

        if settings.DEBUG: print('[create_vm]', '可用主机列表', available_host_list)

        if vlan_id:
            vlan_list = [self.network_api.get_vlan_by_id(vlan_id)]
        elif net_type_id:
            vlan_list = self.network_api.get_vlan_list_by_type_id(net_type_id)
        else:
            raise Error(ERR_VM_CREATE_ARGS_VLAN)

        available_vlan_list = []
        for vlan in vlan_list:
            if vlan.enable and vlan.has_free_ip():
                available_vlan_list.append(vlan)

        if not available_vlan_list:
            raise Error(ERR_VLAN_FILTER_NONE)

        if settings.DEBUG: print('[create_vm]', '网段列表', vlan_list)

        while available_host_list:
            mac_claimed = False
            disk_created = False
            vm_db = None

            host = self.host_api.host_filter(available_host_list,
                                             vcpu,
                                             mem,
                                             claim=True)
            if not host:
                raise Error(ERR_VM_HOST_FILTER)
            available_host_list.remove(host)

            if not host.alive():
                raise Error(ERR_HOST_CONNECTION)

            host_available_vlan_id_list = self.host_api.get_vlan_id_list_of_host(
                host.id)
            if not host_available_vlan_id_list:
                raise Error(ERR_VLAN_FILTER_NONE)

            for vlan in available_vlan_list:
                try:
                    if not vlan.id in host_available_vlan_id_list:
                        continue
                    if settings.DEBUG: print('[create_vm]', '开始创建', host, vlan)
                    mac_claimed = False
                    disk_created = False

                    mac = self.network_api.mac_claim(vlan.id,
                                                     vm_uuid,
                                                     ipv4=ipv4)
                    if mac:
                        mac_claimed = True

                    if mac_claimed:
                        if self.image_api.init_disk(image_id, diskname):
                            disk_created = True
                        else:
                            raise Error(ERR_VM_CREATE_DISK)
                        # image_info = self.image_api.get_image_info_by_id(image_id)

                        xml_tpl = self.image_api.get_xml_tpl(image_id)
                        print(xml_tpl)
                        xml_desc = xml_tpl % {
                            'name': vm_uuid,
                            'uuid': vm_uuid,
                            'mem': mem,
                            'vcpu': vcpu,
                            'ceph_uuid': image_info['ceph_uuid'],
                            'ceph_pool': image_info['ceph_pool'],
                            'diskname': diskname,
                            'ceph_host': image_info['ceph_host'],
                            'ceph_port': image_info['ceph_port'],
                            'ceph_username': image_info['ceph_username'],
                            'ceph_hosts_xml': image_info['ceph_hosts_xml'],
                            'mac': mac,
                            'bridge': vlan.br
                        }
                        print(xml_desc)
                        net_info = self.network_api.get_net_info_by_vmuuid(
                            vm_uuid)

                        vm_db = self.manager.create_vm_db({
                            'host_id':
                            host.id,
                            'image_id':
                            image_id,
                            'image_snap':
                            image_info['image_snap'],
                            'image':
                            image_info['image_name'],
                            'uuid':
                            vm_uuid,
                            'name':
                            vm_uuid,
                            'mem':
                            mem,
                            'vcpu':
                            vcpu,
                            'disk':
                            diskname,
                            'remarks':
                            remarks,
                            'ceph_id':
                            image_info['ceph_id'],
                            'ceph_host':
                            image_info['ceph_host'],
                            'ceph_pool':
                            image_info['ceph_pool'],
                            'ceph_uuid':
                            image_info['ceph_uuid'],
                            'ceph_port':
                            image_info['ceph_port'],
                            'ceph_username':
                            image_info['ceph_username'],
                            'vlan_id':
                            net_info['vlan_id'],
                            'vlan_name':
                            net_info['vlan_name'],
                            'ipv4':
                            net_info['ipv4'],
                            'mac':
                            net_info['mac'],
                            'br':
                            net_info['br']
                        })

                        if vm_db:
                            dom = self.manager.define(host.ipv4, xml_desc)
                            return VM(vm_db)
                        else:
                            raise Error(ERR_VM_CREATE_DB)
                except Error as e:
                    if settings.DEBUG:
                        print('[create_vm]', '创建失败', 'mac_claimed',
                              mac_claimed, 'disk_created', disk_created)

                    if mac_claimed:
                        mac_released = self.network_api.mac_release(
                            mac, vm_uuid)
                        if settings.DEBUG:
                            print('[create_vm]', 'IP地址释放', mac_released)
                    if disk_created:
                        disk_deleted = self.image_api.rm_disk(
                            image_id, diskname)
                        if settings.DEBUG:
                            print('[create_vm]', '磁盘释放', disk_deleted)
                    if vm_db:
                        host_released = self.host_api.host_release(
                            host, vcpu, mem)
                        if settings.DEBUG:
                            print('[create_vm]', '释放宿主机资源', host_released)
                        vm_db_deleted = vm_db.delete()
                        if settings.DEBUG:
                            print('[create_vm]', '删除数据库记录', vm_db_deleted)
                    if settings.DEBUG: print(e)
                    raise e
                except Exception as e:
                    if settings.DEBUG:
                        print('[create_vm]', '创建失败', 'mac_claimed',
                              mac_claimed, 'disk_created', disk_created)

                    if mac_claimed:
                        mac_released = self.network_api.mac_release(
                            mac, vm_uuid)
                        if settings.DEBUG:
                            print('[create_vm]', 'IP地址释放', mac_released)
                    if disk_created:
                        disk_deleted = self.image_api.rm_disk(
                            image_id, diskname)
                        if settings.DEBUG:
                            print('[create_vm]', '磁盘释放', disk_deleted)
                    if vm_db:
                        host_released = self.host_api.host_release(
                            host, vcpu, mem)
                        if settings.DEBUG:
                            print('[create_vm]', '释放宿主机资源', host_released)
                        vm_db_deleted = vm_db.delete()
                        if settings.DEBUG:
                            print('[create_vm]', '删除数据库记录', vm_db_deleted)
                    if settings.DEBUG: print(e)

        return False

    def delete_vm(self, vm_uuid, force=False):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        image_id = vm.image_id
        diskname = vm.disk
        host_id = vm.host_id
        vcpu = vm.vcpu
        mem = vm.mem
        mac = vm.mac
        ceph_pool_id = vm.ceph_id

        from device.api import GPUAPI
        from volume.api import VolumeAPI
        archive_disk_name = ''
        try:
            gpuapi = GPUAPI()
            if len(gpuapi.get_gpu_list_by_vm_uuid(vm_uuid)) > 0:
                raise Error(ERR_VM_DEL_GPU_MOUNTED)

            volumeapi = VolumeAPI()
            if len(volumeapi.get_volume_list_by_vm_uuid(vm_uuid)) > 0:
                raise Error(ERR_VM_DEL_VOL_MOUNTED)

            deletion_permitted = False

            if self.image_api.disk_exists(image_id,
                                          diskname,
                                          cephpool_id=ceph_pool_id):
                archive_disk_name = self.image_api.archive_disk(
                    image_id, diskname, cephpool_id=ceph_pool_id)
                if archive_disk_name != False:
                    deletion_permitted = True
            else:
                deletion_permitted = True
        except Exception as e:
            if not force:  # 不强制删除的话抛出异常
                raise e
            else:  # 强制删除,不管其他操作是否成功,都删除虚拟机记录
                deletion_permitted = True

        if deletion_permitted:
            if vm.delete(archive_disk_name, force=force):
                if not self.host_api.host_release(host_id, vcpu, mem):
                    print('[delete_vm]', '释放宿主机资源失败')
                if not self.network_api.mac_release(mac, vm_uuid):
                    print('[delete_vm]', '释放IP地址失败')
                return True
        return False

    # def reset_vm(self, vm_uuid):
    #     vm = self.manager.get_vm_by_uuid(vm_uuid)
    #     if vm.is_running():
    #         raise Error(ERR_VM_RESET_LIVING)
    #     archive_disk_name = self.image_api.archive_disk(vm.image_id, vm.disk)
    #     if archive_disk_name != False:
    #         init_disk_success = self.image_api.init_disk(vm.image_id, vm.disk)
    #         if init_disk_success:
    #             if vm.start():
    #                 return True
    #             self.image_api.rm_disk(vm.image_id, vm.disk)
    #         self.image_api.restore_disk(vm.image_id, archive_disk_name)
    #     return False

    def edit_vm(self, vm_uuid, vcpu=None, mem=None, remarks=None):
        vm = self.get_vm_by_uuid(vm_uuid)

        if (vcpu != None or mem != None) and vm.is_running():
            raise Error(ERR_VM_EDIT_LIVING)

        if vcpu and not type(vcpu) == int:
            raise Error(ERR_VM_VCPU)

        if mem and not type(mem) == int:
            raise Error(ERR_VM_MEM)

        failed = False
        org_remarks = vm.remarks
        org_vcpu = vm.vcpu
        org_mem = vm.mem

        if not failed and remarks:
            if not vm.set_remarks(remarks):
                failed = True

        if not failed and vcpu:
            if vcpu > vm.vcpu:
                vcpu_claimed = self.host_api.host_claim(
                    vm.host_id, vcpu - vm.vcpu, 0, 0)
            else:
                vcpu_claimed = self.host_api.host_release(
                    vm.host_id, vm.vcpu - vcpu, 0, 0)
        else:
            vcpu_claimed = True

        if not failed and mem:
            if mem > vm.mem:
                mem_claimed = self.host_api.host_claim(vm.host_id, 0,
                                                       mem - vm.mem, 0)
            else:
                mem_claimed = self.host_api.host_release(
                    vm.host_id, 0, vm.mem - mem, 0)
        else:
            mem_claimed = True

        if not failed and vcpu_claimed and mem_claimed:
            if not self.manager.set_vm_configuration(vm_uuid, vcpu, mem):
                failed = True

        if failed:
            if remarks:
                vm.set_remarks(org_remarks)
            if vcpu or mem:
                self.manager.set_vm_configuration(vm_uuid, org_vcpu, org_mem)
                if vcpu and vcpu_claimed:
                    if vcpu > org_vcpu:
                        self.host_api.host_release(vm.host_id, vcpu - org_vcpu,
                                                   0, 0)
                    else:
                        self.host_api.host_claim(vm.host_id, org_vcpu - vcpu,
                                                 0, 0)
                if mem and mem_claimed:
                    if mem > org_mem:
                        self.host_api.host_release(vm.host_id, 0,
                                                   mem - org_mem, 0)
                    else:
                        self.host_api.host_claim(vm.host_id, 0, org_mem - mem,
                                                 0)

            return False

        return True

    def migrate_vm(self, vm_uuid, host_id):
        #参数验证
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        host = self.host_api.get_host_by_id(host_id)
        src_host_alive = vm.is_host_connected

        from device.api import GPUAPI
        from volume.api import VolumeAPI
        gpuapi = GPUAPI()
        volumeapi = VolumeAPI()
        gpu_list = gpuapi.get_gpu_list_by_vm_uuid(vm_uuid)
        volume_list = volumeapi.get_volume_list_by_vm_uuid(vm_uuid)

        #判断是否在同一个center
        if vm.center_id != host.center_id:
            raise Error(ERR_VM_MIGRATE_DIFF_CEPH)

        #是否关机
        if vm.is_running():
            raise Error(ERR_VM_MIGRATE_LIVING)

        #在新宿主机上创建
        image_info = self.image_api.get_image_info_by_id(vm.image_id)

        xml_tpl = self.image_api.get_xml_tpl(vm.image_id)
        xml_desc = xml_tpl % {
            'name': vm_uuid,
            'uuid': vm_uuid,
            'mem': vm.mem,
            'vcpu': vm.vcpu,
            'ceph_uuid': image_info['ceph_uuid'],
            'ceph_pool': image_info['ceph_pool'],
            'diskname': vm.disk,
            'ceph_host': image_info['ceph_host'],
            'ceph_port': image_info['ceph_port'],
            'ceph_username': image_info['ceph_username'],
            'ceph_hosts_xml': image_info['ceph_hosts_xml'],
            'mac': vm.mac,
            'bridge': vm.br
        }

        migrate_res = False
        if self.host_api.host_claim(host_id, vm.vcpu, vm.mem, 1):
            try:
                if src_host_alive:
                    for gpu1 in gpu_list:
                        r1 = vm.detach_device(gpu1.xml_desc)
                        if settings.DEBUG:
                            print('[migrate_vm]', 'detach gpu ', gpu1.id, r1)
                    for volume1 in volume_list:
                        r1 = vm.detach_device(volume1.xml_desc)
                        if settings.DEBUG:
                            print('[migrate_vm]', 'detach volume ', volume1.id,
                                  r1)

                old_host_id = vm.host_id
                if self.manager.migrate(vm_uuid,
                                        host_id,
                                        host.ipv4,
                                        xml_desc,
                                        old_host_alive=src_host_alive):
                    migrate_res = True
                    old_res = self.host_api.host_release(
                        old_host_id, vm.vcpu, vm.mem, 1)
                    if settings.DEBUG:
                        print('[migrate_vm]', '释放原宿主机资源 ', old_res)
                    #重新attach device(只有云硬盘)
                    for volume1 in volume_list:
                        r1 = vm.attach_device(volume1.xml_desc)
                        if settings.DEBUG:
                            print('[migrate_vm]', 'attach volume ', volume1.id,
                                  r1)
            except Exception as e:
                if type(e) == Error:
                    raise e
            finally:
                if not migrate_res:
                    new_res = self.host_api.host_release(
                        host_id, vm.vcpu, vm.mem, 1)
                    if settings.DEBUG:
                        print('[migrate_vm]', '迁移失败,释放新宿主机资源 ', new_res)

        return migrate_res

    def reset_vm(self, vm_uuid, new_image_id=None):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        if new_image_id == None:
            new_image_id = vm.image_id
        host = vm.host
        old_image_id = vm.image_id
        old_diskname = vm.disk
        old_ceph_pool_id = vm.ceph_id

        if vm.is_running():
            raise Error(ERR_VM_RESET_LIVING)

        new_image_info = self.image_api.get_image_info_by_id(new_image_id)
        if not new_image_info:
            raise Error(ERR_IMAGE_INFO)

        from device.api import GPUAPI
        from volume.api import VolumeAPI
        gpuapi = GPUAPI()
        volumeapi = VolumeAPI()
        gpu_list = gpuapi.get_gpu_list_by_vm_uuid(vm_uuid)
        volume_list = volumeapi.get_volume_list_by_vm_uuid(vm_uuid)

        archive_disk_name = ''
        old_image_dict = {
            'image_id': old_image_id,
            'image_snap': vm.image_snap,
            'image_name': vm.image,
            'ceph_id': vm.ceph_id,
            'ceph_host': vm.ceph_host,
            'ceph_pool': vm.ceph_pool,
            'ceph_uuid': vm.ceph_uuid,
            'ceph_port': vm.ceph_port,
            'ceph_username': vm.ceph_username
        }
        old_xml_desc = vm.xml_desc

        res = False
        try:
            #先detach设备(gpu,volume)
            for gpu1 in gpu_list:
                r1 = vm.detach_device(gpu1.xml_desc)
                if settings.DEBUG:
                    print('[reset_vm]', 'detach gpu ', gpu1.id, r1)
            for volume1 in volume_list:
                r1 = vm.detach_device(volume1.xml_desc)
                if settings.DEBUG:
                    print('[reset_vm]', 'detach volume ', volume1.id, r1)

            #dom的destroy和undefine操作
            dom_undefine_res = False
            if self.manager.domain_exists(vm.host_ipv4, vm.uuid):
                dom = self.manager.get_domain(vm.host_ipv4, vm.uuid)
                try:
                    dom.destroy()
                except:
                    pass
                dom.undefine()
            if not self.manager.domain_exists(vm.host_ipv4, vm.uuid):
                dom_undefine_res = True
            if dom_undefine_res:
                archive_disk_name = self.image_api.archive_disk(
                    old_image_id, vm.disk)

            if archive_disk_name:
                init_disk_success = False
                if dom_undefine_res:
                    init_disk_success = self.image_api.init_disk(
                        new_image_id, vm.disk)
                if init_disk_success:
                    #更新vm_db相关image信息
                    vm.db_obj.image_id = new_image_id
                    vm.db_obj.image_snap = new_image_info['image_snap']
                    vm.db_obj.image = new_image_info['image_name']
                    vm.db_obj.ceph_id = new_image_info['ceph_id']
                    vm.db_obj.ceph_host = new_image_info['ceph_host']
                    vm.db_obj.ceph_pool = new_image_info['ceph_pool']
                    vm.db_obj.ceph_uuid = new_image_info['ceph_uuid']
                    vm.db_obj.ceph_port = new_image_info['ceph_port']
                    vm.db_obj.ceph_username = new_image_info['ceph_username']

                    vm.db_obj.save()

                    xml_tpl = self.image_api.get_xml_tpl(new_image_id)
                    xml_desc = xml_tpl % {
                        'name': vm.uuid,
                        'uuid': vm.uuid,
                        'mem': vm.mem,
                        'vcpu': vm.vcpu,
                        'ceph_uuid': new_image_info['ceph_uuid'],
                        'ceph_pool': new_image_info['ceph_pool'],
                        'diskname': vm.disk,
                        'ceph_host': new_image_info['ceph_host'],
                        'ceph_port': new_image_info['ceph_port'],
                        'ceph_username': new_image_info['ceph_username'],
                        'ceph_hosts_xml': new_image_info['ceph_hosts_xml'],
                        'mac': vm.mac,
                        'bridge': vm.br
                    }
                    dom = self.manager.define(host.ipv4, xml_desc)
                    res = True
        except Exception as e:
            if settings.DEBUG: print('[reset_vm]', '重置镜像失败', e)
            res = False
            if archive_disk_name:  #已经归档成功,重新恢复
                self.image_api.restore_disk(vm.image_id, archive_disk_name)

                vm.db_obj.image_id = old_image_dict['image_id']
                vm.db_obj.image_snap = old_image_dict['image_snap']
                vm.db_obj.image = old_image_dict['image_name']
                vm.db_obj.ceph_id = old_image_dict['ceph_id']
                vm.db_obj.ceph_host = old_image_dict['ceph_host']
                vm.db_obj.ceph_pool = old_image_dict['ceph_pool']
                vm.db_obj.ceph_uuid = old_image_dict['ceph_uuid']
                vm.db_obj.ceph_port = old_image_dict['ceph_port']
                vm.db_obj.ceph_username = old_image_dict['ceph_username']
                vm.db_obj.save()

                dom = self.manager.define(host.ipv4, old_xml_desc)
            if settings.DEBUG: print('[reset_vm]', '回滚成功')
        finally:
            for gpu1 in gpu_list:
                r1 = vm.attach_device(gpu1.xml_desc)
                if settings.DEBUG:
                    print('[reset_vm]', 'attach gpu ', gpu1.id, r1)
            for volume1 in volume_list:
                r1 = vm.attach_device(volume1.xml_desc)
                if settings.DEBUG:
                    print('[reset_vm]', 'attach volume ', volume1.id, r1)

        return res

    def get_vm_disk_snap_list(self, vm_uuid):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        return self.image_api.get_disk_snap_list_by_disk(vm.disk)

    def create_vm_disk_snap(self, vm_uuid, remarks=None):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        res = self.image_api.create_disk_snap(vm.ceph_id,
                                              vm.disk,
                                              vm.image_id,
                                              vm_uuid,
                                              remarks=remarks)
        if res:
            return True
        else:
            return False

    def rollback_vm_disk_snap(self, vm_uuid, snap_id):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        if vm.is_running():
            if settings.DEBUG: print('[rollback_vm_disk_snap]', '运行状态无法回滚')
            raise Error(ERR_VM_CREATE_SNAP_LIVING)
        if settings.DEBUG: print('[rollback_vm_disk_snap]', '快照回滚:开始执行')
        res = self.image_api.rollback_disk_snap(vm.disk, snap_id)
        if settings.DEBUG: print('[rollback_vm_disk_snap]', '快照回滚:结束', res)
        if res:
            return True
        else:
            return False

    def delete_vm_disk_snap(self, vm_uuid, snap_id):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        res = self.image_api.delete_disk_snap_by_id(vm.disk, snap_id)
        if settings.DEBUG: print('[delete_vm_disk_snap]', '快照删除', res)
        if res:
            return True
        else:
            return False

    def set_vm_disk_snap_remarks(self, vm_uuid, snap_id, remarks=None):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        res = self.image_api.set_disk_snap_remarks(vm.disk, snap_id, remarks)
        if res:
            return True
        else:
            return False
Beispiel #8
0
def get_type_list(args=None):
    image_api = ImageAPI()
    ret_list = image_api.get_image_type_list()
    return {'res': True, 'list': ret_list}
Beispiel #9
0
class VmAPI(object):
    def __init__(self,
                 manager=None,
                 user_api=None,
                 network_api=None,
                 image_api=None,
                 group_api=None,
                 host_api=None):
        if not manager:
            self.manager = VMManager()
        else:
            self.manager = manager
        if not user_api:
            self.user_api = UserAPI()
        else:
            self.user_api = user_api
        if not network_api:
            self.network_api = NetworkAPI()
        else:
            self.network_api = network_api
        if not image_api:
            self.image_api = ImageAPI()
        else:
            self.image_api = image_api
        if not group_api:
            self.group_api = GroupAPI()
        else:
            self.group_api = group_api
        if not host_api:
            self.host_api = HostAPI()
        else:
            self.host_api = host_api

    def get_vm_by_uuid(self, vm_uuid):
        return self.manager.get_vm_by_uuid(vm_uuid)

    def get_vm_list_by_group_id(self, group_id, host_id=None, order=None):
        return self.manager.get_vm_list_by_group_id(group_id, host_id, order)

    def vm_uuid_exists(self, vm_uuid):
        return self.manager.vm_uuid_exists(vm_uuid)

    def attach_device(self, vm_uuid, xml):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        return vm.attach_device(xml)

    def detach_device(self, vm_uuid, xml):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        return vm.detach_device(xml)

    def set_creator(self, vm_uuid, username):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        return vm.set_creator(str(username))

    def create_vm(self,
                  image_id,
                  vcpu,
                  mem,
                  group_id=None,
                  host_id=None,
                  net_type_id=None,
                  vlan_id=None,
                  diskname=None,
                  vm_uuid=None,
                  remarks=None):
        '''
        参数说明:
            image_id, vcpu, mem 为必要参数。
            group_id, host_id 两者至少必须有其一, host_id存在时指定相应宿主机,
            无host_id但有group_id时在指定集群筛选宿主机。
            net_type_id, vlan_id 两者至少必须有其一,有vlan_id时使用指定的网段,
            无vlan_id但有net_type_id时在指定网络类型中筛选网段。
            其他参数都是可选参数。
        '''
        vcpu = int(vcpu)
        mem = int(mem)

        if not vm_uuid:
            vm_uuid = self.manager.create_vm_uuid()
        if not diskname:
            diskname = vm_uuid

        image = self.image_api.get_image_by_id(image_id)
        if not image.enable:
            raise Error(ERR_IMAGE_ID)

        image_info = self.image_api.get_image_info_by_id(image_id)

        if host_id:
            host_list = [self.host_api.get_host_by_id(host_id)]
        elif group_id:
            host_list = self.host_api.get_host_list_by_group_id(group_id)
        else:
            raise Error(ERR_VM_CREATE_ARGS_HOST)

        available_host_list = []
        for host in host_list:
            if host.enable and not host.exceed_vm_limit(
            ) and not host.exceed_mem_limit(mem):
                available_host_list.append(host)

        if not available_host_list:
            raise Error(ERR_HOST_FILTER_NONE)

        if settings.DEBUG: print('[create_vm]', '可用主机列表', available_host_list)

        if vlan_id:
            vlan_list = [self.network_api.get_vlan_by_id(vlan_id)]
        elif net_type_id:
            vlan_list = self.network_api.get_vlan_list_by_type_id(net_type_id)
        else:
            raise Error(ERR_VM_CREATE_ARGS_VLAN)

        available_vlan_list = []
        for vlan in vlan_list:
            if vlan.enable and vlan.has_free_ip():
                available_vlan_list.append(vlan)

        if not available_vlan_list:
            raise Error(ERR_VLAN_FILTER_NONE)

        if settings.DEBUG: print('[create_vm]', '网段列表', vlan_list)

        while available_host_list:
            mac_claimed = False
            disk_created = False

            host = self.host_api.host_filter(available_host_list,
                                             vcpu,
                                             mem,
                                             claim=True)
            if not host:
                raise Error(ERR_VM_HOST_FILTER)
            available_host_list.remove(host)

            if host.alive():
                host_available_vlan_id_list = self.host_api.get_vlan_id_list_of_host(
                    host.id)
                for vlan in available_vlan_list:
                    try:
                        if not vlan.id in host_available_vlan_id_list:
                            continue
                        if settings.DEBUG:
                            print('[create_vm]', '开始创建', host, vlan)
                        mac_claimed = False
                        disk_created = False

                        mac = self.network_api.mac_claim(vlan.id, vm_uuid)
                        if mac:
                            mac_claimed = True

                        if mac_claimed:
                            if self.image_api.init_disk(image_id, diskname):
                                disk_created = True
                            else:
                                raise Error(ERR_VM_CREATE_DISK)
                            # image_info = self.image_api.get_image_info_by_id(image_id)

                            xml_tpl = self.image_api.get_xml_tpl(image_id)
                            xml_desc = xml_tpl % {
                                'name': vm_uuid,
                                'uuid': vm_uuid,
                                'mem': mem,
                                'vcpu': vcpu,
                                'ceph_uuid': image_info['ceph_uuid'],
                                'ceph_pool': image_info['ceph_pool'],
                                'diskname': diskname,
                                'ceph_host': image_info['ceph_host'],
                                'ceph_port': image_info['ceph_port'],
                                'ceph_username': image_info['ceph_username'],
                                'mac': mac,
                                'bridge': vlan.br
                            }

                            net_info = self.network_api.get_net_info_by_vmuuid(
                                vm_uuid)

                            db = self.manager.create_vm_db({
                                'host_id':
                                host.id,
                                'image_id':
                                image_id,
                                'image_snap':
                                image_info['image_snap'],
                                'image':
                                image_info['image_name'],
                                'uuid':
                                vm_uuid,
                                'name':
                                vm_uuid,
                                'mem':
                                mem,
                                'vcpu':
                                vcpu,
                                'disk':
                                diskname,
                                'remarks':
                                remarks,
                                'ceph_id':
                                image_info['ceph_id'],
                                'ceph_host':
                                image_info['ceph_host'],
                                'ceph_pool':
                                image_info['ceph_pool'],
                                'ceph_uuid':
                                image_info['ceph_uuid'],
                                'ceph_port':
                                image_info['ceph_port'],
                                'ceph_username':
                                image_info['ceph_username'],
                                'vlan_id':
                                net_info['vlan_id'],
                                'vlan_name':
                                net_info['vlan_name'],
                                'ipv4':
                                net_info['ipv4'],
                                'mac':
                                net_info['mac'],
                                'br':
                                net_info['br']
                            })

                            if db:
                                dom = self.manager.define(host.ipv4, xml_desc)
                                return VM(db)
                            else:
                                raise Error(ERR_VM_CREATE_DB)
                    except Error as e:
                        if settings.DEBUG:
                            print('[create_vm]', '创建失败', 'mac_claimed',
                                  mac_claimed, 'disk_created', disk_created)
                        if mac_claimed:
                            mac_released = self.network_api.mac_release(
                                mac, vm_uuid)
                            if settings.DEBUG:
                                print('[create_vm]', 'IP地址释放', mac_released)
                        if disk_created:
                            disk_deleted = self.image_api.rm_disk(
                                image_id, diskname)
                            if settings.DEBUG:
                                print('[create_vm]', '磁盘释放', disk_deleted)
                        if settings.DEBUG: print(e)
                        raise e
                    except Exception as e:
                        if settings.DEBUG:
                            print('[create_vm]', '创建失败', 'mac_claimed',
                                  mac_claimed, 'disk_created', disk_created)

                        if mac_claimed:
                            mac_released = self.network_api.mac_release(
                                mac, vm_uuid)
                            if settings.DEBUG:
                                print('[create_vm]', 'IP地址释放', mac_released)
                        if disk_created:
                            disk_deleted = self.image_api.rm_disk(
                                image_id, diskname)
                            if settings.DEBUG:
                                print('[create_vm]', '磁盘释放', disk_deleted)
                        if settings.DEBUG: print(e)

            host_released = self.host_api.host_release(host, vcpu, mem)
            if settings.DEBUG: print('[create_vm]', '释放宿主机资源', host_released)
        return False

    def delete_vm(self, vm_uuid):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        image_id = vm.image_id
        diskname = vm.disk
        host_id = vm.host_id
        vcpu = vm.vcpu
        mem = vm.mem
        mac = vm.mac

        from device.api import GPUAPI
        from volume.api import CephVolumeAPI

        gpuapi = GPUAPI()
        if len(gpuapi.get_gpu_list_by_vm_uuid(vm_uuid)) > 0:
            raise Error(ERR_VM_DEL_GPU_MOUNTED)

        volumeapi = CephVolumeAPI()
        if len(volumeapi.get_volume_list_by_vm_uuid(vm_uuid)) > 0:
            raise Error(ERR_VM_DEL_VOL_MOUNTED)

        deletion_permitted = False

        archive_disk_name = ''
        if self.image_api.disk_exists(image_id, diskname):
            archive_disk_name = self.image_api.archive_disk(image_id, diskname)
            if archive_disk_name != False:
                deletion_permitted = True
        else:
            deletion_permitted = True
        if deletion_permitted:
            if vm.delete(archive_disk_name):
                if not self.host_api.host_release(host_id, vcpu, mem):
                    print('[delete_vm]', '释放宿主机资源失败')
                if not self.network_api.mac_release(mac, vm_uuid):
                    print('[delete_vm]', '释放IP地址失败')
                return True
        return False

    def reset_vm(self, vm_uuid):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        if vm.is_running():
            raise Error(ERR_VM_RESET_LIVING)
        archive_disk_name = self.image_api.archive_disk(vm.image_id, vm.disk)
        if archive_disk_name != False:
            init_disk_success = self.image_api.init_disk(vm.image_id, vm.disk)
            if init_disk_success:
                if vm.start():
                    return True
                self.image_api.rm_disk(vm.image_id, vm.disk)
            self.image_api.restore_disk(vm.image_id, archive_disk_name)
        return False

    def edit_vm(self, vm_uuid, vcpu=None, mem=None, remarks=None):
        vm = self.get_vm_by_uuid(vm_uuid)

        if (vcpu != None or mem != None) and vm.is_running():
            raise Error(ERR_VM_EDIT_LIVING)

        if vcpu and not type(vcpu) == int:
            raise Error(ERR_VM_VCPU)

        if mem and not type(mem) == int:
            raise Error(ERR_VM_MEM)

        failed = False
        org_remarks = vm.remarks
        org_vcpu = vm.vcpu
        org_mem = vm.mem

        if not failed and remarks:
            if not vm.set_remarks(remarks):
                failed = True

        if not failed and vcpu:
            if vcpu > vm.vcpu:
                vcpu_claimed = self.host_api.host_claim(
                    vm.host_id, vcpu - vm.vcpu, 0, 0)
            else:
                vcpu_claimed = self.host_api.host_release(
                    vm.host_id, vm.vcpu - vcpu, 0, 0)
        else:
            vcpu_claimed = True

        if not failed and mem:
            if mem > vm.mem:
                mem_claimed = self.host_api.host_claim(vm.host_id, 0,
                                                       mem - vm.mem, 0)
            else:
                mem_claimed = self.host_api.host_release(
                    vm.host_id, 0, vm.mem - mem, 0)
        else:
            mem_claimed = True

        if not failed and vcpu_claimed and mem_claimed:
            if not self.manager.set_vm_configuration(vm_uuid, vcpu, mem):
                failed = True

        if failed:
            if remarks:
                vm.set_remarks(org_remarks)
            if vcpu or mem:
                self.manager.set_vm_configuration(vm_uuid, org_vcpu, org_mem)
                if vcpu and vcpu_claimed:
                    if vcpu > org_vcpu:
                        self.host_api.host_release(vm.host_id, vcpu - org_vcpu,
                                                   0, 0)
                    else:
                        self.host_api.host_claim(vm.host_id, org_vcpu - vcpu,
                                                 0, 0)
                if mem and mem_claimed:
                    if mem > org_mem:
                        self.host_api.host_release(vm.host_id, 0,
                                                   mem - org_mem, 0)
                    else:
                        self.host_api.host_claim(vm.host_id, 0, org_mem - mem,
                                                 0)

            return False

        return True

    def migrate_vm(self, vm_uuid, host_id):
        #参数验证
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        host = self.host_api.get_host_by_id(host_id)

        #判断是否在同一个center
        if vm.center_id != host.center_id:
            raise Error(ERR_VM_MIGRATE_DIFF_CEPH)

        #是否关机
        if vm.is_running():
            raise Error(ERR_VM_MIGRATE_LIVING)

        #在新宿主机上创建
        image_info = self.image_api.get_image_info_by_id(vm.image_id)

        xml_tpl = self.image_api.get_xml_tpl(vm.image_id)
        xml_desc = xml_tpl % {
            'name': vm_uuid,
            'uuid': vm_uuid,
            'mem': vm.mem,
            'vcpu': vm.vcpu,
            'ceph_uuid': image_info['ceph_uuid'],
            'ceph_pool': image_info['ceph_pool'],
            'diskname': vm.disk,
            'ceph_host': image_info['ceph_host'],
            'ceph_port': image_info['ceph_port'],
            'ceph_username': image_info['ceph_username'],
            'mac': vm.mac,
            'bridge': vm.br
        }

        if self.host_api.host_claim(host_id, vm.vcpu, vm.mem, 1):
            try:
                old_host_id = vm.host_id
                if self.manager.migrate(vm_uuid, host_id, host.ipv4, xml_desc):
                    self.host_api.host_release(old_host_id, vm.vcpu, vm.mem, 1)
                    return True
            except Exception as e:
                self.host_api.host_release(host_id, vm.vcpu, vm.mem, 1)
                if type(e) == Error:
                    raise e
            else:
                self.host_api.host_release(host_id, vm.vcpu, vm.mem, 1)

        return False
Beispiel #10
0
def get_type_list(args=None):
    image_api = ImageAPI()
    ret_list = image_api.get_image_type_list()
    return {'res': True, 'list': ret_list}
Beispiel #11
0
class VmAPI(object):
    def __init__(self, manager=None, user_api=None, network_api=None, image_api=None, group_api=None, host_api=None):
        if not manager:
            self.manager = VMManager()
        else:
            self.manager = manager
        if not user_api:
            self.user_api = UserAPI()
        else:
            self.user_api = user_api
        if not network_api:
            self.network_api = NetworkAPI()
        else:
            self.network_api = network_api
        if not image_api:
            self.image_api = ImageAPI()
        else:
            self.image_api = image_api
        if not group_api:
            self.group_api = GroupAPI()
        else:
            self.group_api = group_api
        if not host_api:
            self.host_api = HostAPI()
        else:
            self.host_api = host_api

    def get_vm_by_uuid(self, vm_uuid):
        return self.manager.get_vm_by_uuid(vm_uuid)

    def get_vm_list_by_group_id(self, group_id, host_id=None, order=None):
        return self.manager.get_vm_list_by_group_id(group_id, host_id, order)

    def vm_uuid_exists(self, vm_uuid):
        return self.manager.vm_uuid_exists(vm_uuid)
        
    def attach_device(self, vm_uuid, xml):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        return vm.attach_device(xml)

    def detach_device(self, vm_uuid, xml):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        return vm.detach_device(xml)  

    def set_creator(self, vm_uuid, username):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        return vm.set_creator(str(username))

    def create_vm(self, image_id, vcpu, mem, group_id=None, host_id=None,
        net_type_id=None, vlan_id=None, diskname=None, vm_uuid=None, remarks=None):
        '''
        参数说明:
            image_id, vcpu, mem 为必要参数。
            group_id, host_id 两者至少必须有其一, host_id存在时指定相应宿主机,
            无host_id但有group_id时在指定集群筛选宿主机。
            net_type_id, vlan_id 两者至少必须有其一,有vlan_id时使用指定的网段,
            无vlan_id但有net_type_id时在指定网络类型中筛选网段。
            其他参数都是可选参数。
        '''
        vcpu = int(vcpu)
        mem = int(mem)

        if not vm_uuid:
            vm_uuid = self.manager.create_vm_uuid()
        if not diskname:
            diskname = vm_uuid

        image = self.image_api.get_image_by_id(image_id)
        if not image.enable:
            raise Error(ERR_IMAGE_ID)

        image_info = self.image_api.get_image_info_by_id(image_id)

        if host_id:
            host_list = [self.host_api.get_host_by_id(host_id)]
        elif group_id:
            host_list = self.host_api.get_host_list_by_group_id(group_id)
        else:
            raise Error(ERR_VM_CREATE_ARGS_HOST)   
        
        available_host_list = []
        for host in host_list:
            if host.enable and not host.exceed_vm_limit() and not host.exceed_mem_limit(mem):
                available_host_list.append(host)

        if not available_host_list:
            raise Error(ERR_HOST_FILTER_NONE)
        
        if  settings.DEBUG: print('[create_vm]', '可用主机列表', available_host_list)

        if vlan_id:
            vlan_list = [self.network_api.get_vlan_by_id(vlan_id)]
        elif net_type_id:
            vlan_list = self.network_api.get_vlan_list_by_type_id(net_type_id)
        else:
            raise Error(ERR_VM_CREATE_ARGS_VLAN)

        available_vlan_list = []
        for vlan in vlan_list:
            if vlan.enable and vlan.has_free_ip():
                available_vlan_list.append(vlan)

        if not available_vlan_list:
            raise Error(ERR_VLAN_FILTER_NONE)

        if settings.DEBUG: print('[create_vm]', '网段列表', vlan_list)

        while available_host_list:
            mac_claimed = False
            disk_created = False
        
            host = self.host_api.host_filter(available_host_list, vcpu, mem, claim=True)  
            if not host:
                raise Error(ERR_VM_HOST_FILTER)
            available_host_list.remove(host)

            if host.alive():
                host_available_vlan_id_list = self.host_api.get_vlan_id_list_of_host(host.id)
                for vlan in available_vlan_list:
                    try:
                        if not vlan.id in host_available_vlan_id_list:
                            continue
                        if settings.DEBUG: print('[create_vm]', '开始创建', host, vlan)
                        mac_claimed = False
                        disk_created = False

                        mac = self.network_api.mac_claim(vlan.id, vm_uuid)
                        if mac:
                            mac_claimed = True
                        
                        if mac_claimed:
                            if self.image_api.init_disk(image_id, diskname):
                                disk_created = True
                            else:
                                raise Error(ERR_VM_CREATE_DISK)
                            # image_info = self.image_api.get_image_info_by_id(image_id)

                            xml_tpl = self.image_api.get_xml_tpl(image_id)
                            xml_desc = xml_tpl % {
                                'name': vm_uuid,
                                'uuid': vm_uuid,
                                'mem': mem,
                                'vcpu': vcpu,
                                'ceph_uuid': image_info['ceph_uuid'],
                                'ceph_pool': image_info['ceph_pool'],
                                'diskname': diskname,
                                'ceph_host': image_info['ceph_host'],
                                'ceph_port': image_info['ceph_port'],
                                'ceph_username': image_info['ceph_username'],
                                'mac': mac,
                                'bridge': vlan.br
                            }

                            net_info = self.network_api.get_net_info_by_vmuuid(vm_uuid)

                            db = self.manager.create_vm_db({
                                'host_id': host.id,
                                'image_id': image_id,
                                'image_snap': image_info['image_snap'],
                                'image': image_info['image_name'],
                                'uuid': vm_uuid,
                                'name': vm_uuid,
                                'mem': mem,
                                'vcpu': vcpu,
                                'disk': diskname,
                                'remarks': remarks,
                                'ceph_id': image_info['ceph_id'],
                                'ceph_host': image_info['ceph_host'],
                                'ceph_pool': image_info['ceph_pool'],
                                'ceph_uuid': image_info['ceph_uuid'],
                                'ceph_port': image_info['ceph_port'],
                                'ceph_username': image_info['ceph_username'],
                                'vlan_id': net_info['vlan_id'],
                                'vlan_name': net_info['vlan_name'],
                                'ipv4': net_info['ipv4'],
                                'mac': net_info['mac'],
                                'br': net_info['br']
                                })

                            if db:
                                dom = self.manager.define(host.ipv4, xml_desc)                    
                                return VM(db)
                            else:
                                raise Error(ERR_VM_CREATE_DB)
                    except Error as e:
                        if settings.DEBUG: print('[create_vm]', '创建失败','mac_claimed', mac_claimed, 
                            'disk_created', disk_created)
                        if mac_claimed:
                            mac_released = self.network_api.mac_release(mac, vm_uuid)
                            if settings.DEBUG: print('[create_vm]', 'IP地址释放', mac_released)
                        if disk_created:
                            disk_deleted = self.image_api.rm_disk(image_id, diskname)
                            if settings.DEBUG: print('[create_vm]', '磁盘释放', disk_deleted)
                        if settings.DEBUG: print(e)
                        raise e
                    except Exception as e:
                        if settings.DEBUG: print('[create_vm]', '创建失败', 'mac_claimed', mac_claimed, 
                            'disk_created', disk_created)
                        
                        if mac_claimed:
                            mac_released = self.network_api.mac_release(mac, vm_uuid)
                            if settings.DEBUG: print('[create_vm]', 'IP地址释放', mac_released)
                        if disk_created:
                            disk_deleted = self.image_api.rm_disk(image_id, diskname)
                            if settings.DEBUG: print('[create_vm]', '磁盘释放', disk_deleted)
                        if settings.DEBUG: print(e)
            
            host_released = self.host_api.host_release(host, vcpu, mem)
            if settings.DEBUG: print('[create_vm]', '释放宿主机资源', host_released)
        return False
    
    def delete_vm(self, vm_uuid):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        image_id = vm.image_id
        diskname = vm.disk
        host_id = vm.host_id
        vcpu = vm.vcpu
        mem = vm.mem
        mac = vm.mac
        
        from device.api import GPUAPI
        from volume.api import CephVolumeAPI
        
        gpuapi = GPUAPI()
        if len(gpuapi.get_gpu_list_by_vm_uuid(vm_uuid)) > 0:
            raise Error(ERR_VM_DEL_GPU_MOUNTED)

        volumeapi = CephVolumeAPI()
        if len(volumeapi.get_volume_list_by_vm_uuid(vm_uuid)) > 0:
            raise Error(ERR_VM_DEL_VOL_MOUNTED)

        deletion_permitted = False



        archive_disk_name = ''
        if self.image_api.disk_exists(image_id, diskname):
            archive_disk_name = self.image_api.archive_disk(image_id, diskname)
            if archive_disk_name != False:
                deletion_permitted = True
        else:
            deletion_permitted = True
        if deletion_permitted:
            if vm.delete(archive_disk_name):
                if not self.host_api.host_release(host_id, vcpu, mem):
                    print('[delete_vm]', '释放宿主机资源失败')
                if not self.network_api.mac_release(mac, vm_uuid):
                    print('[delete_vm]', '释放IP地址失败')
                return True
        return False

    def reset_vm(self, vm_uuid):
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        if vm.is_running():
            raise Error(ERR_VM_RESET_LIVING)
        archive_disk_name = self.image_api.archive_disk(vm.image_id, vm.disk)
        if archive_disk_name != False:
            init_disk_success = self.image_api.init_disk(vm.image_id, vm.disk)
            if init_disk_success:
                if vm.start():
                    return True
                self.image_api.rm_disk(vm.image_id, vm.disk)
            self.image_api.restore_disk(vm.image_id, archive_disk_name)
        return False 

    def edit_vm(self, vm_uuid, vcpu=None, mem=None, remarks=None):
        vm = self.get_vm_by_uuid(vm_uuid)

        if (vcpu != None or mem != None) and vm.is_running():
            raise Error(ERR_VM_EDIT_LIVING)
        
        if vcpu and not type(vcpu) == int:
            raise Error(ERR_VM_VCPU)

        if mem and not type(mem) == int:
            raise Error(ERR_VM_MEM)

        failed = False
        org_remarks = vm.remarks
        org_vcpu = vm.vcpu
        org_mem = vm.mem

        if not failed and remarks:
            if not vm.set_remarks(remarks):
                failed = True

        if not failed and vcpu:
            if vcpu > vm.vcpu:
                vcpu_claimed = self.host_api.host_claim(vm.host_id, vcpu - vm.vcpu, 0, 0)
            else:
                vcpu_claimed = self.host_api.host_release(vm.host_id, vm.vcpu - vcpu, 0, 0)
        else:
            vcpu_claimed = True

        if not failed and mem:
            if mem > vm.mem:
                mem_claimed = self.host_api.host_claim(vm.host_id, 0, mem - vm.mem, 0)
            else:
                mem_claimed = self.host_api.host_release(vm.host_id, 0, vm.mem - mem, 0)
        else:
            mem_claimed = True

        if not failed and vcpu_claimed and mem_claimed:
            if not self.manager.set_vm_configuration(vm_uuid, vcpu, mem):
                failed = True

        if failed:
            if remarks:
                vm.set_remarks(org_remarks)
            if vcpu or mem:
                self.manager.set_vm_configuration(vm_uuid, org_vcpu, org_mem)
                if vcpu and vcpu_claimed:
                    if vcpu > org_vcpu:
                        self.host_api.host_release(vm.host_id, vcpu - org_vcpu, 0, 0)
                    else:
                        self.host_api.host_claim(vm.host_id, org_vcpu - vcpu, 0, 0)
                if mem and mem_claimed:
                    if mem > org_mem:
                        self.host_api.host_release(vm.host_id, 0, mem - org_mem, 0)
                    else:
                        self.host_api.host_claim(vm.host_id, 0, org_mem - mem, 0)

            return False

        return True

    def migrate_vm(self, vm_uuid, host_id):
        #参数验证
        vm = self.manager.get_vm_by_uuid(vm_uuid)
        host = self.host_api.get_host_by_id(host_id)

        #判断是否在同一个center
        if vm.center_id != host.center_id:
            raise Error(ERR_VM_MIGRATE_DIFF_CEPH)

        #是否关机
        if vm.is_running():
            raise Error(ERR_VM_MIGRATE_LIVING)

        #在新宿主机上创建
        image_info = self.image_api.get_image_info_by_id(vm.image_id)

        xml_tpl = self.image_api.get_xml_tpl(vm.image_id)
        xml_desc = xml_tpl % {
            'name': vm_uuid,
            'uuid': vm_uuid,
            'mem': vm.mem,
            'vcpu': vm.vcpu,
            'ceph_uuid': image_info['ceph_uuid'],
            'ceph_pool': image_info['ceph_pool'],
            'diskname': vm.disk,
            'ceph_host': image_info['ceph_host'],
            'ceph_port': image_info['ceph_port'],
            'ceph_username': image_info['ceph_username'],
            'mac': vm.mac,
            'bridge': vm.br
        }

        if self.host_api.host_claim(host_id, vm.vcpu, vm.mem, 1):
            try:
                old_host_id = vm.host_id
                if self.manager.migrate(vm_uuid, host_id, host.ipv4, xml_desc):
                    self.host_api.host_release(old_host_id, vm.vcpu, vm.mem, 1)
                    return True 
            except Exception as e:
                self.host_api.host_release(host_id, vm.vcpu, vm.mem, 1)
                if type(e) == Error:
                    raise e
            else:
                self.host_api.host_release(host_id, vm.vcpu, vm.mem, 1)

        return False