95 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			95 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from contextlib import contextmanager
 | 
						|
from datetime import datetime
 | 
						|
from os.path import join
 | 
						|
 | 
						|
from .classes import SpecificEtcdEntryBase
 | 
						|
 | 
						|
 | 
						|
class VMStatus:
 | 
						|
    stopped = "STOPPED"  # After requested_shutdown
 | 
						|
    killed = "KILLED"  # either host died or vm died itself
 | 
						|
    running = "RUNNING"
 | 
						|
    error = "ERROR"  # An error occurred that cannot be resolved automatically
 | 
						|
 | 
						|
 | 
						|
class VMEntry(SpecificEtcdEntryBase):
 | 
						|
 | 
						|
    def __init__(self, e):
 | 
						|
        self.owner = None  # type: str
 | 
						|
        self.specs = None  # type: dict
 | 
						|
        self.hostname = None  # type: str
 | 
						|
        self.status = None  # type: str
 | 
						|
        self.image_uuid = None  # type: str
 | 
						|
        self.log = None  # type: list
 | 
						|
        self.in_migration = None  # type: bool
 | 
						|
 | 
						|
        super().__init__(e)
 | 
						|
 | 
						|
    @property
 | 
						|
    def uuid(self):
 | 
						|
        return self.key.split("/")[-1]
 | 
						|
 | 
						|
    def declare_killed(self):
 | 
						|
        self.hostname = ""
 | 
						|
        self.in_migration = False
 | 
						|
        if self.status == VMStatus.running:
 | 
						|
            self.status = VMStatus.killed
 | 
						|
 | 
						|
    def declare_stopped(self):
 | 
						|
        self.hostname = ""
 | 
						|
        self.in_migration = False
 | 
						|
        self.status = VMStatus.stopped
 | 
						|
 | 
						|
    def add_log(self, msg):
 | 
						|
        self.log = self.log[:5]
 | 
						|
        self.log.append("{} - {}".format(datetime.now().isoformat(), msg))
 | 
						|
 | 
						|
 | 
						|
class VmPool:
 | 
						|
    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 by_owner(self, owner, _vms=None):
 | 
						|
        if _vms is None:
 | 
						|
            _vms = self.vms
 | 
						|
        return list(filter(lambda x: x.owner == owner, _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):
 | 
						|
        if not key.startswith(self.prefix):
 | 
						|
            key = join(self.prefix, key)
 | 
						|
        v = self.client.get(key, value_in_json=True)
 | 
						|
        if v:
 | 
						|
            return VMEntry(v)
 | 
						|
        return None
 | 
						|
 | 
						|
    def put(self, obj: VMEntry):
 | 
						|
        self.client.put(obj.key, obj.value, value_in_json=True)
 | 
						|
 | 
						|
    @contextmanager
 | 
						|
    def get_put(self, key) -> VMEntry:
 | 
						|
        # Updates object at key on exit
 | 
						|
        obj = self.get(key)
 | 
						|
        yield obj
 | 
						|
        if obj:
 | 
						|
            self.put(obj)
 |