Esempio n. 1
0
    def command(self, opts, template_name, *params):
        """Add a single graph based on a template

        Arguments:
            template_name   -- the name of the template file
            params          -- other parameters (see below)

        The templates are in json, and is in the same format as the output of
        the dump_graph command.

        Other parameters are specified as "param_name=value" and will
        be substituted in the template. Use {param_name} in the template.
        """
        try:
            template = util.GraphTemplate(template_name)
        except IOError:
            log.error("Unable to open template %s" % template_name)
            sys.exit(1)
        template_params = template.parse_nv_params(params)
        graph_data = template.sub(template_params)
        log.msgnb("Adding graph: %s..." % graph_data["title"])
        try:
            rv = self.api.add_graph(graph_data=json.dumps(graph_data))
            log.msgnf("Success")
        except circonusapi.CirconusAPIError, e:
            log.msgnf("Failed")
            log.error(e.error)
Esempio n. 2
0
    def add_checks(self):
        for name, idx in sorted(self.ports.items()):
            log.msgnb("Adding port %s..." % name)
            metric_names = []
            params = {
                    'account': self.account,
                    'agent_id': self.agent,
                    'target': self.target,
                    'module': "snmp",
                    'display_name_%s' % self.target:
                        "%s port %s interface stats" % (
                            self.friendly_name, name),
                    'community': self.community}
            for k in self.metrics:
                metric_names.append(k)
                params["oid_%s" % k] = "%s.%s" % (self.metrics[k], idx)
            params['metric_name'] = metric_names

            for k in sorted(params):
                log.debug("%20s = %s" % (k, params[k]))

            try:
                rv = self.api.add_check_bundle(**params)
                log.msgnf("Success")
            except circonusapi.CirconusAPIError, e:
                log.msgnf("Failed")
                log.error(e.error)
Esempio n. 3
0
    def command(self, opts, duration, pattern, notes=""):
        """Schedule maintenance for rules matching the pattern

        Arguments:
            duration -- how long should the maintenance window last?
            pattern  -- pattern to match the check name with
            notes    -- optional notes for the maintenance window

        Duration should be of the form <integer>[m|h|d]. Examples:
            10m == 10 minutes
            4h  == 4 hours
            2d  == 2 days
        """
        if duration[-1] not in 'mhd':
            log.error("Duration needs to be of the form <integer>[m|h|d]")
            sys.exit(1)
        rules = self.api.list_rules()
        checks = self.api.list_checks(active='true')
        filtered_checks = {}
        for c in checks:
            if re.search(pattern, c['name'], flags=re.IGNORECASE):
                filtered_checks[c['check_id']] = c
        filtered_rules = [r for r in rules if r['check_id'] in
                filtered_checks]
        # Remove duplicates
        dedup_rules = {}
        for r in filtered_rules:
            dedup_rules[(r['check_id'], r['metric_name'], r['severity'])] = r
        filtered_rules = dedup_rules.values()
        log.msg("Scheduling maintenance for:")
        for r in sorted(filtered_rules):
            print "    Sev %s : %s : %s (from %s)" % (
                    r['severity'],
                    filtered_checks[r['check_id']]['name'],
                    r['metric_name'],
                    filtered_checks[r['check_id']]['agent'])
        if util.confirm():
            log.msg("Setting maintenance:")
            for r in filtered_rules:
                log.msgnb("Sev %s : %s : %s..." % (
                        r['severity'],
                        filtered_checks[r['check_id']]['name'],
                        r['metric_name']))
                try:
                    self.api.add_maintenance(
                        check_id=r['check_id'],
                        start='now',
                        stop=duration,
                        metric_name=r['metric_name'],
                        severity=r['severity'],
                        notes=notes)
                    log.msgnf("Success")
                except circonusapi.CirconusAPIError, e:
                    log.msgnf("Failed")
                    log.error(e.error)
Esempio n. 4
0
def get_agent(api, agent_name):
    rv = api.list_agents()
    agents = dict([(i['name'], i['agent_id']) for i in rv])
    try:
        return agents[agent_name]
    except KeyError:
        log.error("Invalid/Unknown Agent: %s" % agent_name)
        log.msg("Valid Agents:")
        for a in agents:
            log.msgnf("    %s" % a)
        sys.exit(1)
Esempio n. 5
0
    def command(self, opts, pattern, *metrics_to_enable):
        """Activate metrics for checks

        Arguments:
            pattern             -- Pattern for checks
            metrics_to_enable   -- List of metrics to enable
        """
        checks, groups = util.find_checks(self.api, pattern)
        already_enabled = {}

        # Pick only one check per check bundle
        bundles = {}
        for c in checks:
            if c['bundle_id'] in bundles:
                continue
            bundles[c['bundle_id']] = c

        log.msg("Retrieving metrics for checks")
        count = 0
        for c in bundles.values():
            count += 1
            print "\r%s/%s" % (count, len(bundles)),
            sys.stdout.flush()
            rv = self.api.list_metrics(check_id=c['check_id'])
            already_enabled[c['check_id']] = []
            for metric in sorted(rv):
                if metric['enabled']:
                    already_enabled[c['check_id']].append(metric['name'])

        log.msg("Metrics to enable: %s" % (', '.join(metrics_to_enable)))
        log.msg("About to enable metrics for the following checks")
        for c in bundles.values():
            log.msg("    %s (%s)" % (c['name'],
                ', '.join(already_enabled[c['check_id']])))

        if util.confirm():
            for c in bundles.values():
                # Enable metrics here
                log.msgnb("%s..." % c['name'])
                all_metrics = set(already_enabled[c['check_id']]) \
                    | set(metrics_to_enable)
                if all_metrics != set(already_enabled[c['check_id']]):
                    # The set of metrics has changed, apply the edit
                    self.api.edit_check_bundle(
                        bundle_id=c['bundle_id'],
                        metric_name=list(all_metrics))
                    log.msgnf("Done")
                else:
                    log.msgnf("No changes")
Esempio n. 6
0
    def command(self, opts, pattern, *metrics_to_enable):
        """Set the active metrics for a check based on regular expression

        This command will set the enabled metrics to exactly what matches the
        pattern(s) given. Any other metrics will be disabled, regardless of
        what their original setting was.

        Arguments:
            pattern             -- Pattern for checks
            metrics_to_enable   -- One or more regexes for enabled metrics
        """
        checks, groups = util.find_checks(self.api, pattern)
        to_enable = {}

        # Pick only one check per check bundle
        bundles = {}
        for c in checks:
            if c['bundle_id'] in bundles:
                continue
            bundles[c['bundle_id']] = c

        log.msg("Retrieving metrics for checks")
        count = 0
        for c in bundles.values():
            count += 1
            print "\r%s/%s" % (count, len(bundles)),
            sys.stdout.flush()
            rv = self.api.list_available_metrics(check_id=c['check_id'])
            to_enable[c['check_id']] = []
            for mtype in rv['metrics']:
                for metric in rv['metrics'][mtype]:
                    for pattern in metrics_to_enable:
                        if re.match(pattern, metric):
                            to_enable[c['check_id']].append(metric)

        log.msg("About to set enabled metrics for the following checks")
        for c in bundles.values():
            log.msg("    %s (%s)" % (c['name'],
                ', '.join(sorted(to_enable[c['check_id']]))))

        if util.confirm():
            for c in bundles.values():
                # Enable metrics here
                log.msgnb("%s..." % c['name'])
                # The set of metrics has changed, apply the edit
                self.api.edit_check_bundle(
                    bundle_id=c['bundle_id'],
                    metric_name=to_enable[c['check_id']])
                log.msgnf("Done")
Esempio n. 7
0
    def command(self, opts, pattern, replacement):
        """Rename multiple graphs at once

        Arguments:
            pattern     -- a regex to select the graphs to rename
            replacement -- what to replace the graph name with

        The replacement can contain \1, \2 etc. to refer to groups in the
        pattern.
        """
        rv = self.api.list_graphs()
        filtered_graphs = []
        for g in sorted(rv, lambda a, b: cmp(a['title'], b['title'])):
            if re.search(pattern, g['title']):
                filtered_graphs.append(g)
        renames = {}
        log.msg("Going to perform the following renames:")
        for g in filtered_graphs:
            renames[g['title']] = re.sub(pattern, replacement, g['title'])
            log.msg("    %s => %s" % (g['title'], renames[g['title']]))
        if util.confirm():
            for g in filtered_graphs:
                log.msgnb("Renaming %s..." % g['title'])
                try:
                    rv = self.api.get_graph(
                        graph_id=g['graph_id'])
                except circonusapi.CirconusAPIError, e:
                    log.msgnf("Failed to fetch current graph")
                    log.error(e.error)
                    continue
                try:
                    graph_data = json.loads(rv['graph_data'])
                except KeyError:
                    log.msgnf("Failed to fetch current graph")
                    log.error("No graph data returned")
                    continue
                except ValueError:
                    log.msgnf("Failed to fetch current graph")
                    log.error("Unable to parse the graph data")
                    continue
                graph_data['title'] = renames[g['title']]
                try:
                    rv = self.api.edit_graph(graph_id=g['graph_id'],
                                             graph_data=json.dumps(graph_data))
                    log.msgnf("Success")
                except circonusapi.CirconusAPIError, e:
                    log.msgnf("Failed to edit graph")
                    log.error(e.error)
Esempio n. 8
0
 def add_graphs(self, template, checks, groups):
     for c in checks:
         params = {
             "check_name":   c['name'],
             "check_id":     c['check_id'],
             "check_target": c['target'],
             "check_agent":  c['agent']}
         params.update(groups[c['check_id']])
         graph_data = template.sub(params)
         log.msgnb("Adding graph: %s..." % graph_data['title'])
         try:
             rv = self.api.add_graph(graph_data=json.dumps(graph_data))
             log.msgnf("Success")
         except circonusapi.CirconusAPIError, e:
             log.msgnf("Failed")
             log.error(e.error)
Esempio n. 9
0
    def command(self, opts, pattern, replacement):
        """Rename multiple checks at once

        Options:
            -a - Include inactive and deleted checks also

        Arguments:
            pattern     -- a regex to select the checks to rename
            replacement -- what to replace the check name with

        The replacement can contain \1, \2 etc. to refer to groups in the
        pattern.
        """
        active = 'true'
        if ('-a', '') in opts:
            active = ''
        rv = self.api.list_checks(active=active)
        filtered_checks = []
        # We rename bundles, not checks, so only do each bundle once
        bundles = {}
        for check in sorted(rv):
            if re.search(pattern, check['name']):
                if not check['bundle_id'] in bundles:
                    filtered_checks.append(check)
                    bundles[check['bundle_id']] = True
        renames = {}
        log.msg("Going to perform the following renames:")
        for c in filtered_checks:
            renames[c['name']] = re.sub(pattern, replacement, c['name'])
            log.msg("%s => %s" % (c['name'], renames[c['name']]))
        if util.confirm():
            for c in filtered_checks:
                log.msgnb("Renaming %s... " % c['name'])
                metrics = [m['name'] for m in
                           self.api.list_metrics(check_id=c['check_id'])]
                params = {
                    'bundle_id': c['bundle_id'],
                    'metric_name': metrics,
                    'display_name_%s' % c['target']: renames[c['name']]}
                try:
                    rv = self.api.edit_check_bundle(**params)
                    log.msgnf("Success")
                except circonusapi.CirconusAPIError, e:
                    log.msgnf("Failed")
                    log.error(e.error)
Esempio n. 10
0
    def command(self, opts, check_pattern, metric_pattern=None):
        """Removes rules for checks that match the given pattern

        Arguments:
            check_pattern   -- regex to match check names on (optional)
            metric_pattern  -- regex to match metric names on (optional)

        At least one of check_pattern or metric_pattern must be provided. If
        you want to leave out the check_pattern, then specify it as an empty
        string.
        """
        rules = self.api.list_rules()

        if check_pattern and check_pattern != '.':
            checks, groups = util.find_checks(self.api, check_pattern)
            check_ids = dict([(c['check_id'], c['name']) for c in checks])
            matching = [r for r in rules if r['check_id'] in check_ids]
        else:
            checks = self.api.list_checks()
            check_ids = dict([(c['check_id'], c['name']) for c in checks])
            matching = rules

        if metric_pattern:
            matching = [r for r in matching if
                    re.search(metric_pattern, r['metric_name'])]

        matching = sorted(matching, reverse=True,
                key=lambda x: (x['check_id'], x['metric_name'], x['order']))
        log.msg("About to delete the following rules:")
        for r in matching:
            log.msg("%s`%s (%s - %s %s)" % (check_ids[r['check_id']],
                r['metric_name'], r['order'], r['criteria'], r['value']))
        if util.confirm():
            for r in matching:
                log.msgnb("Deleting %s`%s (%s)..." % (
                    check_ids[r['check_id']], r['metric_name'], r['order']))
                try:
                    rv = self.api.remove_metric_rule(check_id=r['check_id'],
                            metric_name=r['metric_name'], order=r['order'])
                    log.msgnf("Success")
                except circonusapi.CirconusAPIError, e:
                    log.msgnf("Failed")
                    log.error(e.error)
Esempio n. 11
0
    def command(self, opts, pattern):
        """Delete multiple graphs at once

        Arguments:
            pattern     -- a regex to select the graphs to delete
        """
        rv = self.api.list_graphs()
        filtered_graphs = []
        for g in sorted(rv, lambda a, b: cmp(a['title'], b['title'])):
            if re.search(pattern, g['title']):
                filtered_graphs.append(g)
        log.msg("Going to DELETE the following graphs:")
        for g in filtered_graphs:
            log.msg("   %s" % g['title'])
        if util.confirm():
            for g in filtered_graphs:
                log.msgnb("Deleting %s..." % g['title'])
                try:
                    rv = self.api.remove_graph(graph_id=g['graph_id'])
                    log.msgnf("Success")
                except circonusapi.CirconusAPIError, e:
                    log.msgnf("Failed")
                    log.error(e.error)
Esempio n. 12
0
    def command(self, opts, old_check_id, old_metric_name, new_check_id,
            new_metric_name):
        """Clone rulesets from one check to another

        Arguments:
            old_check_id    -- the check_id to copy the ruleset from
            old_metric_name -- the metric_name to copy the ruleset from
            new_check_id    -- the check_id to copy the ruleset to
            new_metric_name -- the metric_name to copy the ruleset to
        """
        rules = self.api.list_rules(check_id=old_check_id,
                metric_name=old_metric_name)
        for r in rules:
            r['check_id'] = new_check_id
            r['metric_name'] = new_metric_name

        for r in rules:
            log.msgnb("Adding rule %s... " % r['order'])
                log.msgnf("Success")
            except circonusapi.CirconusAPIError, e:
                log.msgnf("Failed")
                log.error(e.error)
                return
Esempio n. 13
0
    def command(self, opts, title, pattern):
        """Add a worksheet containing matching graphs

        Arguments:
            pattern         -- a regex to match on graph names

        Options:
            -f/--favorite   -- mark the worksheet as a favorite
        """
        rv = self.api.list_graphs()
        filtered_graphs = []
        for g in sorted(rv, lambda a, b: cmp(a['title'], b['title'])):
            if re.search(pattern, g['title']):
                filtered_graphs.append(g)
        favorite = False
        if ('-f', '') in opts or ('--favorite', '') in opts:
            favorite = True
        worksheet_data = {
            'title': title,
            'favorite': favorite,
            'graphs': filtered_graphs}
        log.msg("Adding a worksheet with the following graphs:")
        for i in filtered_graphs:
            log.msg("    %s" % i['title'])
        if favorite:
            log.msg("Worksheet will be marked as a favorite")
        if not util.confirm():
            log.msg("Not adding worksheet")
            sys.exit(1)
        log.msgnb("Adding worksheet... ")
        try:
            self.api.add_worksheet(worksheet_data=json.dumps(worksheet_data))
            log.msgnf("Success")
        except circonusapi.CirconusAPIError, e:
            log.msgnf("Failed")
            log.error("Unable to add worksheet: %s" % e)
Esempio n. 14
0
    def command(self, opts, template_name, pattern, *params):
        """Adds rules for checks that match the given pattern

        Arguments:
            template_name   -- the name of the template file
            pattern         -- regex to match check names on
            params          -- other parameters (see below)

        Other parameters are specified as "param_name=value" and will
        be substituted in the template. Use {param_name} in the template.

        Some predefined parameters:
            {check_id}     - The check ID
            {check_name}   - The check name
            {check_target} - The target of the check (IP address)
            {check_agent}  - The agent the check is run from
            {groupN}       - Matching groups (the parts in parentheses) in the
                            pattern given on the command line. (replace N with
                            a group number)
        """
        template = util.RuleTemplate(template_name)
        template_params = template.parse_nv_params(params)
        checks, groups = util.find_checks(self.api, pattern)
        util.verify_metrics(self.api, template, checks)
        log.msg("About to add %s rules for the following checks:" % (template_name))
        for c in checks:
            log.msg("    %s (%s)" % (c["name"], c["agent"]))
        if not util.confirm():
            log.msg("Not adding rules.")
            sys.exit()

        for c in checks:
            p = {
                "check_name": c["name"],
                "check_id": c["check_id"],
                "check_target": c["target"],
                "check_agent": c["agent"],
            }
            p.update(template_params)
            p.update(groups[c["check_id"]])
            substituted = template.sub(p)

            # Get mapping from contact group name to ID
            rv = self.api.list_contact_groups()
            contact_group_ids = {}
            for i in rv:
                contact_group_ids[i["name"]] = i["contact_group_id"]
            for rule in substituted:
                # Extract the contact groups and get the IDs
                for severity in rule["contact_groups"]:
                    contact_group_names = rule["contact_groups"][severity]
                    del rule["contact_groups"][severity]
                    rule["contact_groups"][severity] = []
                    for cg in contact_group_names:
                        rule["contact_groups"][severity].append({"id": contact_group_ids[cg], "name": cg})

                log.msgnb("Adding rule for %s... " % c["name"])
                try:
                    rv = self.api.set_ruleset(ruleset=json.dumps(rule))
                    log.msgnf("Success")
                except circonusapi.CirconusAPIError, e:
                    log.msgnf("Failed")
                    log.error(e.error)
Esempio n. 15
0
    def command(self, opts, graph_id, new_title, *params):
        """Copy a graph, changing some parameters

        Options:
            -v              -- Show the new graph data before adding the graph

        Arguments:
            graph_id        -- The UUID of the graph you want to copy
            new_title       -- The title of the new graph
            params          -- Search/replace on datapoint values

        The search/replace parameters will replace any datapoint values,
        including the check_id, metric_name, colors, and datapoint names.
        Parameters should be of the form:

        search_term=replacement

        For example, to modify the check id, you can do 1234=2345

        You can also specify a single number without an equals sign. In this
        case, all check ids that aren't replaced with another pattern will be
        set to this value.

        If you have a graph that is only for a single check, then specifying
        the check id mapping as a single number is what you want.
        """
        try:
            uuid.UUID(graph_id)
        except ValueError:
            log.error("Invalid graph ID specified. It should look like a UUID")
            sys.exit(1)
        rv = self.api.get_graph(graph_id=graph_id)
        graph_data = json.loads(rv["graph_data"])

        # Set the new title
        graph_data["title"] = new_title

        subs = {}
        default_check_id = None
        for p in params:
            try:
                # First try to parse as a single check id
                default_check_id = int(p)
                continue
            except ValueError:
                pass
            parts = [i for i in p.split("=", 1)]
            try:
                subs[parts[0]] = parts[1]
            except IndexError:
                log.error("Invalid substitution: %s" % p)
                sys.exit(1)

        for d in graph_data["datapoints"]:
            for k in d:
                if type(d[k]) == str or type(d[k]) == unicode:
                    # String search/replace
                    for s in subs:
                        d[k] = d[k].replace(s, subs[s])
                        print d[k], s, subs[s]
                elif type(d[k]) == int:
                    # Integer replacement (matches only on the whole number)
                    # Used for check_ids
                    if str(d[k]) in subs:
                        d[k] = int(subs[str(d[k])])
                    elif k == "check_id" and default_check_id:
                        # If we didn't do a substitution previously, and we're
                        # considering a check_id, replace the check_id with
                        # the default
                        d[k] = default_check_id

        if ("-v", "") in opts:
            print json.dumps(graph_data, indent=4)
            if not util.confirm():
                log.msg("Not adding graph.")
                sys.exit(0)

        log.msgnb("Adding copied graph: %s..." % graph_data["title"])
        try:
            rv = self.api.add_graph(graph_data=json.dumps(graph_data))
            log.msgnf("Success")
        except circonusapi.CirconusAPIError, e:
            log.msgnf("Failed")
            log.error(e.error)