Esempio n. 1
0
        print_chars(0, "Error creating cloudinit.d directort %s : %s" % (homedir, str(ex)))

    (options, args) = parser.parse_args(args=argv)

    _deal_with_cmd_line_globals(options)

    for opt in all_opts:
        opt.validate(options)

    if not options.name:
        options.name = str(uuid.uuid4()).split("-")[0]

    if options.logdir is None:
        options.logdir = os.path.expanduser("~/.cloudinitd/")

    (options.logger, logfile) = cloudinitd.make_logger(options.loglevel, options.name, logdir=options.logdir)
    if not options.database:
        dbdir = os.path.expanduser("~/.cloudinitd")
        options.database = dbdir

    if options.logstack:
        logger = logging.getLogger("stacktracelog")
        logger.propagate = False
        logger.setLevel(logging.DEBUG)
        logdir = os.path.join(options.logdir, options.name)
        if not os.path.exists(logdir):
            try:
                os.mkdir(logdir)
            except OSError:
                pass
        stacklogfile = os.path.join(logdir, "stacktrace.log")
Esempio n. 2
0
    def __init__(self, db_dir, config_file=None, db_name=None, log_level="warn", logdir=None, level_callback=None, service_callback=None, boot=True, ready=True, terminate=False, continue_on_error=False, fail_if_db_present=False):
        """
        db_dir:     a path to a directories where databases can be stored.

        config_file: the top_level config file describing this boot plan.
                    if this parameter is given then it is assumed that this
                    is a new launch plan.  if it is not given the db_name
                    parameter is required and the plan is loaded from an
                    existing database

        db_name:    the name of the database.  this is not an actual path
                    to a file, it is the run name given when the plan is
                    launched.  The run name can be found in self.name

        level_callback: a callback function that is invoked whenever
                        a level completes or a new level is started.  The signature of the callback is:

                        def func_name(cloudinitd, action, current_level)

                        action is a string from the set
                        ["starting", "transition", "complete", "error"]

        service callback: a callbackfunciton that is invoked whenever
                        a service is started, progresses, or finishes.  The signature is:

                        def func_name(cloudservice, action, msg)

                        action is a string from the set:

                        ["starting", "transition", "complete", "error"]

        boot=True: instructs the object to contextualized the service or now

        ready=True: instructs the service to run the ready program or not

        terminate=False: instructs the service to run the shutdown program or not

        fail_if_db_present=False: instructs the constructor that the caller expects DB present already

        When this object is configured with a config_file a new sqlite
        database is created under @db_dir and a new name is picked for it.
        the data base ends up being called <db_dir>/cloudinitd-<name>.db,
        but the user has no real need to know this.

        The contructor does not actually launch a run.  It simply loads up
        the database with the information in the config file (in the case
        of a new launch) and then builds the inmemory data structures.
        """

        if not db_name and not config_file:
            raise APIUsageException("Cloud boot must have a db_name or a config file to load")
        if not os.path.exists(db_dir):
            raise APIUsageException("Path to the db directory does not exist: %s" % (db_dir))

        self._level_callback = level_callback
        self._service_callback = service_callback

        if not db_name:
            db_name = str(uuid.uuid4()).split("-")[0]

        db_path = "/%s/cloudinitd-%s.db" % (db_dir, db_name)
        self._db_path = db_path
        if config_file is None:
            if not os.path.exists(db_path):
                raise APIUsageException("Path to the db does not exist %s.  New dbs must be given a config file" % (db_path))

        if fail_if_db_present and os.path.exists(db_path):
            raise APIUsageException("Already exists: '%s'" % db_path)

        (self._log, logfile) = cloudinitd.make_logger(log_level, db_name, logdir=logdir)

        self._started = False
        self.run_name = db_name
        dburl = "sqlite://%s" % (db_path)

        self._db = CloudInitDDB(dburl)
        os.chmod(db_path, stat.S_IRUSR | stat.S_IWUSR)
        if config_file:
            self._bo = self._db.load_from_conf(config_file)
        else:
            self._bo = self._db.load_from_db()

        self._levels = []
        self._boot_top = BootTopLevel(log=self._log, level_callback=self._mp_cb, service_callback=self._svc_cb, boot=boot, ready=ready, terminate=terminate, continue_on_error=continue_on_error)
        for level in self._bo.levels:
            level_list = []
            for s in level.services:
                try:
                    (s_log, logfile) = cloudinitd.make_logger(log_level, self.run_name, logdir=logdir, servicename=s.name)

                    svc = self._boot_top.new_service(s, self._db, log=s_log, logfile=logfile, run_name=self.run_name)

                    # if boot is not set we assume it was already booted and we expand
                    if not boot:
                        svc._do_attr_bag()
                    level_list.append(svc)
                except Exception, svcex:
                    if not continue_on_error:
                        raise
                    action = cloudinitd.callback_action_error
                    msg = "ERROR creating SVC object %s, but continue on error set: %s" % (s.name, str(svcex))
                    if self._service_callback:
                        cs = CloudService(self, None, name=s.name)
                        self._service_callback(self, cs, action, msg)

                    cloudinitd.log(self._log, logging.ERROR, msg)

            self._boot_top.add_level(level_list)
            self._levels.append(level_list)