Esempio n. 1
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})

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

        # 取全部活着的 hosts
        available_hosts = Host.get_available_hosts(nonrandom=None)

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

        available_hosts_mapping_by_node_id = dict()

        for host in available_hosts:
            if host['node_id'] not in available_hosts_mapping_by_node_id:
                available_hosts_mapping_by_node_id[host['node_id']] = 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')

            # 忽略宕机计算节点 上面的 虚拟机 迁移请求
            # 忽略目标计算节点 等于 当前所在 计算节点 的虚拟机 迁移请求
            if guest.node_id not in available_hosts_mapping_by_node_id or \
                    available_hosts_mapping_by_node_id[guest.node_id]['hostname'] == destination_host:
                continue

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

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

        return ret

    except ji.PreviewingError, e:
        return json.loads(e.message)
Esempio n. 2
0
def r_delete(ids):
    ret = dict()
    ret['state'] = ji.Common.exchange_state(20000)

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

    # 取全部活着的 hosts
    available_hosts = Host.get_available_hosts(nonrandom=None)

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

    chosen_host = available_hosts[0]
    node_id = chosen_host['node_id']

    os_template_image = OSTemplateImage()

    # TODO: 加入对,是否有被 Guest 引用的判断
    for _id in ids.split(','):
        os_template_image.id = _id
        os_template_image.get()

    for _id in ids.split(','):
        os_template_image.id = _id
        os_template_image.get()

        # 暂时不支持从计算节点上,删除公共镜像
        if os_template_image.kind == OSTemplateImageKind.public.value:
            os_template_image.delete()
            continue

        elif os_template_image.kind == OSTemplateImageKind.custom.value:
            os_template_image.progress = 254

            message = {
                '_object': 'os_template_image',
                'action': 'delete',
                'storage_mode': config.storage_mode,
                'dfs_volume': config.dfs_volume,
                'template_path': os_template_image.path,
                # uuid 这里没有实际意义,仅仅是为了迁就 JimV-C 的个命令格式
                'uuid': None,
                'node_id': node_id,
                'os_template_image_id': os_template_image.id,
                'passback_parameters': {
                    'id': os_template_image.id
                }
            }

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

            os_template_image.update()

    return ret
Esempio n. 3
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 >= int(size):
            ret['state'] = ji.Common.exchange_state(41257)
            return ret

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

        disk.size = int(size)
        disk.quota(config=config)
        # 将在事件返回层(models/event_processor.py:224 附近),更新数据库中 disk 对象

        message = {
            '_object': 'disk',
            'action': 'resize',
            'uuid': disk.uuid,
            'guest_uuid': disk.guest_uuid,
            'storage_mode': config.storage_mode,
            'size': disk.size,
            'dfs_volume': config.dfs_volume,
            'node_id': disk.node_id,
            'image_path': disk.path,
            'disks': [disk.__dict__],
            'passback_parameters': {'size': disk.size}
        }

        if config.storage_mode in [StorageMode.shared_mount.value, StorageMode.ceph.value,
                                   StorageMode.glusterfs.value]:
            message['node_id'] = Host.get_lightest_host()['node_id']

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

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

        return ret

    except ji.PreviewingError, e:
        return json.loads(e.message)
Esempio n. 4
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,
            'node_id': guest.node_id,
            'xml': guest_xml.get_disk(),
            'passback_parameters': {
                'disk_uuid': disk.uuid
            }
        }

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

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

        return ret

    except ji.PreviewingError, e:
        return json.loads(e.message)
Esempio n. 5
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,
                'node_id': guest.node_id
            }

            Utils.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()
                    SSHKeyGuestMapping.delete_by_filter(filter_str=':'.join(['guest_uuid', 'eq', guest.uuid]))

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

    except ji.PreviewingError, e:
        return json.loads(e.message)
Esempio n. 6
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 not in [DiskState.idle.value, DiskState.dirty.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,
                'node_id': disk.node_id,
                'image_path': disk.path
            }

            if config.storage_mode in [StorageMode.shared_mount.value, StorageMode.ceph.value,
                                       StorageMode.glusterfs.value]:
                message['node_id'] = Host.get_lightest_host()['node_id']

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

        return ret

    except ji.PreviewingError, e:
        return json.loads(e.message)
Esempio n. 7
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)
Esempio n. 8
0
def r_get():

    config = Config()

    try:
        config.id = 1
        config.get()

        ret = dict()
        ret['state'] = ji.Common.exchange_state(20000)
        ret['data'] = config.__dict__
        return ret
    except ji.PreviewingError, e:
        return json.loads(e.message)
Esempio n. 9
0
def r_create():

    args_rules = [
        Rules.JIMV_EDITION.value, Rules.STORAGE_MODE.value,
        Rules.DFS_VOLUME.value, Rules.STORAGE_PATH.value,
        Rules.VM_NETWORK.value, Rules.VM_MANAGE_NETWORK.value,
        Rules.START_IP.value, Rules.END_IP.value, Rules.START_VNC_PORT.value,
        Rules.NETMASK.value, Rules.GATEWAY.value, Rules.DNS1.value,
        Rules.DNS2.value
    ]

    config = Config()
    config.id = 1
    config.jimv_edition = int(request.json.get('jimv_edition', 0))
    config.storage_mode = int(request.json.get('storage_mode', 0))
    config.dfs_volume = request.json.get('dfs_volume', '')
    config.storage_path = request.json.get('storage_path')
    config.vm_network = request.json.get('vm_network')
    config.vm_manage_network = request.json.get('vm_manage_network')
    config.start_ip = request.json.get('start_ip')
    config.end_ip = request.json.get('end_ip')
    config.start_vnc_port = int(request.json.get('start_vnc_port'))
    config.netmask = request.json.get('netmask')
    config.gateway = request.json.get('gateway')
    config.dns1 = request.json.get('dns1')
    config.dns2 = request.json.get('dns2')

    try:
        ji.Check.previewing(args_rules, config.__dict__)

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

        if config.exist():
            ret['state'] = ji.Common.exchange_state(40901)
            return ret

        config.check_ip()
        config.generate_available_ip2set()
        config.generate_available_vnc_port()
        config.create()
        config.update_global_config()

        config.id = 1
        config.get()
        ret['data'] = config.__dict__
        return ret
    except ji.PreviewingError, e:
        return json.loads(e.message)
Esempio n. 10
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)
Esempio n. 11
0
    def run(self):
        logger.info('Starting alcazard with state at {}.', self.state_path)

        if not os.path.isfile(self.db_path):
            print('Missing state DB at {}! Exiting.'.format(self.db_path))
            exit(1)

        DB.init(self.db_path)
        DB.connect()
        self._init_db()

        config = Config.get()
        config.db_path = self.db_path
        config.state_path = self.state_path

        orchestrator = None
        if config.is_fully_configured:
            orchestrator = AlcazarOrchestrator(config)
            orchestrator.attach()

        api = AlcazarAPI(config, orchestrator)
        api.run()

        if orchestrator:
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            loop.run_until_complete(orchestrator.shutdown())

        DB.close()

        logger.info('Graceful shutdown done.')
Esempio n. 12
0
def new_feed_worker(url, favicon_dir, answer_box, manager_box):
    logger.info("Fetching feed... [%s]", url)
    try:
        fetched = fetch_and_parse_feed(url)
        feed_dict, real_url = fetched['feed'], fetched['real_url']
    except FetchingException:
        return answer_box.put(Exception("Error with feed: " + url))

    feed = FeedFromDict(feed_dict, Config.get())
    feed.url = sanitize_url(real_url)  # set the real feed url
    logger.info("Fetching favicon... [%s]", feed.url)
    feed.favicon_path = save_favicon(fetch_favicon(feed.url), favicon_dir)
    db.session.add(feed)
    for e in feed_dict['entries'][::-1]:
        entry = EntryFromDict(e, feed.url)
        entry.feed = feed  # set the corresponding feed
        db.session.add(entry)
    db.session.commit()

    most_recent_entry = feed.entries.order_by(Entry.updated.desc()).first()
    feed.updated = most_recent_entry.updated
    db.session.commit()

    answer_box.put(feed)
    manager_box.put({'type': 'new-deadline-worker', 'feed_id': feed.id})
    manager_box.put({'type': 'refresh-cache', 'feed_id': feed.id})
Esempio n. 13
0
def new_feed_worker(url, favicon_dir, answer_box, manager_box):
    logger.info("Fetching feed... [%s]", url)
    try:
        fetched = fetch_and_parse_feed(url)
        feed_dict, real_url = fetched['feed'], fetched['real_url']
    except FetchingException:
        return answer_box.put(Exception("Error with feed: " + url))

    feed = FeedFromDict(feed_dict, Config.get())
    feed.url = sanitize_url(real_url) # set the real feed url
    logger.info("Fetching favicon... [%s]", feed.url)
    feed.favicon_path = save_favicon(fetch_favicon(feed.url), favicon_dir)
    db.session.add(feed)
    for e in feed_dict['entries'][::-1]:
        entry = EntryFromDict(e, feed.url)
        entry.feed = feed # set the corresponding feed
        db.session.add(entry)
    db.session.commit()

    most_recent_entry = feed.entries.order_by(Entry.updated.desc()).first()
    feed.updated = most_recent_entry.updated
    db.session.commit()

    answer_box.put(feed)
    manager_box.put({'type': 'new-deadline-worker', 'feed_id': feed.id})
    manager_box.put({'type': 'refresh-cache', 'feed_id': feed.id})
Esempio n. 14
0
def config_edit():
    c = Config.get()
    if request.method == 'POST':
        c.twitter_consumer_key = request.form.get('twitter_consumer_key', '')
        c.twitter_consumer_secret = request.form.get('twitter_consumer_secret',
                                                     '')
        c.google_analytics_id = request.form.get('google_analytics_id', '')
        c.put()
        return redirect('/admin/config', code=303)
    return render_template('admin/config/edit.html', config=c)
Esempio n. 15
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')

            disks, _ = Disk.get_by_filter(filter_str=':'.join(['guest_uuid', 'eq', guest.uuid]))

            message = {
                '_object': 'guest',
                'action': 'boot',
                'uuid': uuid,
                'node_id': guest.node_id,
                'passback_parameters': {},
                'disks': disks
            }

            Utils.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)
Esempio n. 16
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,
                'node_id': guest.node_id,
                'storage_mode': config.storage_mode,
                'duri': 'qemu+ssh://' + destination_host + '/system'
            }

            Utils.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)
Esempio n. 17
0
def api_edit_config():
    config = Config.get()
    # update all fields, no checks (TODO)
    config_fields = config.fields_set(exclude_fields=['id', 'password'])
    fields = config_fields & set(request.json.keys())
    for field in fields:
        setattr(config, field, request.json[field])
    # change password if the "pw" field isnt empty
    pw = request.json.get('pw')
    if pw:
        Config.change_password(pw)
    db.session.merge(config)
    db.session.commit()
    Config.refresh_instance()  # not necessary ?
    return jsonify({'msg': 'Success !'})
Esempio n. 18
0
def api_edit_config():
    config = Config.get()
    # update all fields, no checks (TODO)
    config_fields = config.fields_set(exclude_fields=['id', 'password'])
    fields = config_fields & set(request.json.keys())
    for field in fields:
        setattr(config, field, request.json[field])
    # change password if the "pw" field isnt empty
    pw = request.json.get('pw')
    if pw:
        Config.change_password(pw)
    db.session.merge(config)
    db.session.commit()
    Config.refresh_instance()  # not necessary ?
    return jsonify({'msg': 'Success !'})
Esempio n. 19
0
def fetching_work(feed, manager_box):
    fetched = fetch_and_parse_feed(feed.url)
    feed_dict, real_url = fetched['feed'], fetched['real_url']
    if feed.url != real_url:
        logger.warning("©©© Feed url changed from %s to %s", feed.url, real_url)
        feed.url = sanitize_url(real_url)
    logger.info("©©© Updated feed: %s", feed.url)
    feed_changed = update_feed(feed, FeedFromDict(feed_dict, Config.get()))
    any_entry_created = any([
        create_or_update_entry(feed.id, EntryFromDict(e, feed.url))
        for e in feed_dict['entries']
    ])
    db.session.commit()

    if any_entry_created:
        most_recent_entry = feed.entries.order_by(Entry.updated.desc()).first()
        feed.updated = most_recent_entry.updated
        feed.has_news = feed.has_news or feed.highlight_news
        db.session.merge(feed)
        db.session.commit()
        manager_box.put({'type': 'refresh-cache', 'feed_id': feed.id})
Esempio n. 20
0
def fetching_work(feed, manager_box):
    fetched = fetch_and_parse_feed(feed.url)
    feed_dict, real_url = fetched['feed'], fetched['real_url']
    if feed.url != real_url:
        logger.warning("©©© Feed url changed from %s to %s", feed.url,
                       real_url)
        feed.url = sanitize_url(real_url)
    logger.info("©©© Updated feed: %s", feed.url)
    feed_changed = update_feed(feed, FeedFromDict(feed_dict, Config.get()))
    any_entry_created = any([
        create_or_update_entry(feed.id, EntryFromDict(e, feed.url))
        for e in feed_dict['entries']
    ])
    db.session.commit()

    if any_entry_created:
        most_recent_entry = feed.entries.order_by(Entry.updated.desc()).first()
        feed.updated = most_recent_entry.updated
        feed.has_news = feed.has_news or feed.highlight_news
        db.session.merge(feed)
        db.session.commit()
        manager_box.put({'type': 'refresh-cache', 'feed_id': feed.id})
Esempio n. 21
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.node_id != disk.node_id:
                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,
            'node_id': guest.node_id,
            'xml': guest_xml.get_disk(),
            'passback_parameters': {
                'disk_uuid': disk.uuid,
                'sequence': disk.sequence
            },
            'disks': [disk.__dict__]
        }

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

        return ret

    except ji.PreviewingError, e:
        return json.loads(e.message)
Esempio n. 22
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
    ]

    if 'node_id' in request.json:
        args_rules.append(Rules.NODE_ID.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

        node_id = request.json.get('node_id', None)

        # 默认只取可随机分配虚拟机的 hosts
        available_hosts = Host.get_available_hosts(nonrandom=False)

        # 当指定了 host 时,取全部活着的 hosts
        if node_id is not None:
            available_hosts = Host.get_available_hosts(nonrandom=None)

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

        if node_id is not None and node_id not in [
                host['node_id'] for host in available_hosts
        ]:
            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.node_id 由 guest 事件处理机更新。涉及迁移时,其所属 node_id 会变更。参见 models/event_processory.py:111 附近。
            disk.node_id = 0
            disk.quota(config=config)
            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.node_id = chosen_host['node_id']

            if node_id is not None:
                guest.node_id = node_id

            guest.node_id = int(guest.node_id)
            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,
                'node_id': guest.node_id,
                'name': guest.label,
                'template_path': os_template.path,
                'os_type': os_template.os_type,
                'disk': disk.__dict__,
                # disk 将被废弃,由 disks 代替,暂时保留它的目的,是为了保持与 JimV-N 的兼容性
                'disks': [disk.__dict__],
                'xml': guest_xml.get_domain(),
                'boot_jobs': _boot_jobs,
                'passback_parameters': {
                    'boot_jobs_id': boot_jobs_id
                }
            }

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

        return ret

    except ji.PreviewingError, e:
        return json.loads(e.message)
Esempio n. 23
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)

            disks, _ = Disk.get_by_filter(
                filter_str=':'.join(['guest_uuid', 'eq', guest.uuid]))

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

            Utils.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)
Esempio n. 24
0
def api_get_config():
    config = Config.get()
    return jsonify(config.to_dict(exclude_fields=['password', 'id']))
Esempio n. 25
0
def r_convert_to_os_template_image(snapshot_id, disk_uuid):

    args_rules = [
        Rules.SNAPSHOT_ID.value,
        Rules.DISK_UUID.value,
        Rules.LABEL.value
    ]

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

        ji.Check.previewing(args_rules, {'snapshot_id': snapshot_id, 'disk_uuid': disk_uuid,
                                         'label': request.json.get('label')})

        rows, _ = SnapshotDiskMapping.get_by_filter(filter_str=':'.join(['snapshot_id', 'eq', snapshot_id]))

        disks_uuid = list()

        for row in rows:
            disks_uuid.append(row['disk_uuid'])

        if disk_uuid not in disks_uuid:
            ret['state'] = ji.Common.exchange_state(40401)
            ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], u': 未在快照: ',
                                                    snapshot_id, u' 中找到磁盘:', disk_uuid])
            return ret

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

        snapshot = Snapshot()
        os_template_image = OSTemplateImage()
        guest = Guest()
        disk = Disk()

        snapshot.snapshot_id = snapshot_id
        snapshot.get_by('snapshot_id')
        snapshot.progress = 252

        guest.uuid = snapshot.guest_uuid
        guest.get_by('uuid')

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

        os_template_image.id = guest.os_template_image_id
        os_template_image.get()

        image_name = '_'.join([snapshot.snapshot_id, disk.uuid]) + '.' + disk.format

        os_template_image.id = 0
        os_template_image.label = request.json.get('label')
        os_template_image.path = '/'.join([os.path.dirname(os_template_image.path), image_name])
        os_template_image.kind = OSTemplateImageKind.custom.value
        os_template_image.progress = 0
        os_template_image.create_time = ji.Common.tus()

        if os_template_image.exist_by('path'):
            ret['state'] = ji.Common.exchange_state(40901)
            ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], ': ', os_template_image.path])
            return ret

        os_template_image.create()
        os_template_image.get_by('path')

        message = {
            '_object': 'snapshot',
            'action': 'convert',
            'uuid': disk.guest_uuid,
            'snapshot_id': snapshot.snapshot_id,
            'storage_mode': config.storage_mode,
            'dfs_volume': config.dfs_volume,
            'node_id': disk.node_id,
            'snapshot_path': disk.path,
            'template_path': os_template_image.path,
            'os_template_image_id': os_template_image.id,
            'passback_parameters': {'id': snapshot.snapshot_id, 'os_template_image_id': os_template_image.id}
        }

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

        snapshot.update()

        return ret

    except ji.PreviewingError, e:
        return json.loads(e.message)
Esempio n. 26
0
def api_get_config():
    config = Config.get()
    return jsonify(config.to_dict(exclude_fields=['password', 'id']))
Esempio n. 27
0
def r_update_quota():

    config = Config()

    args_rules = [
    ]

    if 'iops_base' in request.json:
        args_rules.append(
            Rules.IOPS_BASE.value,
        )

    if 'iops_pre_unit' in request.json:
        args_rules.append(
            Rules.IOPS_PRE_UNIT.value,
        )

    if 'iops_cap' in request.json:
        args_rules.append(
            Rules.IOPS_CAP.value,
        )

    if 'iops_max' in request.json:
        args_rules.append(
            Rules.IOPS_MAX.value,
        )

    if 'iops_max_length' in request.json:
        args_rules.append(
            Rules.IOPS_MAX_LENGTH.value,
        )

    if 'bps_base' in request.json:
        args_rules.append(
            Rules.BPS_BASE.value,
        )

    if 'bps_pre_unit' in request.json:
        args_rules.append(
            Rules.BPS_PRE_UNIT.value,
        )

    if 'bps_cap' in request.json:
        args_rules.append(
            Rules.BPS_CAP.value,
        )

    if 'bps_max' in request.json:
        args_rules.append(
            Rules.BPS_MAX.value,
        )

    if 'bps_max_length' in request.json:
        args_rules.append(
            Rules.BPS_MAX_LENGTH.value,
        )

    if 'influence_current_guest' in request.json:
        args_rules.append(
            Rules.INFLUENCE_CURRENT_GUEST.value,
        )

    if args_rules.__len__() < 1:
        ret = dict()
        ret['state'] = ji.Common.exchange_state(20000)
        return ret

    try:
        config.id = 1
        ji.Check.previewing(args_rules, request.json)
        config.get()

        config.iops_base = int(request.json.get('iops_base', config.iops_base))
        config.iops_pre_unit = int(request.json.get('iops_pre_unit', config.iops_pre_unit))
        config.iops_cap = int(request.json.get('iops_cap', config.iops_cap))
        config.iops_max = int(request.json.get('iops_max', config.iops_max))
        config.iops_max_length = int(request.json.get('iops_max_length', config.iops_max_length))
        config.bps_base = int(request.json.get('bps_base', config.bps_base))
        config.bps_pre_unit = int(request.json.get('bps_pre_unit', config.bps_pre_unit))
        config.bps_cap = int(request.json.get('bps_cap', config.bps_cap))
        config.bps_max = int(request.json.get('bps_max', config.bps_max))
        config.bps_max_length = int(request.json.get('bps_max_length', config.bps_max_length))

        if request.json.get('influence_current_guest', False):
            disks, _ = Disk.get_all()

            disk = Disk()
            for disk_info in disks:
                disk.id = disk_info['id']
                disk.get()
                disk.quota(config=config)
                disk.update()

                if disk.sequence >= 0:
                    message = {
                        '_object': 'disk',
                        'action': 'quota',
                        'uuid': disk.uuid,
                        'guest_uuid': disk.guest_uuid,
                        'node_id': disk.node_id,
                        'disks': [disk.__dict__]
                    }

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

        config.update()
        config.update_global_config()

        config.get()

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

        return ret
    except ji.PreviewingError, e:
        return json.loads(e.message)
Esempio n. 28
0
def practise(sh, ch_mode, max_index, locale=1):
    sh.menu.dicts = QUIZMODES

    sh.header.mode = WELECOMEMODES[ch_mode]
    # 第二层循环
    # 临时存放答案
    answer = ''
    flag = False  # 对于ch_mode为 U 和 R 时,当flag等于True时,表示状态需要重置,更新题目
    while True:
        with db_session:

            if ch_mode == 'Q':
                now_index = Config.get(key='now_index')
                if not now_index:
                    now_index = Config(key='now_index', value=1)
                index = now_index.value
            if ch_mode == 'U':
                mark_index = Config.get(key='mark_index')
                if not mark_index:
                    mark_index = Config(key='mark_index', value=1)
                index = mark_index.value
                if flag == True:
                    quiz = Quiz.select(lambda q: q.mark == True)[:][0]
                    index = quiz.id
                    mark_index.value = quiz.id
                    flag = False
                sh.header.sums = count(q for q in Quiz if q.mark == True)

            if ch_mode == 'R':
                rand_index = Config.get(key='rand_index')
                if not rand_index:
                    rand_index = Config(key='rand_index', value=1)
                index = rand_index.value
                if flag == True:
                    rand_index.value = randint(1, max_index)
                    index = rand_index.value
                    flag = False

            if ch_mode == 'W':
                ch_mode = 'Q'
                now_index = Config.get(key='now_index')
                now_index.value = locale
                index = locale

            sh.header.index = index
            # 显示题目
            quiz = Quiz.get(id=index)

            star = ''
            if quiz.mark:
                star = '★'
            sh.main.title = '{} {}\n\n{}'.format(
                star, quiz.name,
                '\n'.join(sorted([x.name for x in quiz.items])))

            sh.header.kind = quiz.kind

            sh.show()
            # 用于暂停
            ch = getwch().upper()

            # 正确答案
            quiz_answer = quiz.answer
            if quiz_answer == '√':
                quiz_answer = 'A'
            if quiz_answer == '×':
                quiz_answer = 'B'

            if ch in 'ABCDEFGH':
                if ch not in answer:
                    answer = '{}{}'.format(answer, ch)
                    answer_sort = ''.join(sorted(answer))
                    if answer_sort == quiz_answer:
                        sh.state.title = '{}答案[{}]正确{}'.format(
                            Fore.GREEN, answer_sort, Fore.RESET)
                        Done(quiz=quiz,
                             answer=answer_sort,
                             state=True,
                             created=datetime.now())  # 记录做题
                        continue
                    sh.state.title = '{}答案[{}]错误{}'.format(
                        Fore.RED, answer_sort, Fore.RESET)
                    Done(quiz=quiz, answer=answer_sort,
                         created=datetime.now())  # 记录做题
                    continue

            if ch == 'Q':
                sh.state.title = '正确答案[{}]'.format(quiz_answer)

            if ch == 'S':
                answer_trans = lambda x: Fore.GREEN + '正确' + Fore.RESET if x else Fore.RED + '错误' + Fore.RESET

                result = [
                    '{}\t|\t{}\t|\t{}'.format(
                        x.created.strftime('%Y-%m-%d %H:%M:%S'), x.answer,
                        answer_trans(x.state)) for x in quiz.dones
                ]
                result_s = [x.state for x in quiz.dones]
                sh.quote.title = '[{}]\n\n{}\n\n<{}>\n\n[该题总计练习{}次,正确{}次,错误{}次]\n\n{}'.format(
                    quiz.source, quiz.memo,
                    Fore.YELLOW + quiz.other + Fore.RESET, len(result_s),
                    result_s.count(True), result_s.count(False),
                    '\n'.join(sorted([x for x in result])))

            if ch == 'M':
                if quiz.mark:
                    quiz.mark = False
                else:
                    quiz.mark = True

            if ch == 'R':
                sh.state.title = ''
                sh.quote.title = ''
                answer = ''

            if ch in ' PL\r':
                ch = ch_mode
                sh.state.title = ''
                sh.quote.title = ''
                answer = ''
                if ch_mode == 'R':
                    rand_index.value = randint(1, max_index)
                    flag = True  #重置状态
                    break
                if ch_mode == 'U':
                    u_list = Quiz.select(lambda q: q.mark == True)[:]
                    if len(u_list) >= 1:
                        i = randint(0, len(u_list) - 1)
                        mark_index.value = u_list[i].id
                    flag = True  # 重置状态
                    break
                # Q顺序模式
                now_index.value = now_index.value + 1
                if now_index.value > max_index:
                    now_index.value = max_index
                break

            if ch in 'ZK':
                ch = ch_mode
                sh.state.title = ''
                sh.quote.title = ''
                answer = ''
                if ch_mode == 'R':
                    rand_index.value = randint(1, max_index)
                    flag = True  # 重置状态
                    break
                if ch_mode == 'U':
                    u_list = Quiz.select(lambda q: q.mark == True)[:]
                    i = randint(0, len(u_list) - 1)
                    mark_index.value = u_list[i].id
                    flag = True  # 重置状态
                    break
                # Q
                now_index.value = now_index.value - 1
                if now_index.value < 1:
                    now_index.value = 1
                break

            if ch == 'T':
                sh.state.title = ''
                sh.quote.title = ''
                sh.header.sums = ''
                answer = ''
                break

    return ch
Esempio n. 29
0
            if ch == 'T':
                sh.state.title = ''
                sh.quote.title = ''
                sh.header.sums = ''
                answer = ''
                break

    return ch


if __name__ == '__main__':
    init(autoreset=True)  # 颜色自动重置,在这里基本没用

    # 初始化参数
    with db_session:
        max_index = Config.get(key='max_index')
        if not max_index:
            max_index = Config(key='max_index', value=1)
        index = max_index.value
    # 初始化界面生成器
    show = Show()
    show.header = Header()
    show.menu = Menu()
    show.main = Main()
    show.state = State()
    show.quote = Quote()

    ch = 'T'
    # 进入第一层选择旬换
    while True:
        if ch not in 'XUQRW':
Esempio n. 30
0
def r_create():

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

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

    # 非共享模式,必须指定 node_id
    if config.storage_mode not in [StorageMode.shared_mount.value, StorageMode.ceph.value,
                                   StorageMode.glusterfs.value]:
        args_rules.append(
            Rules.NODE_ID.value
        )

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

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

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

        # 如果是共享模式,则让负载最轻的计算节点去创建磁盘
        if config.storage_mode in [StorageMode.shared_mount.value, StorageMode.ceph.value,
                                   StorageMode.glusterfs.value]:
            available_hosts = Host.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__()]
            request.json['node_id'] = chosen_host['node_id']

        node_id = request.json['node_id']

        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.node_id = int(node_id)
            disk.sequence = -1
            disk.format = 'qcow2'
            disk.path = config.storage_path + '/' + disk.uuid + '.' + disk.format
            disk.quota(config=config)

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

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

            disk.create()

        return ret

    except ji.PreviewingError, e:
        return json.loads(e.message)
Esempio n. 31
0
def r_create():

    args_rules = [
        Rules.JIMV_EDITION.value,
        Rules.STORAGE_MODE.value,
        Rules.DFS_VOLUME.value,
        Rules.STORAGE_PATH.value,
        Rules.VM_NETWORK.value,
        Rules.VM_MANAGE_NETWORK.value,
        Rules.START_IP.value,
        Rules.END_IP.value,
        Rules.START_VNC_PORT.value,
        Rules.NETMASK.value,
        Rules.GATEWAY.value,
        Rules.DNS1.value,
        Rules.DNS2.value,
        Rules.IOPS_BASE.value,
        Rules.IOPS_PRE_UNIT.value,
        Rules.IOPS_CAP.value,
        Rules.IOPS_MAX.value,
        Rules.IOPS_MAX_LENGTH.value,
        Rules.BPS_BASE.value,
        Rules.BPS_PRE_UNIT.value,
        Rules.BPS_CAP.value,
        Rules.BPS_MAX.value,
        Rules.BPS_MAX_LENGTH.value
    ]

    config = Config()
    config.id = 1
    config.jimv_edition = int(request.json.get('jimv_edition', 0))
    config.storage_mode = int(request.json.get('storage_mode', 0))
    config.dfs_volume = request.json.get('dfs_volume', '')
    config.storage_path = request.json.get('storage_path')
    config.vm_network = request.json.get('vm_network')
    config.vm_manage_network = request.json.get('vm_manage_network')
    config.start_ip = request.json.get('start_ip')
    config.end_ip = request.json.get('end_ip')
    config.start_vnc_port = int(request.json.get('start_vnc_port', 15900))
    config.netmask = request.json.get('netmask')
    config.gateway = request.json.get('gateway')
    config.dns1 = request.json.get('dns1')
    config.dns2 = request.json.get('dns2')
    config.iops_base = int(request.json.get('iops_base', 1000))
    config.iops_pre_unit = int(request.json.get('iops_pre_unit', 1))
    config.iops_cap = int(request.json.get('iops_cap', 2000))
    config.iops_max = int(request.json.get('iops_max', 3000))
    config.iops_max_length = int(request.json.get('iops_max_length', 20))
    # 200 MiB
    config.bps_base = int(request.json.get('bps_base', 1024 * 1024 * 200))
    # 0.3 MiB
    config.bps_pre_unit = int(request.json.get('bps_pre_unit', 1024 * 1024 * 0.3))
    # 500 MiB
    config.bps_cap = int(request.json.get('bps_cap', 1024 * 1024 * 500))
    # 1 GiB
    config.bps_max = int(request.json.get('bps_max', 1024 * 1024 * 1024))
    config.bps_max_length = int(request.json.get('bps_max_length', 10))

    try:
        ji.Check.previewing(args_rules, config.__dict__)

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

        if config.exist():
            ret['state'] = ji.Common.exchange_state(40901)
            return ret

        config.check_ip()
        config.generate_available_ip2set()
        config.generate_available_vnc_port()
        config.create()
        config.update_global_config()

        config.id = 1
        config.get()
        ret['data'] = config.__dict__
        return ret
    except ji.PreviewingError, e:
        return json.loads(e.message)
Esempio n. 32
0
def r_create():

    args_rules = [
        Rules.CPU.value,
        Rules.MEMORY.value,
        Rules.BANDWIDTH.value,
        Rules.BANDWIDTH_UNIT.value,
        Rules.OS_TEMPLATE_IMAGE_ID.value,
        Rules.QUANTITY.value,
        Rules.REMARK.value,
        Rules.PASSWORD.value,
        Rules.LEASE_TERM.value
    ]

    if 'node_id' in request.json:
        args_rules.append(
            Rules.NODE_ID.value
        )

    if 'ssh_keys_id' in request.json:
        args_rules.append(
            Rules.SSH_KEYS_ID.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_image = OSTemplateImage()
        os_template_profile = OSTemplateProfile()

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

        os_template_image.get()
        os_template_profile.id = os_template_image.os_template_profile_id
        os_template_profile.get()

        os_template_initialize_operates, os_template_initialize_operates_count = \
            OSTemplateInitializeOperate.get_by_filter(
                filter_str='os_template_initialize_operate_set_id:eq:' +
                           os_template_profile.os_template_initialize_operate_set_id.__str__())

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

        node_id = request.json.get('node_id', None)

        # 默认只取可随机分配虚拟机的 hosts
        available_hosts = Host.get_available_hosts(nonrandom=False)

        # 当指定了 host 时,取全部活着的 hosts
        if node_id is not None:
            available_hosts = Host.get_available_hosts(nonrandom=None)

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

        available_hosts_mapping_by_node_id = dict()

        for host in available_hosts:
            if host['node_id'] not in available_hosts_mapping_by_node_id:
                available_hosts_mapping_by_node_id[host['node_id']] = host

        if node_id is not None and node_id not in available_hosts_mapping_by_node_id:
            ret['state'] = ji.Common.exchange_state(50351)
            return ret

        ssh_keys_id = request.json.get('ssh_keys_id', list())
        ssh_keys = list()
        ssh_key_guest_mapping = SSHKeyGuestMapping()

        if ssh_keys_id.__len__() > 0:
            rows, _ = SSHKey.get_by_filter(
                filter_str=':'.join(['id', 'in', ','.join(_id.__str__() for _id in ssh_keys_id)]))

            for row in rows:
                ssh_keys.append(row['public_key'])

        bandwidth = request.json.get('bandwidth')
        bandwidth_unit = request.json.get('bandwidth_unit')

        if bandwidth_unit == 'k':
            bandwidth = bandwidth * 1000

        elif bandwidth_unit == 'm':
            bandwidth = bandwidth * 1000 ** 2

        elif bandwidth_unit == 'g':
            bandwidth = bandwidth * 1000 ** 3

        else:
            ret = dict()
            ret['state'] = ji.Common.exchange_state(41203)
            raise ji.PreviewingError(json.dumps(ret, ensure_ascii=False))

        # http://man7.org/linux/man-pages/man8/tc.8.html
        # 如果带宽大于 tc 所控最大速率,则置其为无限带宽
        # 34359738360 等于 tc 最大可控字节速率,换算出的比特位
        if bandwidth > 34359738360:
            bandwidth = 0

        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.bandwidth = bandwidth
            guest.os_template_image_id = request.json.get('os_template_image_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.node_id 由 guest 事件处理机更新。涉及迁移时,其所属 node_id 会变更。参见 @models/event_processory.py:111 附近。
            disk.node_id = 0
            disk.quota(config=config)
            disk.create()

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

            else:
                chosen_host = available_hosts_mapping_by_node_id[node_id]

            guest.node_id = chosen_host['node_id']

            guest_xml = GuestXML(host=chosen_host, guest=guest, disk=disk, config=config,
                                 os_type=os_template_profile.os_type)
            guest.xml = guest_xml.get_domain()

            guest.node_id = int(guest.node_id)
            guest.create()

            ssh_key_guest_mapping.guest_uuid = guest.uuid

            if ssh_keys_id.__len__() > 0:
                for ssh_key_id in ssh_keys_id:
                    ssh_key_guest_mapping.ssh_key_id = ssh_key_id
                    ssh_key_guest_mapping.create()

            # 替换占位符为有效内容
            _os_template_initialize_operates = copy.deepcopy(os_template_initialize_operates)
            for k, v in enumerate(_os_template_initialize_operates):
                _os_template_initialize_operates[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). \
                    replace('{SSH-KEY}', '\n'.join(ssh_keys))

                _os_template_initialize_operates[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). \
                    replace('{SSH-KEY}', '\n'.join(ssh_keys))

            message = {
                '_object': 'guest',
                'action': 'create',
                'uuid': guest.uuid,
                'storage_mode': config.storage_mode,
                'dfs_volume': config.dfs_volume,
                'node_id': guest.node_id,
                'name': guest.label,
                'template_path': os_template_image.path,
                'os_type': os_template_profile.os_type,
                'disks': [disk.__dict__],
                'xml': guest_xml.get_domain(),
                'os_template_initialize_operates': _os_template_initialize_operates,
                'passback_parameters': {}
            }

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

        return ret

    except ji.PreviewingError, e:
        return json.loads(e.message)
Esempio n. 33
0
def r_update():

    config = Config()

    args_rules = []

    if 'jimv_edition' in request.json:
        args_rules.append(Rules.JIMV_EDITION.value, )

    if 'storage_mode' in request.json:
        args_rules.append(Rules.STORAGE_MODE.value, )

    if 'dfs_volume' in request.json:
        args_rules.append(Rules.DFS_VOLUME.value, )

    if 'storage_path' in request.json:
        args_rules.append(Rules.STORAGE_PATH.value, )

    if 'vm_network' in request.json:
        args_rules.append(Rules.VM_NETWORK.value, )

    if 'vm_manage_network' in request.json:
        args_rules.append(Rules.VM_MANAGE_NETWORK.value, )

    if 'start_ip' in request.json:
        args_rules.append(Rules.START_IP.value, )

    if 'end_ip' in request.json:
        args_rules.append(Rules.END_IP.value, )

    if 'start_vnc_port' in request.json:
        args_rules.append(Rules.START_VNC_PORT.value, )

    if 'netmask' in request.json:
        args_rules.append(Rules.NETMASK.value, )

    if 'gateway' in request.json:
        args_rules.append(Rules.GATEWAY.value, )

    if 'dns1' in request.json:
        args_rules.append(Rules.DNS1.value, )

    if 'dns2' in request.json:
        args_rules.append(Rules.DNS2.value, )

    if args_rules.__len__() < 1:
        ret = dict()
        ret['state'] = ji.Common.exchange_state(20000)
        return ret

    try:
        config.id = 1
        ji.Check.previewing(args_rules, request.json)
        config.get()

        config.jimv_edition = request.json.get('jimv_edition',
                                               config.jimv_edition)
        config.storage_mode = request.json.get('storage_mode',
                                               config.storage_mode)
        config.dfs_volume = request.json.get('dfs_volume', config.dfs_volume)
        config.storage_path = request.json.get('storage_path',
                                               config.storage_path)
        config.vm_network = request.json.get('vm_network', config.vm_network)
        config.vm_manage_network = request.json.get('vm_manage_network',
                                                    config.vm_manage_network)
        config.start_ip = request.json.get('start_ip', config.start_ip)
        config.end_ip = request.json.get('end_ip', config.end_ip)
        config.start_vnc_port = request.json.get('start_vnc_port',
                                                 config.start_vnc_port)
        config.netmask = request.json.get('netmask', config.netmask)
        config.gateway = request.json.get('gateway', config.gateway)
        config.dns1 = request.json.get('dns1', config.dns1)
        config.dns2 = request.json.get('dns2', config.dns2)

        config.check_ip()
        config.generate_available_ip2set()
        config.generate_available_vnc_port()
        config.update()
        config.update_global_config()

        config.get()

        ret = dict()
        ret['state'] = ji.Common.exchange_state(20000)
        ret['data'] = config.__dict__
        return ret
    except ji.PreviewingError, e:
        return json.loads(e.message)
Esempio n. 34
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)