コード例 #1
0
def r_resume(uuids):

    args_rules = [Rules.UUIDS.value]

    try:
        ji.Check.previewing(args_rules, {'uuids': uuids})

        guest = Guest()
        for uuid in uuids.split(','):
            guest.uuid = uuid
            guest.get_by('uuid')

        for uuid in uuids.split(','):
            guest.uuid = uuid
            guest.get_by('uuid')

            message = {
                '_object': 'guest',
                'action': 'resume',
                'uuid': uuid,
                'hostname': guest.on_host
            }

            Guest.emit_instruction(message=json.dumps(message))

        ret = dict()
        ret['state'] = ji.Common.exchange_state(20000)
        return ret

    except ji.PreviewingError, e:
        return json.loads(e.message)
コード例 #2
0
def r_detach_disk(disk_uuid):

    args_rules = [Rules.DISK_UUID.value]

    try:
        ji.Check.previewing(args_rules, {'disk_uuid': disk_uuid})

        disk = Disk()
        disk.uuid = disk_uuid
        disk.get_by('uuid')

        ret = dict()
        ret['state'] = ji.Common.exchange_state(20000)

        if disk.state != DiskState.mounted.value or disk.sequence == 0:
            # 表示未被任何实例使用,已被分离
            # 序列为 0 的表示实例系统盘,系统盘不可以被分离
            # TODO: 系统盘单独范围其它状态
            return ret

        guest = Guest()
        guest.uuid = disk.guest_uuid
        guest.get_by('uuid')

        # 判断 Guest 是否处于可用状态
        if guest.status in (status.GuestState.no_state.value,
                            status.GuestState.dirty.value):
            ret['state'] = ji.Common.exchange_state(41259)
            return ret

        config = Config()
        config.id = 1
        config.get()

        guest_xml = GuestXML(guest=guest, disk=disk, config=config)

        message = {
            '_object': 'guest',
            'action': 'detach_disk',
            'uuid': disk.guest_uuid,
            'hostname': guest.on_host,
            'xml': guest_xml.get_disk(),
            'passback_parameters': {
                'disk_uuid': disk.uuid
            }
        }

        Guest.emit_instruction(message=json.dumps(message))

        disk.state = DiskState.unloading.value
        disk.update()

        return ret

    except ji.PreviewingError, e:
        return json.loads(e.message)
コード例 #3
0
def r_delete(uuids):

    args_rules = [Rules.UUIDS.value]

    try:
        ji.Check.previewing(args_rules, {'uuids': uuids})

        ret = dict()
        ret['state'] = ji.Common.exchange_state(20000)

        disk = Disk()

        # 检测所指定的 UUDIs 磁盘都存在
        for uuid in uuids.split(','):
            disk.uuid = uuid
            disk.get_by('uuid')

            if disk.state != DiskState.idle.value:
                ret['state'] = ji.Common.exchange_state(41256)
                return ret

        config = Config()
        config.id = 1
        config.get()

        # 执行删除操作
        for uuid in uuids.split(','):
            disk.uuid = uuid
            disk.get_by('uuid')

            message = {
                '_object': 'disk',
                'action': 'delete',
                'uuid': disk.uuid,
                'storage_mode': config.storage_mode,
                'dfs_volume': config.dfs_volume,
                'hostname': disk.on_host,
                'image_path': disk.path
            }

            if disk.on_host == 'shared_storage':
                message['hostname'] = Guest.get_lightest_host()['hostname']

            Guest.emit_instruction(
                message=json.dumps(message, ensure_ascii=False))

        return ret

    except ji.PreviewingError, e:
        return json.loads(e.message)
コード例 #4
0
def r_delete(uuids):

    args_rules = [Rules.UUIDS.value]

    # TODO: 加入是否删除使用的数据磁盘开关,如果为True,则顺便删除使用的磁盘。否则解除该磁盘被使用的状态。
    try:
        ji.Check.previewing(args_rules, {'uuids': uuids})

        guest = Guest()
        # 检测所指定的 UUDIs 实例都存在
        for uuid in uuids.split(','):
            guest.uuid = uuid
            guest.get_by('uuid')

        config = Config()
        config.id = 1
        config.get()

        # 执行删除操作
        for uuid in uuids.split(','):
            guest.uuid = uuid
            guest.get_by('uuid')

            message = {
                '_object': 'guest',
                'action': 'delete',
                'uuid': uuid,
                'storage_mode': config.storage_mode,
                'dfs_volume': config.dfs_volume,
                'hostname': guest.on_host
            }

            Guest.emit_instruction(message=json.dumps(message))

            # 删除创建失败的 Guest
            if guest.status == status.GuestState.dirty.value:
                disk = Disk()
                disk.uuid = guest.uuid
                disk.get_by('uuid')

                if disk.state == status.DiskState.pending.value:
                    disk.delete()
                    guest.delete()

        ret = dict()
        ret['state'] = ji.Common.exchange_state(20000)
        return ret

    except ji.PreviewingError, e:
        return json.loads(e.message)
コード例 #5
0
def r_resize(uuid, size):

    args_rules = [Rules.UUID.value, Rules.DISK_SIZE_STR.value]

    try:
        ji.Check.previewing(args_rules, {'uuid': uuid, 'size': size})

        disk = Disk()
        disk.uuid = uuid
        disk.get_by('uuid')

        ret = dict()
        ret['state'] = ji.Common.exchange_state(20000)

        if disk.size >= size:
            ret['state'] = ji.Common.exchange_state(41257)
            return ret

        config = Config()
        config.id = 1
        config.get()

        message = {
            '_object': 'disk',
            'action': 'resize',
            'uuid': disk.uuid,
            'guest_uuid': disk.guest_uuid,
            'storage_mode': config.storage_mode,
            'size': int(size),
            'dfs_volume': config.dfs_volume,
            'hostname': disk.on_host,
            'image_path': disk.path,
            'passback_parameters': {
                'size': size
            }
        }

        if disk.on_host == 'shared_storage':
            message['hostname'] = Guest.get_lightest_host()['hostname']

        if disk.guest_uuid.__len__() == 36:
            message['device_node'] = dev_table[disk.sequence]

        Guest.emit_instruction(message=json.dumps(message, ensure_ascii=False))

        return ret

    except ji.PreviewingError, e:
        return json.loads(e.message)
コード例 #6
0
def r_migrate(uuids, destination_host):

    args_rules = [Rules.UUIDS.value, Rules.DESTINATION_HOST.value]

    try:
        ji.Check.previewing(args_rules, {
            'uuids': uuids,
            'destination_host': destination_host
        })

        guest = Guest()
        for uuid in uuids.split(','):
            guest.uuid = uuid
            guest.get_by('uuid')

        config = Config()
        config.id = 1
        config.get()

        for uuid in uuids.split(','):
            guest.uuid = uuid
            guest.get_by('uuid')

            message = {
                '_object': 'guest',
                'action': 'migrate',
                'uuid': uuid,
                'hostname': guest.on_host,
                'storage_mode': config.storage_mode,
                'duri': 'qemu+ssh://' + destination_host + '/system'
            }

            Guest.emit_instruction(message=json.dumps(message))

        ret = dict()
        ret['state'] = ji.Common.exchange_state(20000)
        return ret

    except ji.PreviewingError, e:
        return json.loads(e.message)
コード例 #7
0
def r_create():

    args_rules = [
        Rules.DISK_SIZE.value, Rules.REMARK.value, Rules.DISK_ON_HOST.value,
        Rules.QUANTITY.value
    ]

    config = Config()
    config.id = 1
    config.get()

    if config.storage_mode in [
            StorageMode.shared_mount.value, StorageMode.ceph.value,
            StorageMode.glusterfs.value
    ]:
        request.json['on_host'] = 'shared_storage'

    try:
        ji.Check.previewing(args_rules, request.json)

        ret = dict()
        ret['state'] = ji.Common.exchange_state(20000)

        size = request.json['size']
        quantity = request.json['quantity']
        on_host = request.json['on_host']

        if size < 1:
            ret['state'] = ji.Common.exchange_state(41255)
            return ret

        while quantity:
            quantity -= 1
            disk = Disk()
            disk.guest_uuid = ''
            disk.size = size
            disk.uuid = uuid4().__str__()
            disk.remark = request.json.get('remark', '')
            disk.on_host = on_host
            disk.sequence = -1
            disk.format = 'qcow2'

            disk.path = config.storage_path + '/' + disk.uuid + '.' + disk.format

            message = {
                '_object': 'disk',
                'action': 'create',
                'uuid': disk.uuid,
                'storage_mode': config.storage_mode,
                'dfs_volume': config.dfs_volume,
                'hostname': disk.on_host,
                'image_path': disk.path,
                'size': disk.size
            }

            if disk.on_host == 'shared_storage':
                available_hosts = Guest.get_available_hosts()

                if available_hosts.__len__() == 0:
                    ret['state'] = ji.Common.exchange_state(50351)
                    return ret

                # 在可用计算节点中平均分配任务
                chosen_host = available_hosts[quantity %
                                              available_hosts.__len__()]
                message['hostname'] = chosen_host['hostname']

            Guest.emit_instruction(
                message=json.dumps(message, ensure_ascii=False))

            disk.create()

        return ret

    except ji.PreviewingError, e:
        return json.loads(e.message)
コード例 #8
0
def r_attach_disk(uuid, disk_uuid):

    args_rules = [Rules.UUID.value, Rules.DISK_UUID.value]

    try:
        ji.Check.previewing(args_rules, {'uuid': uuid, 'disk_uuid': disk_uuid})

        guest = Guest()
        guest.uuid = uuid
        guest.get_by('uuid')

        disk = Disk()
        disk.uuid = disk_uuid
        disk.get_by('uuid')

        config = Config()
        config.id = 1
        config.get()

        ret = dict()
        ret['state'] = ji.Common.exchange_state(20000)

        # 判断欲挂载的磁盘是否空闲
        if disk.guest_uuid.__len__() > 0 or disk.state != DiskState.idle.value:
            ret['state'] = ji.Common.exchange_state(41258)
            return ret

        # 判断 Guest 是否处于可用状态
        if guest.status in (status.GuestState.no_state.value,
                            status.GuestState.dirty.value):
            ret['state'] = ji.Common.exchange_state(41259)
            return ret

        # 判断 Guest 与 磁盘是否在同一宿主机上
        if config.storage_mode in [
                status.StorageMode.local.value,
                status.StorageMode.shared_mount.value
        ]:
            if guest.on_host != disk.on_host:
                ret['state'] = ji.Common.exchange_state(41260)
                return ret

        # 通过检测未被使用的序列,来确定当前磁盘在目标 Guest 身上的序列
        disk.guest_uuid = guest.uuid
        disks, count = disk.get_by_filter(filter_str='guest_uuid:in:' +
                                          guest.uuid)

        already_used_sequence = list()

        for _disk in disks:
            already_used_sequence.append(_disk['sequence'])

        for sequence in range(0, dev_table.__len__()):
            if sequence not in already_used_sequence:
                disk.sequence = sequence
                break

        disk.state = DiskState.mounting.value

        guest_xml = GuestXML(guest=guest, disk=disk, config=config)

        message = {
            '_object': 'guest',
            'action': 'attach_disk',
            'uuid': uuid,
            'hostname': guest.on_host,
            'xml': guest_xml.get_disk(),
            'passback_parameters': {
                'disk_uuid': disk.uuid,
                'sequence': disk.sequence
            }
        }

        Guest.emit_instruction(message=json.dumps(message))
        disk.update()

        return ret

    except ji.PreviewingError, e:
        return json.loads(e.message)
コード例 #9
0
def r_create():

    args_rules = [
        Rules.CPU.value, Rules.MEMORY.value, Rules.OS_TEMPLATE_ID.value,
        Rules.QUANTITY.value, Rules.REMARK.value, Rules.PASSWORD.value,
        Rules.LEASE_TERM.value
    ]

    try:
        ret = dict()
        ret['state'] = ji.Common.exchange_state(20000)

        ji.Check.previewing(args_rules, request.json)

        config = Config()
        config.id = 1
        config.get()

        os_template = OSTemplate()
        os_template.id = request.json.get('os_template_id')
        if not os_template.exist():
            ret['state'] = ji.Common.exchange_state(40450)
            ret['state']['sub']['zh-cn'] = ''.join(
                [ret['state']['sub']['zh-cn'], ': ',
                 os_template.id.__str__()])
            return ret

        os_template.get()
        # 重置密码的 boot job id 固定为 1
        boot_jobs_id = [1, os_template.boot_job_id]

        boot_jobs, boot_jobs_count = OperateRule.get_by_filter(
            filter_str='boot_job_id:in:' + ','.join(
                ['{0}'.format(boot_job_id)
                 for boot_job_id in boot_jobs_id]).__str__())

        if db.r.scard(app.config['ip_available_set']) < 1:
            ret['state'] = ji.Common.exchange_state(50350)
            return ret

        available_hosts = Guest.get_available_hosts()

        if available_hosts.__len__() == 0:
            ret['state'] = ji.Common.exchange_state(50351)
            return ret

        quantity = request.json.get('quantity')

        while quantity:
            quantity -= 1
            guest = Guest()
            guest.uuid = uuid4().__str__()
            guest.cpu = request.json.get('cpu')
            # 虚拟机内存单位,模板生成方法中已置其为GiB
            guest.memory = request.json.get('memory')
            guest.os_template_id = request.json.get('os_template_id')
            guest.label = ji.Common.generate_random_code(length=8)
            guest.remark = request.json.get('remark', '')

            guest.password = request.json.get('password')
            if guest.password is None or guest.password.__len__() < 1:
                guest.password = ji.Common.generate_random_code(length=16)

            guest.ip = db.r.spop(app.config['ip_available_set'])
            db.r.sadd(app.config['ip_used_set'], guest.ip)

            guest.network = config.vm_network
            guest.manage_network = config.vm_manage_network

            guest.vnc_port = db.r.spop(app.config['vnc_port_available_set'])
            db.r.sadd(app.config['vnc_port_used_set'], guest.vnc_port)

            guest.vnc_password = ji.Common.generate_random_code(length=16)

            disk = Disk()
            disk.uuid = guest.uuid
            disk.remark = guest.label.__str__() + '_SystemImage'
            disk.format = 'qcow2'
            disk.sequence = 0
            disk.size = 0
            disk.path = config.storage_path + '/' + disk.uuid + '.' + disk.format
            disk.guest_uuid = ''
            disk.create()

            guest_xml = GuestXML(guest=guest,
                                 disk=disk,
                                 config=config,
                                 os_type=os_template.os_type)
            guest.xml = guest_xml.get_domain()

            # 在可用计算节点中平均分配任务
            chosen_host = available_hosts[quantity % available_hosts.__len__()]

            guest.on_host = chosen_host['hostname']
            guest.create()

            # 替换占位符为有效内容
            _boot_jobs = copy.deepcopy(boot_jobs)
            for k, v in enumerate(_boot_jobs):
                _boot_jobs[k]['content'] = v['content'].replace('{IP}', guest.ip).\
                    replace('{HOSTNAME}', guest.label). \
                    replace('{PASSWORD}', guest.password). \
                    replace('{NETMASK}', config.netmask).\
                    replace('{GATEWAY}', config.gateway).\
                    replace('{DNS1}', config.dns1).\
                    replace('{DNS2}', config.dns2)

                _boot_jobs[k]['command'] = v['command'].replace('{IP}', guest.ip). \
                    replace('{HOSTNAME}', guest.label). \
                    replace('{PASSWORD}', guest.password). \
                    replace('{NETMASK}', config.netmask). \
                    replace('{GATEWAY}', config.gateway). \
                    replace('{DNS1}', config.dns1). \
                    replace('{DNS2}', config.dns2)

            message = {
                '_object': 'guest',
                'action': 'create',
                'uuid': guest.uuid,
                'storage_mode': config.storage_mode,
                'dfs_volume': config.dfs_volume,
                'hostname': guest.on_host,
                'name': guest.label,
                'template_path': os_template.path,
                'os_type': os_template.os_type,
                'disk': disk.__dict__,
                'xml': guest_xml.get_domain(),
                'boot_jobs': _boot_jobs,
                'passback_parameters': {
                    'boot_jobs_id': boot_jobs_id
                }
            }

            Guest.emit_instruction(
                message=json.dumps(message, ensure_ascii=False))

        return ret

    except ji.PreviewingError, e:
        return json.loads(e.message)
コード例 #10
0
def r_boot(uuids):
    # TODO: 做好关系依赖判断,比如boot不可以对suspend的实例操作。

    args_rules = [Rules.UUIDS.value]

    try:
        ji.Check.previewing(args_rules, {'uuids': uuids})

        guest = Guest()
        for uuid in uuids.split(','):
            guest.uuid = uuid
            guest.get_by('uuid')

        config = Config()
        config.id = 1
        config.get()

        for uuid in uuids.split(','):
            guest.uuid = uuid
            guest.get_by('uuid')

            _, boot_jobs_id = guest.get_boot_jobs()

            boot_jobs = list()

            if boot_jobs_id.__len__() > 0:
                boot_jobs, count = OperateRule.get_by_filter(
                    filter_str='boot_job_id:in:' + ','.join(boot_jobs_id))

            # 替换占位符为有效内容
            for k, v in enumerate(boot_jobs):
                boot_jobs[k]['content'] = v['content'].replace('{IP}', guest.ip). \
                    replace('{HOSTNAME}', guest.label). \
                    replace('{PASSWORD}', guest.password). \
                    replace('{NETMASK}', config.netmask). \
                    replace('{GATEWAY}', config.gateway). \
                    replace('{DNS1}', config.dns1). \
                    replace('{DNS2}', config.dns2)

                boot_jobs[k]['command'] = v['command'].replace('{IP}', guest.ip). \
                    replace('{HOSTNAME}', guest.label). \
                    replace('{PASSWORD}', guest.password). \
                    replace('{NETMASK}', config.netmask). \
                    replace('{GATEWAY}', config.gateway). \
                    replace('{DNS1}', config.dns1). \
                    replace('{DNS2}', config.dns2)

            message = {
                '_object': 'guest',
                'action': 'boot',
                'uuid': uuid,
                'boot_jobs': boot_jobs,
                'hostname': guest.on_host,
                'passback_parameters': {
                    'boot_jobs_id': boot_jobs_id
                }
            }

            Guest.emit_instruction(message=json.dumps(message))

        ret = dict()
        ret['state'] = ji.Common.exchange_state(20000)
        return ret

    except ji.PreviewingError, e:
        return json.loads(e.message)