class MachineManager(object): """Base abstract class for analysis machine manager.""" def __init__(self): self.module_name = "" self.options = None self.options_globals = Config( os.path.join(CUCKOO_ROOT, "conf", "cuckoo.conf")) # Database pointer. self.db = Database() # Machine table is cleaned to be filled from configuration file at each start. self.db.clean_machines() def set_options(self, options): """Set machine manager options. @param options: machine manager options dict. """ self.options = options def initialize(self, module_name): """Read and load machines configuration, try to check the configuration. @param module_name: module name. """ # Load. self._initialize(module_name) # Run initialization checks. self._initialize_check() def _initialize(self, module_name): """Read configuration. @param module_name: module name. """ self.module_name = module_name mmanager_opts = self.options.get(module_name) for machine_id in mmanager_opts["machines"].strip().split(","): try: machine_opts = self.options.get(machine_id.strip()) machine = Dictionary() machine.id = machine_id.strip() machine.label = machine_opts["label"].strip() machine.platform = machine_opts["platform"].strip() machine.ip = machine_opts["ip"].strip() self.db.add_machine(name=machine.id, label=machine.label, ip=machine.ip, platform=machine.platform) except (AttributeError, CuckooOperationalError): log.warning( "Configuration details about machine %s are missing. Continue", machine_id) continue def _initialize_check(self): """Runs checks against virtualization software when a machine manager is initialized. @note: in machine manager modules you may override or superclass his method. @raise CuckooMachineError: if a misconfiguration or a unkown vm state is found. """ try: configured_vm = self._list() except NotImplementedError: return for machine in self.machines(): if machine.label not in configured_vm: raise CuckooCriticalError( "Configured machine {0} was not detected or it's not in proper state" .format(machine.label)) if not self.options_globals.timeouts.vm_state: raise CuckooCriticalError( "Virtual machine state change timeout setting not found, please add it to the config file" ) def machines(self): """List virtual machines. @return: virtual machines list """ return self.db.list_machines() def availables(self): """How many machines are free. @return: free machines count. """ return self.db.count_machines_available() def acquire(self, machine_id=None, platform=None): """Acquire a machine to start analysis. @param machine_id: machine ID. @param platform: machine platform. @return: machine or None. """ if machine_id: return self.db.lock_machine(name=machine_id) elif platform: return self.db.lock_machine(platform=platform) else: return self.db.lock_machine() def release(self, label=None): """Release a machine. @param label: machine name. """ self.db.unlock_machine(label) def running(self): """Returns running virtual machines. @return: running virtual machines list. """ return self.db.list_machines(locked=True) def shutdown(self): """Shutdown the machine manager. Kills all alive machines. @raise CuckooMachineError: if unable to stop machine. """ if self.running().count() > 0: log.info("Still %s guests alive. Shutting down...", self.running().count()) for machine in self.running(): try: self.stop(machine.label) except CuckooMachineError as e: log.warning( "Unable to shutdown machine %s, please check " "manually. Error: %s", machine.label, e) def set_status(self, label, status): """Set status for a virtual machine. @param label: virtual machine label @param status: new virtual machine status """ self.db.set_machine_status(label, status) def start(self, label=None): """Start a machine. @param label: machine name. @raise NotImplementedError: this method is abstract. """ raise NotImplementedError def stop(self, label=None): """Stop a machine. @param label: machine name. @raise NotImplementedError: this method is abstract. """ raise NotImplementedError def _list(self): """Lists virtual machines configured. @raise NotImplementedError: this method is abstract. """ raise NotImplementedError def dump_memory(self, path): """Takes a memory dump of a machine. @param path: path to where to store the memory dump. """ raise NotImplementedError def _wait_status(self, label, state): """Waits for a vm status. @param label: virtual machine name. @param state: virtual machine status, accepts more than one states in a list. @raise CuckooMachineError: if default waiting timeout expire. """ # This block was originally suggested by Loic Jaquemet. waitme = 0 try: current = self._status(label) except NameError: return if isinstance(state, str): state = [state] while current not in state: log.debug( "Waiting %i cuckooseconds for machine %s to switch to status %s", waitme, label, state) if waitme > int(self.options_globals.timeouts.vm_state): raise CuckooMachineError( "Timeout hit while for machine {0} to change status". format(label)) time.sleep(1) waitme += 1 current = self._status(label)
class MachineManager(object): """Base abstract class for analysis machine manager.""" def __init__(self): self.module_name = "" self.options = None self.options_globals = Config(os.path.join(CUCKOO_ROOT, "conf", "cuckoo.conf")) # Database pointer. self.db = Database() # Machine table is cleaned to be filled from configuration file at each start. self.db.clean_machines() def set_options(self, options): """Set machine manager options. @param options: machine manager options dict. """ self.options = options def initialize(self, module_name): """Read and load machines configuration, try to check the configuration. @param module_name: module name. """ # Load. self._initialize(module_name) # Run initialization checks. self._initialize_check() def _initialize(self, module_name): """Read configuration. @param module_name: module name. """ self.module_name = module_name mmanager_opts = self.options.get(module_name) for machine_id in mmanager_opts["machines"].strip().split(","): try: machine_opts = self.options.get(machine_id.strip()) machine = Dictionary() machine.id = machine_id.strip() machine.label = machine_opts["label"].strip() machine.platform = machine_opts["platform"].strip() machine.ip = machine_opts["ip"].strip() self.db.add_machine(name=machine.id, label=machine.label, ip=machine.ip, platform=machine.platform) except (AttributeError, CuckooOperationalError): log.warning("Configuration details about machine %s are missing. Continue", machine_id) continue def _initialize_check(self): """Runs checks against virtualization software when a machine manager is initialized. @note: in machine manager modules you may override or superclass his method. @raise CuckooMachineError: if a misconfiguration or a unkown vm state is found. """ try: configured_vm = self._list() except NotImplementedError: return for machine in self.machines(): if machine.label not in configured_vm: raise CuckooCriticalError("Configured machine {0} was not detected or it's not in proper state".format(machine.label)) if not self.options_globals.timeouts.vm_state: raise CuckooCriticalError("Virtual machine state change timeout setting not found, please add it to the config file") def machines(self): """List virtual machines. @return: virtual machines list """ return self.db.list_machines() def availables(self): """How many machines are free. @return: free machines count. """ return self.db.count_machines_available() def acquire(self, machine_id=None, platform=None): """Acquire a machine to start analysis. @param machine_id: machine ID. @param platform: machine platform. @return: machine or None. """ if machine_id: return self.db.lock_machine(name=machine_id) elif platform: return self.db.lock_machine(platform=platform) else: return self.db.lock_machine() def release(self, label=None): """Release a machine. @param label: machine name. """ self.db.unlock_machine(label) def running(self): """Returns running virtual machines. @return: running virtual machines list. """ return self.db.list_machines(locked=True) def shutdown(self): """Shutdown the machine manager. Kills all alive machines. @raise CuckooMachineError: if unable to stop machine. """ if self.running().count() > 0: log.info("Still %s guests alive. Shutting down...", self.running().count()) for machine in self.running(): try: self.stop(machine.label) except CuckooMachineError as e: log.warning("Unable to shutdown machine %s, please check " "manually. Error: %s", machine.label, e) def set_status(self, label, status): """Set status for a virtual machine. @param label: virtual machine label @param status: new virtual machine status """ self.db.set_machine_status(label, status) def start(self, label=None): """Start a machine. @param label: machine name. @raise NotImplementedError: this method is abstract. """ raise NotImplementedError def stop(self, label=None): """Stop a machine. @param label: machine name. @raise NotImplementedError: this method is abstract. """ raise NotImplementedError def _list(self): """Lists virtual machines configured. @raise NotImplementedError: this method is abstract. """ raise NotImplementedError def dump_memory(self, path): """Takes a memory dump of a machine. @param path: path to where to store the memory dump. """ raise NotImplementedError def _wait_status(self, label, state): """Waits for a vm status. @param label: virtual machine name. @param state: virtual machine status, accepts more than one states in a list. @raise CuckooMachineError: if default waiting timeout expire. """ # This block was originally suggested by Loic Jaquemet. waitme = 0 try: current = self._status(label) except NameError: return if isinstance(state, str): state = [state] while current not in state: log.debug("Waiting %i cuckooseconds for machine %s to switch to status %s", waitme, label, state) if waitme > int(self.options_globals.timeouts.vm_state): raise CuckooMachineError("Timeout hit while for machine {0} to change status".format(label)) time.sleep(1) waitme += 1 current = self._status(label)