From 78470501dd7c79d6a8094197cf6d9aa03e621591 Mon Sep 17 00:00:00 2001 From: meow Date: Fri, 31 Jan 2020 23:05:25 +0500 Subject: [PATCH] Directly use builtin XMLRPC client as opposed to pyone library --- .gitignore | 4 +- opennebula-vm-etcd/put-vm-info-into-etcd.py | 177 ++++++++------------ 2 files changed, 71 insertions(+), 110 deletions(-) diff --git a/.gitignore b/.gitignore index 359653f..f8835d9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,5 @@ opennebula-vm-etcd/config-and-secrets.conf *.pyc -.idea/ -.vscode/ +.idea +.vscode diff --git a/opennebula-vm-etcd/put-vm-info-into-etcd.py b/opennebula-vm-etcd/put-vm-info-into-etcd.py index 5b5495f..0ba2275 100644 --- a/opennebula-vm-etcd/put-vm-info-into-etcd.py +++ b/opennebula-vm-etcd/put-vm-info-into-etcd.py @@ -1,39 +1,17 @@ -import pyone +import json from enum import IntEnum +from xmlrpc.client import ServerProxy as RPCClient + +from xmltodict import parse + from config import config, etcd_client -from functools import reduce - -# How to get client secrets? -# 1. Login to OpenNebula -# 2. Go to Settings then Auth -# 3. Click on "Manage login tokens" button -# 4. Click on "Get a new token" button - -one_client = pyone.OneServer( - uri='https://opennebula.ungleich.ch:2634/RPC2', - session=config['oca']['client_secrets'] -) - -host_pool = { - host.NAME: { - 'name': host.NAME, - 'id': host.ID, - 'cluster': { - 'name': host.CLUSTER, - 'id': host.CLUSTER_ID - }, - 'vms': host.VMS.ID - } - for host in one_client.hostpool.info().HOST -} -def get_hostname_of_vm(vm_id): - for hostname, host in host_pool.items(): - if vm_id in host['vms']: - return host - return None +# Constants +ALL_VM_STATES = -1 +START_ID = -1 # First id whatever it is +END_ID = -1 # Last id whatever it is def put_under_list(obj): @@ -42,65 +20,19 @@ def put_under_list(obj): return obj -class Snapshot: - def __init__(self, disk_id, snapshot): - self.active = bool(snapshot.ACTIVE) - self.date = snapshot.DATE - self.id = snapshot.ID - self.name = snapshot.NAME - self.size = snapshot.SIZE - self.disk_id = disk_id - - def get_data(self): - return { - attr: getattr(self, attr) - for attr in dir(self) - if not attr.startswith('__') and not callable(getattr(self, attr)) - } - - -class VM: - def __init__(self, vm): - self.name = vm.get_NAME() - self.id = vm.get_ID() - self.owner = { - 'name': vm.get_UNAME(), - 'id': vm.get_UID(), - } - - template = vm.get_TEMPLATE() - host = get_hostname_of_vm(self.id) - - self.vcpu = template.get('VCPU', None) - self.memory = template.get('MEMORY', None) - self.disks = [dict(disk) for disk in put_under_list(template.get('DISK', []))] - self.graphics = [dict(graphics) for graphics in put_under_list(template.get('GRAPHICS', []))] - self.nics = [dict(nic) for nic in put_under_list(template.get('NIC', []))] - self.status = pyone.VM_STATE(vm.get_STATE()).name.lower() - self.snapshots = [] - - for disk in one_client.vm.info(self.id).SNAPSHOTS: - disk_id = disk.DISK_ID - for snapshot in disk.SNAPSHOT: - self.snapshots.append(Snapshot(disk_id, snapshot).get_data()) - - if host: - self.host = { - 'name': host['name'], - 'id': host['id'] - } - else: - self.host = host - - def get_data(self): - return { - attr: getattr(self, attr) - for attr in dir(self) - if not attr.startswith('__') and not callable(getattr(self, attr)) - } - - def __repr__(self): - return str(self.get_data()) +class VMState(IntEnum): + INIT = 0 + PENDING = 1 + HOLD = 2 + ACTIVE = 3 + STOPPED = 4 + SUSPENDED = 5 + DONE = 6 + FAILED = 7 + POWEROFF = 8 + UNDEPLOYED = 9 + CLONING = 10 + CLONING_FAILURE = 11 class VmFilterFlag(IntEnum): @@ -111,26 +43,55 @@ class VmFilterFlag(IntEnum): UserPrimaryGroupResources = -4 # Resources belonging to the user’s primary group +class VM: + def __init__(self, vm: dict): + self.id = vm.get('ID', None) + self.owner = { + 'id': vm.get('UID', None), + 'name': vm.get('UNAME', None), + 'gname': vm.get('GNAME', None) + } + self.name = vm.get('NAME', None) + self.status = vm.get('STATE', None) + if self.status: + self.status = VMState(int(self.status)).name.lower() + + template = vm['TEMPLATE'] + + self.disk = put_under_list(template.get('DISK', [])) + self.graphics = template.get('GRAPHICS', {}) + self.memory = template.get('MEMORY', None) + self.nic = put_under_list(template.get('NIC', [])) + self.vcpu = template.get('VCPU', None) + self.host = { + 'name': ((vm.get('HISTORY_RECORDS', {}) or {}).get('HISTORY', {}) or {}).get('HOSTNAME', None), + 'id': ((vm.get('HISTORY_RECORDS', {}) or {}).get('HISTORY', {}) or {}).get('HID', None), + } + self.snapshots = put_under_list(vm.get('SNAPSHOTS', [])) + + def get_data(self): + return { + attr: getattr(self, attr) + for attr in dir(self) + if not attr.startswith('__') and not callable(getattr(self, attr)) + } + + def main(): - VM_STATES = list(pyone.VM_STATE) - START_ID = -1 # First id whatever it is - END_ID = -1 # Last id whatever it is + with RPCClient('https://opennebula.ungleich.ch:2634/RPC2') as rpc_client: + success, response, *_ = rpc_client.one.vmpool.infoextended( + config['oca']['client_secrets'], VmFilterFlag.AllResources.value, START_ID, END_ID, ALL_VM_STATES + ) + if success: + vms = json.loads(json.dumps(parse(response)))['VM_POOL']['VM'] + for i, vm in enumerate(vms): + vm_id = vm['ID'] + etcd_client.put(f'/opennebula/vm/{vm_id}', vm) - # Get VMs in all kind of states - - # vms is a list of lists - vms = [ - one_client.vmpool.infoextended(VmFilterFlag.AllResources.value, START_ID, END_ID, vm_state).VM - for vm_state in VM_STATES - ] - # Take out elements from nested lists and put them into the original list - # forming a nice flat list - vms = list(reduce(lambda n, n_1: n + n_1, vms)) - print('Total VMs:', len(vms)) - for i, _vm in enumerate(vms): - vm = VM(_vm) - etcd_client.put('/opennebula/vm/{}'.format(vm.id), vm.get_data()) - print(i, end=' ') + parsed_vm = VM(vm) + etcd_client.put(f'/opennebula/parsed_vm/{parsed_vm.id}', parsed_vm.get_data()) + else: + print(response) if __name__ == "__main__":