Esempio n. 1
0
class RA(command.UI):
    '''
    CIB shadow management class
    '''
    name = "ra"
    provider_classes = ["ocf"]

    def do_classes(self, context):
        "usage: classes"
        for c in ra.ra_classes():
            if c in self.provider_classes:
                providers = ra.ra_providers_all(c)
                if providers:
                    print "%s / %s" % (c, ' '.join(providers))
            else:
                print "%s" % c

    @command.skill_level('administrator')
    def do_providers(self, context, ra_type, ra_class="ocf"):
        "usage: providers <ra> [<class>]"
        print ' '.join(ra.ra_providers(ra_type, ra_class))

    @command.skill_level('administrator')
    @command.completers(compl.call(ra.ra_classes), lambda args: ra.ra_providers_all(args[1]))
    def do_list(self, context, class_, provider_=None):
        "usage: list <class> [<provider>]"
        if not class_ in ra.ra_classes():
            context.fatal_error("class %s does not exist" % class_)
        if provider_ and not provider_ in ra.ra_providers_all(class_):
            context.fatal_error("there is no provider %s for class %s" % (provider_, class_))
        types = ra.ra_types(class_, provider_)
        if options.regression_tests:
            for t in types:
                print t
        else:
            utils.multicolumn(types)

    @command.skill_level('administrator')
    @command.alias('meta')
    @command.completers(complete_class_provider_type)
    def do_info(self, context, *args):
        "usage: info [<class>:[<provider>:]]<type>"
        if len(args) == 0:
            context.fatal_error("Expected [<class>:[<provider>:]]<type>")
        elif len(args) > 1:  # obsolete syntax
            if len(args) < 3:
                ra_type, ra_class, ra_provider = args[0], args[1], "heartbeat"
            else:
                ra_type, ra_class, ra_provider = args[0], args[1], args[2]
        elif args[0] in constants.meta_progs:
            ra_class, ra_provider, ra_type = args[0], None, None
        else:
            ra_class, ra_provider, ra_type = ra.disambiguate_ra_type(args[0])
        agent = ra.RAInfo(ra_class, ra_type, ra_provider)
        if agent.mk_ra_node() is None:
            return False
        try:
            utils.page_string(agent.meta_pretty())
        except Exception, msg:
            context.fatal_error(msg)
Esempio n. 2
0
class CibConfig(command.UI):
    '''
    The configuration class
    '''
    name = "configure"

    def __init__(self):
        command.UI.__init__(self)
        # for interactive use, we want to populate the CIB
        # immediately so that tab completion works
        if options.interactive or options.shell_completion:
            cib_factory.initialize()

    def requires(self):
        # see the configure ptest/simulate command
        has_ptest = utils.is_program('ptest')
        has_simulate = utils.is_program('crm_simulate')
        if not has_ptest:
            vars.simulate_programs["ptest"] = "crm_simulate"
        if not has_simulate:
            vars.simulate_programs["simulate"] = "ptest"
        if not (has_ptest or has_simulate):
            common_warn("neither ptest nor crm_simulate exist, check your installation")
            vars.simulate_programs["ptest"] = ""
            vars.simulate_programs["simulate"] = ""
        return True

    @command.name('_test')
    @command.skill_level('administrator')
    def do_check_structure(self, context):
        return cib_factory.check_structure()

    @command.name('_regtest')
    @command.skill_level('administrator')
    def do_regression_testing(self, context, param):
        return cib_factory.regression_testing(param)

    @command.name('_objects')
    @command.skill_level('administrator')
    def do_showobjects(self, context):
        cib_factory.showobjects()

    @command.level(ui_ra.RA)
    def do_ra(self):
        pass

    @command.level(ui_cib.CibShadow)
    def do_cib(self):
        pass

    @command.level(ui_cibstatus.CibStatusUI)
    def do_cibstatus(self):
        pass

    @command.level(ui_template.Template)
    def do_template(self):
        pass

    @command.level(ui_history.History)
    def do_history(self):
        pass

    @command.level(ui_assist.Assist)
    def do_assist(self):
        pass

    @command.skill_level('administrator')
    @command.completers_repeating(_id_show_list)
    def do_show(self, context, *args):
        "usage: show [xml] [<id>...]"
        if not cib_factory.is_cib_sane():
            context.fatal_error("CIB is not valid")
        set_obj = mkset_obj(*args)
        return set_obj.show()

    @command.skill_level('administrator')
    @command.completers_repeating(compl.null, _id_xml_list, _id_list)
    def do_filter(self, context, filterprog, *args):
        "usage: filter <prog> [xml] [<id>...]"
        if not cib_factory.is_cib_sane():
            context.fatal_error("CIB is not valid")
        set_obj = mkset_obj(*args)
        return set_obj.filter(filterprog)

    @command.skill_level('administrator')
    @command.completers(_f_group_id_list, compl.choice(['add', 'remove']),
                        _prim_id_list, compl.choice(['after', 'before']), _prim_id_list)
    def do_modgroup(self, context, group_id, subcmd, prim_id, *args):
        """usage: modgroup <id> add <id> [after <id>|before <id>]
        modgroup <id> remove <id>"""
        if not cib_factory.is_cib_sane():
            context.fatal_error("CIB is not valid")
        if subcmd not in ("add", "remove"):
            common_err("modgroup subcommand %s unknown" % subcmd)
            return False
        after_before = None
        if args:
            if subcmd != 'add':
                context.fatal_error("Expected add (found %s)" % subcmd)
            if args[0] not in ("after", "before"):
                context.fatal_error("Expected after|before (found %s)" % args[0])
            if len(args) != 2:
                context.fatal_error("Expected 'after|before <id>' (%d arguments given)" %
                                    len(args))
            after_before = args[0]
            ref_member_id = args[1]
        g = cib_factory.find_object(group_id)
        if not g:
            context.fatal_error("group %s does not exist" % group_id)
        if not xmlutil.is_group(g.node):
            context.fatal_error("element %s is not a group" % group_id)
        children = xmlutil.get_rsc_children_ids(g.node)
        if after_before and ref_member_id not in children:
            context.fatal_error("%s is not member of %s" % (ref_member_id, group_id))
        if subcmd == "remove" and prim_id not in children:
            context.fatal_error("%s is not member of %s" % (prim_id, group_id))
        # done checking arguments
        # have a group and children
        if not after_before:
            after_before = "after"
            ref_member_id = children[-1]
        # just do the filter
        # (i wonder if this is a feature abuse?)
        if subcmd == "add":
            if after_before == "after":
                sed_s = r's/ %s( |$)/& %s /' % (ref_member_id, prim_id)
            else:
                sed_s = r's/ %s( |$)/ %s& /' % (ref_member_id, prim_id)
        else:
            sed_s = r's/ %s( |$)/ /' % prim_id
        l = (group_id,)
        set_obj = mkset_obj(*l)
        return set_obj.filter("sed -r '%s'" % sed_s)

    @command.skill_level('administrator')
    @command.completers_repeating(_id_xml_list, _id_list)
    def do_edit(self, context, *args):
        "usage: edit [xml] [<id>...]"
        if not cib_factory.is_cib_sane():
            context.fatal_error("CIB is not valid")
        err_buf.buffer()  # keep error messages
        set_obj = mkset_obj(*args)
        err_buf.release()  # show them, but get an ack from the user
        return set_obj.edit()

    def _verify(self, set_obj_semantic, set_obj_all):
        rc1 = set_obj_all.verify()
        if config.core.check_frequency != "never":
            rc2 = set_obj_semantic.semantic_check(set_obj_all)
        else:
            rc2 = 0
        return rc1 and rc2 <= 1

    @command.skill_level('administrator')
    def do_verify(self, context):
        "usage: verify"
        if not cib_factory.is_cib_sane():
            context.fatal_error("CIB is not valid")
        set_obj_all = mkset_obj("xml")
        return self._verify(set_obj_all, set_obj_all)

    @command.skill_level('administrator')
    def do_save(self, context, *args):
        "usage: save [xml] <filename>"
        if not cib_factory.is_cib_sane():
            context.fatal_error("CIB is not valid")
        if not args:
            context.fatal_error("Expected 1 argument (0 given)")
        if args[0] == "xml":
            if len(args) != 2:
                context.fatal_error("Expected 2 arguments (%d given)" % (len(args)))
            filename = args[1]
            set_obj = mkset_obj("xml")
        else:
            filename = args[0]
            set_obj = mkset_obj()
        return set_obj.save_to_file(filename)

    @command.skill_level('administrator')
    @command.completers(compl.choice(['xml', 'replace', 'update']), _load_2nd_completer)
    def do_load(self, context, *args):
        "usage: load [xml] {replace|update} {<url>|<path>}"
        if not cib_factory.is_cib_sane():
            context.fatal_error("CIB is not valid")
        if len(args) < 2:
            context.fatal_error("Expected 2 arguments (0 given)")
        if args[0] == "xml":
            if len(args) != 3:
                context.fatal_error("Expected 3 arguments (%d given)" % len(args))
            url = args[2]
            method = args[1]
            xml = True
        else:
            if len(args) != 2:
                context.fatal_error("Expected 2 arguments (%d given)" % len(args))
            url = args[1]
            method = args[0]
            xml = False
        if method not in ("replace", "update"):
            context.fatal_error("Unknown method %s" % method)
        if method == "replace":
            if options.interactive and cib_factory.has_cib_changed():
                if not utils.ask("This operation will erase all changes. Do you want to proceed?"):
                    return False
            cib_factory.erase()
        if xml:
            set_obj = mkset_obj("xml")
        else:
            set_obj = mkset_obj()
        return set_obj.import_file(method, url)

    @command.skill_level('administrator')
    @command.completers(compl.choice(gv_types.keys() + ['exportsettings']))
    def do_graph(self, context, *args):
        "usage: graph [<gtype> [<file> [<img_format>]]]"
        if args and args[0] == "exportsettings":
            return utils.save_graphviz_file(userdir.GRAPHVIZ_USER_FILE, vars.graph)
        if not cib_factory.is_cib_sane():
            context.fatal_error("CIB is not valid")
        rc, gtype, outf, ftype = ui_utils.graph_args(args)
        if not rc:
            context.fatal_error("Failed to create graph")
        rc, d = utils.load_graphviz_file(userdir.GRAPHVIZ_USER_FILE)
        if rc and d:
            vars.graph = d
        set_obj = mkset_obj()
        if not outf:
            rc = set_obj.show_graph(gtype)
        elif gtype == ftype:
            rc = set_obj.save_graph(gtype, outf)
        else:
            rc = set_obj.graph_img(gtype, outf, ftype)
        return rc

    @command.skill_level('administrator')
    @command.completers_repeating(_id_list)
    def do_delete(self, context, *args):
        "usage: delete <id> [<id>...]"
        if not cib_factory.is_cib_sane():
            context.fatal_error("CIB is not valid")
        return cib_factory.delete(*args)

    @command.name('default-timeouts')
    @command.alias('default_timeouts')
    @command.completers_repeating(_id_list)
    def do_default_timeouts(self, context, *args):
        "usage: default-timeouts <id> [<id>...]"
        if not cib_factory.is_cib_sane():
            context.fatal_error("CIB is not valid")
        return cib_factory.default_timeouts(*args)

    @command.skill_level('administrator')
    @command.completers(_id_list, _id_list)
    def do_rename(self, context, old_id, new_id):
        "usage: rename <old_id> <new_id>"
        if not cib_factory.is_cib_sane():
            context.fatal_error("CIB is not valid")
        return cib_factory.rename(old_id, new_id)

    @command.skill_level('administrator')
    @command.completers(compl.choice(['nodes']))
    def do_erase(self, context, nodes=None):
        "usage: erase [nodes]"
        if not cib_factory.is_cib_sane():
            context.fatal_error("CIB is not valid")
        if nodes is None:
            return cib_factory.erase()
        if nodes != 'nodes':
            context.fatal_error("Expected 'nodes' (found '%s')" % (nodes))
        return cib_factory.erase_nodes()

    @command.skill_level('administrator')
    def do_refresh(self, context):
        "usage: refresh"
        if options.interactive and cib_factory.has_cib_changed():
            if not utils.ask("All changes will be dropped. Do you want to proceed?"):
                return
        cib_factory.refresh()

    @command.alias('simulate')
    @command.completers(compl.choice(['nograph']))
    def do_ptest(self, context, *args):
        "usage: ptest [nograph] [v...] [scores] [utilization] [actions]"
        if not cib_factory.is_cib_sane():
            return False
        # use ptest/crm_simulate depending on which command was
        # used
        config.core.ptest = vars.simulate_programs[context.get_command_name()]
        if not config.core.ptest:
            return False
        set_obj = mkset_obj("xml")
        return ui_utils.ptestlike(set_obj.ptest, 'vv', context.get_command_name(), args)

    def _commit(self, force=None):
        if force and force != "force":
            syntax_err(('configure.commit', force))
            return False
        if not cib_factory.is_cib_sane():
            return False
        if not cib_factory.has_cib_changed():
            common_info("apparently there is nothing to commit")
            common_info("try changing something first")
            return True
        rc1 = True
        if not (force or utils.cibadmin_can_patch()):
            rc1 = cib_factory.is_current_cib_equal()
        rc2 = cib_factory.is_cib_empty() or \
            self._verify(mkset_obj("xml", "changed"), mkset_obj("xml"))
        if rc1 and rc2:
            return cib_factory.commit()
        if force or config.core.force:
            common_info("commit forced")
            return cib_factory.commit(force=True)
        if utils.ask("Do you still want to commit?"):
            return cib_factory.commit(force=True)
        return False

    @command.skill_level('administrator')
    @command.wait
    @command.completers(compl.choice(['force']))
    def do_commit(self, context, force=None):
        "usage: commit [force]"
        return self._commit(force=force)

    @command.skill_level('administrator')
    @command.completers(compl.choice(['force']))
    def do_upgrade(self, context, force=None):
        "usage: upgrade [force]"
        if not cib_factory.is_cib_sane():
            return False
        if force and force != "force":
            syntax_err((context.get_command_name(), force))
            return False
        if config.core.force or force:
            return cib_factory.upgrade_cib_06to10(True)
        else:
            return cib_factory.upgrade_cib_06to10()

    @command.skill_level('administrator')
    def do_schema(self, context, schema_st=None):
        "usage: schema [<schema>]"
        if not cib_factory.is_cib_sane():
            return False
        if not schema_st:
            print cib_factory.get_schema()
            return True
        return cib_factory.change_schema(schema_st)

    def __conf_object(self, cmd, *args):
        "The configure object command."
        if not cib_factory.is_cib_sane():
            return False
        if cmd in vars.cib_cli_map.values() and \
                not cib_factory.is_elem_supported(cmd):
            common_err("%s not supported by the RNG schema" % cmd)
            return False
        f = lambda: cib_factory.create_object(cmd, *args)
        return f()

    @command.skill_level('administrator')
    @command.completers(_node_id_list, compl.choice(vars.node_attributes_keyw))
    def do_node(self, context, *args):
        """usage: node <uname>[:<type>]
           [attributes <param>=<value> [<param>=<value>...]]
           [utilization <param>=<value> [<param>=<value>...]]"""
        return self.__conf_object(context.get_command_name(), *args)

    @command.skill_level('administrator')
    @command.completers_repeating(compl.null, ra_classes_or_tmpl, primitive_complete_complex)
    def do_primitive(self, context, *args):
        """usage: primitive <rsc> {[<class>:[<provider>:]]<type>|@<template>}
        [params <param>=<value> [<param>=<value>...]]
        [meta <attribute>=<value> [<attribute>=<value>...]]
        [utilization <attribute>=<value> [<attribute>=<value>...]]
        [operations id_spec
            [op op_type [<attribute>=<value>...] ...]]"""
        return self.__conf_object(context.get_command_name(), *args)

    @command.skill_level('administrator')
    @command.completers_repeating(compl.null, _group_completer)
    def do_group(self, context, *args):
        """usage: group <name> <rsc> [<rsc>...]
        [params <param>=<value> [<param>=<value>...]]
        [meta <attribute>=<value> [<attribute>=<value>...]]"""
        return self.__conf_object(context.get_command_name(), *args)

    @command.skill_level('administrator')
    @command.completers_repeating(compl.null, _f_children_id_list, _clone_completer)
    def do_clone(self, context, *args):
        """usage: clone <name> <rsc>
        [params <param>=<value> [<param>=<value>...]]
        [meta <attribute>=<value> [<attribute>=<value>...]]"""
        return self.__conf_object(context.get_command_name(), *args)

    @command.alias('master')
    @command.skill_level('administrator')
    @command.completers_repeating(compl.null, _f_children_id_list, _ms_completer)
    def do_ms(self, context, *args):
        """usage: ms <name> <rsc>
        [params <param>=<value> [<param>=<value>...]]
        [meta <attribute>=<value> [<attribute>=<value>...]]"""
        return self.__conf_object(context.get_command_name(), *args)

    @command.skill_level('administrator')
    @command.completers_repeating(compl.null, ui_ra.complete_class_provider_type,
                                  primitive_complete_complex)
    def do_rsc_template(self, context, *args):
        """usage: rsc_template <name> [<class>:[<provider>:]]<type>
        [params <param>=<value> [<param>=<value>...]]
        [meta <attribute>=<value> [<attribute>=<value>...]]
        [utilization <attribute>=<value> [<attribute>=<value>...]]
        [operations id_spec
            [op op_type [<attribute>=<value>...] ...]]"""
        return self.__conf_object(context.get_command_name(), *args)

    @command.skill_level('administrator')
    @command.completers(compl.null, _top_rsc_id_list)
    def do_location(self, context, *args):
        """usage: location <id> <rsc> {node_pref|rules}

        node_pref :: <score>: <node>

        rules ::
          rule [id_spec] [$role=<role>] <score>: <expression>
          [rule [id_spec] [$role=<role>] <score>: <expression> ...]

        id_spec :: $id=<id> | $id-ref=<id>
        score :: <number> | <attribute> | [-]inf
        expression :: <simple_exp> [bool_op <simple_exp> ...]
        bool_op :: or | and
        simple_exp :: <attribute> [type:]<binary_op> <value>
                      | <unary_op> <attribute>
                      | date <date_expr>
        type :: string | version | number
        binary_op :: lt | gt | lte | gte | eq | ne
        unary_op :: defined | not_defined"""
        return self.__conf_object(context.get_command_name(), *args)

    @command.alias('collocation')
    @command.skill_level('administrator')
    @command.completers_repeating(compl.null, compl.null, top_rsc_tmpl_id_list)
    def do_colocation(self, context, *args):
        """usage: colocation <id> <score>: <rsc>[:<role>] <rsc>[:<role>] ...
        [node-attribute=<node_attr>]"""
        return self.__conf_object(context.get_command_name(), *args)

    @command.skill_level('administrator')
    @command.completers_repeating(compl.null,
                                  compl.call(schema.rng_attr_values, 'rsc_order', 'kind'),
                                  top_rsc_tmpl_id_list)
    def do_order(self, context, *args):
        """usage: order <id> {kind|<score>}: <rsc>[:<action>] <rsc>[:<action>] ...
        [symmetrical=<bool>]"""
        return self.__conf_object(context.get_command_name(), *args)

    @command.skill_level('administrator')
    @command.completers_repeating(compl.null, compl.null, top_rsc_tmpl_id_list)
    def do_rsc_ticket(self, context, *args):
        """usage: rsc_ticket <id> <ticket_id>: <rsc>[:<role>] [<rsc>[:<role>] ...]
        [loss-policy=<loss_policy_action>]"""
        return self.__conf_object(context.get_command_name(), *args)

    @command.skill_level('administrator')
    @command.completers_repeating(_property_completer)
    def do_property(self, context, *args):
        "usage: property [$id=<set_id>] <option>=<value>"
        return self.__conf_object(context.get_command_name(), *args)

    @command.skill_level('administrator')
    @command.completers_repeating(_prim_meta_completer)
    def do_rsc_defaults(self, context, *args):
        "usage: rsc_defaults [$id=<set_id>] <option>=<value>"
        return self.__conf_object(context.get_command_name(), *args)

    @command.skill_level('administrator')
    @command.completers_repeating(op_attr_list)
    def do_op_defaults(self, context, *args):
        "usage: op_defaults [$id=<set_id>] <option>=<value>"
        return self.__conf_object(context.get_command_name(), *args)

    @command.skill_level('administrator')
    @command.completers_repeating(node_id_colon_list, stonith_resource_list)
    def do_fencing_topology(self, context, *args):
        "usage: fencing_topology [<node>:] stonith_resources [stonith_resources ...]"
        return self.__conf_object(context.get_command_name(), *args)

    @command.skill_level('administrator')
    def do_xml(self, context, *args):
        "usage: xml <xml>"
        return self.__conf_object(context.get_command_name(), *args)

    @command.skill_level('administrator')
    @command.completers(_f_children_id_list)
    def do_monitor(self, context, *args):
        "usage: monitor <rsc>[:<role>] <interval>[:<timeout>]"
        return self.__conf_object(context.get_command_name(), *args)

    @command.skill_level('expert')
    @command.completers_repeating(compl.null, compl.choice(["role:", "read", "write", "deny"]))
    def do_user(self, context, *args):
        """user <uid> {roles|rules}

        roles :: role:<role-ref> [role:<role-ref> ...]
        rules :: rule [rule ...]

        (See the role command for details on rules.)"""
        return self.__conf_object(context.get_command_name(), *args)

    @command.skill_level('expert')
    @command.completers_repeating(compl.null, compl.choice(["read", "write", "deny"]))
    def do_role(self, context, *args):
        """role <role-id> rule [rule ...]

        rule :: acl-right cib-spec [attribute:<attribute>]

        acl-right :: read | write | deny

        cib-spec :: xpath-spec | tag-ref-spec
        xpath-spec :: xpath:<xpath> | shortcut
        tag-ref-spec :: tag:<tag> | ref:<id> | tag:<tag> ref:<id>

        shortcut :: meta:<rsc>[:<attr>]
                    params:<rsc>[:<attr>]
                    utilization:<rsc>
                    location:<rsc>
                    property[:<attr>]
                    node[:<node>]
                    nodeattr[:<attr>]
                    nodeutil[:<node>]
                    status"""
        return self.__conf_object(context.get_command_name(), *args)

    @command.skill_level('administrator')
    @command.completers_repeating(compl.null, top_rsc_tmpl_id_list)
    def do_tag(self, context, *args):
        return self.__conf_object(context.get_command_name(), *args)

    @command.skill_level('expert')
    @command.completers_repeating(_rsc_id_list)
    def do_rsctest(self, context, *args):
        "usage: rsctest <rsc_id> [<rsc_id> ...] [<node_id> ...]"
        if not cib_factory.is_cib_sane():
            return False
        rc = True
        rsc_l = []
        node_l = []
        current = "r"
        for ident in args:
            el = cib_factory.find_object(ident)
            if not el:
                common_err("element %s does not exist" % ident)
                rc = False
            elif current == "r" and xmlutil.is_resource(el.node):
                if xmlutil.is_container(el.node):
                    rsc_l += el.node.findall("primitive")
                else:
                    rsc_l.append(el.node)
            elif xmlutil.is_normal_node(el.node):
                current = "n"
                node_l.append(el.node.get("uname"))
            else:
                syntax_err((context.get_command_name(), ident), context='rsctest')
                return False
        if not rc:
            return False
        if not rsc_l:
            common_err("specify at least one resource")
            return False
        all_nodes = cib_factory.node_id_list()
        if not node_l:
            node_l = all_nodes
        return rsctest.test_resources(rsc_l, node_l, all_nodes)

    def should_wait(self):
        return cib_factory.has_cib_changed()

    def end_game(self, no_questions_asked=False):
        ok = True
        if cib_factory.has_cib_changed():
            if no_questions_asked or not options.interactive:
                ok = self._commit()
            elif utils.ask("There are changes pending. Do you want to commit them?"):
                ok = self._commit()
        cib_factory.reset()
        return ok
Esempio n. 3
0
import ui_utils
import ui_assist
from crm_gv import gv_types

err_buf = ErrorBuffer.getInstance()
cib_factory = CibFactory.getInstance()


def _type_completions():
    "completer for type: use in show"
    typelist = cib_factory.type_list()
    return ['type:%s' % (t) for t in typelist]


# Tab completion helpers
_id_list = compl.call(cib_factory.id_list)
_id_xml_list = compl.join(_id_list, compl.choice(['xml']))
_id_show_list = compl.join(_id_list,
                           compl.choice(['xml', 'changed']),
                           compl.call(_type_completions))
_prim_id_list = compl.call(cib_factory.prim_id_list)
_f_prim_free_id_list = compl.call(cib_factory.f_prim_free_id_list)
_f_group_id_list = compl.call(cib_factory.f_group_id_list)
_f_children_id_list = compl.call(cib_factory.f_children_id_list)
_rsc_id_list = compl.call(cib_factory.rsc_id_list)
_top_rsc_id_list = compl.call(cib_factory.top_rsc_id_list)
_node_id_list = compl.call(cib_factory.node_id_list)
_rsc_template_list = compl.call(cib_factory.rsc_template_list)
_group_completer = compl.join(_f_prim_free_id_list, compl.choice(['params', 'meta']))
_clone_completer = compl.choice(['params', 'meta'])
_ms_completer = compl.choice(['params', 'meta'])
Esempio n. 4
0
class Template(command.UI):
    '''
    Configuration templates.
    '''
    name = "template"

    def __init__(self):
        command.UI.__init__(self)
        self.curr_conf = ''
        self.init_dir()

    @command.skill_level('administrator')
    @command.completers_repeating(compl.null, compl.call(utils.listtemplates))
    def do_new(self, context, name, *args):
        "usage: new <config> <template> [<template> ...] [params name=value ...]"
        if not utils.is_filename_sane(name):
            return False
        if os.path.isfile("%s/%s" % (userdir.CRMCONF_DIR, name)):
            common_err("config %s exists; delete it first" % name)
            return False
        lt = LoadTemplate(name)
        rc = True
        mode = 0
        params = {}
        for s in args:
            if mode == 0 and s == "params":
                params["id"] = name
                mode = 1
            elif mode == 1:
                a = s.split('=')
                if len(a) != 2:
                    syntax_err(args, context='new')
                    rc = False
                else:
                    params[a[0]] = a[1]
            elif not lt.load_template(s):
                rc = False
        if rc:
            lt.post_process(params)
        if not rc or not lt.write_config(name):
            return False
        self.curr_conf = name

    @command.skill_level('administrator')
    @command.completers(compl.call(utils.listconfigs))
    def do_delete(self, context, name, force=''):
        "usage: delete <config> [force]"
        if force:
            if force != "force" and force != "--force":
                syntax_err((context.get_command_name(), force),
                           context='delete')
                return False
        if not self.config_exists(name):
            return False
        if name == self.curr_conf:
            if not force and not config.core.force and \
                    not utils.ask("Do you really want to remove config %s which is in use?" %
                                  self.curr_conf):
                return False
            else:
                self.curr_conf = ''
        os.remove("%s/%s" % (userdir.CRMCONF_DIR, name))

    @command.skill_level('administrator')
    @command.completers(compl.call(utils.listconfigs))
    def do_load(self, context, name=''):
        "usage: load [<config>]"
        if not name:
            self.curr_conf = ''
            return True
        if not self.config_exists(name):
            return False
        self.curr_conf = name

    @command.skill_level('administrator')
    @command.completers(compl.call(utils.listconfigs))
    def do_edit(self, context, name=''):
        "usage: edit [<config>]"
        if not name and not self.curr_conf:
            common_err("please load a config first")
            return False
        if name:
            if not self.config_exists(name):
                return False
            utils.edit_file("%s/%s" % (userdir.CRMCONF_DIR, name))
        else:
            utils.edit_file("%s/%s" % (userdir.CRMCONF_DIR, self.curr_conf))

    @command.completers(compl.call(utils.listconfigs))
    def do_show(self, context, name=''):
        "usage: show [<config>]"
        if not name and not self.curr_conf:
            common_err("please load a config first")
            return False
        if name:
            if not self.config_exists(name):
                return False
            print self.process(name)
        else:
            print self.process()

    @command.skill_level('administrator')
    @command.completers(
        compl.join(compl.call(utils.listconfigs),
                   compl.choice(['replace', 'update'])),
        compl.call(utils.listconfigs))
    def do_apply(self, context, *args):
        "usage: apply [<method>] [<config>]"
        method = "replace"
        name = ''
        if len(args) > 0:
            i = 0
            if args[0] in ("replace", "update"):
                method = args[0]
                i += 1
            if len(args) > i:
                name = args[i]
        if not name and not self.curr_conf:
            common_err("please load a config first")
            return False
        if name:
            if not self.config_exists(name):
                return False
            s = self.process(name)
        else:
            s = self.process()
        if not s:
            return False
        tmp = utils.str2tmp(s)
        if not tmp:
            return False
        if method == "replace":
            if options.interactive and cib_factory.has_cib_changed():
                if not utils.ask(
                        "This operation will erase all changes. Do you want to proceed?"
                ):
                    return False
            cib_factory.erase()
        set_obj = mkset_obj()
        rc = set_obj.import_file(method, tmp)
        try:
            os.unlink(tmp)
        except:
            pass
        return rc

    @command.completers(compl.choice(['templates']))
    def do_list(self, context, templates=''):
        "usage: list [templates]"
        if templates == "templates":
            utils.multicolumn(utils.listtemplates())
        else:
            utils.multicolumn(utils.listconfigs())

    def init_dir(self):
        '''Create the conf directory, link to templates'''
        if not os.path.isdir(userdir.CRMCONF_DIR):
            try:
                os.makedirs(userdir.CRMCONF_DIR)
            except os.error, msg:
                common_err("makedirs: %s" % msg)
Esempio n. 5
0
class History(command.UI):
    '''
    The history class
    '''
    name = "history"

    def __init__(self):
        command.UI.__init__(self)
        self.current_session = None
        self._source_inited = False

    def _init_source(self):
        if self._source_inited:
            return True
        self._source_inited = True
        return self._set_source(options.history)

    def _set_period(self, from_time='', to_time=''):
        '''
        parse time specs and set period
        '''
        from_dt = to_dt = None
        if from_time:
            from_dt = utils.parse_time(from_time)
            if not from_dt:
                return False
        if to_time:
            to_dt = utils.parse_time(to_time)
            if not to_dt:
                return False
        if to_dt and to_dt <= from_dt:
            common_err("%s - %s: bad period" % (from_time, to_time))
            return False
        return crm_report().set_period(from_dt, to_dt)

    def _check_source(self, src):
        'a (very) quick source check'
        if src == "live" or os.path.isfile(src) or os.path.isdir(src):
            return True
        else:
            common_err("source %s doesn't exist" % src)
            return False

    def _set_source(self, src, live_from_time=None):
        '''
        Have the last history source survive the History
        and Report instances
        '''
        common_debug("setting source to %s" % src)
        if not self._check_source(src):
            return False
        crm_report().set_source(src)
        options.history = src
        self.current_session = None
        to_time = ''
        if src == "live":
            from_time = time.ctime(live_from_time and live_from_time
                                   or (time.time() - 60 * 60))
        else:
            from_time = ''
        return self._set_period(from_time, to_time)

    @command.skill_level('administrator')
    def do_source(self, context, src=None):
        "usage: source {<dir>|<file>|live}"
        if src is None:
            print "Current source: %s" % (options.history)
            return True
        self._init_source()
        if src != options.history:
            return self._set_source(src)

    @command.skill_level('administrator')
    @command.alias('timeframe')
    def do_limit(self, context, from_time='', to_time=''):
        "usage: limit [<from_time> [<to_time>]]"
        self._init_source()
        if options.history == "live" and not from_time:
            from_time = time.ctime(time.time() - 60 * 60)
        return self._set_period(from_time, to_time)

    @command.skill_level('administrator')
    def do_refresh(self, context, force=''):
        "usage: refresh"
        self._init_source()
        if options.history != "live":
            common_info("nothing to refresh if source isn't live")
            return False
        if force:
            if force != "force" and force != "--force":
                context.fatal_error(
                    "Expected 'force' or '--force' (was '%s')" % (force))
            force = True
        return crm_report().refresh_source(force)

    @command.skill_level('administrator')
    def do_detail(self, context, detail_lvl):
        "usage: detail <detail_level>"
        self._init_source()
        detail_num = utils.convert2ints(detail_lvl)
        if not (isinstance(detail_num, int) and int(detail_num) >= 0):
            bad_usage(context.get_command_name(), detail_lvl)
            return False
        return crm_report().set_detail(detail_lvl)

    @command.skill_level('administrator')
    @command.completers_repeating(compl.call(lambda: crm_report().node_list()))
    def do_setnodes(self, context, *args):
        "usage: setnodes <node> [<node> ...]"
        self._init_source()
        if options.history != "live":
            common_info(
                "setting nodes not necessary for existing reports, proceeding anyway"
            )
        return crm_report().set_nodes(*args)

    @command.skill_level('administrator')
    def do_info(self, context):
        "usage: info"
        self._init_source()
        return crm_report().info()

    @command.skill_level('administrator')
    def do_latest(self, context):
        "usage: latest"
        self._init_source()
        if not utils.wait4dc("transition", not options.batch):
            return False
        self._set_source("live")
        crm_report().refresh_source()
        f = self._get_pe_byidx(-1)
        if not f:
            return False
        crm_report().show_transition_log(f)

    @command.skill_level('administrator')
    @command.completers_repeating(compl.call(lambda: crm_report().rsc_list()))
    def do_resource(self, context, *args):
        "usage: resource <rsc> [<rsc> ...]"
        self._init_source()
        return crm_report().resource(*args)

    @command.skill_level('administrator')
    @command.wait
    @command.completers_repeating(compl.call(lambda: crm_report().node_list()))
    def do_node(self, context, *args):
        "usage: node <node> [<node> ...]"
        self._init_source()
        return crm_report().node(*args)

    @command.skill_level('administrator')
    @command.completers_repeating(compl.call(lambda: crm_report().node_list()))
    def do_log(self, context, *args):
        "usage: log [<node> ...]"
        self._init_source()
        return crm_report().log(*args)

    def ptest(self, nograph, scores, utilization, actions, verbosity):
        'Send a decompressed self.pe_file to ptest'
        try:
            s = bz2.decompress(open(self.pe_file).read())
        except IOError, msg:
            common_err("open: %s" % msg)
            return False
        return utils.run_ptest(s, nograph, scores, utilization, actions,
                               verbosity)
Esempio n. 6
0
        self._init_source()
        return crm_report().log(*args)

    def ptest(self, nograph, scores, utilization, actions, verbosity):
        'Send a decompressed self.pe_file to ptest'
        try:
            s = bz2.decompress(open(self.pe_file).read())
        except IOError, msg:
            common_err("open: %s" % msg)
            return False
        return utils.run_ptest(s, nograph, scores, utilization, actions,
                               verbosity)

    @command.skill_level('administrator')
    @command.completers_repeating(
        compl.join(compl.call(lambda: crm_report().peinputs_list()),
                   compl.choice(['v'])))
    def do_peinputs(self, context, *args):
        """usage: peinputs [{<range>|<number>} ...] [v]"""
        self._init_source()
        argl = list(args)
        opt_l = utils.fetch_opts(argl, ["v"])
        if argl:
            l = []
            for s in argl:
                a = utils.convert2ints(s.split(':'))
                if a and len(a) == 2 and not utils.check_range(a):
                    common_err("%s: invalid peinputs range" % a)
                    return False
                l += crm_report().pelist(a, long=("v" in opt_l))
        else:
Esempio n. 7
0
# General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#

import command
import completers as compl
import utils
import ui_utils
import constants
from cibstatus import cib_status


_status_node_list = compl.call(cib_status.status_node_list)


class CibStatusUI(command.UI):
    '''
    The CIB status section management user interface class
    '''
    name = "cibstatus"

    @command.skill_level('expert')
    def do_load(self, context, org):
        "usage: load {<file>|shadow:<cib>|live}"
        return cib_status.load(org)

    @command.skill_level('expert')
    def do_save(self, context, dest=None):
Esempio n. 8
0
#
# You should have received a copy of the GNU General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#

import command
import completers as compl
import utils
import ui_utils
import vars
from cibstatus import CibStatus


cib_status = CibStatus.getInstance()
_status_node_list = compl.call(cib_status.status_node_list)


class CibStatusUI(command.UI):
    '''
    The CIB status section management user interface class
    '''
    name = "cibstatus"

    @command.skill_level('expert')
    def do_load(self, context, org):
        "usage: load {<file>|shadow:<cib>|live}"
        return cib_status.load(org)

    @command.skill_level('expert')
    def do_save(self, context, dest=None):
Esempio n. 9
0
    def do_log(self, context, *args):
        "usage: log [<node> ...]"
        self._init_source()
        return crm_report().log(*args)

    def ptest(self, nograph, scores, utilization, actions, verbosity):
        'Send a decompressed self.pe_file to ptest'
        try:
            s = bz2.decompress(open(self.pe_file).read())
        except IOError, msg:
            common_err("open: %s" % msg)
            return False
        return utils.run_ptest(s, nograph, scores, utilization, actions, verbosity)

    @command.skill_level('administrator')
    @command.completers_repeating(compl.join(compl.call(lambda: crm_report().peinputs_list()),
                                             compl.choice(['v'])))
    def do_peinputs(self, context, *args):
        """usage: peinputs [{<range>|<number>} ...] [v]"""
        self._init_source()
        argl = list(args)
        opt_l = utils.fetch_opts(argl, ["v"])
        if argl:
            l = []
            for s in argl:
                a = utils.convert2ints(s.split(':'))
                if a and len(a) == 2 and not utils.check_range(a):
                    common_err("%s: invalid peinputs range" % a)
                    return False
                l += crm_report().pelist(a, long=("v" in opt_l))
        else:
Esempio n. 10
0
class Assist(command.UI):
    '''
    The assist UI collects what could be called
    configuration macros. Things like merging
    multiple resources into a template, or building
    a colocated set with a relation to a dummy
    resource.
    '''
    name = "assist"

    def __init__(self):
        command.UI.__init__(self)

    def requires(self):
        return cib_factory.initialize()

    @command.skill_level('administrator')
    @command.completers_repeating(compl.call(cib_factory.prim_id_list))
    def do_template(self, context, *primitives):
        '''
        Create a shared template for the given primitives
        '''
        if len(primitives) < 1:
            context.fatal_error("Expected at least one primitive argument")
        objs = [cib_factory.find_object(p) for p in primitives]
        for prim, obj in zip(primitives, objs):
            if obj is None:
                context.fatal_error("Primitive %s not found" % (prim))
        if objs and all(obj.obj_type == 'primitive' for obj in objs):
            return self._template_primitives(context, objs)
        context.fatal_error("Cannot create a template for the given resources")

    def _template_primitives(self, context, primitives):
        """
        Try to template the given primitives:
        Templating means creating a rsc_template and moving
        shared attributes and other commonalities into that template
        (this second step is currently not available)
        """
        shared_template = None
        if all('template' in obj.node.attrib for obj in primitives):
            return True
        if len(set(xmlutil.mk_rsc_type(obj.node) for obj in primitives)) != 1:
            context.fatal_error("Cannot template the given primitives")

        node = primitives[0].node
        template_name = self.make_unique_name('template-%s-' %
                                              (node.get('type').lower()))
        shared_template = cib_factory.create_object('rsc_template',
                                                    template_name,
                                                    xmlutil.mk_rsc_type(node))
        if not shared_template:
            context.fatal_error("Error creating template")
        for obj in primitives:
            obj.node.set('template', template_name)
            rmattrs(obj.node, 'class', 'provider', 'type')
            obj.set_updated()

        if not self._pull_attributes(context, shared_template, primitives):
            context.fatal_error("Error when copying attributes into template")

        context.info("Template created: %s" % (template_name))
        return True

    def _pull_attributes(self, context, template, primitives):
        '''
        TODO: take any attributes shared by all primitives and
        move them into the shared template
        '''
        return True

    @command.skill_level('administrator')
    @command.completers_repeating(compl.call(cib_factory.prim_id_list))
    @command.name('weak-bond')
    @command.alias('weak_bond')
    def do_weak_bond(self, context, *nodes):
        '''
        Create a 'weak' colocation:
        Colocating a non-sequential resource set with
        a dummy resource which is not monitored creates,
        in effect, a colocation which does not imply any
        internal relationship between resources.
        '''
        if len(nodes) < 2:
            context.fatal_error("Need at least two arguments")

        for node in nodes:
            obj = cib_factory.find_object(node)
            if not obj:
                context.fatal_error("Object not found: %s" % (node))
            if not xmlutil.is_primitive(obj.node):
                context.fatal_error("Object not primitive: %s" % (node))

        constraint_name = self.make_unique_name('place-constraint-')
        dummy_name = self.make_unique_name('place-dummy-')
        print "Create weak bond / independent colocation"
        print "The following elements will be created:"
        print "   * Colocation constraint, ID: %s" % (constraint_name)
        print "   * Dummy resource, ID: %s" % (dummy_name)
        if not utils.can_ask() or utils.ask("Create resources?"):
            cib_factory.create_object('primitive', dummy_name,
                                      'ocf:heartbeat:Dummy')
            colo = ['colocation', constraint_name, 'inf:', '(']
            colo.extend(nodes)
            colo.append(')')
            colo.append(dummy_name)
            cib_factory.create_object(*colo)

    def make_unique_name(self, prefix):
        n = 0
        while n < 1000:
            n += 1
            name = "%s%s" % (prefix, n)
            for _id in cib_factory.id_list():
                if name == _id.lower():
                    continue
            return name
        raise ValueError(
            "Failed to generate unique resource ID with prefix '%s'" %
            (prefix))
Esempio n. 11
0
class Maintenance(command.UI):
    '''
    Commands that should only be run while in
    maintenance mode.
    '''
    name = "maintenance"

    rsc_maintenance = "crm_resource -r '%s' --meta -p maintenance -v '%s'"

    def __init__(self):
        command.UI.__init__(self)

    def requires(self):
        return cib_factory.initialize()

    def _onoff(self, resource, onoff):
        if resource is not None:
            return utils.ext_cmd(self.rsc_maintenance % (resource, onoff)) == 0
        else:
            return cib_factory.create_object('property',
                                             'maintenance-mode=%s' % (onoff))

    @command.skill_level('administrator')
    @command.completers_repeating(compl.call(cib_factory.rsc_id_list))
    def do_on(self, context, resource=None):
        '''
        Enable maintenance mode (for the optional resource or for everything)
        '''
        return self._onoff(resource, 'true')

    @command.skill_level('administrator')
    @command.completers_repeating(compl.call(cib_factory.rsc_id_list))
    def do_off(self, context, resource=None):
        '''
        Disable maintenance mode (for the optional resource or for everything)
        '''
        return self._onoff(resource, 'false')

    def _in_maintenance_mode(self, obj):
        if cib_factory.get_property("maintenance-mode") == "true":
            return True
        v = obj.meta_attributes("maintenance")
        return v and all(x == 'true' for x in v)

    def _runs_on_this_node(self, resource):
        nodes = utils.running_on(resource)
        return set(nodes) == set([utils.this_node()])

    @command.skill_level('administrator')
    @command.completers(compl.call(cib_factory.rsc_id_list), _compl_actions,
                        compl.choice(["ssh"]))
    def do_action(self, context, resource, action, ssh=None):
        '''
        Issue action out-of-band to the given resource, making
        sure that the resource is in maintenance mode first
        '''
        obj = cib_factory.find_object(resource)
        if not obj:
            context.fatal_error("Resource not found: %s" % (resource))
        if not xmlutil.is_resource(obj.node):
            context.fatal_error("Not a resource: %s" % (resource))
        if not self._in_maintenance_mode(obj):
            context.fatal_error("Not in maintenance mode.")

        if ssh is None:
            if action not in ('start', 'monitor'):
                if not self._runs_on_this_node(resource):
                    context.fatal_error(
                        "Resource %s must be running on this node (%s)" %
                        (resource, utils.this_node()))

            import rsctest
            return rsctest.call_resource(obj.node,
                                         action, [utils.this_node()],
                                         local_only=True)
        elif ssh == "ssh":
            import rsctest
            if action in ('start', 'promote', 'demote', 'recover',
                          'meta-data'):
                return rsctest.call_resource(obj.node,
                                             action, [utils.this_node()],
                                             local_only=True)
            else:
                all_nodes = cib_factory.node_id_list()
                return rsctest.call_resource(obj.node,
                                             action,
                                             all_nodes,
                                             local_only=False)
        else:
            context.fatal_error("Unknown argument: %s" % (ssh))
Esempio n. 12
0
    def ptest(self, nograph, scores, utilization, actions, verbosity):
        'Send a decompressed self.pe_file to ptest'
        try:
            f = open(self.pe_file)
        except IOError, msg:
            common_err("open: %s" % msg)
            return False
        s = bz2.decompress(''.join(f))
        f.close()
        return utils.run_ptest(s, nograph, scores, utilization, actions,
                               verbosity)

    @command.skill_level('administrator')
    @command.completers_repeating(
        compl.join(compl.call(crm_report.peinputs_list), compl.choice(['v'])))
    def do_peinputs(self, context, *args):
        """usage: peinputs [{<range>|<number>} ...] [v]"""
        argl = list(args)
        opt_l = utils.fetch_opts(argl, ["v"])
        if argl:
            l = []
            for s in argl:
                a = utils.convert2ints(s.split(':'))
                if a and len(a) == 2 and not utils.check_range(a):
                    common_err("%s: invalid peinputs range" % a)
                    return False
                l += crm_report.pelist(a, long=("v" in opt_l))
        else:
            l = crm_report.pelist(long=("v" in opt_l))
        if not l:
Esempio n. 13
0
class CibStatusUI(command.UI):
    '''
    The CIB status section management user interface class
    '''
    name = "cibstatus"

    @command.skill_level('expert')
    def do_load(self, context, org):
        "usage: load {<file>|shadow:<cib>|live}"
        return cib_status.load(org)

    @command.skill_level('expert')
    def do_save(self, context, dest=None):
        "usage: save [<file>|shadow:<cib>]"
        return cib_status.save(dest)

    @command.skill_level('administrator')
    def do_origin(self, context):
        "usage: origin"
        state = cib_status.modified and " (modified)" or ""
        print "%s%s" % (cib_status.origin, state)

    @command.skill_level('administrator')
    @command.completers(compl.choice(['changed']))
    def do_show(self, context, changed=""):
        "usage: show [changed]"
        if changed:
            if changed != "changed":
                context.fatal_error("Expected 'changed', got '%s'" % (changed))
            return cib_status.list_changes()
        return cib_status.show()

    @command.skill_level('administrator')
    @command.completers(compl.booleans)
    def do_quorum(self, context, opt):
        "usage: quorum <bool>"
        if not utils.verify_boolean(opt):
            context.fatal_error("%s: bad boolean option" % opt)
        return cib_status.set_quorum(utils.is_boolean_true(opt))

    @command.skill_level('expert')
    @command.completers(_status_node_list, compl.choice(vars.node_states))
    def do_node(self, context, node, state):
        "usage: node <node> {online|offline|unclean}"
        return cib_status.edit_node(node, state)

    @command.skill_level('expert')
    @command.completers(compl.null, compl.choice(cib_status.ticket_ops.keys()))
    def do_ticket(self, context, ticket, subcmd):
        "usage: ticket <ticket> {grant|revoke|activate|standby}"
        return cib_status.edit_ticket(ticket, subcmd)

    @command.skill_level('expert')
    @command.completers(compl.choice(vars.ra_operations),
                        compl.call(cib_status.status_rsc_list),
                        compl.choice(vars.lrm_exit_codes.keys()),
                        compl.choice(vars.lrm_status_codes.keys()),
                        compl.choice(vars.node_states))
    def do_op(self, context, op, rsc, rc, op_status=None, node=''):
        "usage: op <operation> <resource> <exit_code> [<op_status>] [<node>]"
        if rc in vars.lrm_exit_codes:
            num_rc = vars.lrm_exit_codes[rc]
        else:
            num_rc = rc
        if not num_rc.isdigit():
            context.fatal_error("Invalid exit code '%s'" % num_rc)
        num_op_status = op_status
        if op_status:
            if op_status in vars.lrm_status_codes:
                num_op_status = vars.lrm_status_codes[op_status]
            if not num_op_status.isdigit():
                context.fatal_error("Invalid operation status '%s'" % num_op_status)
        return cib_status.edit_op(op, rsc, num_rc, num_op_status, node)

    @command.skill_level('administrator')
    @command.completers(compl.choice(['nograph']))
    def do_run(self, context, *args):
        "usage: run [nograph] [v...] [scores] [utilization]"
        return ui_utils.ptestlike(cib_status.run, '', context.get_command_name(), args)

    @command.skill_level('administrator')
    @command.completers(compl.choice(['nograph']))
    def do_simulate(self, context, *args):
        "usage: simulate [nograph] [v...] [scores] [utilization]"
        return ui_utils.ptestlike(cib_status.simulate, '', context.get_command_name(), args)
Esempio n. 14
0
        logfile = corosync.get_value('logging.logfile')
        if not logfile:
            context.fatal_error("No corosync log file configured")
        utils.page_file(logfile)

    @command.name('add-node')
    @command.alias('add_node')
    @command.skill_level('administrator')
    def do_addnode(self, context, name):
        "Add a node to the corosync nodelist"
        corosync.add_node(name)

    @command.name('del-node')
    @command.alias('del_node')
    @command.skill_level('administrator')
    def do_delnode(self, context, name):
        "Remove a node from the corosync nodelist"
        corosync.del_node(name)

    @command.skill_level('administrator')
    @command.completers(completers.call(corosync.get_all_paths))
    def do_get(self, context, path):
        "Get a corosync configuration value"
        for v in corosync.get_values(path):
            print v

    @command.skill_level('administrator')
    def do_set(self, context, path, value):
        "Set a corosync configuration value"
        corosync.set_value(path, value)
Esempio n. 15
0
    def do_log(self, context, *args):
        "usage: log [<node> ...]"
        self._init_source()
        return crm_report.log(*args)

    def ptest(self, nograph, scores, utilization, actions, verbosity):
        'Send a decompressed self.pe_file to ptest'
        try:
            s = bz2.decompress(open(self.pe_file).read())
        except IOError, msg:
            common_err("open: %s" % msg)
            return False
        return utils.run_ptest(s, nograph, scores, utilization, actions, verbosity)

    @command.skill_level('administrator')
    @command.completers_repeating(compl.join(compl.call(crm_report.peinputs_list),
                                             compl.choice(['v'])))
    def do_peinputs(self, context, *args):
        """usage: peinputs [{<range>|<number>} ...] [v]"""
        self._init_source()
        argl = list(args)
        opt_l = utils.fetch_opts(argl, ["v"])
        if argl:
            l = []
            for s in argl:
                a = utils.convert2ints(s.split(':'))
                if a and len(a) == 2 and not utils.check_range(a):
                    common_err("%s: invalid peinputs range" % a)
                    return False
                l += crm_report.pelist(a, long=("v" in opt_l))
        else:
Esempio n. 16
0
        logfile = corosync.get_value('logging.logfile')
        if not logfile:
            context.fatal_error("No corosync log file configured")
        utils.page_file(logfile)

    @command.name('add-node')
    @command.alias('add_node')
    @command.skill_level('administrator')
    def do_addnode(self, context, name):
        "Add a node to the corosync nodelist"
        corosync.add_node(name)

    @command.name('del-node')
    @command.alias('del_node')
    @command.skill_level('administrator')
    def do_delnode(self, context, name):
        "Remove a node from the corosync nodelist"
        corosync.del_node(name)

    @command.skill_level('administrator')
    @command.completers(completers.call(corosync.get_all_paths))
    def do_get(self, context, path):
        "Get a corosync configuration value"
        for v in corosync.get_values(path):
            print v

    @command.skill_level('administrator')
    def do_set(self, context, path, value):
        "Set a corosync configuration value"
        corosync.set_value(path, value)
Esempio n. 17
0
class Assist(command.UI):
    '''
    The assist UI collects what could be called
    configuration macros. Things like merging
    multiple resources into a template, or building
    a colocated set with a relation to a dummy
    resource.
    '''
    name = "assist"

    def __init__(self):
        command.UI.__init__(self)
        # for interactive use, we want to populate the CIB
        # immediately so that tab completion works
        if options.interactive:
            cib_factory.initialize()

    #def do_distill(self, context):
    #    '''
    #    Detect and merge resources if the
    #    resulting template makes for a smaller
    #    configuration.
    #    '''
    #    # TODO
    #    return True

    @command.skill_level('administrator')
    @command.completers_repeating(compl.call(cib_factory.prim_id_list))
    @command.name('weak-bond')
    @command.alias('weak_bond')
    def do_weak_bond(self, context, *nodes):
        '''
        Create a 'weak' colocation:
        Colocating a non-sequential resource set with
        a dummy resource which is not monitored creates,
        in effect, a colocation which does not imply any
        internal relationship between resources.
        '''
        if not cib_factory.is_cib_sane():
            return False

        if len(nodes) < 2:
            context.fatal_error("Need at least two arguments")

        for node in nodes:
            obj = cib_factory.find_object(node)
            if not obj:
                context.fatal_error("Object not found: %s" % (node))
            if not xmlutil.is_primitive(obj.node):
                context.fatal_error("Object not primitive: %s" % (node))

        constraint_name = self.make_unique_name('place-constraint-')
        dummy_name = self.make_unique_name('place-dummy-')
        print "Create weak bond / independent colocation"
        print "The following elements will be created:"
        print "   * Colocation constraint, ID: %s" % (constraint_name)
        print "   * Dummy resource, ID: %s" % (dummy_name)
        if not utils.can_ask() or utils.ask("Create resources?"):
            cib_factory.create_object('primitive', dummy_name, 'ocf:heartbeat:Dummy')
            colo = ['colocation', constraint_name, 'inf:', '(']
            colo.extend(nodes)
            colo.append(')')
            colo.append(dummy_name)
            cib_factory.create_object(*colo)

    def make_unique_name(self, prefix):
        n = 0
        while n < 1000:
            n += 1
            name = "%s%s" % (prefix, n)
            for _id in cib_factory.id_list():
                if name == _id.lower():
                    continue
            return name
        raise ValueError("Failed to generate unique resource ID with prefix '%s'" % (prefix))