def r_update(uuid): args_rules = [Rules.UUID.value] if 'remark' in request.json: args_rules.append(Rules.REMARK.value) if args_rules.__len__() < 2: ret = dict() ret['state'] = ji.Common.exchange_state(20000) return ret request.json['uuid'] = uuid try: ji.Check.previewing(args_rules, request.json) disk = Disk() disk.uuid = uuid disk.get_by('uuid') disk.remark = request.json.get('remark', disk.remark) disk.update() disk.get() ret = dict() ret['state'] = ji.Common.exchange_state(20000) ret['data'] = disk.__dict__ return ret except ji.PreviewingError, e: return json.loads(e.message)
def get(self): host = self.request.get("host") if not host: self.response.out.write(u""""host" not given.""") self.response.set_status(405) return new_disk = Disk(host = host) new_disk.put() self.response.out.write(u"OK. New host appended: %s" %new_disk.host)
def api_disks(): ''' Get all disk. Request url [GET /api/disks] Response: id: disk identity slot: disk slot on machine device: disk device name name: disk name capacity: disk capacity(Bytes) state: 0-normal; 1-abnormal ''' disks_cur = yield from disk_list() disk_ids = [disk.id for disk in disks_cur] for disk in disks_cur: r = yield from Disk.find(disk.id) if r is None: if disk.capacity == 0: disk.state = _disk_abnormal_state yield from disk.save() disks_in_db = yield from Disk.findall() if disks_in_db: for disk in disks_in_db: d = [disk_cur for disk_cur in disks_cur if disk_cur.id == disk.id] if (len(d) != 0): disk_cur = d[0] if disk.state == _disk_abnormal_state: disk.state = _disk_normal_state yield from disk.update() if disk.device != disk_cur.device: disk.device = disk_cur.device yield from disk.update() else: disk.state = _disk_abnormal_state yield from disk.update() else: if disk.capacity == 0: disk.state = _disk_abnormal_state yield from disk.update() else: # disk.state = _disk_abnormal_state; yield from disk.remove(); # yield from disk.update() return dict(retcode=0, disks=disks_in_db)
def api_disks(): ''' Get all disk. Request url [GET /api/disks] Response: id: disk identity slot: disk slot on machine device: disk device name name: disk name capacity: disk capacity(Bytes) state: 0-normal; 1-abnormal ''' disks_cur = yield from disk_list() disk_ids = [disk.id for disk in disks_cur] for disk in disks_cur: r = yield from Disk.find(disk.id) if r is None: if disk.capacity == 0: disk.state = _disk_abnormal_state yield from disk.save() disks_in_db = yield from Disk.findall() if disks_in_db: for disk in disks_in_db: d = [disk_cur for disk_cur in disks_cur if disk_cur.id == disk.id] if (len(d) != 0): disk_cur = d[0] if disk.state == _disk_abnormal_state: disk.state = _disk_normal_state yield from disk.update() if disk.device != disk_cur.device: disk.device = disk_cur.device yield from disk.update() else: disk.state = _disk_abnormal_state yield from disk.update() else: if disk.capacity == 0: disk.state = _disk_abnormal_state yield from disk.update() else: # disk.state = _disk_abnormal_state; yield from disk.remove() # yield from disk.update() return dict(retcode=0, disks=disks_in_db)
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)
def r_distribute_count(): from models import Disk rows, count = Disk.get_all() ret = dict() ret['state'] = ji.Common.exchange_state(20000) ret['data'] = { 'kind': { 'system': 0, 'data_mounted': 0, 'data_idle': 0 }, 'total_size': 0, 'disks': rows.__len__() } for disk in rows: if disk['sequence'] == 0: ret['data']['kind']['system'] += 1 elif disk['sequence'] < 0: ret['data']['kind']['data_idle'] += 1 else: ret['data']['kind']['data_mounted'] += 1 ret['data']['total_size'] += disk['size'] return ret
def r_force_reboot(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') disks, _ = Disk.get_by_filter( filter_str=':'.join(['guest_uuid', 'eq', guest.uuid])) message = { '_object': 'guest', 'action': 'force_reboot', 'uuid': uuid, 'node_id': guest.node_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)
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)
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)
def get(self): key = self.request.get("key") if not key: self.response.out.write(u""""key" not given.""") self.response.set_status(405) return disk = Disk.get(db.Key(key)) disk.delete() self.response.out.write(u"OK. host removed.")
def get(self): template_file = {} disks = Disk.all().fetch(10000) total = Disk.total for d in disks: d.free_str = approximate_size(total - d.used) d.used_str = approximate_size(d.used) template_file["disks"] = disks self.render("views/admin.html", template_file)
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)
def disk_list(): try: output = subprocess.check_output([grgrant_prog, grdisk_prog, 'list'], universal_newlines=True) lines = output.split(os.linesep) disks = [] for line in lines: fields = line.split(' ') if len(fields) < 8: return disks if not fields[1].startswith('disk') or fields[0] in _exclude_slot: continue slot = get_slot(fields[0]) disk = Disk(id=fields[3], device=fields[2], name=fields[5], slot=slot) disk.capacity=fields[6]; disks.append(disk) return disks except subprocess.CalledProcessError as e: logging.exception(e) pass
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)
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)
def post_smart_report(request): server = request.DATA.get('server') body = request.DATA.get('body') unix_device = request.DATA.get('unix_device') server = Server.objects.get(name=server) parser = SmartParse(body,'6.2') try: server = Server.objects.get(name=server) parser = SmartParse(body,'6.2') try: disk = Disk.objects.get(pk=parser.get_pk()) except ObjectDoesNotExist, e: disk = Disk(pk=parser.get_pk(),server=server,unix_device=unix_device,**parser.info) disk.save() SM = SmartReport(disk=disk,server=server,firmware=parser.info['firmware'],text=body,parsed=datetime.now(),ip=request.META['REMOTE_ADDR']) SM.save() for attr in parser.attrs: a = Attribute(smart_report=SM,name=attr['name'],value=attr['value'],worst=attr['worst'],thresh=attr['thresh'],failed=attr['failed'],raw_value=attr['raw_value']) a.save() # Disk.objects.create() return Response({'info':parser.info,'attrs':parser.attrs,'pk':parser.get_pk()})
def disk_list(): try: output = subprocess.check_output([grgrant_prog, grdisk_prog, 'list'], universal_newlines=True) lines = output.split(os.linesep) disks = [] for line in lines: fields = line.split(' ') if len(fields) < 8: return disks if not fields[1].startswith('disk') or fields[0] in _exclude_slot: continue slot = get_slot(fields[0]) disk = Disk(id=fields[3], device=fields[2], name=fields[5], slot=slot) disk.capacity = fields[6] disks.append(disk) return disks except subprocess.CalledProcessError as e: logging.exception(e) pass
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)
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)
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)
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)
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)
def response_processor(cls): _object = cls.message['message']['_object'] action = cls.message['message']['action'] uuid = cls.message['message']['uuid'] state = cls.message['type'] data = cls.message['message']['data'] node_id = cls.message['node_id'] if _object == 'guest': if action == 'create': if state == ResponseState.success.value: # 系统盘的 UUID 与其 Guest 的 UUID 相同 cls.disk.uuid = uuid cls.disk.get_by('uuid') cls.disk.guest_uuid = uuid cls.disk.state = DiskState.mounted.value # disk_info['virtual-size'] 的单位为Byte,需要除以 1024 的 3 次方,换算成单位为 GB 的值 cls.disk.size = data['disk_info']['virtual-size'] / (1024** 3) cls.disk.update() else: cls.guest.uuid = uuid cls.guest.get_by('uuid') cls.guest.status = GuestState.dirty.value cls.guest.update() elif action == 'migrate': pass elif action == 'delete': if state == ResponseState.success.value: cls.config.get() cls.guest.uuid = uuid cls.guest.get_by('uuid') if IP(cls.config.start_ip).int() <= IP( cls.guest.ip).int() <= IP(cls.config.end_ip).int(): if db.r.srem(app.config['ip_used_set'], cls.guest.ip): db.r.sadd(app.config['ip_available_set'], cls.guest.ip) if (cls.guest.vnc_port - cls.config.start_vnc_port) <= \ (IP(cls.config.end_ip).int() - IP(cls.config.start_ip).int()): if db.r.srem(app.config['vnc_port_used_set'], cls.guest.vnc_port): db.r.sadd(app.config['vnc_port_available_set'], cls.guest.vnc_port) cls.guest.delete() # TODO: 加入是否删除使用的数据磁盘开关,如果为True,则顺便删除使用的磁盘。否则解除该磁盘被使用的状态。 cls.disk.uuid = uuid cls.disk.get_by('uuid') cls.disk.delete() cls.disk.update_by_filter( { 'guest_uuid': '', 'sequence': -1, 'state': DiskState.idle.value }, filter_str='guest_uuid:eq:' + cls.guest.uuid) SSHKeyGuestMapping.delete_by_filter(filter_str=':'.join( ['guest_uuid', 'eq', cls.guest.uuid])) elif action == 'reset_password': if state == ResponseState.success.value: cls.guest.uuid = uuid cls.guest.get_by('uuid') cls.guest.password = cls.message['message'][ 'passback_parameters']['password'] cls.guest.update() elif action == 'attach_disk': cls.disk.uuid = cls.message['message']['passback_parameters'][ 'disk_uuid'] cls.disk.get_by('uuid') if state == ResponseState.success.value: cls.disk.guest_uuid = uuid cls.disk.sequence = cls.message['message'][ 'passback_parameters']['sequence'] cls.disk.state = DiskState.mounted.value cls.disk.update() elif action == 'detach_disk': cls.disk.uuid = cls.message['message']['passback_parameters'][ 'disk_uuid'] cls.disk.get_by('uuid') if state == ResponseState.success.value: cls.disk.guest_uuid = '' cls.disk.sequence = -1 cls.disk.state = DiskState.idle.value cls.disk.update() elif action == 'boot': if state == ResponseState.success.value: pass elif _object == 'disk': if action == 'create': cls.disk.uuid = uuid cls.disk.get_by('uuid') cls.disk.node_id = node_id if state == ResponseState.success.value: cls.disk.state = DiskState.idle.value else: cls.disk.state = DiskState.dirty.value cls.disk.update() elif action == 'resize': if state == ResponseState.success.value: cls.config.get() cls.disk.uuid = uuid cls.disk.get_by('uuid') cls.disk.size = cls.message['message'][ 'passback_parameters']['size'] cls.disk.quota(config=cls.config) cls.disk.update() elif action == 'delete': cls.disk.uuid = uuid cls.disk.get_by('uuid') cls.disk.delete() elif _object == 'snapshot': if action == 'create': cls.snapshot.id = cls.message['message'][ 'passback_parameters']['id'] cls.snapshot.get() if state == ResponseState.success.value: cls.snapshot.snapshot_id = data['snapshot_id'] cls.snapshot.parent_id = data['parent_id'] cls.snapshot.xml = data['xml'] cls.snapshot.progress = 100 cls.snapshot.update() disks, _ = Disk.get_by_filter(filter_str='guest_uuid:eq:' + cls.snapshot.guest_uuid) for disk in disks: cls.snapshot_disk_mapping.snapshot_id = cls.snapshot.snapshot_id cls.snapshot_disk_mapping.disk_uuid = disk['uuid'] cls.snapshot_disk_mapping.create() else: cls.snapshot.progress = 255 cls.snapshot.update() if action == 'delete': if state == ResponseState.success.value: cls.snapshot.id = cls.message['message'][ 'passback_parameters']['id'] cls.snapshot.get() # 更新子快照的 parent_id 为,当前快照的 parent_id。因为当前快照已被删除。 Snapshot.update_by_filter( {'parent_id': cls.snapshot.parent_id}, filter_str='parent_id:eq:' + cls.snapshot.snapshot_id) SnapshotDiskMapping.delete_by_filter(filter_str=':'.join( ['snapshot_id', 'eq', cls.snapshot.snapshot_id])) cls.snapshot.delete() else: pass if action == 'revert': # 不论恢复成功与否,都使快照恢复至正常状态。 cls.snapshot.id = cls.message['message'][ 'passback_parameters']['id'] cls.snapshot.get() cls.snapshot.progress = 100 cls.snapshot.update() if action == 'convert': cls.snapshot.snapshot_id = cls.message['message'][ 'passback_parameters']['id'] cls.snapshot.get_by('snapshot_id') cls.snapshot.progress = 100 cls.snapshot.update() cls.os_template_image.id = cls.message['message'][ 'passback_parameters']['os_template_image_id'] cls.os_template_image.get() if state == ResponseState.success.value: cls.os_template_image.progress = 100 else: cls.os_template_image.progress = 255 cls.os_template_image.update() elif _object == 'os_template_image': if action == 'delete': cls.os_template_image.id = cls.message['message'][ 'passback_parameters']['id'] cls.os_template_image.get() if state == ResponseState.success.value: cls.os_template_image.delete() else: pass else: pass
#!/usr/bin/env python # -*- coding: utf-8 -*- from models import Disk, Log list = Disk.select().where(Disk.id >= 1559, Disk.avail_type != "Draft") print "<Table>" print "<tr>\ <th>#</th>\ <th>Call Number</th>\ <th>Title</th>\ <th>Price(HKD)</th>\ <th>Purchase Date</th>\ </tr>" counter = 1 for disk in list: print "<tr>\ <td>%d</td>\ <td>%s</td>\ <td>%s/%s<\td>\ <td></td>\ <td>%s</td>\ <tr>"%( counter, disk.get_callnumber(), disk.title_en, disk.title_ch, Log.select().where( Log.log_type == 'create',
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)
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)
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)
def r_update(uuids): ret = dict() ret['state'] = ji.Common.exchange_state(20000) ret['data'] = list() args_rules = [ Rules.UUIDS.value ] if 'remark' in request.json: args_rules.append( Rules.REMARK.value ) if 'iops' in request.json: args_rules.append( Rules.IOPS.value ) if 'iops_rd' in request.json: args_rules.append( Rules.IOPS_RD.value ) if 'iops_wr' in request.json: args_rules.append( Rules.IOPS_WR.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' in request.json: args_rules.append( Rules.BPS.value ) if 'bps_rd' in request.json: args_rules.append( Rules.BPS_RD.value ) if 'bps_wr' in request.json: args_rules.append( Rules.BPS_WR.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 args_rules.__len__() < 2: return ret request.json['uuids'] = uuids need_update_quota = False need_update_quota_parameters = ['iops', 'iops_rd', 'iops_wr', 'iops_max', 'iops_max_length', 'bps', 'bps_rd', 'bps_wr', 'bps_max', 'bps_max_length'] if filter(lambda p: p in request.json, need_update_quota_parameters).__len__() > 0: need_update_quota = True try: ji.Check.previewing(args_rules, request.json) disk = Disk() # 检测所指定的 UUDIs 磁盘都存在 for uuid in uuids.split(','): disk.uuid = uuid disk.get_by('uuid') for uuid in uuids.split(','): disk.uuid = uuid disk.get_by('uuid') disk.remark = request.json.get('remark', disk.remark) disk.iops = request.json.get('iops', disk.iops) disk.iops_rd = request.json.get('iops_rd', disk.iops_rd) disk.iops_wr = request.json.get('iops_wr', disk.iops_wr) disk.iops_max = request.json.get('iops_max', disk.iops_max) disk.iops_max_length = request.json.get('iops_max_length', disk.iops_max_length) disk.bps = request.json.get('bps', disk.bps) disk.bps_rd = request.json.get('bps_rd', disk.bps_rd) disk.bps_wr = request.json.get('bps_wr', disk.bps_wr) disk.bps_max = request.json.get('bps_max', disk.bps_max) disk.bps_max_length = request.json.get('bps_max_length', disk.bps_max_length) disk.update() disk.get() if disk.sequence >= 0 and need_update_quota: 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)) ret['data'].append(disk.__dict__) return ret except ji.PreviewingError, e: return json.loads(e.message)
class EventProcessor(object): message = None log = Log() guest = Guest() guest_migrate_info = GuestMigrateInfo() disk = Disk() config = Config() cpu_memory = CPUMemory() traffic = Traffic() disk_io = DiskIO() host_cpu_memory = HostCPUMemory() host_traffic = HostTraffic() host_disk_usage_io = HostDiskUsageIO() @classmethod def log_processor(cls): cls.log.set(type=cls.message['type'], timestamp=cls.message['timestamp'], host=cls.message['host'], message=cls.message['message'], full_message='' if cls.message['message'].__len__() < 255 else cls.message['message']) cls.log.create() @classmethod def guest_event_processor(cls): cls.guest.uuid = cls.message['message']['uuid'] cls.guest.get_by('uuid') cls.guest.on_host = cls.message['host'] last_status = cls.guest.status cls.guest.status = cls.message['type'] if cls.message['type'] == GuestState.update.value: # 更新事件不改变 Guest 的状态 cls.guest.status = last_status cls.guest.xml = cls.message['message']['xml'] elif cls.guest.status == GuestState.migrating.value: try: cls.guest_migrate_info.uuid = cls.guest.uuid cls.guest_migrate_info.get_by('uuid') cls.guest_migrate_info.type = cls.message['message'][ 'migrating_info']['type'] cls.guest_migrate_info.time_elapsed = cls.message['message'][ 'migrating_info']['time_elapsed'] cls.guest_migrate_info.time_remaining = cls.message['message'][ 'migrating_info']['time_remaining'] cls.guest_migrate_info.data_total = cls.message['message'][ 'migrating_info']['data_total'] cls.guest_migrate_info.data_processed = cls.message['message'][ 'migrating_info']['data_processed'] cls.guest_migrate_info.data_remaining = cls.message['message'][ 'migrating_info']['data_remaining'] cls.guest_migrate_info.mem_total = cls.message['message'][ 'migrating_info']['mem_total'] cls.guest_migrate_info.mem_processed = cls.message['message'][ 'migrating_info']['mem_processed'] cls.guest_migrate_info.mem_remaining = cls.message['message'][ 'migrating_info']['mem_remaining'] cls.guest_migrate_info.file_total = cls.message['message'][ 'migrating_info']['file_total'] cls.guest_migrate_info.file_processed = cls.message['message'][ 'migrating_info']['file_processed'] cls.guest_migrate_info.file_remaining = cls.message['message'][ 'migrating_info']['file_remaining'] cls.guest_migrate_info.update() except ji.PreviewingError as e: ret = json.loads(e.message) if ret['state']['code'] == '404': cls.guest_migrate_info.type = cls.message['message'][ 'migrating_info']['type'] cls.guest_migrate_info.time_elapsed = cls.message[ 'message']['migrating_info']['time_elapsed'] cls.guest_migrate_info.time_remaining = cls.message[ 'message']['migrating_info']['time_remaining'] cls.guest_migrate_info.data_total = cls.message['message'][ 'migrating_info']['data_total'] cls.guest_migrate_info.data_processed = cls.message[ 'message']['migrating_info']['data_processed'] cls.guest_migrate_info.data_remaining = cls.message[ 'message']['migrating_info']['data_remaining'] cls.guest_migrate_info.mem_total = cls.message['message'][ 'migrating_info']['mem_total'] cls.guest_migrate_info.mem_processed = cls.message[ 'message']['migrating_info']['mem_processed'] cls.guest_migrate_info.mem_remaining = cls.message[ 'message']['migrating_info']['mem_remaining'] cls.guest_migrate_info.file_total = cls.message['message'][ 'migrating_info']['file_total'] cls.guest_migrate_info.file_processed = cls.message[ 'message']['migrating_info']['file_processed'] cls.guest_migrate_info.file_remaining = cls.message[ 'message']['migrating_info']['file_remaining'] cls.guest_migrate_info.create() elif cls.guest.status == GuestState.creating.value: cls.guest.progress = cls.message['message']['progress'] cls.guest.update() # 限定特殊情况下更新磁盘所属 Guest,避免迁移、创建时频繁被无意义的更新 if cls.guest.status in [ GuestState.running.value, GuestState.shutoff.value ]: cls.disk.update_by_filter({'on_host': cls.guest.on_host}, filter_str='guest_uuid:eq:' + cls.guest.uuid) @classmethod def host_event_processor(cls): key = cls.message['message']['node_id'] value = { 'hostname': cls.message['host'], 'cpu': cls.message['message']['cpu'], 'system_load': cls.message['message']['system_load'], 'memory': cls.message['message']['memory'], 'memory_available': cls.message['message']['memory_available'], 'interfaces': cls.message['message']['interfaces'], 'disks': cls.message['message']['disks'], 'boot_time': cls.message['message']['boot_time'], 'timestamp': ji.Common.ts() } db.r.hset(app.config['hosts_info'], key=key, value=json.dumps(value, ensure_ascii=False)) @classmethod def response_processor(cls): _object = cls.message['message']['_object'] action = cls.message['message']['action'] uuid = cls.message['message']['uuid'] state = cls.message['type'] data = cls.message['message']['data'] hostname = cls.message['host'] if _object == 'guest': if action == 'create': if state == ResponseState.success.value: # 系统盘的 UUID 与其 Guest 的 UUID 相同 cls.disk.uuid = uuid cls.disk.get_by('uuid') cls.disk.guest_uuid = uuid cls.disk.state = DiskState.mounted.value # disk_info['virtual-size'] 的单位为Byte,需要除以 1024 的 3 次方,换算成单位为 GB 的值 cls.disk.size = data['disk_info']['virtual-size'] / (1024** 3) cls.disk.update() else: cls.guest.uuid = uuid cls.guest.get_by('uuid') cls.guest.status = GuestState.dirty.value cls.guest.update() elif action == 'migrate': pass elif action == 'delete': if state == ResponseState.success.value: cls.config.id = 1 cls.config.get() cls.guest.uuid = uuid cls.guest.get_by('uuid') if IP(cls.config.start_ip).int() <= IP( cls.guest.ip).int() <= IP(cls.config.end_ip).int(): if db.r.srem(app.config['ip_used_set'], cls.guest.ip): db.r.sadd(app.config['ip_available_set'], cls.guest.ip) if (cls.guest.vnc_port - cls.config.start_vnc_port) <= \ (IP(cls.config.end_ip).int() - IP(cls.config.start_ip).int()): if db.r.srem(app.config['vnc_port_used_set'], cls.guest.vnc_port): db.r.sadd(app.config['vnc_port_available_set'], cls.guest.vnc_port) cls.guest.delete() # TODO: 加入是否删除使用的数据磁盘开关,如果为True,则顺便删除使用的磁盘。否则解除该磁盘被使用的状态。 cls.disk.uuid = uuid cls.disk.get_by('uuid') cls.disk.delete() cls.disk.update_by_filter( { 'guest_uuid': '', 'sequence': -1, 'state': DiskState.idle.value }, filter_str='guest_uuid:eq:' + cls.guest.uuid) elif action == 'attach_disk': cls.disk.uuid = cls.message['message']['passback_parameters'][ 'disk_uuid'] cls.disk.get_by('uuid') if state == ResponseState.success.value: cls.disk.guest_uuid = uuid cls.disk.sequence = cls.message['message'][ 'passback_parameters']['sequence'] cls.disk.state = DiskState.mounted.value cls.disk.update() elif action == 'detach_disk': cls.disk.uuid = cls.message['message']['passback_parameters'][ 'disk_uuid'] cls.disk.get_by('uuid') if state == ResponseState.success.value: cls.disk.guest_uuid = '' cls.disk.sequence = -1 cls.disk.state = DiskState.idle.value cls.disk.update() elif action == 'boot': boot_jobs_id = cls.message['message']['passback_parameters'][ 'boot_jobs_id'] if state == ResponseState.success.value: cls.guest.uuid = uuid cls.guest.delete_boot_jobs(boot_jobs_id=boot_jobs_id) elif _object == 'disk': if action == 'create': cls.disk.uuid = uuid cls.disk.get_by('uuid') cls.disk.on_host = hostname if state == ResponseState.success.value: cls.disk.state = DiskState.idle.value else: cls.disk.state = DiskState.dirty.value cls.disk.update() elif action == 'resize': if state == ResponseState.success.value: cls.disk.uuid = uuid cls.disk.get_by('uuid') cls.disk.size = cls.message['message'][ 'passback_parameters']['size'] cls.disk.update() elif action == 'delete': cls.disk.uuid = uuid cls.disk.get_by('uuid') cls.disk.delete() else: pass @classmethod def collection_performance_processor(cls): data_kind = cls.message['type'] timestamp = ji.Common.ts() timestamp -= (timestamp % 60) data = cls.message['message']['data'] if data_kind == CollectionPerformanceDataKind.cpu_memory.value: for item in data: cls.cpu_memory.guest_uuid = item['guest_uuid'] cls.cpu_memory.cpu_load = item['cpu_load'] cls.cpu_memory.memory_available = item['memory_available'] cls.cpu_memory.memory_unused = item['memory_unused'] cls.cpu_memory.timestamp = timestamp cls.cpu_memory.create() if data_kind == CollectionPerformanceDataKind.traffic.value: for item in data: cls.traffic.guest_uuid = item['guest_uuid'] cls.traffic.name = item['name'] cls.traffic.rx_bytes = item['rx_bytes'] cls.traffic.rx_packets = item['rx_packets'] cls.traffic.rx_errs = item['rx_errs'] cls.traffic.rx_drop = item['rx_drop'] cls.traffic.tx_bytes = item['tx_bytes'] cls.traffic.tx_packets = item['tx_packets'] cls.traffic.tx_errs = item['tx_errs'] cls.traffic.tx_drop = item['tx_drop'] cls.traffic.timestamp = timestamp cls.traffic.create() if data_kind == CollectionPerformanceDataKind.disk_io.value: for item in data: cls.disk_io.disk_uuid = item['disk_uuid'] cls.disk_io.rd_req = item['rd_req'] cls.disk_io.rd_bytes = item['rd_bytes'] cls.disk_io.wr_req = item['wr_req'] cls.disk_io.wr_bytes = item['wr_bytes'] cls.disk_io.timestamp = timestamp cls.disk_io.create() else: pass @classmethod def host_collection_performance_processor(cls): data_kind = cls.message['type'] timestamp = ji.Common.ts() timestamp -= (timestamp % 60) data = cls.message['message']['data'] if data_kind == HostCollectionPerformanceDataKind.cpu_memory.value: cls.host_cpu_memory.node_id = data['node_id'] cls.host_cpu_memory.cpu_load = data['cpu_load'] cls.host_cpu_memory.memory_available = data['memory_available'] cls.host_cpu_memory.timestamp = timestamp cls.host_cpu_memory.create() if data_kind == HostCollectionPerformanceDataKind.traffic.value: for item in data: cls.host_traffic.node_id = item['node_id'] cls.host_traffic.name = item['name'] cls.host_traffic.rx_bytes = item['rx_bytes'] cls.host_traffic.rx_packets = item['rx_packets'] cls.host_traffic.rx_errs = item['rx_errs'] cls.host_traffic.rx_drop = item['rx_drop'] cls.host_traffic.tx_bytes = item['tx_bytes'] cls.host_traffic.tx_packets = item['tx_packets'] cls.host_traffic.tx_errs = item['tx_errs'] cls.host_traffic.tx_drop = item['tx_drop'] cls.host_traffic.timestamp = timestamp cls.host_traffic.create() if data_kind == HostCollectionPerformanceDataKind.disk_usage_io.value: for item in data: cls.host_disk_usage_io.node_id = item['node_id'] cls.host_disk_usage_io.mountpoint = item['mountpoint'] cls.host_disk_usage_io.used = item['used'] cls.host_disk_usage_io.rd_req = item['rd_req'] cls.host_disk_usage_io.rd_bytes = item['rd_bytes'] cls.host_disk_usage_io.wr_req = item['wr_req'] cls.host_disk_usage_io.wr_bytes = item['wr_bytes'] cls.host_disk_usage_io.timestamp = timestamp cls.host_disk_usage_io.create() else: pass @classmethod def launch(cls): logger.info(msg='Thread EventProcessor is launched.') while True: if Utils.exit_flag: msg = 'Thread EventProcessor say bye-bye' print msg logger.info(msg=msg) return try: report = db.r.lpop(app.config['upstream_queue']) if report is None: time.sleep(1) continue cls.message = json.loads(report) if cls.message['kind'] == EmitKind.log.value: cls.log_processor() elif cls.message['kind'] == EmitKind.guest_event.value: cls.guest_event_processor() elif cls.message['kind'] == EmitKind.host_event.value: cls.host_event_processor() elif cls.message['kind'] == EmitKind.response.value: cls.response_processor() elif cls.message[ 'kind'] == EmitKind.collection_performance.value: cls.collection_performance_processor() elif cls.message[ 'kind'] == EmitKind.host_collection_performance.value: cls.host_collection_performance_processor() else: pass except Exception as e: logger.error(traceback.format_exc())
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)