Exemplo n.º 1
0
class MkConfig(Command):
    """${cmd_usage}

    Generate a config file for a backup
    plugin.

    ${cmd_option_list}

    """

    name = 'mk-config'

    aliases = [
        'mc'
    ]

    options = [
        option('--name',
                help='Name of the backupset'),
        option('--edit', action='store_true',
                help='Edit the generated config'),
        option('--provider', action='store_true',
                help='Generate a provider config'),
        option('--file', '-f',
                help='Save the final config to the specified file'),
        option('--minimal', '-m', action='store_true', default=False,
               help="Do not include comment from a backup "
                    "plugin's configspec"),
    ]

    description = 'Generate a config file for a backup plugin'


    # After initial validation:
    #   run through and flag required parameters with a 'REQUIRED' comment
    #   run through and comment out default=None parameters
    def _cleanup_config(self, config, skip_comments=False):
        errors = config.validate(validator, preserve_errors=True,copy=True)
        # First flag any required parameters
        for entry in flatten_errors(config, errors):
            section_list, key, error = entry
            section_name, = section_list
            if error is False:
                config[section_name][key] = ''
                config[section_name].comments[key].append('REQUIRED')
            elif error:
                print >>sys.stderr, "Bad configspec generated error", error

        pending_comments = []
        for section in list(config):
            if pending_comments:
                if skip_comments:
                    comments = []
                else:
                    comments = config.comments.get(section, [])
                comments = pending_comments + comments
                config.comments[section] = comments
                del pending_comments[:]
            for idx, (key, value) in enumerate(config[section].items()):
                if value is None:
                    if not skip_comments:
                        pending_comments.extend(config[section].comments.get(key, []))
                    pending_comments.append('%s = "" # no default' % key)
                    del config[section][key]
                else:
                    if skip_comments:
                        del config[section].comments[key][:]
                    if pending_comments:
                        if skip_comments:
                            comments = []
                        else:
                            comments = config[section].comments.get(key, [])
                        comments = pending_comments + comments
                        config[section].comments[key] = comments
                        del pending_comments[:]
                    if value is True or value is False:
                        config[section][key] = ['no','yes'][value]

        if pending_comments:
            if skip_comments:
                config.final_comment = pending_comments
            else:
                config.final_comment = pending_comments + config.final_comment

        # drop initial whitespace
        config.initial_comment = []
        # insert a blank between [holland:backup] and first section
        try:
            config.comments[config.sections[1]].insert(0, '')
        except IndexError:
            pass

    def run(self, cmd, opts, plugin_type):
        if opts.name and opts.provider:
            print >>sys.stderr, "Can't specify a name for a global provider config"
            return 1

        try:
            plugin_cls = load_first_entrypoint('holland.backup', plugin_type)
        except PluginLoadError, exc:
            logging.info("Failed to load backup plugin %r: %s",
                         plugin_type, exc)
            return 1

        try:
            cfgspec = sys.modules[plugin_cls.__module__].CONFIGSPEC
        except:
            print >>sys.stderr, "Could not load config-spec from plugin %r" % plugin_type
            return 1

        base_config = """
        [holland:backup]
        plugin                  = ""
        backups-to-keep         = 1
        auto-purge-failures     = yes
        purge-policy            = after-backup
        """.lstrip().splitlines()
        cfg = ConfigObj(base_config, configspec=cfgspec, list_values=True,stringify=True)
        cfg['holland:backup']['plugin'] = plugin_type
        self._cleanup_config(cfg, skip_comments=opts.minimal)

        if opts.edit:
            done = False
            editor = _find_editor()
            if not editor:
                print >>sys.stderr, "Could not find a valid editor"
                return 1

            tmpfileobj = tempfile.NamedTemporaryFile()
            cfg.filename = tmpfileobj.name
            cfg.write()
            while not done:
                status = subprocess.call([editor, cfg.filename])
                if status != 0:
                    if not confirm("Editor exited with non-zero status[%d]. "
                                   "Would you like to retry?" % status):
                        print >>sys.stderr, "Aborting"
                        return 1
                    else:
                        continue
                try:
                    cfg.reload()
                except ParseError, exc:
                    print >>sys.stderr, "%s : %s" % \
                    (exc.msg, exc.line)
                else:
                    errors = cfg.validate(validator,preserve_errors=True)
                    if errors is True:
                        done = True
                        continue
                    else:
                        _report_errors(cfg, errors)

                if not confirm('There were configuration errors. Continue?'):
                    print >>sys.stderr, "Aborting"
                    return 1
            tmpfileobj.close()
Exemplo n.º 2
0
    def run(self, cmd, opts, *plugin_type):
        if not plugin_type:
            print("Missing plugin name", file=sys.stderr)
            return 1
        if opts.name and opts.provider:
            print("Can't specify a name for a global provider config",
                  file=sys.stderr)
            return 1

        try:
            plugin_cls = load_first_entrypoint('holland.backup',
                                               plugin_type[0])
        except PluginLoadError as exc:
            logging.info("Failed to load backup plugin %r: %s", plugin_type[0],
                         exc)
            return 1

        try:
            cfgspec = sys.modules[plugin_cls.__module__].CONFIGSPEC
        except BaseException as ex:
            print("Could not load config-spec from plugin %r, %s" %
                  (plugin_type[0], ex),
                  file=sys.stderr)
            return 1

        base_config = """
        [holland:backup]
        plugin                  = ""
        backups-to-keep         = 1
        auto-purge-failures     = yes
        purge-policy            = after-backup
        estimated-size-factor   = 1.0
        """.lstrip().splitlines()
        cfg = ConfigObj(base_config,
                        configspec=cfgspec,
                        list_values=True,
                        stringify=True)
        cfg['holland:backup']['plugin'] = plugin_type[0]
        self._cleanup_config(cfg, skip_comments=opts.minimal)

        if opts.edit:
            done = False
            editor = _find_editor()
            if not editor:
                print("Could not find a valid editor", file=sys.stderr)
                return 1

            tmpfileobj = tempfile.NamedTemporaryFile()
            cfg.filename = tmpfileobj.name
            cfg.write()
            while not done:
                status = subprocess.call([editor, cfg.filename])
                if status != 0:
                    if not confirm("Editor exited with non-zero status[%d]. "
                                   "Would you like to retry?" % status):
                        print("Aborting", file=sys.stderr)
                        return 1
                try:
                    cfg.reload()
                except ParseError as exc:
                    print("%s : %s" % \
                    (exc.msg, exc.line), file=sys.stderr)
                else:
                    errors = cfg.validate(VALIDATOR, preserve_errors=True)
                    if errors is True:
                        done = True
                        continue
                    else:
                        _report_errors(cfg, errors)

                if not confirm('There were configuration errors. Continue?'):
                    print("Aborting", file=sys.stderr)
                    return 1
            tmpfileobj.close()

        if not opts.name and not opts.file:
            buf = getattr(sys.stdout, 'buffer', sys.stdout)
            cfg.write(buf)
            buf.flush()

        if opts.file:
            print("Saving config to %r" % opts.file, file=sys.stderr)
            filehandle = open(opts.file, 'w')
            buf = getattr(filehandle, 'buffer', filehandle)
            cfg.write(buf)
            buf.flush()
        elif opts.name:
            base_dir = os.path.dirname(HOLLANDCFG.filename)
            path = os.path.join(base_dir, 'backupsets', opts.name + '.conf')
            print("Saving config to %r" % path, file=sys.stderr)
            filehandle = open(path, 'w')
            buf = getattr(filehandle, 'buffer', filehandle)
            cfg.write(buf)
            buf.flush()
        return 0
Exemplo n.º 3
0
    def run(self, cmd, opts, *plugin_type):
        if not plugin_type:
            print("Missing plugin name", file=sys.stderr)
            return 1
        if opts.name and opts.provider:
            print("Can't specify a name for a global provider config", file=sys.stderr)
            return 1

        try:
            plugin_cls = load_first_entrypoint("holland.backup", plugin_type[0])
        except PluginLoadError as exc:
            logging.info("Failed to load backup plugin %r: %s", plugin_type[0], exc)
            return 1

        try:
            cfgspec = sys.modules[plugin_cls.__module__].CONFIGSPEC
        except BaseException as ex:
            print(
                "Could not load config-spec from plugin %r, %s" % (plugin_type[0], ex),
                file=sys.stderr,
            )
            return 1

        base_config = """
        [holland:backup]
        plugin                  = ""
        backups-to-keep         = 1
        auto-purge-failures     = yes
        purge-policy            = after-backup
        estimated-size-factor   = 1.0
        """.lstrip().splitlines()
        cfg = ConfigObj(base_config, configspec=cfgspec, list_values=True, stringify=True)
        cfg["holland:backup"]["plugin"] = plugin_type[0]
        self._cleanup_config(cfg, skip_comments=opts.minimal)

        if opts.edit:
            done = False
            editor = _find_editor()
            if not editor:
                print("Could not find a valid editor", file=sys.stderr)
                return 1

            tmpfileobj = tempfile.NamedTemporaryFile()
            cfg.filename = tmpfileobj.name
            cfg.write()
            while not done:
                status = subprocess.call([editor, cfg.filename])
                if status != 0:
                    if not confirm(
                        "Editor exited with non-zero status[%d]. "
                        "Would you like to retry?" % status
                    ):
                        print("Aborting", file=sys.stderr)
                        return 1
                try:
                    cfg.reload()
                except ParseError as exc:
                    print("%s : %s" % (exc.msg, exc.line), file=sys.stderr)
                else:
                    errors = cfg.validate(VALIDATOR, preserve_errors=True)
                    if errors is True:
                        done = True
                        continue
                    else:
                        _report_errors(cfg, errors)

                if not confirm("There were configuration errors. Continue?"):
                    print("Aborting", file=sys.stderr)
                    return 1
            tmpfileobj.close()

        if not opts.name and not opts.file:
            buf = getattr(sys.stdout, "buffer", sys.stdout)
            cfg.write(buf)
            buf.flush()

        if opts.file:
            print("Saving config to %r" % opts.file, file=sys.stderr)
            filehandle = open(opts.file, "w")
            buf = getattr(filehandle, "buffer", filehandle)
            cfg.write(buf)
            buf.flush()
        elif opts.name:
            base_dir = os.path.dirname(HOLLANDCFG.filename)
            path = os.path.join(base_dir, "backupsets", opts.name + ".conf")
            print("Saving config to %r" % path, file=sys.stderr)
            filehandle = open(path, "w")
            buf = getattr(filehandle, "buffer", filehandle)
            cfg.write(buf)
            buf.flush()
        return 0