]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/volumes/module.py
import 14.2.4 nautilus point release
[ceph.git] / ceph / src / pybind / mgr / volumes / module.py
1 from threading import Event
2 import errno
3 import json
4 try:
5 import queue as Queue
6 except ImportError:
7 import Queue
8
9 from mgr_module import MgrModule
10 import orchestrator
11
12 from .fs.volume import VolumeClient
13
14 class PurgeJob(object):
15 def __init__(self, volume_fscid, subvolume_path):
16 """
17 Purge tasks work in terms of FSCIDs, so that if we process
18 a task later when a volume was deleted and recreated with
19 the same name, we can correctly drop the task that was
20 operating on the original volume.
21 """
22 self.fscid = volume_fscid
23 self.subvolume_path = subvolume_path
24
25 class Module(orchestrator.OrchestratorClientMixin, MgrModule):
26 COMMANDS = [
27 {
28 'cmd': 'fs volume ls',
29 'desc': "List volumes",
30 'perm': 'r'
31 },
32 {
33 'cmd': 'fs volume create '
34 'name=name,type=CephString '
35 'name=size,type=CephString,req=false ',
36 'desc': "Create a CephFS volume",
37 'perm': 'rw'
38 },
39 {
40 'cmd': 'fs volume rm '
41 'name=vol_name,type=CephString',
42 'desc': "Delete a CephFS volume",
43 'perm': 'rw'
44 },
45 {
46 'cmd': 'fs subvolumegroup create '
47 'name=vol_name,type=CephString '
48 'name=group_name,type=CephString '
49 'name=pool_layout,type=CephString,req=false '
50 'name=mode,type=CephString,req=false ',
51 'desc': "Create a CephFS subvolume group in a volume, and optionally, "
52 "with a specific data pool layout, and a specific numeric mode",
53 'perm': 'rw'
54 },
55 {
56 'cmd': 'fs subvolumegroup rm '
57 'name=vol_name,type=CephString '
58 'name=group_name,type=CephString '
59 'name=force,type=CephBool,req=false ',
60 'desc': "Delete a CephFS subvolume group in a volume",
61 'perm': 'rw'
62 },
63 {
64 'cmd': 'fs subvolume create '
65 'name=vol_name,type=CephString '
66 'name=sub_name,type=CephString '
67 'name=size,type=CephInt,req=false '
68 'name=group_name,type=CephString,req=false '
69 'name=pool_layout,type=CephString,req=false '
70 'name=mode,type=CephString,req=false ',
71 'desc': "Create a CephFS subvolume in a volume, and optionally, "
72 "with a specific size (in bytes), a specific data pool layout, "
73 "a specific mode, and in a specific subvolume group",
74 'perm': 'rw'
75 },
76 {
77 'cmd': 'fs subvolume rm '
78 'name=vol_name,type=CephString '
79 'name=sub_name,type=CephString '
80 'name=group_name,type=CephString,req=false '
81 'name=force,type=CephBool,req=false ',
82 'desc': "Delete a CephFS subvolume in a volume, and optionally, "
83 "in a specific subvolume group",
84 'perm': 'rw'
85 },
86 {
87 'cmd': 'fs subvolumegroup getpath '
88 'name=vol_name,type=CephString '
89 'name=group_name,type=CephString ',
90 'desc': "Get the mountpath of a CephFS subvolume group in a volume",
91 'perm': 'r'
92 },
93 {
94 'cmd': 'fs subvolume getpath '
95 'name=vol_name,type=CephString '
96 'name=sub_name,type=CephString '
97 'name=group_name,type=CephString,req=false ',
98 'desc': "Get the mountpath of a CephFS subvolume in a volume, "
99 "and optionally, in a specific subvolume group",
100 'perm': 'rw'
101 },
102 {
103 'cmd': 'fs subvolumegroup snapshot create '
104 'name=vol_name,type=CephString '
105 'name=group_name,type=CephString '
106 'name=snap_name,type=CephString ',
107 'desc': "Create a snapshot of a CephFS subvolume group in a volume",
108 'perm': 'rw'
109 },
110 {
111 'cmd': 'fs subvolumegroup snapshot rm '
112 'name=vol_name,type=CephString '
113 'name=group_name,type=CephString '
114 'name=snap_name,type=CephString '
115 'name=force,type=CephBool,req=false ',
116 'desc': "Delete a snapshot of a CephFS subvolume group in a volume",
117 'perm': 'rw'
118 },
119 {
120 'cmd': 'fs subvolume snapshot create '
121 'name=vol_name,type=CephString '
122 'name=sub_name,type=CephString '
123 'name=snap_name,type=CephString '
124 'name=group_name,type=CephString,req=false ',
125 'desc': "Create a snapshot of a CephFS subvolume in a volume, "
126 "and optionally, in a specific subvolume group",
127 'perm': 'rw'
128 },
129 {
130 'cmd': 'fs subvolume snapshot rm '
131 'name=vol_name,type=CephString '
132 'name=sub_name,type=CephString '
133 'name=snap_name,type=CephString '
134 'name=group_name,type=CephString,req=false '
135 'name=force,type=CephBool,req=false ',
136 'desc': "Delete a snapshot of a CephFS subvolume in a volume, "
137 "and optionally, in a specific subvolume group",
138 'perm': 'rw'
139 },
140
141 # volume ls [recursive]
142 # subvolume ls <volume>
143 # volume authorize/deauthorize
144 # subvolume authorize/deauthorize
145
146 # volume describe (free space, etc)
147 # volume auth list (vc.get_authorized_ids)
148
149 # snapshots?
150
151 # FIXME: we're doing CephFSVolumeClient.recover on every
152 # path where we instantiate and connect a client. Perhaps
153 # keep clients alive longer, or just pass a "don't recover"
154 # flag in if it's the >1st time we connected a particular
155 # volume in the lifetime of this module instance.
156 ]
157
158 def __init__(self, *args, **kwargs):
159 super(Module, self).__init__(*args, **kwargs)
160 self._initialized = Event()
161 self.vc = VolumeClient(self)
162
163 self._background_jobs = Queue.Queue()
164
165 def serve(self):
166 # TODO: discover any subvolumes pending purge, and enqueue
167 # them in background_jobs at startup
168
169 # TODO: consume background_jobs
170 # skip purge jobs if their fscid no longer exists
171
172 # TODO: on volume delete, cancel out any background jobs that
173 # affect subvolumes within that volume.
174
175 # ... any background init needed? Can get rid of this
176 # and _initialized if not
177 self._initialized.set()
178
179 def handle_command(self, inbuf, cmd):
180 self._initialized.wait()
181
182 handler_name = "_cmd_" + cmd['prefix'].replace(" ", "_")
183 try:
184 handler = getattr(self, handler_name)
185 except AttributeError:
186 return -errno.EINVAL, "", "Unknown command"
187
188 return handler(inbuf, cmd)
189
190 def _cmd_fs_volume_create(self, inbuf, cmd):
191 # TODO: validate name against any rules for pool/fs names
192 # (...are there any?)
193 vol_id = cmd['name']
194 size = cmd.get('size', None)
195
196 return self.vc.create_volume(vol_id, size)
197
198 def _cmd_fs_volume_rm(self, inbuf, cmd):
199 vol_name = cmd['vol_name']
200 return self.vc.delete_volume(vol_name)
201
202 def _cmd_fs_volume_ls(self, inbuf, cmd):
203 return self.vc.list_volumes()
204
205 def _cmd_fs_subvolumegroup_create(self, inbuf, cmd):
206 """
207 :return: a 3-tuple of return code(int), empty string(str), error message (str)
208 """
209 return self.vc.create_subvolume_group(
210 None, vol_name=cmd['vol_name'], group_name=cmd['group_name'],
211 pool_layout=cmd.get('pool_layout', None), mode=cmd.get('mode', '755'))
212
213 def _cmd_fs_subvolumegroup_rm(self, inbuf, cmd):
214 """
215 :return: a 3-tuple of return code(int), empty string(str), error message (str)
216 """
217 return self.vc.remove_subvolume_group(None, vol_name=cmd['vol_name'],
218 group_name=cmd['group_name'],
219 force=cmd.get('force', False))
220
221 def _cmd_fs_subvolume_create(self, inbuf, cmd):
222 """
223 :return: a 3-tuple of return code(int), empty string(str), error message (str)
224 """
225 return self.vc.create_subvolume(None, vol_name=cmd['vol_name'],
226 sub_name=cmd['sub_name'],
227 group_name=cmd.get('group_name', None),
228 size=cmd.get('size', None),
229 pool_layout=cmd.get('pool_layout', None),
230 mode=cmd.get('mode', '755'))
231
232 def _cmd_fs_subvolume_rm(self, inbuf, cmd):
233 """
234 :return: a 3-tuple of return code(int), empty string(str), error message (str)
235 """
236 return self.vc.remove_subvolume(None, vol_name=cmd['vol_name'],
237 sub_name=cmd['sub_name'],
238 group_name=cmd.get('group_name', None),
239 force=cmd.get('force', False))
240
241 def _cmd_fs_subvolumegroup_getpath(self, inbuf, cmd):
242 return self.vc.getpath_subvolume_group(
243 None, vol_name=cmd['vol_name'], group_name=cmd['group_name'])
244
245 def _cmd_fs_subvolume_getpath(self, inbuf, cmd):
246 return self.vc.subvolume_getpath(None, vol_name=cmd['vol_name'],
247 sub_name=cmd['sub_name'],
248 group_name=cmd.get('group_name', None))
249
250 def _cmd_fs_subvolumegroup_snapshot_create(self, inbuf, cmd):
251 return self.vc.create_subvolume_group_snapshot(None, vol_name=cmd['vol_name'],
252 group_name=cmd['group_name'],
253 snap_name=cmd['snap_name'])
254
255 def _cmd_fs_subvolumegroup_snapshot_rm(self, inbuf, cmd):
256 return self.vc.remove_subvolume_group_snapshot(None, vol_name=cmd['vol_name'],
257 group_name=cmd['group_name'],
258 snap_name=cmd['snap_name'],
259 force=cmd.get('force', False))
260
261 def _cmd_fs_subvolume_snapshot_create(self, inbuf, cmd):
262 return self.vc.create_subvolume_snapshot(None, vol_name=cmd['vol_name'],
263 sub_name=cmd['sub_name'],
264 snap_name=cmd['snap_name'],
265 group_name=cmd.get('group_name', None))
266
267 def _cmd_fs_subvolume_snapshot_rm(self, inbuf, cmd):
268 return self.vc.remove_subvolume_snapshot(None, vol_name=cmd['vol_name'],
269 sub_name=cmd['sub_name'],
270 snap_name=cmd['snap_name'],
271 group_name=cmd.get('group_name', None),
272 force=cmd.get('force', False))