Example #1
0
def exit_with_return_code(value):
    "Provide proper output to the CNM server"
    if type(value) != type(0):
        Logger.error("Invalid exit code, not an integer: %s" % value)
        value = FAIL
    Logger.warning("==EXIT-CODE==:%s" % value)
    sys.exit(value)
Example #2
0
def fix_spkg(instance_name, pkn, action, package_factory):
    """A user is requesting to take a package that is currently flagged
    as 'broken' and set it to be 'installed'. Perhaps they have manually
    fixed the package on the system."""
    progress_file = get_progress_path(instance_name)
    status_data = open(progress_file, 'r').read()
    try:
        status = json.loads(status_data)
    except ValueError:
        Logger.error("Data in %s is not parsable by json" % progress_file)
        return FAIL
    if status.get("install-progress") == None:
        status["install-progress"] = {}
        Logger.warning( "Status file is empty." )
    now = time.asctime()
    if action == FIX:
        fix_name = []
        base_names = re.compile("(\s+)\-\d+").findall(pkn)
        if base_names:
            base_name = base_names[0]
        else:
            base_name = pkn
        for possible_pkn in status["install-progress"]:
            if base_name in possible_pkn:
                fix_name.append(possible_pkn)
        if len(fix_name) > 1:
            msg = "Package name %s is ambigious. (possible %s)"
            msg = msg % (pkn, ' '.join(fix_name))
            Logger.error(msg)
            return FAIL
        elif len(fix_name) == 1:
            pkn = fix_name[0]
        elif len(fix_name) == 0:
            new_package = package_factory.get_me_one(pkn)
            pkn = new_package.full_name
            Logger.info("Selecting previously UNINSTALLED package: %s" % pkn)
        status["install-progress"]["%s" % pkn] = {"INSTALLED": now,
                                                  "UNINSTALLED": "NA",
                                                  "VERIFIED": now}
        Logger.info("==OUTPUT==:%s has been set to INSTALLED." % pkn )
    elif action == PURGE:
        if status["install-progress"].get(pkn):
            del status["install-progress"][pkn]
            msg = "==OUTPUT==:%s has been removed from %s status"
            msg = msg % (pkn, instance_name)
            Logger.info(msg)
        else:
            Logger.info("==OUTPUT==:%s is not in the status file" % pkn)
            pkns = status["install-progress"]
            possible_names = [x for x in pkns if pkn in x]
            msg = "==OUTPUT==:Maybe you want one of these: %s"
            msg = msg % str(possible_names)
            Logger.info(msg)
            return FAIL
    open(get_progress_path(instance_name), 'w').write(json.dumps(status))
    return OK
Example #3
0
 def use_pkg(self, pkn, action, script_name, arguments):
     """
     Main entry point to the class. Performs an action using a package
     pkn -- name of the package to use
     action -- STATUS, INSTALL, UNINSTALL, CONFIGURE, VERIFY, or EXEC
     script_name -- the name of a method to run within the package
     arguments -- arguments to the executable, typically a restore target
     """
     try:
         pkg = self._get_new_pkg(pkn)
         if pkg.status == FAIL:
             self.operation_status = FAIL
             return self._cleanup()
         if action == INSTALL:
             pdat = self.progress.get_progress_data(False)
             installed_pkns, broken_pkns = Progress.get_installed(pdat)
             if pkn in [installed_pkns + broken_pkns]:
                 Logger.error("Package %s cannot be installed." % pkn)
                 self.operation_status = FAIL
                 return FAIL
             add_pkd = {pkn: pkg}
             status = self._install_pkgs(add_pkd)
         if action == UNINSTALL:
             pdat = self.progress.get_progress_data(False)
             installed_pkns, broken_pkns = Progress.get_installed(pdat)
             bom_pkns = installed_pkns
             if pkn in bom_pkns:
                 bom_pkns.remove(pkn)
             self.config.set_bom_pkgs(bom_pkns)
             add_pkd, del_pkd, uninstall_order = self._ck_inst_stat([])
             status = self._uninstall_pkgs(del_pkd, uninstall_order)
         if action == VERIFY:
             status = pkg.verify()
         if action == CONFIGURE:
             self._check_configuration(pkg)
             status = pkg.configure()
             hash_path = make_path(pkg.get_path(), HASH_FILE)
             msg = "Writing configuration fingerprint to %s" % hash_path
             Logger.info(msg)
             self.config.save_hash(hash_path)
         if action in [EXECUTE, BACKUP, RESTORE]:
             status = pkg.execute_maint_script(script_name, arguments)
             if status == FAIL:
                 self.operation_status = FAIL
         msg = "Finished %s for %s."
         msg = msg % (ACTION_REVERSE_LOOKUP[action], pkn)
         self.operation_output.append(msg)
         status = self._cleanup()
         return self._cleanup()
     except Exceptions.BadPackage, err:
         errmsg = "Cannot perform action %s on package %s: %s"
         errmsg = errmsg % (ACTION_REVERSE_LOOKUP[action], err.pkn, err.errmsg)
         Logger.warning(errmsg)
         Logger.info("RETURN FAIL 1")
         return FAIL
Example #4
0
 def initialize(self):
     '''Evaluate the package meta-data for consistency
     and initialize parameters. Verify that data on the disk for
     this package is consistent.
     '''
     try:
         self.meta_data = self.repository.get_meta_data(self.name)
     except BadPackage, bpe:
         Logger.error("initialize INVALIDATING")
         self._invalidate(bpe)
         return
Example #5
0
def process_action(action, instance_name, pkn, method_name,
                   arguments, package_factory):
    """
    Performs a Bombardier action on this system
    action -- either INIT, INSTALL, UNINSTALL, VERIFY, CONFIGURE,
              EXECUTE, RECONCILE, CHECK_STATUS, FIX, or PURGE
    instance_name -- the name of the machine
    pkn -- the package name to operate on. Could be none for actions
           that operate on the whole machine, such as RECONCILE,
           CHECK_STATUS, or INIT 
    method_name -- Only applicable for the EXECUTE action, runs a named
                   method within a package.
    package_factory -- provides packages we may need
    """
    if action == INIT:
        instance_setup(instance_name)
        return OK

    if action in [ UNINSTALL, VERIFY, CONFIGURE, EXECUTE, BACKUP ]:
        try:
            pkn = find_likely_pkn(instance_name, pkn)
        except ValueError:
            return FAIL

    status = FAIL
    try:
        if action in [ FIX, PURGE ]:
            status = fix_spkg(instance_name, pkn, action, package_factory)
            return status
        bc_obj = get_bc(instance_name, package_factory.env)
        if action == CHECK_STATUS:
            status_dict = bc_obj.check_system()
            if type(status_dict) == type({}):
                if not status_dict["Packages that are BROKEN"]:
                    status = OK
            else:
                status = FAIL
        elif action in [ RECONCILE, DRY_RUN ]:
            bc_obj.record_errors = True
            status = bc_obj.reconcile_system(action)
        else: # INSTALL, UNINSTALL, VERIFY, BACKUP, CONFIGURE, EXECUTE, RESTORE
            bc_obj.record_errors = False
            status = bc_obj.use_pkg(pkn, action, method_name, arguments)
    except:
        err = StringIO.StringIO()
        traceback.print_exc(file = err)
        err.seek(0)
        data = err.read()
        ermsg = ''
        for line in data.split('\n'):
            ermsg += "\n||>>>%s" % line
        Logger.error(ermsg)
        return FAIL
    return status
Example #6
0
 def is_running(self):
     'ability to check if the job is finished'
     if self.job_thread:
         if self.job_thread.isAlive():
             return True
         if type(self.job_thread.cmd_status) == type(0) \
            or type(self.job_thread.cmd_status) == type('str'):
             Logger.debug("-- status: %s" % (self.job_thread.cmd_status))
             self.job_status = self.job_thread.cmd_status
         else:
             msg = "Invalid return status (type: %s)"
             Logger.error(msg % (type(self.job_thread.cmd_status)))
             self.job_status = FAIL
     return False
Example #7
0
 def run(self):
     'Thread interface'
     Logger.debug("Running %s..." % self.cmd)
     try:
         exec(self.import_string)
         exec("self.cmd_status = %s" % self.cmd)
     except StandardError, err:
         Logger.error("Failed to run %s (%s)" % (self.cmd, err))
         sio = StringIO.StringIO()
         traceback.print_exc(file=sio)
         sio.seek(0)
         data = sio.read()
         ermsg = ''
         for line in data.split('\n'):
             ermsg += "\n||>>>%s" % line
         Logger.error(ermsg)
         self.cmd_status = FAIL
Example #8
0
    def _find_cmd(self, action, arguments=[], future_pkns=[], dry_run=False):
        '''
        Perform the action on the system, importing modules from the package
        and running the appropriate method on the class within.
        action -- INSTALL, UNINSTALL, CONFIGURE, VERIFY
        future_pkns -- future package names. Some packages want to know
                       about the packages that will come after them
        dry_run -- boolean flag to see if we're really going to do this
        '''
        ret_val = None
        if type(action) == type(1):
            action = ACTION_REVERSE_LOOKUP[action]

        cwd = get_slash_cwd()
        obj, rand_string = self._get_object(future_pkns)
        try:
            if not hasattr(obj, action):
                msg = "Class %s does not have a %s method."
                raise BadPackage(self.name, msg % (self.class_name, action))
            if not dry_run:
                if arguments:
                    if ACTION_LOOKUP.get(action) == RESTORE:
                        if len(arguments) != 1:
                            Logger.error("Incorrect number of arguments passed to restore")
                            return FAIL
                        restore_path = make_path(get_spkg_path(), "archive",
                                                    self.name, str(arguments[0]))
                        if not os.path.isdir(restore_path):
                            msg = "Cannot execute restore: archive data does not "\
                                  "exist in %s" % (restore_path)
                            Logger.error(msg)
                            return FAIL
                        self._prepare_restore(obj, restore_path)
                        exec("ret_val = obj.%s('%s')" % (action, restore_path))
                else:
                    exec("ret_val = obj.%s()" % (action))
            else:
                ret_val = OK
            self._cleanup(obj)
            del rand_string
        except SystemExit, err:
            if err.code:
                ret_val = err.code
            else:
                ret_val = OK
            del rand_string
Example #9
0
 def execute(self):
     'starts a job and waits for it to finish'
     self.start_time = time.time()
     status = FAIL
     if self.is_running():
         msg = "Refusing to run %s; it is already running" % self.cmd
         Logger.error(msg)
         return FAIL
     self.job_thread = JobThread(self.import_string, self.cmd, self.config)
     self.job_thread.start()
     Logger.info("Started job...")
     counter = 1
     while self.is_running():
         time.sleep(1)
         counter += 1
         if not counter % 100:
             msg = "Waiting for completion (%s)..."
             Logger.info(msg % time.strftime(time.ctime()))
             counter = 1
     status = self.job_thread.cmd_status
     return status
Example #10
0
def find_likely_pkn(instance_name, pkn):
    """Sometimes an ambiguous package name is requested.
    This attempts to help a guy out."""
    progress_file = get_progress_path(instance_name)
    try:
        status_yml = json.loads(open(progress_file).read())
    except ValueError:
        Logger.error("Progress data in %s is not parsable." % progress_file)
        raise
    pkns = []
    status_packages = status_yml['install-progress']
    for name in status_packages:
        if status_packages[name]['INSTALLED'] in [ 'NA', 'BROKEN' ]:
            continue
        if pkn.lower() in name.lower():
            pkns.append(name)
    if len(pkns) > 1:
        msg = 'Ambiguous package name: %s could be any of %s' % (pkn, str(pkns))
        Logger.error( msg )
        exit_with_return_code(FAIL)
    if len(pkns) == 0:
        Logger.error( 'Package not found: %s' %pkn )
        exit_with_return_code(FAIL)
    else:
        pkn = '-'.join(pkns[0].split('-')[:-1])
        Logger.info( 'Using %s' %pkn)
        return pkn
Example #11
0
    def get_type_4(self, full_name):
        '''
        Get a type-4 package from the filesystem, and process it
        full_name -- name of package (with version)
        '''
        pkg_dir = get_package_path(self.instance_name)
        os.system('bash -c "mkdir -p %s"' % pkg_dir)
        pkg_path = make_path(pkg_dir, full_name)
        if not os.path.isfile(pkg_path + ".spkg"):
            erstr = "No package file in %s." % (pkg_path + ".spkg")
            Logger.error(erstr)
            raise Exceptions.BadPackage(full_name, erstr)
        if sys.platform != 'win32':
            cmd = 'bash -c "cd %s && tar -mxzf %s.spkg"' % (pkg_dir, full_name)
            Logger.info("Untarring with command: %s" %cmd)
            if not os.system(cmd) == OK:
                raise Exceptions.BadPackage(full_name, "Could not unpack")
            return OK
        if self.unzip_type_5(pkg_path, full_name) == FAIL:
            raise Exceptions.BadPackage(full_name, "could not unzip")
#        tar = tarfile.open(pkg_path + ".tar", "r")
#        tar.errorlevel = 2
        cwd = get_slash_cwd()
        os.chdir(pkg_dir)
#        for tarinfo in tar:
#            try:
#                tar.extract(tarinfo)
#            except tarfile.ExtractError, err:
#                Logger.warning("Error with package %s,%s: "\
#                               "%s" % (full_name, tarinfo.name, err))
#        tar.close()
        if not os.path.isdir(make_path(pkg_path, full_name)):
            erstr = "Package %s is malformed." % (full_name)
            os.chdir(cwd)
            raise Exceptions.BadPackage(full_name, erstr)
        os.chdir(cwd)
#        os.unlink(pkg_path + ".tar")
        return OK
Example #12
0
 def _install_pkgs(self, add_pkd, dry_run=False):
     """
     Provided a dictionary of packages, we will install those that need to
     be installed.
     add_pkd -- a dictionary of packages that need to be added
     dry_run -- whether or not to just 'fake it'
     """
     status = OK
     making_progress = True
     pkns_left = ["initialize"]
     while making_progress and pkns_left:
         making_progress = False
         install_order = self._find_install_order(add_pkd)
         pkns_left = list(install_order)
         for pkn in install_order:
             msg = "Packages remaining to install (in order):"
             Logger.info(msg)
             for tpkn in pkns_left:
                 Logger.info("  +   %s" % tpkn)
             pkns_left.remove(pkn)
             pkg = add_pkd[pkn]
             erstr = "Currently installing package priority %s [%s]"
             Logger.info(erstr % (pkg.get_priority(), pkn))
             pkg_status = pkg.install_and_verify(pkns_left)
             if not dry_run:
                 hash_path = make_path(pkg.get_path(), HASH_FILE)
                 self.config.save_hash(hash_path)
             if pkg_status == FAIL:
                 status = FAIL
                 erstr = "Package installation failure -- re-calculating" " package installation order"
                 Logger.error(erstr)
                 break
             else:
                 making_progress = True
     if status != OK:
         msg = "There are packages that are broken, and we have done all" " we can do. ; ;"
         Logger.error(msg)
     return status
Example #13
0
    def _get_object(self, future_pkns):
        '''
        Import modules from the package in order to run an appropriate method
        on the class within.
        future_pkns -- future package names. Some packages want to know
                       about the packages that will come after them
        '''
        lib_path = self._get_lib_path()
        sys.path.insert(0, lib_path)
        Logger.info("Adding %s to our path..." % lib_path)
        obj = None

        try:
            class_name = '.'.join(self.class_name.split('.')[1:])
            obj = Spkg.SpkgV5(self.config)
            os.chdir(self.working_dir)
            Logger.info("CHANGING TO: %s" % self.working_dir)
            letters = [ chr( x ) for x in range(65, 91) ]
            random.shuffle(letters)
            rand_string = ''.join(letters)
            exec("import %s as %s" % (self.class_name, rand_string))
            self.config["__FUTURE_PACKAGES__"] = future_pkns
            self.config["__INSTANCE__"] = self.instance_name
            cmd_str = "obj = %s.%s(self.config)"
            exec(cmd_str % (rand_string, class_name))
        except ImportError, ie:
            tb_str = StringIO.StringIO()
            traceback.print_exc(file=tb_str)
            tb_str.seek(0)
            data = tb_str.read()
            ermsg = ''
            for line in data.split('\n'):
                Logger.error(line)
            self.status = FAIL
            msg = "Class %s is not importable." % self.class_name
            raise BadPackage(self.name, msg)
Example #14
0
 def _dump_error(cls, err, file_name):
     '''
     perform a traceback for logging purposes
     err -- an exception object
     file_name -- the module that was running
     '''
     Logger.error("Error detected in %s (%s)." % (file_name, err))
     sio = StringIO.StringIO()
     traceback.print_exc(file=sio)
     sio.seek(0)
     data = sio.read()
     ermsg = ''
     for line in data.split('\n'):
         ermsg += "\n||>>>%s" % line
     Logger.error(ermsg)
     Logger.error("Error ocurred in %s" % file_name)
Example #15
0
    def _prepare_restore(self, obj, restore_path):
        """
        Command to deal with setting up the environment prior to a
        restore action
        obj -- package object which owns methods for restoring, etc.
        restore_path -- place where restore files have been dropped
        """
        if hasattr(obj, "pre_restore_cmd"):
            pre_backup_cmd = obj.pre_backup_cmd
            status = self._find_cmd(obj.pre_restore_cmd)
            if status != OK:
                erstr = "%s: restore FAILED because %s failed."
                Logger.error(erstr % (self.full_name, pre_backup_cmd))
                return FAIL

        backup_data = yaml_load(open(make_path(restore_path, "backup_info.yml")).read())
        for backup_target in backup_data:
            if backup_target.startswith("__"):
                continue
            md5_data = backup_data[backup_target].get("md5", {})
            backup_file_name = backup_data[backup_target].get("backup_file", '')
            if not md5_data or not backup_file_name:
                Logger.error("Corrupted backup data for %s, aborting." % (backup_target))
                return FAIL
            source_file = make_path(restore_path, rpartition(backup_target, os.path.sep)[0][1:], backup_file_name)
            destination_file = make_path(restore_path, backup_target[1:])
            Logger.debug("=================================")
            Logger.debug("backup_target: %s..." % (backup_target))
            Logger.debug("current directory: %s" % (restore_path))
            Logger.debug("backup_file_name: %s..." % (backup_file_name))
            Logger.debug("destination_file: %s..." % (destination_file))
            Logger.debug("source_file: %s" % (source_file))
            Logger.debug("=================================")
            if not os.path.isfile(source_file):
                Logger.error("Restore file %s does not exist, aborting" % (source_file))
                return FAIL
            rfp = ReversePluggableFileProcessor(source_file, destination_file, md5_data, Logger)
            rfp.process_all()
Example #16
0
                        self._prepare_restore(obj, restore_path)
                        exec("ret_val = obj.%s('%s')" % (action, restore_path))
                else:
                    exec("ret_val = obj.%s()" % (action))
            else:
                ret_val = OK
            self._cleanup(obj)
            del rand_string
        except SystemExit, err:
            if err.code:
                ret_val = err.code
            else:
                ret_val = OK
            del rand_string
        except KeyboardInterrupt:
            Logger.error("Keyboard interrupt detected. Exiting...")
            ret_val = FAIL
            sys.exit(10) # FIXME: Literal
        except SyntaxError, err:
            self._dump_error(err, self.class_name)
            ret_val = FAIL
            del rand_string
        except StandardError, err:
            self._dump_error(err, self.class_name)
            ret_val = FAIL
            del rand_string
        os.chdir(cwd)

        if ACTION_LOOKUP.get(action) == BACKUP:
            if type(ret_val) != type({}):
                erstr = "%s: backup method did not return a "\
Example #17
0
    def _backup(self, obj, backup_data, future_pkns, dry_run):
        "Perform basic backup functions for a package"

        pre_backup_cmd = obj.pre_backup
        post_backup_cmd = obj.post_backup

        if pre_backup_cmd:
            status = self._find_cmd(pre_backup_cmd, future_pkns=future_pkns, dry_run=dry_run)
            if status != OK:
                erstr = "%s: backup FAILED because pre-backup command failed."
                Logger.error(erstr % self.full_name)
                return FAIL

        file_names = backup_data.get("file_names")
        if type(file_names) != type([]):
            errmsg = "Package %s did not define its backup data correctly."\
                     " '%s' should be a list."
            Logger.error(errmsg % (self.full_name, file_names))
            return FAIL
        options = backup_data.get("options", [COMPRESS])
        if type(options) != type([]):
            errmsg = "Package %s did not define its backup data correctly."\
                     " '%s' should be a list."
            Logger.error(errmsg % (self.full_name, options))
            return FAIL

        backup_dir = tempfile.mkdtemp()
        Logger.info("Temporary backup dir: %s" % backup_dir)
        start_time = time.time()
        backup_data = {"__START_TIME__": start_time}

        for file_name in file_names:
            backup_data[file_name] = {}
            current_start = time.time()
            if file_name.startswith(os.path.sep):
                backup_destination = make_path(backup_dir, file_name[1:])
            fpf = ForwardPluggableFileProcessor(file_name, backup_destination, options, Logger)
            backup_file_name, md5_dict = fpf.process_all()
            if not os.path.isfile(backup_file_name):
                Logger.error("Backup file not created.")
                return FAIL
            backup_data[file_name]["md5"] = md5_dict
            backup_data[file_name]["backup_file"] = rpartition(backup_file_name, os.path.sep)[-1]
            elapsed_time = time.time() - current_start
            backup_data[file_name]["elapsed_time"] = elapsed_time
            size = os.stat(file_name)[stat.ST_SIZE]
            backup_data[file_name]["size"] = size
            backup_data[file_name]["status"] = OK

        if post_backup_cmd:
            status = self._find_cmd(post_backup_cmd, future_pkns=future_pkns, dry_run=dry_run)
            if status != OK:
                erstr = "%s: backup FAILED because post-backup command failed."
                Logger.error(erstr % self.full_name)
                return FAIL

        backup_data["__BACKUP_DIR__"] = backup_dir
        dump_string = yaml_dump(backup_data)
        for line in dump_string.split('\n'):
            Logger.info("==REPORT==:%s" % line)
        return OK
Example #18
0
 def _find_cmd(self, action, argument='', future_pkns=[], dry_run=False):
     '''
     Perform the action on the system, importing modules from the package
     and running the appropriate method on the class within.
     action -- INSTALL, UNINSTALL, CONFIGURE, VERIFY
     future_pkns -- future package names. Some packages want to know
                    about the packages that will come after them
     dry_run -- boolean flag to see if we're really going to do this
     '''
     cwd = get_slash_cwd()
     sys.path.insert(0, self.scripts_dir)
     os.chdir(self.scripts_dir)
     files = self._get_possible_module_files()
     status = FAIL
     file_found = False
     for file_name in files:
         try:
             obj = Spkg.SpkgV4(self.config, logger=Logger)
             os.chdir(self.working_dir)
             letters = [ chr( x ) for x in range(65, 91) ]
             random.shuffle(letters)
             rand_string = ''.join(letters)
             exec("import %s as %s" % (file_name, rand_string))
             self.config["__FUTURE_PACKAGES__"] = future_pkns
             self.config["__INSTANCE__"] = self.instance_name
             cmd_str = "obj = %s.%s(self.config, Logger)"
             exec(cmd_str % (rand_string, file_name))
             file_found = True
             if not dry_run:
                 if action == INSTALL:
                     status = obj.installer()
                 elif action == VERIFY:
                     status = obj.verify()
                 elif action == UNINSTALL:
                     status = obj.uninstaller()
                 elif action == CONFIGURE:
                     status = obj.configure()
                 else:
                     raise FeatureRemovedException(action)
             else:
                 status = OK
             del rand_string
             if file_name in sys.modules:
                 sys.modules.pop(file_name)
             while self.scripts_dir in sys.path:
                 sys.path.remove(self.scripts_dir)
             break
         except ImportError:
             msg = "File %s is not runnable. Looking for others" % file_name
             Logger.debug(msg)
             continue
         except SystemExit, err:
             if err.code:
                 status = err.code
             else:
                 status = 0
             file_found = True
             break
         except KeyboardInterrupt:
             Logger.error("Keyboard interrupt detected. Exiting...")
             sys.exit(10)
Example #19
0
    def data_request(self):
        "Obtain configuration data from the server"
        b64_data = []
        while True:
            #Logger.info( "STARTING READ" )
            chunk = sys.stdin.read(STREAM_BLOCK_SIZE).strip()
            #Logger.info( "READ FROM SERVER: [%s]" % chunk)
            if not chunk or chunk[0] == ' ' or chunk.endswith("-"):
                chunk = chunk[:-1]
                b64_data.append(chunk)
                break
            b64_data.append(chunk)
            sys.stdout.write(">\n")
            sys.stdout.flush()
        #Logger.info("FINISHED INPUT LOOP")
        #print "b64_data: ", b64_data
        json_data = ''
        #json_data = zlib.decompress(base64.decodestring(''.join(b64_data)))
      
        json_data = base64.decodestring(''.join(b64_data))
        #print "json_dataa", json_data
        Logger.debug("Received %s lines of json" % len(json_data.split('\n')))

        try:
            input_data = json.loads(json_data)
            #print "input_dataa", input_data
        except:
            ermsg = "Configuration data not YAML-parseable: %s" % (repr(json_data))
            file_number, filename = tempfile.mkstemp(suffix=".yml")
            fh = open(filename, 'w')
            Logger.error("Writing bad data to %s" % filename)
            for line in json_data.split('\n'):
                fh.write("[%s]" % line)
            fh.flush()
            fh.close()
            raise ConfigurationException(ermsg)
        if type(input_data) == type("string"):
            ermsg = "Configuration data not YAML-parseable: %s" % (repr(json_data))
            raise ConfigurationException(ermsg)
        if type(input_data) != type({}) and type(input_data) != type([]):
            input_data = input_data.next()
        config_key = input_data.get("config_key", None)
        if config_key:
            try:
                from bombardier_core.Cipher import Cipher
            except ImportError:
                msg = "This machine cannot accept an encrypted configuration"
                raise ConfigurationException(msg)
            enc_json_file = make_path(get_spkg_path(), self.instance_name,
                                         'client.yml.enc')
            if not os.path.isfile(enc_json_file):
                msg = "%s file doesn't exist" % enc_json_file
                raise ConfigurationException(msg)
            enc_data = open(enc_json_file).read()
            cipher = Cipher(config_key)
            plain_json_str = cipher.decrypt_string(enc_data)
            try:
                input_data = json.loads(plain_json_str)
            except:
                ermsg = "Received bad YAML file: %s" % enc_json_file
                raise ConfigurationException(ermsg)

        config_data  = input_data.get("config_data")
        if not config_data:
            raise ConfigurationException("No configuration data received")
        package_data = input_data.get("package_data", {})
        self.config = Config(self.instance_name, config_data)
        self.repository = Repository(self.instance_name, package_data)
Example #20
0
def main():
    Logger.add_std_err_logging()

    parser = optparse.OptionParser('\n'.join(USAGE))

    parser.add_option("-s", "--status", dest="action",
                      action="store_const", const=CHECK_STATUS,
                      help="display the status of the system")
    parser.add_option("-c", "--configure", dest="action",
                      action="store_const", const=CONFIGURE,
                      help="configure a package")
    parser.add_option("-v", "--verify", dest="action",
                      action="store_const", const=VERIFY,
                      help="verify a package")
    parser.add_option("-i", "--install", dest="action",
                      action="store_const", const=INSTALL,
                      help="install a package")
    parser.add_option("-r", "--reconcile", dest="action",
                      action="store_const", const=RECONCILE,
                      help="reconcile the system")
    parser.add_option("-x", "--execute", dest="action",
                      action="store_const", const=EXECUTE,
                      help="Execute a maintenance script")
    parser.add_option("-u", "--uninstall", dest="action",
                      action="store_const", const=UNINSTALL,
                      help="uninstall a package")
    parser.add_option("-f", "--fix", dest="action",
                      action="store_const", const=FIX,
                      help="set a package status to INSTALLED without doing anything")
    parser.add_option("-p", "--purge", dest="action",
                      action="store_const", const=PURGE,
                      help="Remove a package from the status")
    parser.add_option("-d", "--dry-run", dest="action",
                      action="store_const", const=DRY_RUN,
                      help="Do a test reconcile")
    parser.add_option("-n", "--init", dest="action",
                      action="store_const", const=INIT,
                      help="Initialize the client after installation")
    parser.add_option("-B", "--backup", dest="action",
                      action="store_const", const=BACKUP,
                      help="Tell a package to back itself up")
    parser.add_option("-R", "--restore", dest="action",
                      action="store_const", const=RESTORE,
                      help="Tell a package to restore itself")

    (options, args) = parser.parse_args()
    Logger.info("options: (%s) / args: (%s)" % (options, args))
    if options.action:
        Logger.info("Action: %s" % (ACTION_REVERSE_LOOKUP[options.action]))
    if len(args) < 1:
        print "CMD: %s" % ' '.join(sys.argv)
        print "This command requires an instance name."
        parser.print_help()
        exit_with_return_code(1)
    instance_name = args[0]
    env = BombardierEnvironment(instance_name)
    env.data_request()
    package_factory = PackageFactory(env)
    arguments = []

    if options.action in [ RECONCILE, CHECK_STATUS, DRY_RUN, INIT ]:
        status = process_action(options.action, instance_name,
                               '', '', '', package_factory)
    else:
        method_name   = ""
        if len(args) < 2:
            print "CMD: %s" % ' '.join(sys.argv)
            print "This command requires a package name as an argument."
            Logger.error("This command requires a package name as an argument.")
            parser.print_help()
            exit_with_return_code( 1 )
        package_name = args[1]
        if options.action == BACKUP:
            method_name = "backup"
        if options.action == RESTORE:
            method_name = "restore"
            arguments = args[2:]

        if options.action == EXECUTE:
            if len(args) < 3:
                print "CMD: %s" % ' '.join(sys.argv)
                print "This command requires a package name and a script name."
                Logger.error("This command requires a package name and a script name.")
                parser.print_help()
                exit_with_return_code( 1 )
            package_name = args[1]
            method_name = args[2]
            if len(args) > 3:
                arguments = args[3:]

        status = process_action(options.action, instance_name,
                                package_name, method_name, arguments,
                                package_factory)
        if status != OK:
            exit_with_return_code(status)
    exit_with_return_code(status)
Example #21
0
 def _invalidate(self, exception_object):
     'set the package as not operable'
     erstr = "INVALID PACKAGE: %s" % self.name
     Logger.error(erstr)
     Logger.error(str(exception_object))
     self.status = FAIL
Example #22
0
                else:
                    status = 0
                file_found = True
                break
            except KeyboardInterrupt:
                Logger.error("Keyboard interrupt detected. Exiting...")
                sys.exit(10)
            except SyntaxError, err:
                self._dump_error(err, file_name)
                file_found = False
                break
            except StandardError, err:
                self._dump_error(err, file_name)
                file_found = True
                status = FAIL
                break
        os.chdir(cwd)
        if not file_found:
            msg = "Unable to find a suitable script to install."
            raise BadPackage(self.name, msg)
        if status == None:
            status = OK
        if status == REBOOT:
            raise RebootRequiredException(self.name)
        if status != OK:
            erstr = "%s: failed with status %s" % (self.full_name, status)
            Logger.error(erstr)
            return FAIL
        return OK