def _get_env(self): env_addons = {} tox_fn = sh.joinpths(self.get_option("app_dir"), "tox.ini") if sh.isfile(tox_fn): # Suck out some settings from the tox file try: tox_cfg = cfg.BuiltinConfigParser(fns=[tox_fn]) env_values = tox_cfg.get("testenv", "setenv") or "" for env_line in env_values.splitlines(): env_line = env_line.strip() env_line = env_line.split("#")[0].strip() if not env_line: continue env_entry = env_line.split("=", 1) if len(env_entry) == 2: (name, value) = env_entry name = name.strip() value = value.strip() if name.lower() != "virtual_env": env_addons[name] = value if env_addons: LOG.debug("From %s we read in %s environment settings:", tox_fn, len(env_addons)) utils.log_object(env_addons, logger=LOG, level=logging.DEBUG) except IOError: pass return env_addons
def _on_finish(self, persona, groups): LOG.info("Tearing down your components.") LOG.debug("Final environment settings:") utils.log_object(env.get(), logger=LOG, level=logging.DEBUG, item_max_len=64)
def _get_env(self): env_addons = DEFAULT_ENV.copy() tox_fn = sh.joinpths(self.get_option('app_dir'), 'tox.ini') if sh.isfile(tox_fn): # Suck out some settings from the tox file try: tox_cfg = ini_parser.BuiltinConfigParser(fns=[tox_fn]) env_values = tox_cfg.get('testenv', 'setenv') or '' for env_line in env_values.splitlines(): env_line = env_line.strip() env_line = env_line.split("#")[0].strip() if not env_line: continue env_entry = env_line.split('=', 1) if len(env_entry) == 2: (name, value) = env_entry name = name.strip() value = value.strip() if name.lower() != 'virtual_env': env_addons[name] = value if env_addons: LOG.debug("From %s we read in %s environment settings:", tox_fn, len(env_addons)) utils.log_object(env_addons, logger=LOG, level=logging.DEBUG) except IOError: pass return env_addons
def _on_start(self, persona, component_order, instances): LOG.info("Booting up your components.") LOG.debug("Starting environment settings:") utils.log_object(env.get(), logger=LOG, level=logging.DEBUG, item_max_len=64) self._establish_passwords(component_order, instances) self._verify_components(component_order, instances) self._warm_components(component_order, instances)
def _create_package(self): files = self._gather_files() params = { "files": files, "requires": self._requirements(), "obsoletes": self._obsoletes(), "conflicts": self._conflicts(), "defines": self._defines(), "undefines": self._undefines(), "build": self._build_details(), "who": sh.getuser(), "date": utils.iso8601(), "patches": self._patches(), "details": self.details, } (_fn, content) = utils.load_template("packaging", "spec.tmpl") spec_base = self._make_fn("spec") spec_fn = sh.joinpths(self.build_paths["specs"], spec_base) LOG.debug("Creating spec file %s with params:", spec_fn) files["sources"].append("%s.tar.gz" % (spec_base)) utils.log_object(params, logger=LOG, level=logging.DEBUG) sh.write_file(spec_fn, utils.expand_template(content, params)) tar_it( sh.joinpths(self.build_paths["sources"], "%s.tar.gz" % (spec_base)), spec_base, wkdir=self.build_paths["specs"], )
def _get_env(self): env_addons = DEFAULT_ENV.copy() tox_fn = sh.joinpths(self.get_option("app_dir"), "tox.ini") if sh.isfile(tox_fn): # Suck out some settings from the tox file try: tox_cfg = cfg.BuiltinConfigParser(fns=[tox_fn]) env_values = tox_cfg.get("testenv", "setenv") or "" for env_line in env_values.splitlines(): env_line = env_line.strip() env_line = env_line.split("#")[0].strip() if not env_line: continue env_entry = env_line.split("=", 1) if len(env_entry) == 2: (name, value) = env_entry name = name.strip() value = value.strip() if name.lower() != "virtual_env": env_addons[name] = value if env_addons: LOG.debug("From %s we read in %s environment settings:", tox_fn, len(env_addons)) utils.log_object(env_addons, logger=LOG, level=logging.DEBUG) except IOError: pass if not colorizer.color_enabled(): env_addons["NOSE_OPENSTACK_COLOR"] = "0" if self.get_bool_option("verbose", default_value=True): env_addons["NOSE_OPENSTACK_STDOUT"] = "1" return env_addons
def _create_package(self): files = self._gather_files() params = { 'files': files, 'requires': self._requirements(), 'obsoletes': self._obsoletes(), 'conflicts': self._conflicts(), 'defines': self._defines(), 'undefines': self._undefines(), 'build': self._build_details(), 'who': sh.getuser(), 'date': utils.iso8601(), 'details': self.details, } (_fn, content) = utils.load_template('packaging', 'spec.tmpl') spec_base = self._make_fn("spec") spec_fn = sh.joinpths(self.build_paths['specs'], spec_base) LOG.debug("Creating spec file %s with params:", spec_fn) files['sources'].append("%s.tar.gz" % (spec_base)) utils.log_object(params, logger=LOG, level=logging.DEBUG) sh.write_file(spec_fn, utils.expand_template(content, params)) tar_it(sh.joinpths(self.build_paths['sources'], "%s.tar.gz" % (spec_base)), spec_base, wkdir=self.build_paths['specs'])
def _on_start(self, persona, groups): LOG.info("Booting up your components.") LOG.debug("Starting environment settings:") utils.log_object(env.get(), logger=LOG, level=logging.DEBUG, item_max_len=64) sh.mkdirslist(self.phase_dir) self._verify_components(groups) self._warm_components(groups)
def _on_start(self, persona, component_order, instances): LOG.info("Booting up your components.") LOG.debug("Starting environment settings:") utils.log_object(env.get(), logger=LOG, level=logging.DEBUG, item_max_len=64) sh.mkdirslist(self.phase_dir) self._establish_passwords(component_order, instances) self._verify_components(component_order, instances) self._warm_components(component_order, instances)
def construct_entry_point(fullname, *args, **kwargs): cls = import_entry_point(fullname) LOG.debug("Constructing %r (%s)", fullname, cls) if kwargs: LOG.debug("Kwargs are:") utils.log_object(kwargs, logger=LOG, level=logging.DEBUG) if args: LOG.debug("Args are:") utils.log_object(args, logger=LOG, level=logging.DEBUG) return cls(*args, **kwargs)
def _on_finish(self, persona, component_order, instances): LOG.info("Tearing down your components.") LOG.debug("Final environment settings:") utils.log_object(env.get(), logger=LOG, level=logging.DEBUG, item_max_len=64) exports_filename = "%s.rc" % (self.name) self._write_exports(component_order, instances, sh.joinpths("/etc/anvil", exports_filename))
def _construct_siblings(self, name, siblings, params, sibling_instances): there_siblings = {} for (action, cls_name) in siblings.items(): if action not in sibling_instances: sibling_instances[action] = {} cls = importer.import_entry_point(cls_name) sibling_params = utils.merge_dicts(params, self.cli_opts, preserve=True) sibling_params["instances"] = sibling_instances[action] LOG.debug("Construction of sibling component %r (%r) params are:", name, action) utils.log_object(sibling_params, logger=LOG, level=logging.DEBUG) a_sibling = cls(**sibling_params) # Update the sibling we are returning and the corresponding # siblings for that action (so that the sibling can have the # correct 'sibling' instances associated with it, if it needs those...) there_siblings[action] = a_sibling sibling_instances[action][name] = a_sibling return there_siblings
def _construct_instances(self, persona): """ Create component objects for each component in the persona. """ persona_subsystems = persona.wanted_subsystems or {} persona_opts = persona.component_options or {} instances = {} sibling_instances = {} for c in persona.wanted_components: ((cls, distro_opts), siblings) = self.distro.extract_component(c, self.lookup_name) LOG.debug("Constructing component %r (%s)", c, tu.obj_name(cls)) instance_params = {} instance_params['name'] = c # First create its siblings with a 'minimal' set of options # This is done, so that they will work in a minimal state, they do not # get access to the persona options since those are action specific (or could be), # if this is not useful, we can give them full access, unsure if its worse or better... instance_params['subsystems'] = {} instance_params['siblings'] = {} instance_params['passwords'] = self.passwords instance_params['distro'] = self.distro instance_params['options'] = self._merge_options( c, self._get_interp_options(c), distro_opts, {}) LOG.debug("Constructing %r siblings...", c) siblings = self._construct_siblings(c, siblings, instance_params, sibling_instances) # Now inject the full options instance_params['instances'] = instances instance_params['options'] = self._merge_options( c, self._get_interp_options(c), distro_opts, (persona_opts.get(c) or {})) instance_params['subsystems'] = self._merge_subsystems( (distro_opts.pop('subsystems', None) or {}), (persona_subsystems.get(c) or {})) instance_params['siblings'] = siblings instance_params = utils.merge_dicts(instance_params, self.cli_opts, preserve=True) LOG.debug("Construction of %r params are:", c) utils.log_object(instance_params, logger=LOG, level=logging.DEBUG) instances[c] = cls(**instance_params) return instances
def _construct_siblings(self, name, siblings, params, sibling_instances): there_siblings = {} for (action, cls_name) in siblings.items(): if action not in sibling_instances: sibling_instances[action] = {} cls = importer.import_entry_point(cls_name) sibling_params = utils.merge_dicts(params, self.cli_opts, preserve=True) sibling_params['instances'] = sibling_instances[action] LOG.debug("Construction of sibling component %r (%r) params are:", name, action) utils.log_object(sibling_params, logger=LOG, level=logging.DEBUG) a_sibling = cls(**sibling_params) # Update the sibling we are returning and the corresponding # siblings for that action (so that the sibling can have the # correct 'sibling' instances associated with it, if it needs those...) there_siblings[action] = a_sibling sibling_instances[action][name] = a_sibling return there_siblings
def _construct_instances(self, persona): """ Create component objects for each component in the persona. """ persona_subsystems = persona.wanted_subsystems or {} persona_opts = persona.component_options or {} instances = {} sibling_instances = {} for c in persona.wanted_components: ((cls, distro_opts), siblings) = self.distro.extract_component(c, self.lookup_name) LOG.debug("Constructing component %r (%s)", c, tu.obj_name(cls)) instance_params = {} instance_params["name"] = c # First create its siblings with a 'minimal' set of options # This is done, so that they will work in a minimal state, they do not # get access to the persona options since those are action specific (or could be), # if this is not useful, we can give them full access, unsure if its worse or better... instance_params["subsystems"] = {} instance_params["siblings"] = {} instance_params["passwords"] = self.passwords instance_params["distro"] = self.distro instance_params["options"] = self._merge_options(c, self._get_interp_options(c), distro_opts, {}) LOG.debug("Constructing %r siblings...", c) siblings = self._construct_siblings(c, siblings, instance_params, sibling_instances) # Now inject the full options instance_params["instances"] = instances instance_params["options"] = self._merge_options( c, self._get_interp_options(c), distro_opts, (persona_opts.get(c) or {}) ) instance_params["subsystems"] = self._merge_subsystems( (distro_opts.pop("subsystems", None) or {}), (persona_subsystems.get(c) or {}) ) instance_params["siblings"] = siblings instance_params = utils.merge_dicts(instance_params, self.cli_opts, preserve=True) LOG.debug("Construction of %r params are:", c) utils.log_object(instance_params, logger=LOG, level=logging.DEBUG) instances[c] = cls(**instance_params) return instances
def run(args): """Starts the execution after args have been parsed and logging has been setup. """ LOG.debug("CLI arguments are:") utils.log_object(args, logger=LOG, level=logging.DEBUG, item_max_len=128) # Keep the old args around so we have the full set to write out saved_args = dict(args) action = args.pop("action", '').strip().lower() if re.match(r"^moo[o]*$", action): return try: runner_cls = actions.class_for(action) except Exception as ex: raise excp.OptionException(str(ex)) if runner_cls.needs_sudo: ensure_perms() # Check persona file exists persona_fn = args.pop('persona_fn') if not persona_fn: raise excp.OptionException("No persona file name specified!") if not sh.isfile(persona_fn): raise excp.OptionException("Invalid persona file %r specified!" % (persona_fn)) # Check origin file exists origins_fn = args.pop('origins_fn') if not origins_fn: raise excp.OptionException("No origin file name specified!") if not sh.isfile(origins_fn): raise excp.OptionException("Invalid origin file %r specified!" % (origins_fn)) args['origins_fn'] = sh.abspth(origins_fn) # Determine the root directory... root_dir = sh.abspth(args.pop("dir")) (repeat_string, line_max_len) = utils.welcome() print(pprint.center_text("Action Runner", repeat_string, line_max_len)) # !! # Here on out we should be using the logger (and not print)!! # !! # Ensure the anvil dirs are there if others are about to use it... if not sh.isdir(root_dir): LOG.info("Creating anvil root directory at path: %s", root_dir) sh.mkdir(root_dir) try: for d in ANVIL_DIRS: if sh.isdir(d): continue LOG.info("Creating anvil auxiliary directory at path: %s", d) sh.mkdir(d) except OSError as e: LOG.warn("Failed ensuring auxiliary directories due to %s", e) # Load the origins... origins = _origins.load(args['origins_fn'], patch_file=args.get('origins_patch')) # Load the distro/s possible_distros = distro.load(settings.DISTRO_DIR, distros_patch=args.get('distros_patch')) # Load + match the persona to the possible distros... try: persona_obj = persona.load(persona_fn) except Exception as e: raise excp.OptionException("Error loading persona file: %s due to %s" % (persona_fn, e)) else: dist = persona_obj.match(possible_distros, origins) LOG.info('Persona selected distro: %s from %s possible distros', colorizer.quote(dist.name), len(possible_distros)) # Update the dist with any other info... dist.inject_platform_overrides(persona_obj.distro_updates, source=persona_fn) dist.inject_platform_overrides(origins, source=origins_fn) # Print it out... LOG.debug("Distro settings are:") for line in dist.pformat(item_max_len=128).splitlines(): LOG.debug(line) # Get the object we will be running with... runner = runner_cls(distro=dist, root_dir=root_dir, name=action, cli_opts=args) # Now that the settings are known to work, store them for next run store_current_settings(saved_args) LOG.info("Starting action %s on %s for distro: %s", colorizer.quote(action), colorizer.quote(utils.iso8601()), colorizer.quote(dist.name)) LOG.info("Using persona: %s", colorizer.quote(persona_fn)) LOG.info("Using origins: %s", colorizer.quote(origins_fn)) LOG.info("In root directory: %s", colorizer.quote(root_dir)) start_time = time.time() runner.run(persona_obj) end_time = time.time() pretty_time = utils.format_time(end_time - start_time) LOG.info("It took %s seconds or %s minutes to complete action %s.", colorizer.quote(pretty_time['seconds']), colorizer.quote(pretty_time['minutes']), colorizer.quote(action))
def _on_finish(self, persona, component_order, instances): LOG.info("Tearing down your components.") LOG.debug("Final environment settings:") utils.log_object(env.get(), logger=LOG, level=logging.DEBUG, item_max_len=64)
def get_directory_details(path, pbr_version=None): if not sh.isdir(path): raise IOError("Can not detail non-existent directory %s" % (path)) # Check if we already got the details of this dir previously with EGGS_DETAILED_LOCK: path = sh.abspth(path) cache_key = "d:%s" % (sh.abspth(path)) if cache_key in EGGS_DETAILED: return EGGS_DETAILED[cache_key] details = None skip_paths = [ sh.joinpths(path, "PKG-INFO"), sh.joinpths(path, "EGG-INFO"), ] skip_paths.extend(glob.glob(sh.joinpths(path, "*.egg-info"))) if any(sh.exists(a_path) for a_path in skip_paths): # Some packages seem to not support the 'egg_info' call and # provide there own path/file that contains this information # already, so just use it if we can get at it... # # Ie for pyyaml3.x: # # error: invalid command 'egg_info' details = pkginfo.Develop(path) if not details or not details.name: cmd = [sys.executable, 'setup.py', 'egg_info'] if pbr_version: env_overrides = { "PBR_VERSION": str(pbr_version), } else: env_overrides = {} sh.execute(cmd, cwd=path, env_overrides=env_overrides) details = pkginfo.get_metadata(path) if not details or not details.name: raise RuntimeError("No egg detail information discovered" " at '%s'" % path) egg_details = { 'req': create_requirement(details.name, version=details.version), } for attr_name in [ 'description', 'author', 'version', 'name', 'summary' ]: egg_details[attr_name] = getattr(details, attr_name) for attr_name in ['description', 'author', 'summary']: attr_value = egg_details[attr_name] if isinstance(attr_value, six.text_type): # Fix any unicode which will cause unicode decode failures... # versions or names shouldn't be unicode, and the rest # we don't really care about being unicode (since its # just used for logging right now anyway...). # # The reason this is done is that 'elasticsearch' seems to # have a unicode author name, and that causes the log_object # to blowup, so just avoid that by replacing this information # in the first place. egg_details[attr_name] = attr_value.encode("ascii", errors='replace') LOG.debug("Extracted '%s' egg detail information:", path) utils.log_object(egg_details, logger=LOG, level=logging.DEBUG) EGGS_DETAILED[cache_key] = egg_details return egg_details
def run(args): """Starts the execution after args have been parsed and logging has been setup. """ LOG.debug("CLI arguments are:") utils.log_object(args, logger=LOG, level=logging.DEBUG, item_max_len=128) # Keep the old args around so we have the full set to write out saved_args = dict(args) action = args.pop("action", '').strip().lower() if re.match(r"^moo[o]*$", action): return try: runner_cls = actions.class_for(action) except Exception as ex: raise excp.OptionException(str(ex)) if runner_cls.needs_sudo: ensure_perms() persona_fn = args.pop('persona_fn') if not persona_fn: raise excp.OptionException("No persona file name specified!") if not sh.isfile(persona_fn): raise excp.OptionException("Invalid persona file %r specified!" % (persona_fn)) # Determine the root directory... root_dir = sh.abspth(args.pop("dir")) (repeat_string, line_max_len) = utils.welcome() print(pprint.center_text("Action Runner", repeat_string, line_max_len)) # !! # Here on out we should be using the logger (and not print)!! # !! # Stash the dryrun value (if any) if 'dryrun' in args: sh.set_dry_run(args['dryrun']) # Ensure the anvil dirs are there if others are about to use it... ensure_anvil_dirs(root_dir) # Load the distro dist = distro.load(settings.DISTRO_DIR) # Load + verify the person try: persona_obj = persona.load(persona_fn) persona_obj.verify(dist) except Exception as e: raise excp.OptionException("Error loading persona file: %s due to %s" % (persona_fn, e)) yum.YumDependencyHandler.jobs = args["jobs"] # Get the object we will be running with... runner = runner_cls(distro=dist, root_dir=root_dir, name=action, cli_opts=args) # Now that the settings are known to work, store them for next run store_current_settings(saved_args) LOG.info("Starting action %s on %s for distro: %s", colorizer.quote(action), colorizer.quote(utils.iso8601()), colorizer.quote(dist.name)) LOG.info("Using persona: %s", colorizer.quote(persona_fn)) LOG.info("In root directory: %s", colorizer.quote(root_dir)) start_time = time.time() runner.run(persona_obj) end_time = time.time() pretty_time = utils.format_time(end_time - start_time) LOG.info("It took %s seconds or %s minutes to complete action %s.", colorizer.quote(pretty_time['seconds']), colorizer.quote(pretty_time['minutes']), colorizer.quote(action))
def run(args): """ Starts the execution after args have been parsed and logging has been setup. """ LOG.debug("CLI arguments are:") utils.log_object(args, logger=LOG, level=logging.DEBUG, item_max_len=128) # Keep the old args around so we have the full set to write out saved_args = dict(args) action = args.pop("action", '').strip().lower() try: runner_cls = actions.class_for(action) except Exception as ex: raise excp.OptionException(str(ex)) if runner_cls.needs_sudo: ensure_perms() persona_fn = args.pop('persona_fn') if not persona_fn: raise excp.OptionException("No persona file name specified!") if not sh.isfile(persona_fn): raise excp.OptionException("Invalid persona file %r specified!" % (persona_fn)) # Determine + setup the root directory... # If not provided attempt to locate it via the environment control files args_root_dir = args.pop("dir") root_dir = env.get_key('INSTALL_ROOT') if not root_dir: root_dir = args_root_dir if not root_dir: root_dir = sh.joinpths(sh.gethomedir(), 'openstack') root_dir = sh.abspth(root_dir) (repeat_string, line_max_len) = utils.welcome() print(center_text("Action Runner", repeat_string, line_max_len)) # !! # Here on out we should be using the logger (and not print)!! # !! # Stash the dryrun value (if any) if 'dryrun' in args: sh.set_dry_run(args['dryrun']) # Ensure the anvil dirs are there if others are about to use it... ensure_anvil_dirs(root_dir) # Load the distro dist = distro.load(settings.DISTRO_DIR) # Load + verify the person try: persona_obj = persona.load(persona_fn) persona_obj.verify(dist) except Exception as e: raise excp.OptionException("Error loading persona file: %s due to %s" % (persona_fn, e)) # Get the object we will be running with... runner = runner_cls(distro=dist, root_dir=root_dir, name=action, cli_opts=args) # Now that the settings are known to work, store them for next run store_current_settings(saved_args) LOG.info("Starting action %s on %s for distro: %s", colorizer.quote(action), colorizer.quote(utils.iso8601()), colorizer.quote(dist.name)) LOG.info("Using persona: %s", colorizer.quote(persona_fn)) LOG.info("In root directory: %s", colorizer.quote(root_dir)) start_time = time.time() runner.run(persona_obj) end_time = time.time() pretty_time = utils.format_time(end_time - start_time) LOG.info("It took %s seconds or %s minutes to complete action %s.", colorizer.quote(pretty_time['seconds']), colorizer.quote(pretty_time['minutes']), colorizer.quote(action))
def run(args): """ Starts the execution after args have been parsed and logging has been setup. Arguments: N/A Returns: True for success to run, False for failure to start """ LOG.debug("CLI arguments are:") utils.log_object(args, logger=LOG, level=logging.DEBUG, item_max_len=128) # Keep the old args around so we have the full set to write out saved_args = dict(args) action = args.pop("action", '').strip().lower() if action not in actions.names(): raise excp.OptionException("Invalid action name %r specified!" % (action)) # Determine + setup the root directory... # If not provided attempt to locate it via the environment control files args_root_dir = args.pop("dir") root_dir = env.get_key('INSTALL_ROOT') if not root_dir: root_dir = args_root_dir if not root_dir: root_dir = sh.joinpths(sh.gethomedir(), 'openstack') root_dir = sh.abspth(root_dir) sh.mkdir(root_dir) persona_fn = args.pop('persona_fn') if not persona_fn: raise excp.OptionException("No persona file name specified!") if not sh.isfile(persona_fn): raise excp.OptionException("Invalid persona file %r specified!" % (persona_fn)) # !! # Here on out we should be using the logger (and not print)!! # !! # Stash the dryrun value (if any) if 'dryrun' in args: env.set("ANVIL_DRYRUN", str(args['dryrun'])) # Ensure the anvil etc dir is there if others are about to use it ensure_anvil_dir() # Load the distro dist = distro.load(settings.DISTRO_DIR) # Load + verify the person try: persona_obj = persona.load(persona_fn) persona_obj.verify(dist) except Exception as e: raise excp.OptionException("Error loading persona file: %s due to %s" % (persona_fn, e)) # Get the object we will be running with... runner_cls = actions.class_for(action) runner = runner_cls(distro=dist, root_dir=root_dir, name=action, cli_opts=args) (repeat_string, line_max_len) = utils.welcome() print(center_text("Action Runner", repeat_string, line_max_len)) # Now that the settings are known to work, store them for next run store_current_settings(saved_args) LOG.info("Starting action %s on %s for distro: %s", colorizer.quote(action), colorizer.quote(utils.iso8601()), colorizer.quote(dist.name)) LOG.info("Using persona: %s", colorizer.quote(persona_fn)) LOG.info("In root directory: %s", colorizer.quote(root_dir)) start_time = time.time() runner.run(persona_obj) end_time = time.time() pretty_time = utils.format_time(end_time - start_time) LOG.info("It took %s seconds or %s minutes to complete action %s.", colorizer.quote(pretty_time['seconds']), colorizer.quote(pretty_time['minutes']), colorizer.quote(action))
def get_directory_details(path, pbr_version=None): if not sh.isdir(path): raise IOError("Can not detail non-existent directory %s" % (path)) # Check if we already got the details of this dir previously with EGGS_DETAILED_LOCK: path = sh.abspth(path) cache_key = "d:%s" % (sh.abspth(path)) if cache_key in EGGS_DETAILED: return EGGS_DETAILED[cache_key] details = None skip_paths = [ sh.joinpths(path, "PKG-INFO"), sh.joinpths(path, "EGG-INFO"), ] skip_paths.extend(glob.glob(sh.joinpths(path, "*.egg-info"))) if any(sh.exists(a_path) for a_path in skip_paths): # Some packages seem to not support the 'egg_info' call and # provide there own path/file that contains this information # already, so just use it if we can get at it... # # Ie for pyyaml3.x: # # error: invalid command 'egg_info' details = pkginfo.Develop(path) if not details or not details.name: cmd = [sys.executable, 'setup.py', 'egg_info'] if pbr_version: env_overrides = { "PBR_VERSION": str(pbr_version), } else: env_overrides = {} sh.execute(cmd, cwd=path, env_overrides=env_overrides) details = pkginfo.get_metadata(path) if not details or not details.name: raise RuntimeError("No egg detail information discovered" " at '%s'" % path) egg_details = { 'req': create_requirement(details.name, version=details.version), } for attr_name in ['description', 'author', 'version', 'name', 'summary']: egg_details[attr_name] = getattr(details, attr_name) for attr_name in ['description', 'author', 'summary']: attr_value = egg_details[attr_name] if isinstance(attr_value, six.text_type): # Fix any unicode which will cause unicode decode failures... # versions or names shouldn't be unicode, and the rest # we don't really care about being unicode (since its # just used for logging right now anyway...). # # The reason this is done is that 'elasticsearch' seems to # have a unicode author name, and that causes the log_object # to blowup, so just avoid that by replacing this information # in the first place. egg_details[attr_name] = attr_value.encode("ascii", errors='replace') LOG.debug("Extracted '%s' egg detail information:", path) utils.log_object(egg_details, logger=LOG, level=logging.DEBUG) EGGS_DETAILED[cache_key] = egg_details return egg_details
def run(args): """Starts the execution after args have been parsed and logging has been setup. """ LOG.debug("CLI arguments are:") utils.log_object(args, logger=LOG, level=logging.DEBUG, item_max_len=128) # Keep the old args around so we have the full set to write out saved_args = dict(args) action = args.pop("action", "").strip().lower() if re.match(r"^moo[o]*$", action): return try: runner_cls = actions.class_for(action) except Exception as ex: raise excp.OptionException(str(ex)) if runner_cls.needs_sudo: ensure_perms() # Check persona file exists persona_fn = args.pop("persona_fn") if not persona_fn: raise excp.OptionException("No persona file name specified!") if not sh.isfile(persona_fn): raise excp.OptionException("Invalid persona file %r specified!" % (persona_fn)) # Check origin file exists origins_fn = args.pop("origins_fn") if not origins_fn: raise excp.OptionException("No origin file name specified!") if not sh.isfile(origins_fn): raise excp.OptionException("Invalid origin file %r specified!" % (origins_fn)) args["origins_fn"] = sh.abspth(origins_fn) # Determine the root directory... root_dir = sh.abspth(args.pop("dir")) (repeat_string, line_max_len) = utils.welcome() print(pprint.center_text("Action Runner", repeat_string, line_max_len)) # !! # Here on out we should be using the logger (and not print)!! # !! # Stash the dryrun value (if any) if "dryrun" in args: sh.set_dry_run(args["dryrun"]) # Ensure the anvil dirs are there if others are about to use it... ensure_anvil_dirs(root_dir) # Load the distro dist = distro.load(settings.DISTRO_DIR) # Load + verify the person try: persona_obj = persona.load(persona_fn) persona_obj.verify(dist) except Exception as e: raise excp.OptionException("Error loading persona file: %s due to %s" % (persona_fn, e)) yum.YumDependencyHandler.jobs = args["jobs"] # Get the object we will be running with... runner = runner_cls(distro=dist, root_dir=root_dir, name=action, cli_opts=args) # Now that the settings are known to work, store them for next run store_current_settings(saved_args) LOG.info( "Starting action %s on %s for distro: %s", colorizer.quote(action), colorizer.quote(utils.iso8601()), colorizer.quote(dist.name), ) LOG.info("Using persona: %s", colorizer.quote(persona_fn)) LOG.info("Using origins: %s", colorizer.quote(origins_fn)) LOG.info("In root directory: %s", colorizer.quote(root_dir)) start_time = time.time() runner.run(persona_obj) end_time = time.time() pretty_time = utils.format_time(end_time - start_time) LOG.info( "It took %s seconds or %s minutes to complete action %s.", colorizer.quote(pretty_time["seconds"]), colorizer.quote(pretty_time["minutes"]), colorizer.quote(action), )