summaryrefslogtreecommitdiffstats
path: root/src/pybind/mgr/hello/module.py
blob: b164dfb620d0f4c15b28f6051902f487f532996a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
"""
A hello world module

See doc/mgr/hello.rst for more info.
"""

from mgr_module import MgrModule, HandleCommandResult
from threading import Event
import errno

class Hello(MgrModule):
    # these are CLI commands we implement
    COMMANDS = [
        {
            "cmd": "hello "
                   "name=person_name,type=CephString,req=false",
            "desc": "Say hello",
            "perm": "r"
        },
        {
            "cmd": "count "
                   "name=num,type=CephInt",
            "desc": "Do some counting",
            "perm": "r"
        },
    ]

    # These are module options we understand.  These can be set with
    #
    #   ceph config set global mgr/hello/<name> <value>
    #
    # e.g.,
    #
    #   ceph config set global mgr/hello/place Earth
    #
    MODULE_OPTIONS = [
        {
            'name': 'place',
            'default': 'world',
            'desc': 'a place in the world',
            'runtime': True,   # can be updated at runtime (no mgr restart)
        },
        {
            'name': 'emphatic',
            'type': 'bool',
            'desc': 'whether to say it loudly',
            'default': True,
            'runtime': True,
        },
        {
            'name': 'foo',
            'type': 'enum',
            'enum_allowed': [ 'a', 'b', 'c' ],
            'default': 'a',
            'runtime': True,
        },
    ]

    # These are "native" Ceph options that this module cares about.
    NATIVE_OPTIONS = [
        'mgr_tick_period',
    ]

    def __init__(self, *args, **kwargs):
        super(Hello, self).__init__(*args, **kwargs)

        # set up some members to enable the serve() method and shutdown()
        self.run = True
        self.event = Event()

        # ensure config options members are initialized; see config_notify()
        self.config_notify()


    def config_notify(self):
        """
        This method is called whenever one of our config options is changed.
        """
        # This is some boilerplate that stores MODULE_OPTIONS in a class
        # member, so that, for instance, the 'emphatic' option is always
        # available as 'self.emphatic'.
        for opt in self.MODULE_OPTIONS:
            setattr(self,
                    opt['name'],
                    self.get_module_option(opt['name']))
            self.log.debug(' mgr option %s = %s',
                           opt['name'], getattr(self, opt['name']))
        # Do the same for the native options.
        for opt in self.NATIVE_OPTIONS:
            setattr(self,
                    opt,
                    self.get_ceph_option(opt))
            self.log.debug(' native option %s = %s', opt, getattr(self, opt))

    def handle_command(self, inbuf, cmd):
        ret = 0
        out = ''
        err = ''
        if cmd['prefix'] == 'hello':
            if 'person_name' in cmd:
                out = "Hello, " + cmd['person_name']
            else:
                out = "Hello " + self.get_module_option('place')
            if self.get_module_option('emphatic'):
                out += '!'
        elif cmd['prefix'] == 'count':
            num = cmd.get('num', 0)
            if num < 1:
                err = 'That\'s too small a number'
                ret = -errno.EINVAL
            elif num > 10:
                err = 'That\'s too big a number'
                ret = -errno.EINVAL
            else:
                out = 'Hello, I am the count!\n'
                out += ', '.join([str(x) for x in range(1, num + 1)]) + '!'
        return HandleCommandResult(
            retval=ret,   # exit code
            stdout=out,   # stdout
            stderr=err)

    def serve(self):
        """
        This method is called by the mgr when the module starts and can be
        used for any background activity.
        """
        self.log.info("Starting")
        while self.run:
            # Do some useful background work here.

            # Use mgr_tick_period (default: 2) here just to illustrate
            # consuming native ceph options.  Any real background work
            # would presumably have some more appropriate frequency.
            sleep_interval = self.mgr_tick_period
            self.log.debug('Sleeping for %d seconds', sleep_interval)
            ret = self.event.wait(sleep_interval)
            self.event.clear()

    def shutdown(self):
        """
        This method is called by the mgr when the module needs to shut
        down (i.e., when the serve() function needs to exit).
        """
        self.log.info('Stopping')
        self.run = False
        self.event.set()