예제 #1
0
    def _create_destinations(self):
        """Populate self.destinations with a list of  list with them

            @param reset: Whether to kill existing destinations or not, defaults
            to false
            @type: bool
        """
        dests = []
        for info in self.dest_to_source_mapper.dests:
            # Dests should already include all destinations we want created
            # at this time. This method will make no assumptions of creating
            # defaults of any kind.
            source_keys = self.dest_to_source_mapper.dest_to_sources_map[info]
            info.name = "destination_%s" % hash(info)
            logger = log.getLogger(name=info.name)
            manager = Manager.fromInfo(logger, self.options, info)
            dest_class = info_to_destination_class[type(info)]
            dest = dest_class(config=info, logger=logger,
                              source_keys=source_keys,
                              options=self.options,
                              source=self.datastore, dest=manager,
                              terminate_event=self.terminate_event,
                              interval=self.options[VW_GLOBAL]['interval'],
                              oneshot=self.options[VW_GLOBAL]['oneshot'])
            dests.append(dest)
        return dests
예제 #2
0
 def test_get_logger_no_config(self, open, getQueueLogger, isdir):
     open.return_value = None
     isdir.return_value = True
     queueLogger = log.QueueLogger('virtwho')
     queueLogger.logger.handlers = []
     mockQueueLogger = Mock(wraps=queueLogger)
     getQueueLogger.return_value = mockQueueLogger
     conf_values = {
         'global': {
             'debug': False,
             'background': True,
             'log_file': log.DEFAULT_LOG_FILE,
             'log_dir': log.DEFAULT_LOG_DIR,
             'log_per_config': False
         }
     }
     config = StubEffectiveConfig(conf_values)
     log.init(config)
     main_logger = log.getLogger(name='main')
     self.assertTrue(main_logger.name == 'virtwho.main')
     self.assertTrue(len(main_logger.handlers) == 1)
     self.assertTrue(isinstance(main_logger.handlers[0], log.QueueHandler))
     queue_handlers = queueLogger.logger.handlers
     self.assertTrue(len(queue_handlers) == 2)
     self.assertEqual(queue_handlers[0].baseFilename, '%s/%s' % (log.DEFAULT_LOG_DIR, log.DEFAULT_LOG_FILE))
예제 #3
0
    def _create_destinations(self):
        """Populate self.destinations with a list of  list with them

            @param reset: Whether to kill existing destinations or not, defaults
            to false
            @type: bool
        """
        dests = []
        for info in self.dest_to_source_mapper.dests:
            # Dests should already include all destinations we want created
            # at this time. This method will make no assumptions of creating
            # defaults of any kind.
            source_keys = self.dest_to_source_mapper.dest_to_sources_map[info]
            info.name = "destination_%s" % hash(info)
            logger = log.getLogger(name=info.name)
            manager = Manager.fromInfo(logger, self.options, info)
            dest_class = info_to_destination_class[type(info)]
            dest = dest_class(config=info,
                              logger=logger,
                              source_keys=source_keys,
                              options=self.options,
                              source=self.datastore,
                              dest=manager,
                              terminate_event=self.terminate_event,
                              interval=self.options[VW_GLOBAL]['interval'],
                              oneshot=self.options[VW_GLOBAL]['oneshot'],
                              status=self.options[VW_GLOBAL]['status'])
            dests.append(dest)
        return dests
예제 #4
0
    def association(self):
        # Apply filter
        logger = log.getLogger(name='virt', queue=False)
        assoc = []
        for host in self._assoc['hypervisors']:
            if self.exclude_hosts is not None and self.exclude_hosts != NotSetSentinel:
                if self._filter(host.hypervisorId, self.exclude_hosts):
                    logger.debug(
                        "Skipping host '%s' because its ID was excluded by filter '%s'"
                        % (host.hypervisorId, self.exclude_hosts))
                    continue
                else:
                    logger.debug("Host %s passed filter %s" %
                                 (host.hypervisorId, self.exclude_hosts))

            if self.filter_hosts is not None and self.filter_hosts != NotSetSentinel:
                if self._filter(host.hypervisorId, self.filter_hosts):
                    logger.debug("Host %s passed filter %s" %
                                 (host.hypervisorId, self.filter_hosts))
                else:
                    logger.debug(
                        "Skipping host '%s' because its ID was not included in filter '%s'"
                        % (host.hypervisorId, self.filter_hosts))
                    continue

            assoc.append(host)
        return {'hypervisors': assoc}
예제 #5
0
    def test_get_logger_different_log_file(self, getFileHandler,
                                           getQueueLogger):
        queueLogger = log.QueueLogger('virtwho')
        queueLogger.logger.handlers = []
        mockQueueLogger = Mock(wraps=queueLogger)
        getQueueLogger.return_value = mockQueueLogger

        config = Mock()
        config.name = 'test'
        config.log_file = 'test.log'
        config.log_dir = '/test/'

        options = Mock()
        options.debug = False
        options.background = True
        options.log_per_config = True
        options.log_dir = ''
        options.log_file = ''
        log.init(options)
        test_logger = log.getLogger(name='test', config=config)

        self.assertTrue(test_logger.name == 'virtwho.test')
        self.assertTrue(len(test_logger.handlers) == 1)
        self.assertTrue(len(queueLogger.logger.handlers) == 1)
        getFileHandler.assert_called_with(name=test_logger.name, config=config)
예제 #6
0
 def test_get_logger_no_config(self, open, getQueueLogger, isdir):
     open.return_value = None
     isdir.return_value = True
     queueLogger = log.QueueLogger('virtwho')
     queueLogger.logger.handlers = []
     mockQueueLogger = Mock(wraps=queueLogger)
     getQueueLogger.return_value = mockQueueLogger
     options = Mock()
     options.debug = False
     options.background = True
     options.log_file = log.DEFAULT_LOG_FILE
     options.log_dir = log.DEFAULT_LOG_DIR
     options.log_per_config = False
     log.init(options)
     main_logger = log.getLogger(name='main')
     self.assertTrue(main_logger.name == 'virtwho.main')
     self.assertTrue(len(main_logger.handlers) == 1)
     self.assertTrue(isinstance(main_logger.handlers[0], log.QueueHandler))
     queue_handlers = queueLogger.logger.handlers
     self.assertTrue(len(queue_handlers) == 1)
     self.assertEquals(queue_handlers[0].baseFilename, '%s/%s' % (log.DEFAULT_LOG_DIR, log.DEFAULT_LOG_FILE))
예제 #7
0
    def test_get_logger_different_log_file(self, getFileHandler, getQueueLogger):
        queueLogger = log.QueueLogger('virtwho')
        queueLogger.logger.handlers = []
        mockQueueLogger = Mock(wraps=queueLogger)
        getQueueLogger.return_value = mockQueueLogger

        options = {
            'global': {
                'debug': False,
                'background': True,
                'log_per_config': True,
                'log_dir': '/test/',
                'log_file': 'test.log',
            },
        }
        log.init(options)
        test_logger = log.getLogger(config=options)

        self.assertTrue(test_logger.name == 'virtwho.test_log')
        self.assertTrue(len(test_logger.handlers) == 1)
        self.assertTrue(len(queueLogger.logger.handlers) == 2)
        getFileHandler.assert_called_with(name=test_logger.name, config=options)
예제 #8
0
 def test_get_logger_no_config(self, open, getQueueLogger, isdir):
     open.return_value = None
     isdir.return_value = True
     queueLogger = log.QueueLogger('virtwho')
     queueLogger.logger.handlers = []
     mockQueueLogger = Mock(wraps=queueLogger)
     getQueueLogger.return_value = mockQueueLogger
     options = Mock()
     options.debug = False
     options.background = True
     options.log_file = log.DEFAULT_LOG_FILE
     options.log_dir = log.DEFAULT_LOG_DIR
     options.log_per_config = False
     log.init(options)
     main_logger = log.getLogger(name='main')
     self.assertTrue(main_logger.name == 'virtwho.main')
     self.assertTrue(len(main_logger.handlers) == 1)
     self.assertTrue(isinstance(main_logger.handlers[0], log.QueueHandler))
     queue_handlers = queueLogger.logger.handlers
     self.assertTrue(len(queue_handlers) == 1)
     self.assertEquals(
         queue_handlers[0].baseFilename,
         '%s/%s' % (log.DEFAULT_LOG_DIR, log.DEFAULT_LOG_FILE))
예제 #9
0
파일: virt.py 프로젝트: candlepin/virt-who
    def association(self):
        # Apply filter
        logger = log.getLogger(name='virt', queue=False)
        assoc = []
        for host in self._assoc['hypervisors']:
            if self.exclude_hosts is not None and self.exclude_hosts != NotSetSentinel:
                if self._filter(host.hypervisorId, self.exclude_hosts):
                    logger.debug("Skipping host '%s' because its ID was excluded by filter '%s'" %
                                 (host.hypervisorId, self.exclude_hosts))
                    continue
                else:
                    logger.debug("Host %s passed filter %s" % (host.hypervisorId, self.exclude_hosts))

            if self.filter_hosts is not None and self.filter_hosts != NotSetSentinel:
                if self._filter(host.hypervisorId, self.filter_hosts):
                    logger.debug("Host %s passed filter %s" % (host.hypervisorId, self.filter_hosts))
                else:
                    logger.debug("Skipping host '%s' because its ID was not included in filter '%s'" %
                                 (host.hypervisorId, self.filter_hosts))
                    continue

            assoc.append(host)
        return {'hypervisors': assoc}
예제 #10
0
    def test_get_logger_different_log_file(self, getFileHandler, getQueueLogger):
        queueLogger = log.QueueLogger('virtwho')
        queueLogger.logger.handlers = []
        mockQueueLogger = Mock(wraps=queueLogger)
        getQueueLogger.return_value = mockQueueLogger

        config = Mock()
        config.name = 'test'
        config.log_file = 'test.log'
        config.log_dir = '/test/'

        options = Mock()
        options.debug = False
        options.background = True
        options.log_per_config = True
        options.log_dir = ''
        options.log_file = ''
        log.init(options)
        test_logger = log.getLogger(name='test', config=config)

        self.assertTrue(test_logger.name == 'virtwho.test')
        self.assertTrue(len(test_logger.handlers) == 1)
        self.assertTrue(len(queueLogger.logger.handlers) == 1)
        getFileHandler.assert_called_with(name=test_logger.name, config=config)
예제 #11
0
def main():
    logger = effective_config = None
    try:
        logger, effective_config = parse_options()
        # We now have the effective_config
    except OptionError as e:
        print(str(e), file=sys.stderr)
        exit(1, status="virt-who can't be started: %s" % str(e))

    lock = PIDLock(PIDFILE)
    if lock.is_locked():
        msg = "virt-who seems to be already running. If not, remove %s" % \
              PIDFILE
        print(msg, file=sys.stderr)
        exit(1, status=msg)

    if not effective_config[VW_GLOBAL].is_valid():
        message = "Required section 'global' is invalid:\n"
        message += "\n".join([
            msg
            for (level, msg) in effective_config[VW_GLOBAL].validation_messages
        ])
        message += "\n"
        exit(1, "virt-who can't be started: %s" % message)

    valid_virt_sections = [(name, section)
                           for (name,
                                section) in effective_config.virt_sections()
                           if section.is_valid()]

    if not valid_virt_sections:
        err = "virt-who can't be started: no valid configuration found"
        logger.error(err)
        exit(1, err)

    global executor
    has_error = False
    try:
        executor = Executor(logger, effective_config)
    except (InvalidKeyFile, InvalidPasswordFormat) as e:
        logger.error(str(e))
        exit(1, "virt-who can't be started: %s" % str(e))

    if len(executor.dest_to_source_mapper.dests) == 0:
        if has_error:
            err = "virt-who can't be started: no valid destination found"
            logger.error(err)
            exit(1, err)

    if len(effective_config[VW_GLOBAL]['configs']) > 0:
        # When config file is provided using -c or --config, then other config
        # files in /etc/virt-who.d are ignored. When it is not possible to read
        # any configuration file, then virt-who should be terminated
        cli_config_file_readable = False
        for file_name in effective_config[VW_GLOBAL]['configs']:
            if os.path.isfile(file_name):
                cli_config_file_readable = True

        if cli_config_file_readable is False:
            err = 'No valid configuration file provided using -c/--config'
            logger.error(err)
            exit(1, "virt-who can't be started: %s" % str(err))

    for name, config in executor.dest_to_source_mapper.configs:
        logger.info('Using configuration "%s" ("%s" mode)', name,
                    config['type'])

    logger.info("Using reporter_id='%s'",
                effective_config[VW_GLOBAL]['reporter_id'])
    log.closeLogger(logger)

    with lock:
        signal.signal(signal.SIGHUP, reload)
        signal.signal(signal.SIGTERM, atexit_fn)

        executor.logger = logger = log.getLogger(name='main', queue=True)

        sd_notify("READY=1\nMAINPID=%d" % os.getpid())
        while True:
            try:
                return _main(executor)
            except ReloadRequest:
                logger.info("Reloading")
                continue
            except ExitRequest as e:
                exit(e.code, status=e.message)
예제 #12
0
파일: parser.py 프로젝트: virt-who/virt-who
def parse_options():
    """
    This function parses all options from command line and environment variables
    :return: Tuple of logger and options
    """

    # These options are deprecated
    DEPRECATED_OPTIONS = ['log_per_config', 'log_dir', 'log_file', 'reporter_id', 'virt_type',
                          'owner', 'env', 'server', 'username', 'password',
                          'sat_server', 'sat_username', 'sat_password',  'sm_type']
    VIRT_TYPE_OPTIONS = ['owner', 'server', 'username', 'password']
    SAT_OPTION_MAP = {'sat_server':'satellite-server', 'sat_username':'******', 'sat_password':'******'}

    # Read command line arguments first
    cli_options, errors, defaults = parse_cli_arguments()

    if 'version' in cli_options and cli_options['version']:
        print(get_version())
        exit(os.EX_OK)

    # Read configuration env. variables
    env_options = read_config_env_variables()

    if six.PY2:
        # Read environments variables for virtualization backends
        env_options, env_errors = read_vm_backend_env_variables(env_options)
        errors.extend(env_errors)

    # Create the effective config that virt-who will use to run
    effective_config = init_config(env_options, cli_options)
    # Ensure validation errors during effective config creation are logged
    errors.extend(effective_config.validation_messages)

    logger = log.getLogger(config=effective_config, queue=False)

    used_deprecated_cli_options = []
    for option in DEPRECATED_OPTIONS:
        display_option = option
        if option in cli_options and not cli_options[option] == defaults[option]:
            if option == 'virt_type' or option == 'sm_type':
                display_option = cli_options[option]
            elif any(option in s for s in VIRT_TYPE_OPTIONS):
                display_option = '%s-%s' % (cli_options['virt_type'], option)
            elif option in SAT_OPTION_MAP:
                display_option = SAT_OPTION_MAP[option]
            used_deprecated_cli_options.append(display_option)

    # These two flags set the value of sm_type to the default value ('sam'), so ArgumentParser will not
    # include them in the cli_options list, thus we have to manually check for and add them to
    # the deprecated list for them to be included in the warning:
    if '--satellite6' in _sys.argv:
        used_deprecated_cli_options.append('satellite6')
    if '--sam' in _sys.argv:
        used_deprecated_cli_options.append('sam')

    deprecated_options_msg = "The following cli options: %s are deprecated and will be removed " \
    "in the next release. Please see 'man virt-who-config' for details on adding a configuration "\
    "section."
    if used_deprecated_cli_options:
        logger.warning(deprecated_options_msg % ', '.join('--' + item for item in used_deprecated_cli_options))

    # Log pending errors
    for err in errors:
        method = getattr(logger, err[0])
        if method is not None and err[0] == 'error':
            method(err[1])

    return logger, effective_config
예제 #13
0
def parse_options():
    """
    This function parses all options from command line and environment variables
    :return: Tuple of logger and options
    """

    # These options are deprecated
    DEPRECATED_OPTIONS = ['log_per_config', 'log_dir', 'log_file', 'reporter_id', 'virt_type',
                          'owner', 'env', 'server', 'username', 'password',
                          'sat_server', 'sat_username', 'sat_password',  'sm_type']
    VIRT_TYPE_OPTIONS = ['owner', 'server', 'username', 'password']
    SAT_OPTION_MAP = {'sat_server': 'satellite-server', 'sat_username': '******', 'sat_password': '******'}

    # Read command line arguments first
    cli_options, errors, defaults = parse_cli_arguments()

    if 'version' in cli_options and cli_options['version']:
        print(get_version())
        exit(os.EX_OK)

    if 'status' in cli_options and ('print' in cli_options or 'oneshot' in cli_options):
        print("You may not use the --print or --one-shot options with the --status option.")
        exit(os.EX_USAGE)

    if 'json' in cli_options and 'status' not in cli_options:
        print("The --json option must only be used with the --status option.")
        exit(os.EX_USAGE)

    # Create the effective config that virt-who will use to run
    effective_config = init_config(cli_options)
    # Ensure validation errors during effective config creation are logged
    errors.extend(effective_config.validation_messages)

    logger = log.getLogger(config=effective_config, queue=False)

    used_deprecated_cli_options = []
    for option in DEPRECATED_OPTIONS:
        display_option = option
        if option in cli_options and not cli_options[option] == defaults[option]:
            if option == 'virt_type' or option == 'sm_type':
                display_option = cli_options[option]
            elif any(option in s for s in VIRT_TYPE_OPTIONS):
                display_option = '%s-%s' % (cli_options['virt_type'], option)
            elif option in SAT_OPTION_MAP:
                display_option = SAT_OPTION_MAP[option]
            used_deprecated_cli_options.append(display_option)

    # These two flags set the value of sm_type to the default value ('sam'), so ArgumentParser will not
    # include them in the cli_options list, thus we have to manually check for and add them to
    # the deprecated list for them to be included in the warning:
    if '--satellite6' in _sys.argv:
        used_deprecated_cli_options.append('satellite6')
    if '--sam' in _sys.argv:
        used_deprecated_cli_options.append('sam')

    deprecated_options_msg = (
        "The following cli options: %s are deprecated and will be removed "
        "in the next release. Please see 'man virt-who-config' for details on adding "
        "a configuration section."
    )
    if used_deprecated_cli_options:
        logger.warning(deprecated_options_msg % ', '.join('--' + item for item in used_deprecated_cli_options))

    # Log pending errors
    for err in errors:
        method = getattr(logger, err[0])
        if method is not None and err[0] == 'error':
            method(err[1])

    return logger, effective_config
예제 #14
0
"""
This module is used for parsing command line arguments and reading
configuration from environment variables.
"""

import os
import sys as _sys

from argparse import ArgumentParser, Action

from virtwho import log, SAT5, SAT6
from virtwho.config import NotSetSentinel, init_config, DEFAULTS, VW_ENV_CLI_SECTION_NAME
from virtwho.virt.virt import Virt

# Module-level logger
logger = log.getLogger(name='parser', queue=False)

# List of supported virtualization backends
VIRT_BACKENDS = Virt.hypervisor_types()

SAT5_VM_DISPATCHER = {
    'libvirt': {'owner': False, 'server': False, 'username': False},
    'esx': {'owner': False, 'server': True, 'username': True},
    'rhevm': {'owner': False, 'server': True, 'username': True},
    'hyperv': {'owner': False, 'server': True, 'username': True},
    'kubevirt': {'owner': False, 'server': False, 'username': False, 'kubeconfig': True, 'kubeversion': False, 'insecure': False},
    'ahv': {'owner': False, 'server': False, 'username': False},
}

SAT6_VM_DISPATCHER = {
    'libvirt': {'owner': False, 'server': False, 'username': False},
예제 #15
0
    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)

        # This set is used both for oneshot mode and to bypass rate-limit
        # when virt-who is starting
        self.oneshot_remaining = set(virt.config.name for virt in self.virts)

        if len(self.virts) == 0:
            err = "virt-who can't be started: no suitable virt backend found"
            self.logger.error(err)
            exit(1, err)

        # 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 immediately
        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" hasn\'t changed, not sending', report.config.name)
                    else:
                        if report.config.name in self.oneshot_remaining:
                            # Send the report immediately
                            self.oneshot_remaining.remove(report.config.name)
                            if not self.options.print_:
                                self.send_report(report.config.name, report)
                            else:
                                self.queued_reports[report.config.name] = report
                        else:
                            self.queued_reports[report.config.name] = report
                elif report in ['exit', 'reload']:
                    # Reload and exit reports takes priority, do not process
                    # any other reports
                    break

                # Get next report from queue
                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 and not self.reports_in_progress:
                break

        self.queue = None
        self.stop_virts()

        self.virt = []
        if self.options.print_:
            return self.queued_reports
예제 #16
0
def main():
    logger = options = None
    try:
        logger, options = parse_options()
        # We now have the effective_config
    except OptionError as e:
        print(str(e), file=sys.stderr)
        exit(1, status="virt-who can't be started: %s" % str(e))

    lock = PIDLock(PIDFILE)
    if lock.is_locked():
        msg = "virt-who seems to be already running. If not, remove %s" % \
              PIDFILE
        print(msg, file=sys.stderr)
        exit(1, status=msg)

    if not options[VW_GLOBAL].is_valid():
        message = "Required section 'global' is invalid:\n"
        message += "\n".join([msg for (level, msg) in options[VW_GLOBAL].validation_messages])
        message += "\n"
        exit(1, "virt-who can't be started: %s" % message)

    valid_virt_sections = [(name, section) for (name, section) in options.virt_sections()
                           if section.is_valid()]

    if not valid_virt_sections:
        err = "virt-who can't be started: no valid configuration found"
        logger.error(err)
        exit(1, err)

    global executor
    has_error = False
    try:
        executor = Executor(logger, options)
    except (InvalidKeyFile, InvalidPasswordFormat) as e:
        logger.error(str(e))
        exit(1, "virt-who can't be started: %s" % str(e))

    if len(executor.dest_to_source_mapper.dests) == 0:
        if has_error:
            err = "virt-who can't be started: no valid destination found"
            logger.error(err)
            exit(1, err)

    for name, config in executor.dest_to_source_mapper.configs:
        logger.info('Using configuration "%s" ("%s" mode)', name,
                    config['type'])

    logger.info("Using reporter_id='%s'", options[VW_GLOBAL]['reporter_id'])
    log.closeLogger(logger)

    with lock:
        signal.signal(signal.SIGHUP, reload)
        signal.signal(signal.SIGTERM, atexit_fn)

        executor.logger = logger = log.getLogger(name='main', queue=True)

        sd_notify("READY=1\nMAINPID=%d" % os.getpid())
        while True:
            try:
                return _main(executor)
            except ReloadRequest:
                logger.info("Reloading")
                continue
            except ExitRequest as e:
                exit(e.code, status=e.message)
예제 #17
0
파일: main.py 프로젝트: shihliu/virt-who
def main():
    logger = options = None
    try:
        logger, options = parseOptions()
    except OptionError as e:
        print >>sys.stderr, str(e)
        exit(1, status="virt-who can't be started: %s" % str(e))

    lock = PIDLock(PIDFILE)
    if lock.is_locked():
        msg = "virt-who seems to be already running. If not, remove %s" % PIDFILE
        print >>sys.stderr, msg
        exit(1, status=msg)

    global executor
    try:
        executor = Executor(logger, options)
    except (InvalidKeyFile, InvalidPasswordFormat) as e:
        logger.error(str(e))
        exit(1, "virt-who can't be started: %s" % str(e))

    if options.virtType is not None:
        config = Config("env/cmdline", options.virtType, executor.configManager._defaults, **options)
        try:
            config.checkOptions(logger)
        except InvalidOption as e:
            err = "virt-who can't be started: %s" % str(e)
            logger.error(err)
            exit(1, err)
        executor.configManager.addConfig(config)
    has_error = False
    for conffile in options.configs:
        try:
            executor.configManager.readFile(conffile)
        except InvalidPasswordFormat as e:
            err = "virt-who can't be started: %s" % str(e)
            logger.error(err)
            exit(1, err)
        except Exception as e:
            logger.error('Config file "%s" skipped because of an error: %s', conffile, str(e))
            has_error = True

    if len(executor.configManager.configs) == 0:
        if has_error:
            err = "virt-who can't be started: no valid configuration found"
            logger.error(err)
            exit(1, err)
        # In order to keep compatibility with older releases of virt-who,
        # fallback to using libvirt as default virt backend
        logger.info("No configurations found, using libvirt as backend")
        executor.configManager.addConfig(Config("env/cmdline", "libvirt"))

    for config in executor.configManager.configs:
        if config.name is None:
            logger.info('Using commandline or sysconfig configuration ("%s" mode)', config.type)
        else:
            logger.info('Using configuration "%s" ("%s" mode)', config.name, config.type)

    logger.info("Using reporter_id='%s'", options.reporter_id)
    log.closeLogger(logger)
    if options.background:
        locker = lambda: daemon.DaemonContext(pidfile=lock)  # flake8: noqa
    else:
        locker = lambda: lock  # flake8: noqa

    with locker():
        signal.signal(signal.SIGHUP, reload)
        signal.signal(signal.SIGTERM, atexit_fn)

        executor.logger = logger = log.getLogger(name='main', config=None, queue=True)

        sd_notify("READY=1\nMAINPID=%d" % os.getpid())
        while True:
            try:
                return _main(executor)
            except ReloadRequest:
                logger.info("Reloading")
                continue
예제 #18
0
파일: parser.py 프로젝트: virt-who/virt-who
def parseOptions():
    parser = OptionParserEpilog(
        usage="virt-who [-d] [-i INTERVAL] [-o] [--sam|--satellite5|--satellite6] [--libvirt|--vdsm|--esx|--rhevm|--hyperv|--xen]",
        description="Agent for reporting virtual guest IDs to subscription manager",
        epilog="virt-who also reads environment variables. They have the same name as command line arguments but uppercased, with underscore instead of dash and prefixed with VIRTWHO_ (e.g. VIRTWHO_ONE_SHOT). Empty variables are considered as disabled, non-empty as enabled",
    )
    parser.add_option("-d", "--debug", action="store_true", dest="debug", default=False, help="Enable debugging output")
    parser.add_option(
        "-o",
        "--one-shot",
        action="store_true",
        dest="oneshot",
        default=False,
        help="Send the list of guest IDs and exit immediately",
    )
    parser.add_option(
        "-i",
        "--interval",
        type="int",
        dest="interval",
        default=NotSetSentinel(),
        help="Acquire list of virtual guest each N seconds. Send if changes are detected.",
    )
    parser.add_option(
        "-p",
        "--print",
        action="store_true",
        dest="print_",
        default=False,
        help="Print the host/guest association obtained from virtualization backend (implies oneshot)",
    )
    parser.add_option(
        "-c",
        "--config",
        action="append",
        dest="configs",
        default=[],
        help="Configuration file that will be processed, can be used multiple times",
    )
    parser.add_option(
        "-m",
        "--log-per-config",
        action="store_true",
        dest="log_per_config",
        default=NotSetSentinel(),
        help="Write one log file per configured virtualization backend.\nImplies a log_dir of %s/virtwho (Default: all messages are written to a single log file)"
        % log.DEFAULT_LOG_DIR,
    )
    parser.add_option(
        "-l",
        "--log-dir",
        action="store",
        dest="log_dir",
        default=log.DEFAULT_LOG_DIR,
        help="The absolute path of the directory to log to. (Default '%s')" % log.DEFAULT_LOG_DIR,
    )
    parser.add_option(
        "-f",
        "--log-file",
        action="store",
        dest="log_file",
        default=log.DEFAULT_LOG_FILE,
        help="The file name to write logs to. (Default '%s')" % log.DEFAULT_LOG_FILE,
    )
    parser.add_option(
        "-r",
        "--reporter-id",
        action="store",
        dest="reporter_id",
        default=NotSetSentinel(),
        help="Label host/guest associations obtained by this instance of virt-who with the provided id.",
    )

    virtGroup = OptionGroup(
        parser,
        "Virtualization backend",
        "Choose virtualization backend that should be used to gather host/guest associations",
    )
    virtGroup.add_option(
        "--libvirt",
        action="store_const",
        dest="virtType",
        const="libvirt",
        default=None,
        help="Use libvirt to list virtual guests [default]",
    )
    virtGroup.add_option(
        "--vdsm", action="store_const", dest="virtType", const="vdsm", help="Use vdsm to list virtual guests"
    )
    virtGroup.add_option(
        "--esx", action="store_const", dest="virtType", const="esx", help="Register ESX machines using vCenter"
    )
    virtGroup.add_option(
        "--xen", action="store_const", dest="virtType", const="xen", help="Register XEN machines using XenServer"
    )
    virtGroup.add_option(
        "--rhevm", action="store_const", dest="virtType", const="rhevm", help="Register guests using RHEV-M"
    )
    virtGroup.add_option(
        "--hyperv", action="store_const", dest="virtType", const="hyperv", help="Register guests using Hyper-V"
    )
    parser.add_option_group(virtGroup)

    managerGroup = OptionGroup(
        parser, "Subscription manager", "Choose where the host/guest associations should be reported"
    )
    managerGroup.add_option(
        "--sam",
        action="store_const",
        dest="smType",
        const=SAT6,
        default=SAT6,
        help="Report host/guest associations to the Subscription Asset Manager [default]",
    )
    managerGroup.add_option(
        "--satellite6",
        action="store_const",
        dest="smType",
        const=SAT6,
        help="Report host/guest associations to the Satellite 6 server",
    )
    managerGroup.add_option(
        "--satellite5",
        action="store_const",
        dest="smType",
        const=SAT5,
        help="Report host/guest associations to the Satellite 5 server",
    )
    managerGroup.add_option("--satellite", action="store_const", dest="smType", const=SAT5, help=SUPPRESS_HELP)
    parser.add_option_group(managerGroup)

    libvirtGroup = OptionGroup(parser, "Libvirt options", "Use these options with --libvirt")
    libvirtGroup.add_option(
        "--libvirt-owner",
        action="store",
        dest="owner",
        default="",
        help="Organization who has purchased subscriptions of the products, default is owner of current system",
    )
    libvirtGroup.add_option(
        "--libvirt-env",
        action="store",
        dest="env",
        default="",
        help="Environment where the server belongs to, default is environment of current system",
    )
    libvirtGroup.add_option(
        "--libvirt-server",
        action="store",
        dest="server",
        default="",
        help="URL of the libvirt server to connect to, default is empty for libvirt on local computer",
    )
    libvirtGroup.add_option(
        "--libvirt-username",
        action="store",
        dest="username",
        default="",
        help="Username for connecting to the libvirt daemon",
    )
    libvirtGroup.add_option(
        "--libvirt-password",
        action="store",
        dest="password",
        default="",
        help="Password for connecting to the libvirt daemon",
    )
    parser.add_option_group(libvirtGroup)

    esxGroup = OptionGroup(parser, "vCenter/ESX options", "Use these options with --esx")
    esxGroup.add_option(
        "--esx-owner",
        action="store",
        dest="owner",
        default="",
        help="Organization who has purchased subscriptions of the products",
    )
    esxGroup.add_option(
        "--esx-env", action="store", dest="env", default="", help="Environment where the vCenter server belongs to"
    )
    esxGroup.add_option(
        "--esx-server", action="store", dest="server", default="", help="URL of the vCenter server to connect to"
    )
    esxGroup.add_option(
        "--esx-username", action="store", dest="username", default="", help="Username for connecting to vCenter"
    )
    esxGroup.add_option(
        "--esx-password", action="store", dest="password", default="", help="Password for connecting to vCenter"
    )
    parser.add_option_group(esxGroup)

    rhevmGroup = OptionGroup(parser, "RHEV-M options", "Use these options with --rhevm")
    rhevmGroup.add_option(
        "--rhevm-owner",
        action="store",
        dest="owner",
        default="",
        help="Organization who has purchased subscriptions of the products",
    )
    rhevmGroup.add_option(
        "--rhevm-env", action="store", dest="env", default="", help="Environment where the RHEV-M belongs to"
    )
    rhevmGroup.add_option(
        "--rhevm-server",
        action="store",
        dest="server",
        default="",
        help="URL of the RHEV-M server to connect to (preferable use secure connection - https://<ip or domain name>:<secure port, usually 8443>)",
    )
    rhevmGroup.add_option(
        "--rhevm-username",
        action="store",
        dest="username",
        default="",
        help="Username for connecting to RHEV-M in the format username@domain",
    )
    rhevmGroup.add_option(
        "--rhevm-password", action="store", dest="password", default="", help="Password for connecting to RHEV-M"
    )
    parser.add_option_group(rhevmGroup)

    hypervGroup = OptionGroup(parser, "Hyper-V options", "Use these options with --hyperv")
    hypervGroup.add_option(
        "--hyperv-owner",
        action="store",
        dest="owner",
        default="",
        help="Organization who has purchased subscriptions of the products",
    )
    hypervGroup.add_option(
        "--hyperv-env", action="store", dest="env", default="", help="Environment where the Hyper-V belongs to"
    )
    hypervGroup.add_option(
        "--hyperv-server", action="store", dest="server", default="", help="URL of the Hyper-V server to connect to"
    )
    hypervGroup.add_option(
        "--hyperv-username", action="store", dest="username", default="", help="Username for connecting to Hyper-V"
    )
    hypervGroup.add_option(
        "--hyperv-password", action="store", dest="password", default="", help="Password for connecting to Hyper-V"
    )
    parser.add_option_group(hypervGroup)

    xenGroup = OptionGroup(parser, "XenServer options", "Use these options with --xen")
    xenGroup.add_option(
        "--xen-owner",
        action="store",
        dest="owner",
        default="",
        help="Organization who has purchased subscriptions of the products",
    )
    xenGroup.add_option(
        "--xen-env", action="store", dest="env", default="", help="Environment where the XenServer belongs to"
    )
    xenGroup.add_option(
        "--xen-server", action="store", dest="server", default="", help="URL of the XenServer server to connect to"
    )
    xenGroup.add_option(
        "--xen-username", action="store", dest="username", default="", help="Username for connecting to XenServer"
    )
    xenGroup.add_option(
        "--xen-password", action="store", dest="password", default="", help="Password for connecting to XenServer"
    )
    parser.add_option_group(xenGroup)

    satelliteGroup = OptionGroup(parser, "Satellite 5 options", "Use these options with --satellite5")
    satelliteGroup.add_option(
        "--satellite-server", action="store", dest="sat_server", default="", help="Satellite server URL"
    )
    satelliteGroup.add_option(
        "--satellite-username",
        action="store",
        dest="sat_username",
        default="",
        help="Username for connecting to Satellite server",
    )
    satelliteGroup.add_option(
        "--satellite-password",
        action="store",
        dest="sat_password",
        default="",
        help="Password for connecting to Satellite server",
    )
    parser.add_option_group(satelliteGroup)

    (cli_options, args) = parser.parse_args()

    options = GlobalConfig.fromFile(VIRTWHO_GENERAL_CONF_PATH)

    # Handle defaults from the command line options parser

    options.update(**parser.defaults)

    # Handle environment variables

    env = os.getenv("VIRTWHO_LOG_PER_CONFIG", "0").strip().lower()
    if env in ["1", "true"]:
        options.log_per_config = True

    env = os.getenv("VIRTWHO_LOG_DIR", log.DEFAULT_LOG_DIR).strip()
    if env != log.DEFAULT_LOG_DIR:
        options.log_dir = env
    elif options.log_per_config:
        options.log_dir = os.path.join(log.DEFAULT_LOG_DIR, "virtwho")

    env = os.getenv("VIRTWHO_LOG_FILE", log.DEFAULT_LOG_FILE).strip()
    if env != log.DEFAULT_LOG_FILE:
        options.log_file = env

    env = os.getenv("VIRTWHO_REPORTER_ID", "").strip()
    if len(env) > 0:
        options.reporter_id = env

    env = os.getenv("VIRTWHO_DEBUG", "0").strip().lower()
    if env in ["1", "true"] or cli_options.debug is True:
        options.debug = True

    # Used only when starting as service (initscript sets it to 1, systemd to 0)
    env = os.getenv("VIRTWHO_BACKGROUND", "0").strip().lower()
    options.background = env in ["1", "true"]

    log.init(options)
    logger = log.getLogger(name="init", queue=False)

    env = os.getenv("VIRTWHO_ONE_SHOT", "0").strip().lower()
    if env in ["1", "true"]:
        options.oneshot = True

    env = os.getenv("VIRTWHO_INTERVAL")
    if env:
        try:
            env = int(env.strip().lower())
            if env >= MinimumSendInterval:
                options.interval = env
            elif env < MinimumSendInterval:
                options.interval = MinimumSendInterval
        except ValueError:
            logger.warning("Interval is not number, ignoring")

    env = os.getenv("VIRTWHO_SAM", "0").strip().lower()
    if env in ["1", "true"]:
        options.smType = SAT6

    env = os.getenv("VIRTWHO_SATELLITE6", "0").strip().lower()
    if env in ["1", "true"]:
        options.smType = SAT6

    env = os.getenv("VIRTWHO_SATELLITE5", "0").strip().lower()
    if env in ["1", "true"]:
        options.smType = SAT5

    env = os.getenv("VIRTWHO_SATELLITE", "0").strip().lower()
    if env in ["1", "true"]:
        options.smType = SAT5

    env = os.getenv("VIRTWHO_LIBVIRT", "0").strip().lower()
    if env in ["1", "true"]:
        options.virtType = "libvirt"

    env = os.getenv("VIRTWHO_VDSM", "0").strip().lower()
    if env in ["1", "true"]:
        options.virtType = "vdsm"

    env = os.getenv("VIRTWHO_ESX", "0").strip().lower()
    if env in ["1", "true"]:
        options.virtType = "esx"

    env = os.getenv("VIRTWHO_XEN", "0").strip().lower()
    if env in ["1", "true"]:
        options.virtType = "xen"

    env = os.getenv("VIRTWHO_RHEVM", "0").strip().lower()
    if env in ["1", "true"]:
        options.virtType = "rhevm"

    env = os.getenv("VIRTWHO_HYPERV", "0").strip().lower()
    if env in ["1", "true"]:
        options.virtType = "hyperv"

    def getNonDefaultOptions(cli_options, defaults):
        return dict(
            (option, value)
            for option, value in cli_options.iteritems()
            if defaults.get(option, NotSetSentinel()) != value
        )

    # Handle non-default command line options
    options.update(**getNonDefaultOptions(vars(cli_options), parser.defaults))

    # Check Env
    def checkEnv(variable, option, name, required=True):
        """
        If `option` is empty, check environment `variable` and return its value.
        Exit if it's still empty
        """
        if not option or len(option) == 0:
            option = os.getenv(variable, "").strip()
        if required and (not option or len(option) == 0):
            raise OptionError("Required parameter '%s' is not set, exiting" % name)
        return option

    if options.smType == SAT5:
        options.sat_server = checkEnv("VIRTWHO_SATELLITE_SERVER", options.sat_server, "satellite-server")
        options.sat_username = checkEnv("VIRTWHO_SATELLITE_USERNAME", options.sat_username, "satellite-username")
        if len(options.sat_password) == 0:
            options.sat_password = os.getenv("VIRTWHO_SATELLITE_PASSWORD", "")

    if options.virtType == "libvirt":
        options.owner = checkEnv("VIRTWHO_LIBVIRT_OWNER", options.owner, "owner", required=False)
        options.env = checkEnv("VIRTWHO_LIBVIRT_ENV", options.env, "env", required=False)
        options.server = checkEnv("VIRTWHO_LIBVIRT_SERVER", options.server, "server", required=False)
        options.username = checkEnv("VIRTWHO_LIBVIRT_USERNAME", options.username, "username", required=False)
        if len(options.password) == 0:
            options.password = os.getenv("VIRTWHO_LIBVIRT_PASSWORD", "")

    if options.virtType == "esx":
        options.owner = checkEnv("VIRTWHO_ESX_OWNER", options.owner, "owner", required=False)
        options.env = checkEnv("VIRTWHO_ESX_ENV", options.env, "env", required=False)
        options.server = checkEnv("VIRTWHO_ESX_SERVER", options.server, "server")
        options.username = checkEnv("VIRTWHO_ESX_USERNAME", options.username, "username")
        if len(options.password) == 0:
            options.password = os.getenv("VIRTWHO_ESX_PASSWORD", "")

    if options.virtType == "xen":
        options.owner = checkEnv("VIRTWHO_XEN_OWNER", options.owner, "owner", required=False)
        options.env = checkEnv("VIRTWHO_XEN_ENV", options.env, "env", required=False)
        options.server = checkEnv("VIRTWHO_XEN_SERVER", options.server, "server")
        options.username = checkEnv("VIRTWHO_XEN_USERNAME", options.username, "username")
        if len(options.password) == 0:
            options.password = os.getenv("VIRTWHO_XEN_PASSWORD", "")

    if options.virtType == "rhevm":
        options.owner = checkEnv("VIRTWHO_RHEVM_OWNER", options.owner, "owner", required=False)
        options.env = checkEnv("VIRTWHO_RHEVM_ENV", options.env, "env", required=False)
        options.server = checkEnv("VIRTWHO_RHEVM_SERVER", options.server, "server")
        options.username = checkEnv("VIRTWHO_RHEVM_USERNAME", options.username, "username")
        if len(options.password) == 0:
            options.password = os.getenv("VIRTWHO_RHEVM_PASSWORD", "")

    if options.virtType == "hyperv":
        options.owner = checkEnv("VIRTWHO_HYPERV_OWNER", options.owner, "owner", required=False)
        options.env = checkEnv("VIRTWHO_HYPERV_ENV", options.env, "env", required=False)
        options.server = checkEnv("VIRTWHO_HYPERV_SERVER", options.server, "server")
        options.username = checkEnv("VIRTWHO_HYPERV_USERNAME", options.username, "username")
        if len(options.password) == 0:
            options.password = os.getenv("VIRTWHO_HYPERV_PASSWORD", "")

    if options.smType == "sam" and options.virtType in ("esx", "rhevm", "hyperv", "xen"):
        if not options.owner:
            raise OptionError(
                "Option --%s-owner (or VIRTWHO_%s_OWNER environment variable) needs to be set"
                % (options.virtType, options.virtType.upper())
            )
        if not options.env:
            raise OptionError(
                "Option --%s-env (or VIRTWHO_%s_ENV environment variable) needs to be set"
                % (options.virtType, options.virtType.upper())
            )

    if not options.interval or options.interval == parser.defaults["interval"]:
        logger.info("Interval set to the default of %d seconds.", DefaultInterval)
        options.interval = DefaultInterval
    elif options.interval < MinimumSendInterval:
        logger.warning(
            "Interval value can't be lower than {min} seconds. Default value of {min} seconds will be used.".format(
                min=MinimumSendInterval
            )
        )
        options.interval = MinimumSendInterval

    if options.print_:
        options.oneshot = True

    return logger, options
예제 #19
0
    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)

        # This set is used both for oneshot mode and to bypass rate-limit
        # when virt-who is starting
        self.oneshot_remaining = set(virt.config.name for virt in self.virts)

        if len(self.virts) == 0:
            err = "virt-who can't be started: no suitable virt backend found"
            self.logger.error(err)
            exit(1, err)

        # 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 immediately
        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" hasn\'t changed, not sending',
                            report.config.name)
                    else:
                        if report.config.name in self.oneshot_remaining:
                            # Send the report immediately
                            self.oneshot_remaining.remove(report.config.name)
                            if not self.options.print_:
                                self.send_report(report.config.name, report)
                            else:
                                self.queued_reports[
                                    report.config.name] = report
                        else:
                            self.queued_reports[report.config.name] = report
                elif report in ['exit', 'reload']:
                    # Reload and exit reports takes priority, do not process
                    # any other reports
                    break

                # Get next report from queue
                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 and not self.reports_in_progress:
                break

        self.queue = None
        self.stop_virts()

        self.virt = []
        if self.options.print_:
            return self.queued_reports
예제 #20
0
def parseOptions():
    parser = OptionParserEpilog(
        usage=
        "virt-who [-d] [-i INTERVAL] [-o] [--sam|--satellite5|--satellite6] [--libvirt|--vdsm|--esx|--rhevm|--hyperv|--xen]",
        description=
        "Agent for reporting virtual guest IDs to subscription manager",
        epilog=
        "virt-who also reads environment variables. They have the same name as command line arguments but uppercased, with underscore instead of dash and prefixed with VIRTWHO_ (e.g. VIRTWHO_ONE_SHOT). Empty variables are considered as disabled, non-empty as enabled"
    )
    parser.add_option("-d",
                      "--debug",
                      action="store_true",
                      dest="debug",
                      default=False,
                      help="Enable debugging output")
    parser.add_option("-o",
                      "--one-shot",
                      action="store_true",
                      dest="oneshot",
                      default=False,
                      help="Send the list of guest IDs and exit immediately")
    parser.add_option(
        "-i",
        "--interval",
        type="int",
        dest="interval",
        default=NotSetSentinel(),
        help=
        "Acquire list of virtual guest each N seconds. Send if changes are detected."
    )
    parser.add_option(
        "-p",
        "--print",
        action="store_true",
        dest="print_",
        default=False,
        help=
        "Print the host/guest association obtained from virtualization backend (implies oneshot)"
    )
    parser.add_option(
        "-c",
        "--config",
        action="append",
        dest="configs",
        default=[],
        help=
        "Configuration file that will be processed, can be used multiple times"
    )
    parser.add_option(
        "-m",
        "--log-per-config",
        action="store_true",
        dest="log_per_config",
        default=NotSetSentinel(),
        help=
        "Write one log file per configured virtualization backend.\nImplies a log_dir of %s/virtwho (Default: all messages are written to a single log file)"
        % log.DEFAULT_LOG_DIR)
    parser.add_option(
        "-l",
        "--log-dir",
        action="store",
        dest="log_dir",
        default=log.DEFAULT_LOG_DIR,
        help="The absolute path of the directory to log to. (Default '%s')" %
        log.DEFAULT_LOG_DIR)
    parser.add_option("-f",
                      "--log-file",
                      action="store",
                      dest="log_file",
                      default=log.DEFAULT_LOG_FILE,
                      help="The file name to write logs to. (Default '%s')" %
                      log.DEFAULT_LOG_FILE)
    parser.add_option(
        "-r",
        "--reporter-id",
        action="store",
        dest="reporter_id",
        default=NotSetSentinel(),
        help=
        "Label host/guest associations obtained by this instance of virt-who with the provided id."
    )

    virtGroup = OptionGroup(
        parser, "Virtualization backend",
        "Choose virtualization backend that should be used to gather host/guest associations"
    )
    virtGroup.add_option("--libvirt",
                         action="store_const",
                         dest="virtType",
                         const="libvirt",
                         default=None,
                         help="Use libvirt to list virtual guests [default]")
    virtGroup.add_option("--vdsm",
                         action="store_const",
                         dest="virtType",
                         const="vdsm",
                         help="Use vdsm to list virtual guests")
    virtGroup.add_option("--esx",
                         action="store_const",
                         dest="virtType",
                         const="esx",
                         help="Register ESX machines using vCenter")
    virtGroup.add_option("--xen",
                         action="store_const",
                         dest="virtType",
                         const="xen",
                         help="Register XEN machines using XenServer")
    virtGroup.add_option("--rhevm",
                         action="store_const",
                         dest="virtType",
                         const="rhevm",
                         help="Register guests using RHEV-M")
    virtGroup.add_option("--hyperv",
                         action="store_const",
                         dest="virtType",
                         const="hyperv",
                         help="Register guests using Hyper-V")
    parser.add_option_group(virtGroup)

    managerGroup = OptionGroup(
        parser, "Subscription manager",
        "Choose where the host/guest associations should be reported")
    managerGroup.add_option(
        "--sam",
        action="store_const",
        dest="smType",
        const=SAT6,
        default=SAT6,
        help=
        "Report host/guest associations to the Subscription Asset Manager [default]"
    )
    managerGroup.add_option(
        "--satellite6",
        action="store_const",
        dest="smType",
        const=SAT6,
        help="Report host/guest associations to the Satellite 6 server")
    managerGroup.add_option(
        "--satellite5",
        action="store_const",
        dest="smType",
        const=SAT5,
        help="Report host/guest associations to the Satellite 5 server")
    managerGroup.add_option("--satellite",
                            action="store_const",
                            dest="smType",
                            const=SAT5,
                            help=SUPPRESS_HELP)
    parser.add_option_group(managerGroup)

    libvirtGroup = OptionGroup(parser, "Libvirt options",
                               "Use these options with --libvirt")
    libvirtGroup.add_option(
        "--libvirt-owner",
        action="store",
        dest="owner",
        default="",
        help=
        "Organization who has purchased subscriptions of the products, default is owner of current system"
    )
    libvirtGroup.add_option(
        "--libvirt-env",
        action="store",
        dest="env",
        default="",
        help=
        "Environment where the server belongs to, default is environment of current system"
    )
    libvirtGroup.add_option(
        "--libvirt-server",
        action="store",
        dest="server",
        default="",
        help=
        "URL of the libvirt server to connect to, default is empty for libvirt on local computer"
    )
    libvirtGroup.add_option(
        "--libvirt-username",
        action="store",
        dest="username",
        default="",
        help="Username for connecting to the libvirt daemon")
    libvirtGroup.add_option(
        "--libvirt-password",
        action="store",
        dest="password",
        default="",
        help="Password for connecting to the libvirt daemon")
    parser.add_option_group(libvirtGroup)

    esxGroup = OptionGroup(parser, "vCenter/ESX options",
                           "Use these options with --esx")
    esxGroup.add_option(
        "--esx-owner",
        action="store",
        dest="owner",
        default="",
        help="Organization who has purchased subscriptions of the products")
    esxGroup.add_option("--esx-env",
                        action="store",
                        dest="env",
                        default="",
                        help="Environment where the vCenter server belongs to")
    esxGroup.add_option("--esx-server",
                        action="store",
                        dest="server",
                        default="",
                        help="URL of the vCenter server to connect to")
    esxGroup.add_option("--esx-username",
                        action="store",
                        dest="username",
                        default="",
                        help="Username for connecting to vCenter")
    esxGroup.add_option("--esx-password",
                        action="store",
                        dest="password",
                        default="",
                        help="Password for connecting to vCenter")
    parser.add_option_group(esxGroup)

    rhevmGroup = OptionGroup(parser, "RHEV-M options",
                             "Use these options with --rhevm")
    rhevmGroup.add_option(
        "--rhevm-owner",
        action="store",
        dest="owner",
        default="",
        help="Organization who has purchased subscriptions of the products")
    rhevmGroup.add_option("--rhevm-env",
                          action="store",
                          dest="env",
                          default="",
                          help="Environment where the RHEV-M belongs to")
    rhevmGroup.add_option(
        "--rhevm-server",
        action="store",
        dest="server",
        default="",
        help=
        "URL of the RHEV-M server to connect to (preferable use secure connection - https://<ip or domain name>:<secure port, usually 8443>)"
    )
    rhevmGroup.add_option(
        "--rhevm-username",
        action="store",
        dest="username",
        default="",
        help="Username for connecting to RHEV-M in the format username@domain")
    rhevmGroup.add_option("--rhevm-password",
                          action="store",
                          dest="password",
                          default="",
                          help="Password for connecting to RHEV-M")
    parser.add_option_group(rhevmGroup)

    hypervGroup = OptionGroup(parser, "Hyper-V options",
                              "Use these options with --hyperv")
    hypervGroup.add_option(
        "--hyperv-owner",
        action="store",
        dest="owner",
        default="",
        help="Organization who has purchased subscriptions of the products")
    hypervGroup.add_option("--hyperv-env",
                           action="store",
                           dest="env",
                           default="",
                           help="Environment where the Hyper-V belongs to")
    hypervGroup.add_option("--hyperv-server",
                           action="store",
                           dest="server",
                           default="",
                           help="URL of the Hyper-V server to connect to")
    hypervGroup.add_option("--hyperv-username",
                           action="store",
                           dest="username",
                           default="",
                           help="Username for connecting to Hyper-V")
    hypervGroup.add_option("--hyperv-password",
                           action="store",
                           dest="password",
                           default="",
                           help="Password for connecting to Hyper-V")
    parser.add_option_group(hypervGroup)

    xenGroup = OptionGroup(parser, "XenServer options",
                           "Use these options with --xen")
    xenGroup.add_option(
        "--xen-owner",
        action="store",
        dest="owner",
        default="",
        help="Organization who has purchased subscriptions of the products")
    xenGroup.add_option("--xen-env",
                        action="store",
                        dest="env",
                        default="",
                        help="Environment where the XenServer belongs to")
    xenGroup.add_option("--xen-server",
                        action="store",
                        dest="server",
                        default="",
                        help="URL of the XenServer server to connect to")
    xenGroup.add_option("--xen-username",
                        action="store",
                        dest="username",
                        default="",
                        help="Username for connecting to XenServer")
    xenGroup.add_option("--xen-password",
                        action="store",
                        dest="password",
                        default="",
                        help="Password for connecting to XenServer")
    parser.add_option_group(xenGroup)

    satelliteGroup = OptionGroup(parser, "Satellite 5 options",
                                 "Use these options with --satellite5")
    satelliteGroup.add_option("--satellite-server",
                              action="store",
                              dest="sat_server",
                              default="",
                              help="Satellite server URL")
    satelliteGroup.add_option(
        "--satellite-username",
        action="store",
        dest="sat_username",
        default="",
        help="Username for connecting to Satellite server")
    satelliteGroup.add_option(
        "--satellite-password",
        action="store",
        dest="sat_password",
        default="",
        help="Password for connecting to Satellite server")
    parser.add_option_group(satelliteGroup)

    (cli_options, args) = parser.parse_args()

    options = GlobalConfig.fromFile(VIRTWHO_GENERAL_CONF_PATH)

    # Handle defaults from the command line options parser

    options.update(**parser.defaults)

    # Handle environment variables

    env = os.getenv("VIRTWHO_LOG_PER_CONFIG", "0").strip().lower()
    if env in ["1", "true"]:
        options.log_per_config = True

    env = os.getenv("VIRTWHO_LOG_DIR", log.DEFAULT_LOG_DIR).strip()
    if env != log.DEFAULT_LOG_DIR:
        options.log_dir = env
    elif options.log_per_config:
        options.log_dir = os.path.join(log.DEFAULT_LOG_DIR, 'virtwho')

    env = os.getenv("VIRTWHO_LOG_FILE", log.DEFAULT_LOG_FILE).strip()
    if env != log.DEFAULT_LOG_FILE:
        options.log_file = env

    env = os.getenv("VIRTWHO_REPORTER_ID", "").strip()
    if len(env) > 0:
        options.reporter_id = env

    env = os.getenv("VIRTWHO_DEBUG", "0").strip().lower()
    if env in ["1", "true"] or cli_options.debug is True:
        options.debug = True

    # Used only when starting as service (initscript sets it to 1, systemd to 0)
    env = os.getenv("VIRTWHO_BACKGROUND", "0").strip().lower()
    options.background = env in ["1", "true"]

    log.init(options)
    logger = log.getLogger(name='init', queue=False)

    env = os.getenv("VIRTWHO_ONE_SHOT", "0").strip().lower()
    if env in ["1", "true"]:
        options.oneshot = True

    env = os.getenv("VIRTWHO_INTERVAL")
    if env:
        try:
            env = int(env.strip().lower())
            if env >= MinimumSendInterval:
                options.interval = env
            elif env < MinimumSendInterval:
                options.interval = MinimumSendInterval
        except ValueError:
            logger.warning("Interval is not number, ignoring")

    env = os.getenv("VIRTWHO_SAM", "0").strip().lower()
    if env in ["1", "true"]:
        options.smType = SAT6

    env = os.getenv("VIRTWHO_SATELLITE6", "0").strip().lower()
    if env in ["1", "true"]:
        options.smType = SAT6

    env = os.getenv("VIRTWHO_SATELLITE5", "0").strip().lower()
    if env in ["1", "true"]:
        options.smType = SAT5

    env = os.getenv("VIRTWHO_SATELLITE", "0").strip().lower()
    if env in ["1", "true"]:
        options.smType = SAT5

    env = os.getenv("VIRTWHO_LIBVIRT", "0").strip().lower()
    if env in ["1", "true"]:
        options.virtType = "libvirt"

    env = os.getenv("VIRTWHO_VDSM", "0").strip().lower()
    if env in ["1", "true"]:
        options.virtType = "vdsm"

    env = os.getenv("VIRTWHO_ESX", "0").strip().lower()
    if env in ["1", "true"]:
        options.virtType = "esx"

    env = os.getenv("VIRTWHO_XEN", "0").strip().lower()
    if env in ["1", "true"]:
        options.virtType = "xen"

    env = os.getenv("VIRTWHO_RHEVM", "0").strip().lower()
    if env in ["1", "true"]:
        options.virtType = "rhevm"

    env = os.getenv("VIRTWHO_HYPERV", "0").strip().lower()
    if env in ["1", "true"]:
        options.virtType = "hyperv"

    def getNonDefaultOptions(cli_options, defaults):
        return dict((option, value)
                    for option, value in cli_options.iteritems()
                    if defaults.get(option, NotSetSentinel()) != value)

    # Handle non-default command line options
    options.update(**getNonDefaultOptions(vars(cli_options), parser.defaults))

    # Check Env
    def checkEnv(variable, option, name, required=True):
        """
        If `option` is empty, check environment `variable` and return its value.
        Exit if it's still empty
        """
        if not option or len(option) == 0:
            option = os.getenv(variable, "").strip()
        if required and (not option or len(option) == 0):
            raise OptionError("Required parameter '%s' is not set, exiting" %
                              name)
        return option

    if options.smType == SAT5:
        options.sat_server = checkEnv("VIRTWHO_SATELLITE_SERVER",
                                      options.sat_server, "satellite-server")
        options.sat_username = checkEnv("VIRTWHO_SATELLITE_USERNAME",
                                        options.sat_username,
                                        "satellite-username")
        if len(options.sat_password) == 0:
            options.sat_password = os.getenv("VIRTWHO_SATELLITE_PASSWORD", "")

    if options.virtType == "libvirt":
        options.owner = checkEnv("VIRTWHO_LIBVIRT_OWNER",
                                 options.owner,
                                 "owner",
                                 required=False)
        options.env = checkEnv("VIRTWHO_LIBVIRT_ENV",
                               options.env,
                               "env",
                               required=False)
        options.server = checkEnv("VIRTWHO_LIBVIRT_SERVER",
                                  options.server,
                                  "server",
                                  required=False)
        options.username = checkEnv("VIRTWHO_LIBVIRT_USERNAME",
                                    options.username,
                                    "username",
                                    required=False)
        if len(options.password) == 0:
            options.password = os.getenv("VIRTWHO_LIBVIRT_PASSWORD", "")

    if options.virtType == "esx":
        options.owner = checkEnv("VIRTWHO_ESX_OWNER",
                                 options.owner,
                                 "owner",
                                 required=False)
        options.env = checkEnv("VIRTWHO_ESX_ENV",
                               options.env,
                               "env",
                               required=False)
        options.server = checkEnv("VIRTWHO_ESX_SERVER", options.server,
                                  "server")
        options.username = checkEnv("VIRTWHO_ESX_USERNAME", options.username,
                                    "username")
        if len(options.password) == 0:
            options.password = os.getenv("VIRTWHO_ESX_PASSWORD", "")

    if options.virtType == "xen":
        options.owner = checkEnv("VIRTWHO_XEN_OWNER",
                                 options.owner,
                                 "owner",
                                 required=False)
        options.env = checkEnv("VIRTWHO_XEN_ENV",
                               options.env,
                               "env",
                               required=False)
        options.server = checkEnv("VIRTWHO_XEN_SERVER", options.server,
                                  "server")
        options.username = checkEnv("VIRTWHO_XEN_USERNAME", options.username,
                                    "username")
        if len(options.password) == 0:
            options.password = os.getenv("VIRTWHO_XEN_PASSWORD", "")

    if options.virtType == "rhevm":
        options.owner = checkEnv("VIRTWHO_RHEVM_OWNER",
                                 options.owner,
                                 "owner",
                                 required=False)
        options.env = checkEnv("VIRTWHO_RHEVM_ENV",
                               options.env,
                               "env",
                               required=False)
        options.server = checkEnv("VIRTWHO_RHEVM_SERVER", options.server,
                                  "server")
        options.username = checkEnv("VIRTWHO_RHEVM_USERNAME", options.username,
                                    "username")
        if len(options.password) == 0:
            options.password = os.getenv("VIRTWHO_RHEVM_PASSWORD", "")

    if options.virtType == "hyperv":
        options.owner = checkEnv("VIRTWHO_HYPERV_OWNER",
                                 options.owner,
                                 "owner",
                                 required=False)
        options.env = checkEnv("VIRTWHO_HYPERV_ENV",
                               options.env,
                               "env",
                               required=False)
        options.server = checkEnv("VIRTWHO_HYPERV_SERVER", options.server,
                                  "server")
        options.username = checkEnv("VIRTWHO_HYPERV_USERNAME",
                                    options.username, "username")
        if len(options.password) == 0:
            options.password = os.getenv("VIRTWHO_HYPERV_PASSWORD", "")

    if options.smType == 'sam' and options.virtType in ('esx', 'rhevm',
                                                        'hyperv', 'xen'):
        if not options.owner:
            raise OptionError(
                "Option --%s-owner (or VIRTWHO_%s_OWNER environment variable) needs to be set"
                % (options.virtType, options.virtType.upper()))
        if not options.env:
            raise OptionError(
                "Option --%s-env (or VIRTWHO_%s_ENV environment variable) needs to be set"
                % (options.virtType, options.virtType.upper()))

    if not options.interval or options.interval == parser.defaults['interval']:
        logger.info("Interval set to the default of %d seconds.",
                    DefaultInterval)
        options.interval = DefaultInterval
    elif options.interval < MinimumSendInterval:
        logger.warning(
            "Interval value can't be lower than {min} seconds. Default value of {min} seconds will be used."
            .format(min=MinimumSendInterval))
        options.interval = MinimumSendInterval

    if options.print_:
        options.oneshot = True

    return logger, options
예제 #21
0
파일: main.py 프로젝트: candlepin/virt-who
def main():
    logger = effective_config = None
    try:
        logger, effective_config = parse_options()
        # We now have the effective_config
    except OptionError as e:
        print(str(e), file=sys.stderr)
        exit(1, status="virt-who can't be started: %s" % str(e))

    lock = PIDLock(PIDFILE)
    if lock.is_locked():
        msg = "virt-who seems to be already running. If not, remove %s" % \
              PIDFILE
        print(msg, file=sys.stderr)
        exit(1, status=msg)

    if not effective_config[VW_GLOBAL].is_valid():
        message = "Required section 'global' is invalid:\n"
        message += "\n".join([msg for (level, msg) in effective_config[VW_GLOBAL].validation_messages])
        message += "\n"
        exit(1, "virt-who can't be started: %s" % message)

    valid_virt_sections = [(name, section) for (name, section) in effective_config.virt_sections()
                           if section.is_valid()]

    if not valid_virt_sections:
        err = "virt-who can't be started: no valid configuration found"
        logger.error(err)
        exit(1, err)

    global executor
    has_error = False
    try:
        executor = Executor(logger, effective_config)
    except (InvalidKeyFile, InvalidPasswordFormat) as e:
        logger.error(str(e))
        exit(1, "virt-who can't be started: %s" % str(e))

    if len(executor.dest_to_source_mapper.dests) == 0:
        if has_error:
            err = "virt-who can't be started: no valid destination found"
            logger.error(err)
            exit(1, err)

    for name, config in executor.dest_to_source_mapper.configs:
        logger.info('Using configuration "%s" ("%s" mode)', name,
                    config['type'])

    logger.info("Using reporter_id='%s'", effective_config[VW_GLOBAL]['reporter_id'])
    log.closeLogger(logger)

    with lock:
        signal.signal(signal.SIGHUP, reload)
        signal.signal(signal.SIGTERM, atexit_fn)

        executor.logger = logger = log.getLogger(name='main', queue=True)

        sd_notify("READY=1\nMAINPID=%d" % os.getpid())
        while True:
            try:
                return _main(executor)
            except ReloadRequest:
                logger.info("Reloading")
                continue
            except ExitRequest as e:
                exit(e.code, status=e.message)