]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/hello/module.py
import quincy beta 17.1.0
[ceph.git] / ceph / src / pybind / mgr / hello / module.py
1
2 """
3 A hello world module
4
5 See doc/mgr/hello.rst for more info.
6 """
7
8 from mgr_module import CLIReadCommand, HandleCommandResult, MgrModule, Option
9 from threading import Event
10 from typing import cast, Any, Optional, TYPE_CHECKING
11 import errno
12
13
14 class Hello(MgrModule):
15 # These are module options we understand. These can be set with
16 #
17 # ceph config set global mgr/hello/<name> <value>
18 #
19 # e.g.,
20 #
21 # ceph config set global mgr/hello/place Earth
22 #
23 MODULE_OPTIONS = [
24 Option(name='place',
25 default='world',
26 desc='a place in the world',
27 runtime=True), # can be updated at runtime (no mgr restart)
28 Option(name='emphatic',
29 type='bool',
30 desc='whether to say it loudly',
31 default=True,
32 runtime=True),
33 Option(name='foo',
34 type='str',
35 enum_allowed=['a', 'b', 'c'],
36 default='a',
37 runtime=True)
38 ]
39
40 # These are "native" Ceph options that this module cares about.
41 NATIVE_OPTIONS = [
42 'mgr_tick_period',
43 ]
44
45 def __init__(self, *args: Any, **kwargs: Any):
46 super().__init__(*args, **kwargs)
47
48 # set up some members to enable the serve() method and shutdown()
49 self.run = True
50 self.event = Event()
51
52 # ensure config options members are initialized; see config_notify()
53 self.config_notify()
54
55 # for mypy which does not run the code
56 if TYPE_CHECKING:
57 self.mgr_tick_period = 0
58
59 def config_notify(self) -> None:
60 """
61 This method is called whenever one of our config options is changed.
62 """
63 # This is some boilerplate that stores MODULE_OPTIONS in a class
64 # member, so that, for instance, the 'emphatic' option is always
65 # available as 'self.emphatic'.
66 for opt in self.MODULE_OPTIONS:
67 setattr(self,
68 opt['name'],
69 self.get_module_option(opt['name']))
70 self.log.debug(' mgr option %s = %s',
71 opt['name'], getattr(self, opt['name']))
72 # Do the same for the native options.
73 for opt in self.NATIVE_OPTIONS:
74 setattr(self,
75 opt,
76 self.get_ceph_option(opt))
77 self.log.debug(' native option %s = %s', opt, getattr(self, opt))
78
79 # there are CLI commands we implement
80 @CLIReadCommand('hello')
81 def hello(self, person_name: Optional[str] = None) -> HandleCommandResult:
82 """
83 Say hello
84 """
85 if person_name is None:
86 who = cast(str, self.get_module_option('place'))
87 else:
88 who = person_name
89 fin = '!' if self.get_module_option('emphatic') else ''
90 return HandleCommandResult(stdout=f'Hello, {who}{fin}')
91
92 @CLIReadCommand('count')
93 def count(self, num: int) -> HandleCommandResult:
94 """
95 Do some counting
96 """
97 ret = 0
98 out = ''
99 err = ''
100 if num < 1:
101 err = 'That\'s too small a number'
102 ret = -errno.EINVAL
103 elif num > 10:
104 err = 'That\'s too big a number'
105 ret = -errno.EINVAL
106 else:
107 out = 'Hello, I am the count!\n'
108 out += ', '.join([str(x) for x in range(1, num + 1)]) + '!'
109 return HandleCommandResult(retval=ret,
110 stdout=out,
111 stderr=err)
112
113 def serve(self) -> None:
114 """
115 This method is called by the mgr when the module starts and can be
116 used for any background activity.
117 """
118 self.log.info("Starting")
119 while self.run:
120 # Do some useful background work here.
121
122 # Use mgr_tick_period (default: 2) here just to illustrate
123 # consuming native ceph options. Any real background work
124 # would presumably have some more appropriate frequency.
125 sleep_interval = self.mgr_tick_period
126 self.log.debug('Sleeping for %d seconds', sleep_interval)
127 self.event.wait(sleep_interval)
128 self.event.clear()
129
130 def shutdown(self) -> None:
131 """
132 This method is called by the mgr when the module needs to shut
133 down (i.e., when the serve() function needs to exit).
134 """
135 self.log.info('Stopping')
136 self.run = False
137 self.event.set()