from etcd3_wrapper import EtcdEntry from .helpers import SpecificEtcdEntryBase class VMStatus(object): # Must be only assigned to brand new VM requested_new = "REQUESTED_NEW" # Host assigned to VM but not created yet. scheduled_deploy = "SCHEDULED_DEPLOY" # Only Assigned to already created vm requested_start = "REQUESTED_START" # These all are for running vms requested_shutdown = "REQUESTED_SHUTDOWN" requested_suspend = "REQUESTED_SUSPEND" requested_resume = "REQUESTED_RESUME" requested_migrate = "REQUESTED_MIGRATE" # either its image is not found or user requested # to delete it deleted = "DELETED" stopped = "STOPPED" # After requested_shutdown killed = "KILLED" # either host died or vm died itself running = "RUNNING" suspended = "SUSPENDED" RUNNING_VM_STATUSES = [VMStatus.requested_shutdown, VMStatus.requested_suspend, VMStatus.requested_resume, VMStatus.requested_migrate, VMStatus.running, VMStatus.suspended] class VMEntry(SpecificEtcdEntryBase): def __init__(self, e: EtcdEntry): self.owner = "" self.specs = dict() self.hostname = "" self.status = "" self.image_uuid = "" super().__init__(e) @property def uuid(self): return self.key.split("/")[-1] def declare_killed(self): self.hostname = "" if self.status in RUNNING_VM_STATUSES: self.status = VMStatus.killed class VmPool(object): def __init__(self, etcd_client, vm_prefix): self.client = etcd_client self.prefix = vm_prefix @property def vms(self): _vms = self.client.get_prefix(self.prefix, value_in_json=True) return [VMEntry(vm) for vm in _vms] def by_host(self, host, _vms=None): if _vms is None: _vms = self.vms return list(filter(lambda x: x.hostname == host, _vms)) def by_status(self, status, _vms=None): if _vms is None: _vms = self.vms return list(filter(lambda x: x.status == status, _vms)) def except_status(self, status, _vms=None): if _vms is None: _vms = self.vms return list(filter(lambda x: x.status != status, _vms)) def get(self, key): v = self.client.get(key, value_in_json=True) return VMEntry(v) def put(self, obj: VMEntry): self.client.put(obj.key, obj.value, value_in_json=True)