def getMapping(self): mapping = {} for config in self.configManager.configs: logger = log.getLogger(config=config) virt = Virt.fromConfig(logger, config) mapping[config.name or 'none'] = self._readGuests(virt) return mapping
def getMapping(self): mapping = {} for config in self.configManager.configs: logger = log.getLogger(self.options, config) virt = Virt.fromConfig(logger, config) mapping[config.name or 'none'] = self._readGuests(virt) return mapping
def run_virt(self, config, in_queue=None): v = Virt.fromConfig(self.logger, config) v._queue = in_queue or Queue() v._terminate_event = Event() v._interval = 3600 v._oneshot = True v._run()
class VirtTest(unittest.TestCase): def setUp(self): self.virt = Virt(logger) def test_connection(self): self.assertTrue(self.virt.virt.getVersion() > 0) def test_listDomains(self): uuids = [] for domain in self.virt.listDomains(): uuids.append(domain.UUIDString()) virsh_list = subprocess.Popen(["virsh", "-r", "list", "--all"], stdout=subprocess.PIPE).communicate()[0] lines = virsh_list.split("\n")[2:] for line in lines: if len(line) == 0: continue domId = line.split()[1] uuid = subprocess.Popen( ["virsh", "-r", "domuuid", domId], stdout=subprocess.PIPE).communicate()[0].strip() self.assertTrue( uuid in uuids, "virsh returns more domains then virt-who (%s)" % uuid) uuids.remove(uuid) self.assertEqual( len(uuids), 0, "virsh returns less domains then virt-who (%s)" % ",".join(uuids))
def test_read_hypervisor(self): with open(self.hypervisor_file, "w") as f: f.write(HYPERVISOR_JSON) with open(self.config_file, "w") as f: f.write(""" [test] type=fake is_hypervisor=true file=%s """ % self.hypervisor_file) manager = ConfigManager(self.logger, self.config_dir) self.assertEquals(len(manager.configs), 1) virt = Virt.fromConfig(self.logger, manager.configs[0]) self.assertEquals(type(virt), FakeVirt) mapping = virt.getHostGuestMapping() self.assertTrue("hypervisors" in mapping) hypervisors = mapping["hypervisors"] self.assertEquals(len(hypervisors), 1) hypervisor = hypervisors[0] self.assertEquals(type(hypervisor), Hypervisor) self.assertEquals(hypervisor.hypervisorId, "60527517-6284-7593-6AAB-75BF2A6375EF") self.assertEquals(len(hypervisor.guestIds), 1) guest = hypervisor.guestIds[0] self.assertEquals(guest.uuid, "07ED8178-95D5-4244-BC7D-582A54A48FF8") self.assertEquals(guest.state, 1)
def _readGuests(self, config): virt = Virt.fromConfig(self.logger, config) if not self.options.oneshot and virt.canMonitor(): virt.startMonitoring(self.sync_event) if config.type not in ["esx", "rhevm", "hyperv"]: return virt.listDomains() else: return virt.getHostGuestMapping()
def test_read_non_hypervisor_from_hypervisor(self): with open(self.hypervisor_file, "w") as f: f.write(HYPERVISOR_JSON) with open(self.config_file, "w") as f: f.write(""" [test] type=fake is_hypervisor=false file=%s """ % self.hypervisor_file) manager = ConfigManager(self.logger, self.config_dir) self.assertEquals(len(manager.configs), 1) virt = Virt.fromConfig(self.logger, manager.configs[0]) self.assertEquals(type(virt), FakeVirt) self.assertRaises(VirtError, virt.listDomains)
def initVirt(self): """ Connect to the virtualization supervisor (libvirt or VDSM) """ if self.options.virtType == "vdsm": self.virt = VDSM(self.logger) elif self.options.virtType == "libvirt": self.virt = Virt(self.logger, registerEvents=self.options.background) # We can listen for libvirt events self.tryRegisterEventCallback() elif self.options.virtType == "rhevm": self.virt = RHEVM(self.logger, self.options.server, self.options.username, self.options.password) elif self.options.virtType == "hyperv": self.virt = HyperV(self.logger, self.options.server, self.options.username, self.options.password) else: # ESX self.virt = VSphere(self.logger, self.options.server, self.options.username, self.options.password)
class VirtTest(unittest.TestCase): def setUp(self): self.virt = Virt(logger) def test_connection(self): self.assertTrue(self.virt.virt.getVersion() > 0) def test_listDomains(self): uuids = [] for domain in self.virt.listDomains(): uuids.append(domain.UUIDString()) virsh_list = subprocess.Popen(["virsh", "-r", "list", "--all"], stdout=subprocess.PIPE).communicate()[0] lines = virsh_list.split("\n")[2:] for line in lines: if len(line) == 0: continue domId = line.split()[1] uuid = subprocess.Popen(["virsh", "-r", "domuuid", domId], stdout=subprocess.PIPE).communicate()[0].strip() self.assertTrue(uuid in uuids, "virsh returns more domains then virt-who (%s)" % uuid) uuids.remove(uuid) self.assertEqual(len(uuids), 0, "virsh returns less domains then virt-who (%s)" % ",".join(uuids))
def test_read_non_hypervisor(self): with open(self.hypervisor_file, "w") as f: f.write(NON_HYPERVISOR_JSON) with open(self.config_file, "w") as f: f.write(""" [test] type=fake is_hypervisor=false file=%s """ % self.hypervisor_file) manager = ConfigManager(self.logger, self.config_dir) self.assertEquals(len(manager.configs), 1) virt = Virt.fromConfig(self.logger, manager.configs[0]) self.assertEquals(type(virt), FakeVirt) guests = virt.listDomains() self.assertEquals(len(guests), 1) guest = guests[0] self.assertEquals(guest.uuid, "9f06a84d-5f56-4e7e-be0c-937b3c1924d7") self.assertEquals(guest.state, 1)
def _send(self, config, retry): """ Send list of uuids to subscription manager. This method will call itself once if sending fails. retry - Should be True on first run, False on second. return - True if sending is successful, False otherwise """ virt = Virt.fromConfig(self.logger, config) try: virtualGuests = self._readGuests(virt) except (KeyboardInterrupt, SystemExit): raise except Exception, e: exceptionCheck(e) # Retry once if retry: self.logger.exception("Error in communication with virtualization backend, trying to recover:") return self._send(config, False) else: self.logger.error(self.unableToRecoverStr) return False
def run(self): self.reloading = False if not self.options.oneshot: self.logger.debug("Starting infinite loop with %d seconds interval" % self.options.interval) # Queue for getting events from virt backends if self.queue is None: self.queue = Queue(len(self.configManager.configs)) # Run the virtualization backends self.virts = [] for config in self.configManager.configs: try: virt = Virt.fromConfig(self.logger, config) except Exception as e: self.logger.error('Unable to use configuration "%s": %s' % (config.name, str(e))) continue # Run the process virt.start(self.queue, self.terminate_event, self.options.interval, self.options.oneshot) self.virts.append(virt) if self.options.oneshot: oneshot_remaining = set(virt.config.name for virt in self.virts) if len(self.virts) == 0: self.logger.error("No suitable virt backend found") return result = {} report = None while not self.terminate_event.is_set(): # Wait for incoming report from virt backend try: report = self.queue.get(block=True, timeout=None) except Empty: report = None pass except IOError: continue try: # Run all jobs that have been queued as a result of sending last # time self.runJobs() except Empty: pass except IOError: pass # FIXME Not sure about how to integrate this into the new jobs # scheme of things if report is not None: if report == "exit": break if report == "reload": for virt in self.virts: virt.terminate() self.virts = [] raise ReloadRequest() # Send the report if not self.options.print_ and not isinstance(report, ErrorReport): try: self.send(report) except ManagerFatalError: # System not register (probably), stop the backends for virt in self.virts: virt.terminate() self.virts = [] if self.options.oneshot: try: oneshot_remaining.remove(report.config.name) if not isinstance(report, ErrorReport): if self.options.print_: result[report.config] = report self.logger.debug("Association for config %s gathered" % report.config.name) for virt in self.virts: if virt.config.name == report.config.name: virt.stop() except KeyError: self.logger.debug("Association for config %s already gathered, ignoring" % report.config.name) if not oneshot_remaining: break self.queue = None self.jobs = None for virt in self.virts: virt.terminate() self.virt = [] if self.options.print_: return result
def test_read_fail(self, virt): logger = logging.getLogger() config = Config('test', 'libvirt') libvirtd = Virt.fromConfig(logger, config) virt.side_effect = raiseLibvirtError self.assertRaises(VirtError, libvirtd.listDomains)
def test_read(self, libvirt): logger = logging.getLogger() config = Config('test', 'libvirt') libvirtd = Virt.fromConfig(logger, config) domains = libvirtd.listDomains() libvirt.assert_called_with("")
def setUp(self): self.virt = Virt(logger)
def test_read(self, libvirt): config = Config('test', 'libvirt') libvirtd = Virt.fromConfig(self.logger, config) self.run_virt(config) libvirt.assert_called_with("")
def test_remote_url_with_username_and_password(self, virt): config = Config('test', 'libvirt', 'abc://server/test', 'user', 'pass') Virt.fromConfig(self.logger, config).listDomains() virt.assert_called_with('abc://user@server/test?no_tty=1', ANY, ANY)
def test_read(self, libvirt): config = Config('test', 'libvirt') libvirtd = Virt.fromConfig(self.logger, config) domains = libvirtd.listDomains() libvirt.assert_called_with("")
def test_read_fail(self, virt): config = Config('test', 'libvirt') libvirtd = Virt.fromConfig(self.logger, config) virt.side_effect = raiseLibvirtError self.assertRaises(VirtError, libvirtd.listDomains)
def run(self): self.reloading = False if not self.options.oneshot: self.logger.debug("Starting infinite loop with %d seconds interval" % self.options.interval) # Queue for getting events from virt backends if self.queue is None: self.queue = Queue() # Run the virtualization backends self.virts = [] for config in self.configManager.configs: try: logger = log.getLogger(config=config) virt = Virt.fromConfig(logger, config) except Exception as e: self.logger.error('Unable to use configuration "%s": %s' % (config.name, str(e))) continue # Run the process virt.start(self.queue, self.terminate_event, self.options.interval, self.options.oneshot) self.virts.append(virt) if self.options.oneshot or self.options.print_: oneshot_remaining = set(virt.config.name for virt in self.virts) if len(self.virts) == 0: self.logger.error("No suitable virt backend found") return result = {} report = None report_sent = None while not self.terminate_event.is_set(): if self.jobs: # There is an existing job, we want to check it's state often timeout = 1 else: timeout = self.queue_timeout # Wait for incoming report from virt backend try: report = self.queue.get(block=True, timeout=timeout) except Empty: report = None except IOError: continue # Read all the reports from the queue in order to remove obsoleted # reports from same virt reports = [report] while True: try: report = self.queue.get(block=False) reports.append(report) except Empty: break reports = self._remove_obsolete(reports) try: # Run all jobs that have been queued as a result of sending last # time self.runJobs() if self.options.oneshot and not oneshot_remaining and not self.jobs: break except Empty: pass except IOError: pass report_sent = None for report in reports: if report == "exit": break if report == "reload": self.stop_virts() raise ReloadRequest() if isinstance(report, ErrorReport): if self.options.oneshot: # Don't hang on the failed backend oneshot_remaining.remove(report.config.name) self.logger.warn('Unable to collect report for config "%s"' % report.config.name) # Send the report if not self.options.print_ and not isinstance(report, ErrorReport): self.update_report_to_send(report) # Check to see if it is time to send a report try: if time.time() >= self.send_after: # It is time, send the current report config, report_sent = self.send_current_report() else: # It's not time update our queue_timeout to make sure we # don't wait too long wait_time = self.send_after - time.time() self.queue_timeout = max(0, wait_time) self.logger.debug('Waiting to send report') except ManagerFatalError: # System not register (probably), stop the backends self.stop_virts() continue if self.options.print_: report_sent = report if (self.options.oneshot and report_sent) or self.options.print_: try: oneshot_remaining.remove(report_sent.config.name) except KeyError: pass if not isinstance(report_sent, ErrorReport): if self.options.print_: result[report_sent.config] = report_sent for virt in self.virts: if virt.config.name == report_sent.config.name: virt.stop() if not oneshot_remaining and not self.jobs: break self.queue = None self.jobs = None self.stop_virts() self.virt = [] if self.options.print_: return result
def test_remote_url(self, virt): config = Config('test', 'libvirt', 'abc://server/test') Virt.fromConfig(self.logger, config).listDomains() virt.assert_called_with('abc://server/test?no_tty=1')
def run(self): self.queue_logger = log.getDefaultQueueLogger() self.reloading = False if not self.options.oneshot: self.logger.debug( "Starting infinite loop with %d seconds interval" % self.options.interval) # Queue for getting events from virt backends if self.queue is None: self.queue = Queue() # Run the virtualization backends self.virts = [] for config in self.configManager.configs: try: logger = log.getLogger(self.options, config) virt = Virt.fromConfig(logger, config) except Exception as e: self.logger.error('Unable to use configuration "%s": %s' % (config.name, str(e))) continue # Run the process virt.start(self.queue, self.terminate_event, self.options.interval, self.options.oneshot) self.virts.append(virt) if self.options.oneshot: oneshot_remaining = set(virt.config.name for virt in self.virts) if len(self.virts) == 0: self.logger.error("No suitable virt backend found") return result = {} report = None report_sent = None while not self.terminate_event.is_set(): # Wait for incoming report from virt backend try: report = self.queue.get(block=True, timeout=self.queue_timeout) except Empty: report = None except IOError: continue # Read all the reports from the queue in order to remove obsoleted # reports from same virt reports = [report] while True: try: report = self.queue.get(block=False) reports.append(report) except Empty: break reports = self._remove_obsolete(reports) try: # Run all jobs that have been queued as a result of sending last # time self.runJobs() if self.options.oneshot and not oneshot_remaining and not self.jobs: break except Empty: pass except IOError: pass report_sent = None for report in reports: if report == "exit": break if report == "reload": self.stop_virts() raise ReloadRequest() if isinstance(report, ErrorReport): if self.options.oneshot: # Don't hang on the failed backend oneshot_remaining.remove(report.config.name) self.logger.warn( 'Unable to collect report for config "%s"' % report.config.name) # Send the report if not self.options.print_ and not isinstance( report, ErrorReport): self.update_report_to_send(report) # Check to see if it is time to send a report try: if time.time() >= self.send_after: # It is time, send the current report config, report_sent = self.send_current_report() else: # It's not time update our queue_timeout to make sure we # don't wait too long wait_time = self.send_after - time.time() self.queue_timeout = max(0, wait_time) self.logger.debug('Waiting to send report') except ManagerFatalError: # System not register (probably), stop the backends self.stop_virts() continue if self.options.print_: report_sent = report if (self.options.oneshot and report_sent) or self.options.print_: oneshot_remaining.remove(report_sent.config.name) if not isinstance(report_sent, ErrorReport): if self.options.print_: result[report_sent.config] = report_sent for virt in self.virts: if virt.config.name == report_sent.config.name: virt.stop() if not oneshot_remaining and not self.jobs: break self.queue = None self.jobs = None self.stop_virts() self.virt = [] if self.options.print_: return result
def test_remote_hostname_with_username(self, virt): config = Config('test', 'libvirt', 'server', 'user') Virt.fromConfig(self.logger, config).listDomains() virt.assert_called_with('qemu+ssh://user@server/system?no_tty=1')
def getMapping(self): mapping = {} for config in self.configManager.configs: virt = Virt.fromConfig(self.logger, config) mapping[config.name or "none"] = self._readGuests(virt) return mapping
def run(self): self.reloading = False if not self.options.oneshot: self.logger.debug("Starting infinite loop with %d seconds interval", self.options.interval) # Queue for getting events from virt backends if self.queue is None: self.queue = Queue() # Run the virtualization backends self.virts = [] for config in self.configManager.configs: try: logger = log.getLogger(config=config) virt = Virt.fromConfig(logger, config) except Exception as e: self.logger.error('Unable to use configuration "%s": %s', config.name, str(e)) continue # Run the process virt.start(self.queue, self.terminate_event, self.options.interval, self.options.oneshot) self.virts.append(virt) if self.options.oneshot: self.oneshot_remaining = set(virt.config.name for virt in self.virts) if len(self.virts) == 0: self.logger.error("No suitable virt backend found") return # queued reports depend on OrderedDict feature that if key exists # when setting an item, it will remain in the same order self.queued_reports.clear() # Clear last reports, we need to resend them when reloaded self.last_reports_hash.clear() # List of reports that are being processed by server self.reports_in_progress = [] # Send the first report immediatelly self.send_after = time.time() while not self.terminate_event.is_set(): if self.reports_in_progress: # Check sent report status regularly timeout = 1 elif time.time() > self.send_after: if self.queued_reports: # Reports are queued and we can send them right now, # don't wait in queue timeout = 0 else: # No reports in progress or queued and we can send report # immediately, we can wait for report as long as we want timeout = 3600 else: # We can't send report right now, wait till we can timeout = max(1, self.send_after - time.time()) # Wait for incoming report from virt backend or for timeout try: report = self.queue.get(block=True, timeout=timeout) except Empty: report = None except IOError: continue # Read rest of the reports from the queue in order to remove # obsoleted reports from same virt while True: if isinstance(report, ErrorReport): if self.options.oneshot: # Don't hang on the failed backend try: self.oneshot_remaining.remove(report.config.name) except KeyError: pass self.logger.warn('Unable to collect report for config "%s"', report.config.name) elif isinstance(report, AbstractVirtReport): if self.last_reports_hash.get(report.config.name, None) == report.hash: self.logger.info('Report for config "%s" haven\'t changed, not sending', report.config.name) else: self.queued_reports[report.config.name] = report if self.options.print_: try: self.oneshot_remaining.remove(report.config.name) except KeyError: pass elif report in ['exit', 'reload']: # Reload and exit reports takes priority, do not process # any other reports break try: report = self.queue.get(block=False) except Empty: break if report == 'exit': break elif report == 'reload': self.stop_virts() raise ReloadRequest() self.check_reports_state() if not self.reports_in_progress and self.queued_reports and time.time() > self.send_after: # No report is processed, send next one if not self.options.print_: self.send_current_report() if self.options.oneshot and not self.oneshot_remaining: break self.queue = None self.stop_virts() self.virt = [] if self.options.print_: return self.queued_reports