]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/rest/app/serializers/v2.py
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / pybind / mgr / rest / app / serializers / v2.py
1
2 from distutils.version import StrictVersion
3
4 import rest_framework
5 from rest_framework import serializers
6 import rest.app.serializers.fields as fields
7 from rest.app.types import CRUSH_RULE_TYPE_REPLICATED, \
8 CRUSH_RULE_TYPE_ERASURE, USER_REQUEST_COMPLETE, \
9 USER_REQUEST_SUBMITTED, OSD_FLAGS
10
11
12 class ValidatingSerializer(serializers.Serializer):
13 @property
14 def init_data(self):
15 """
16 Compatibility alias for django rest framework 2 vs. 3
17 """
18 return self.initial_data
19
20 def is_valid(self, http_method):
21 if StrictVersion(rest_framework.__version__) < StrictVersion("3.0.0"):
22 self._errors = super(ValidatingSerializer, self).errors or {}
23 else:
24 # django rest framework >= 3 has different is_Valid prototype
25 # than <= 2
26 super(ValidatingSerializer, self).is_valid(False)
27
28 if self.init_data is not None:
29 if http_method == 'POST':
30 self._errors.update(
31 self.construct_errors(self.Meta.create_allowed,
32 self.Meta.create_required,
33 self.init_data.keys(),
34 http_method))
35
36 elif http_method in ('PATCH', 'PUT'):
37 self._errors.update(
38 self.construct_errors(self.Meta.modify_allowed,
39 self.Meta.modify_required,
40 self.init_data.keys(),
41 http_method))
42 else:
43 self._errors.update([[http_method, 'Not a valid method']])
44
45 return not self._errors
46
47 def construct_errors(self, allowed, required, init_data, action):
48 errors = {}
49
50 not_allowed = set(init_data) - set(allowed)
51 errors.update(
52 dict([x, 'Not allowed during %s' % action] for x in not_allowed))
53
54 required = set(required) - set(init_data)
55 errors.update(
56 dict([x, 'Required during %s' % action] for x in required))
57
58 return errors
59
60 def get_data(self):
61 # like http://www.django-rest-framework.org/api-guide/serializers#dynamically-modifying-fields
62 filtered_data = {}
63 for field, value in self.init_data.iteritems():
64 filtered_data[field] = self.data[field]
65
66 return filtered_data
67
68
69 class PoolSerializer(ValidatingSerializer):
70 class Meta:
71 fields = ('name', 'id', 'size', 'pg_num', 'crush_ruleset', 'min_size',
72 'crash_replay_interval', 'crush_ruleset',
73 'pgp_num', 'hashpspool', 'full', 'quota_max_objects',
74 'quota_max_bytes')
75 create_allowed = ('name', 'pg_num', 'pgp_num', 'size', 'min_size',
76 'crash_replay_interval', 'crush_ruleset',
77 'quota_max_objects', 'quota_max_bytes', 'hashpspool')
78 create_required = ('name', 'pg_num')
79 modify_allowed = ('name', 'pg_num', 'pgp_num', 'size', 'min_size',
80 'crash_replay_interval', 'crush_ruleset',
81 'quota_max_objects', 'quota_max_bytes', 'hashpspool')
82 modify_required = ()
83
84 # Required in creation
85 name = serializers.CharField(required=False, source='pool_name',
86 help_text="Human readable name of the pool, may"
87 "change over the pools lifetime at user request.")
88 pg_num = serializers.IntegerField(required=False,
89 help_text="Number of placement groups in this pool")
90
91 # Not required in creation, immutable
92 id = serializers.CharField(source='pool', required=False,
93 help_text="Unique numeric ID")
94
95 # May be set in creation or updates
96 size = serializers.IntegerField(required=False,
97 help_text="Replication factor")
98 min_size = serializers.IntegerField(required=False,
99 help_text="Minimum number of replicas required for I/O")
100 crash_replay_interval = serializers.IntegerField(required=False,
101 help_text="Number of seconds to allow clients to "
102 "replay acknowledged, but uncommitted requests")
103 crush_ruleset = serializers.IntegerField(required=False,
104 help_text="CRUSH ruleset in use")
105 # In 'ceph osd pool set' it's called pgp_num, but in 'ceph osd dump' it's called
106 # pg_placement_num :-/
107 pgp_num = serializers.IntegerField(source='pg_placement_num',
108 required=False,
109 help_text="Effective number of placement groups to use when calculating "
110 "data placement")
111
112 # This is settable by 'ceph osd pool set' but in 'ceph osd dump' it only appears
113 # within the 'flags' integer. We synthesize a boolean from the flags.
114 hashpspool = serializers.BooleanField(required=False,
115 help_text="Enable HASHPSPOOL flag")
116
117 # This is synthesized from ceph's 'flags' attribute, read only.
118 full = serializers.BooleanField(required=False,
119 help_text="True if the pool is full")
120
121 quota_max_objects = serializers.IntegerField(required=False,
122 help_text="Quota limit on object count (0 is unlimited)")
123 quota_max_bytes = serializers.IntegerField(required=False,
124 help_text="Quota limit on usage in bytes (0 is unlimited)")
125
126
127 class OsdSerializer(ValidatingSerializer):
128 class Meta:
129 fields = ('uuid', 'up', 'in', 'id', 'reweight', 'server', 'pools',
130 'valid_commands', 'public_addr', 'cluster_addr')
131 create_allowed = ()
132 create_required = ()
133 modify_allowed = ('up', 'in', 'reweight')
134 modify_required = ()
135
136 id = serializers.IntegerField(read_only=True, source='osd',
137 help_text="ID of this OSD within this cluster")
138 uuid = fields.UuidField(read_only=True,
139 help_text="Globally unique ID for this OSD")
140 up = fields.BooleanField(required=False,
141 help_text="Whether the OSD is running from the point of view of the rest of the cluster")
142 _in = fields.BooleanField(required=False,
143 help_text="Whether the OSD is 'in' the set of OSDs which will be used to store data")
144 reweight = serializers.FloatField(required=False,
145 help_text="CRUSH weight factor")
146 server = serializers.CharField(read_only=True,
147 help_text="FQDN of server this OSD was last running on")
148 pools = serializers.ListField(
149 help_text="List of pool IDs which use this OSD for storage",
150 required=False)
151 valid_commands = serializers.CharField(read_only=True,
152 help_text="List of commands that can be applied to this OSD")
153
154 public_addr = serializers.CharField(read_only=True,
155 help_text="Public/frontend IP address")
156 cluster_addr = serializers.CharField(read_only=True,
157 help_text="Cluster/backend IP address")
158
159
160 class OsdConfigSerializer(ValidatingSerializer):
161 class Meta:
162 fields = OSD_FLAGS
163 create_allowed = ()
164 create_required = ()
165 modify_allowed = OSD_FLAGS
166 modify_required = ()
167
168 pause = serializers.BooleanField(
169 help_text="Disable IO requests to all OSDs in cluster", required=False)
170 noup = serializers.BooleanField(
171 help_text="Prevent OSDs from automatically getting marked as Up by the monitors. This setting is useful for troubleshooting",
172 required=False)
173 nodown = serializers.BooleanField(
174 help_text="Prevent OSDs from automatically getting marked as Down by the monitors. This setting is useful for troubleshooting",
175 required=False)
176 noout = serializers.BooleanField(
177 help_text="Prevent Down OSDs from being marked as out", required=False)
178 noin = serializers.BooleanField(
179 help_text="Prevent OSDs from booting OSDs from being marked as IN. Will cause cluster health to be set to WARNING",
180 required=False)
181 nobackfill = serializers.BooleanField(
182 help_text="Disable backfill operations on cluster", required=False)
183 norecover = serializers.BooleanField(
184 help_text="Disable replication of Placement Groups", required=False)
185 noscrub = serializers.BooleanField(
186 help_text="Disables automatic periodic scrub operations on OSDs. May still be initiated on demand",
187 required=False)
188 nodeepscrub = serializers.BooleanField(
189 help_text="Disables automatic periodic deep scrub operations on OSDs. May still be initiated on demand",
190 required=False)
191
192
193 class CrushRuleSerializer(serializers.Serializer):
194 class Meta:
195 fields = (
196 'id', 'name', 'ruleset', 'type', 'min_size', 'max_size', 'steps',
197 'osd_count')
198
199 id = serializers.IntegerField(source='rule_id')
200 name = serializers.CharField(source='rule_name',
201 help_text="Human readable name")
202 ruleset = serializers.IntegerField(
203 help_text="ID of the CRUSH ruleset of which this rule is a member")
204 type = fields.EnumField({CRUSH_RULE_TYPE_REPLICATED: 'replicated',
205 CRUSH_RULE_TYPE_ERASURE: 'erasure'},
206 help_text="Data redundancy type")
207 min_size = serializers.IntegerField(
208 help_text="If a pool makes more replicas than this number, CRUSH will NOT select this rule")
209 max_size = serializers.IntegerField(
210 help_text="If a pool makes fewer replicas than this number, CRUSH will NOT select this rule")
211 steps = serializers.ListField(
212 help_text="List of operations used to select OSDs")
213 osd_count = serializers.IntegerField(
214 help_text="Number of OSDs which are used for data placement")
215
216
217 class CrushRuleSetSerializer(serializers.Serializer):
218 class Meta:
219 fields = ('id', 'rules')
220
221 id = serializers.IntegerField()
222 rules = CrushRuleSerializer(many=True)
223
224
225 class RequestSerializer(serializers.Serializer):
226 class Meta:
227 fields = (
228 'id', 'state', 'error', 'error_message', 'headline', 'status',
229 'requested_at', 'completed_at')
230
231 id = serializers.CharField(
232 help_text="A globally unique ID for this request")
233 state = serializers.CharField(
234 help_text="One of '{complete}', '{submitted}'".format(
235 complete=USER_REQUEST_COMPLETE, submitted=USER_REQUEST_SUBMITTED))
236 error = serializers.BooleanField(
237 help_text="True if the request completed unsuccessfully")
238 error_message = serializers.CharField(
239 help_text="Human readable string describing failure if ``error`` is True")
240 headline = serializers.CharField(
241 help_text="Single sentence human readable description of the request")
242 status = serializers.CharField(
243 help_text="Single sentence human readable description of the request's current "
244 "activity, if it has more than one stage. May be null.")
245 requested_at = serializers.DateTimeField(
246 help_text="Time at which the request was received by calamari server")
247 completed_at = serializers.DateTimeField(
248 help_text="Time at which the request completed, may be null.")
249
250
251 class ServiceSerializer(serializers.Serializer):
252 class Meta:
253 fields = ('type', 'id')
254
255 type = serializers.CharField()
256 id = serializers.CharField()
257
258
259 class ServerSerializer(serializers.Serializer):
260 class Meta:
261 fields = ('hostname', 'services', 'ceph_version')
262
263 # Identifying information
264 hostname = serializers.CharField(help_text="Domain name")
265
266 ceph_version = serializers.CharField(
267 help_text="The version of Ceph installed."
268 )
269 services = ServiceSerializer(many=True,
270 help_text="List of Ceph services seen"
271 "on this server")
272
273
274 class ConfigSettingSerializer(serializers.Serializer):
275 class Meta:
276 fields = ('key', 'value')
277
278 # This is very simple for now, but later we may add more things like
279 # schema information, allowed values, defaults.
280
281 key = serializers.CharField(help_text="Name of the configuration setting")
282 value = serializers.CharField(
283 help_text="Current value of the setting, as a string")
284
285
286 class MonSerializer(serializers.Serializer):
287 class Meta:
288 fields = ('name', 'rank', 'in_quorum', 'server', 'addr')
289
290 name = serializers.CharField(help_text="Human readable name")
291 rank = serializers.IntegerField(
292 help_text="Unique of the mon within the cluster")
293 in_quorum = serializers.BooleanField(
294 help_text="True if the mon is a member of current quorum")
295 server = serializers.CharField(
296 help_text="Hostname of server running the OSD")
297 addr = serializers.CharField(help_text="IP address of monitor service")
298 leader = serializers.BooleanField(
299 help_text="True if this monitor is the leader of the quorum. False otherwise")
300
301
302 class CliSerializer(serializers.Serializer):
303 class Meta:
304 fields = ('out', 'err', 'status')
305
306 out = serializers.CharField(help_text="Standard out")
307 err = serializers.CharField(help_text="Standard error")
308 status = serializers.IntegerField(help_text="Exit code")
309
310
311 # Declarative metaclass definitions are great until you want
312 # to use a reserved word
313 if StrictVersion(rest_framework.__version__) < StrictVersion("3.0.0"):
314 # In django-rest-framework 2.3.x (Calamari used this)
315 OsdSerializer.base_fields['in'] = OsdSerializer.base_fields['_in']
316 OsdConfigSerializer.base_fields['nodeep-scrub'] = \
317 OsdConfigSerializer.base_fields['nodeepscrub']
318 else:
319 OsdSerializer._declared_fields['in'] = OsdSerializer._declared_fields[
320 '_in']
321 del OsdSerializer._declared_fields['_in']
322 OsdSerializer._declared_fields['in'].source = "in"
323 OsdConfigSerializer._declared_fields['nodeep-scrub'] = \
324 OsdConfigSerializer._declared_fields['nodeepscrub']
325
326