1#!/usr/local/bin/python3.8
2"""
3
4=head1 NAME
5
6nova_instance_ - monitor status of Floating IPs in Nova
7
8
9=head1 CONFIGURATION
10
11
12To monitor instance states, link instance_states to this file.
13E.g.
14
15 ln -s /usr/share/munin/plugins/nova_instance_states /etc/munin/plugins/
16
17Needs following minimal configuration in plugin-conf.d/nova:
18
19 [nova_*]
20 user nova
21
22
23=head1 AUTHORS
24
25Copyright 2012 Mehdi Abaakouk <sileht@sileht.net>
26
27
28=head1 MAGIC MARKERS
29
30 #%# capabilities=autoconf suggest
31 #%# family=auto
32
33=cut
34"""
35
36import os
37import sys
38
39
40try:
41    from nova import context
42    from nova import db
43    from nova import flags
44    from nova import utils
45    from nova.compute import power_state
46except ImportError:
47    successful_import = False
48else:
49    successful_import = True
50
51
52class InstanceState:
53    instance_counts = None
54    states = None
55
56    @classmethod
57    def init(cls, metric):
58        if cls.states and cls.instance_counts:
59            return
60        ctxt = context.get_admin_context()
61        instances = db.instance_get_all(ctxt)
62        cls.instance_counts = {}
63        instance_types = {}
64        for it in db.instance_type_get_all(ctxt, True):
65            instance_types[it['id']] = it['name']
66
67        for instance in instances:
68            i = dict(instance)
69            i['type'] = instance_types.get(instance.instance_type_id, '(unknown')
70            i['instance_type'] = i['type']
71            val = cls.instance_counts.get(i[metric], 0)
72            cls.instance_counts[i[metric]] = val + 1
73        cls.states = cls.instance_counts.keys()
74
75    @classmethod
76    def get_states(cls, metric):
77        InstanceState.init(metric)
78        return cls.states
79
80    @classmethod
81    def get_instance_counts(cls, metric):
82        InstanceState.init(metric)
83        return cls.instance_counts
84
85
86def get_name(metric, code):
87    if metric == "power_state":
88        return power_state.name(code)
89    elif metric in ["root_gb", "ephemeral_gb"]:
90        return "%d gb" % code
91    else:
92        return code
93
94
95def print_config(metric):
96    states = InstanceState.get_states(metric)
97    print('graph_title Nova Instance %s' % metric)
98    print('graph_vlabel instances')
99    print('graph_args --base 1000 --lower-limit 0')
100    print('graph_category cloud')
101    print('graph_scale no')
102    print('graph_info This graph shows the number of instances by %s' % metric)
103    for state in states:
104        print('%s.label %s' % (state, get_name(metric, state)))
105        print('%s.draw LINE2' % state)
106        print('%s.info %s IPs' % (state, state))
107
108
109def print_values(metric):
110    status = InstanceState.get_instance_counts(metric)
111    for (state, value) in status.items():
112        print('%s.value %s' % (state, value))
113
114
115def print_suggest():
116    suggest = [
117        "vm_state",
118        "vcpus",
119        "task_state",
120        "root_gb",
121        "ephemeral_gb",
122        "power_state",
123        "memory_mb",
124        "instance_type_id",
125    ]
126    print(os.linesep.join(suggest))
127
128
129if __name__ == '__main__':
130    argv = sys.argv[:]
131    utils.default_flagfile()
132    flags.FLAGS(sys.argv)
133    metric = argv[0].split('nova_instance_').pop() or 'vm_state'
134
135    if len(argv) > 1:
136        if argv[1] == 'config':
137            print_config(metric)
138        elif argv[1] == 'suggest':
139            print_suggest()
140        elif argv[1] == 'autoconf':
141            if not successful_import:
142                print('no (failed import nova module)')
143            else:
144                print('yes')
145            sys.exit(0)
146    elif successful_import:
147        print_values(metric)
148