diff --git a/lib/rapi/connector.py b/lib/rapi/connector.py index 2528c1550f39312f54a25f59d00914c915090f3b..0d3a961ce29b23183db5135f9dbcbef8af9b9bae 100644 --- a/lib/rapi/connector.py +++ b/lib/rapi/connector.py @@ -157,6 +157,7 @@ CONNECTOR.update({ "/2/jobs": rlib2.R_2_jobs, "/2/nodes": rlib2.R_2_nodes, re.compile(r'^/2/nodes/([\w\._-]+)$'): rlib2.R_2_nodes_name, + re.compile(r'^/2/nodes/([\w\._-]+)/tags$'): rlib2.R_2_nodes_name_tags, "/2/instances": rlib2.R_2_instances, re.compile(r'^/2/instances/([\w\._-]+)$'): rlib2.R_2_instances_name, re.compile(r'^/2/instances/([\w\._-]+)/tags$'): rlib2.R_2_instances_name_tags, diff --git a/lib/rapi/rlib2.py b/lib/rapi/rlib2.py index b04063eea314ca6275c05484238679ed497afa3d..0e44c1685e5499d6390da12a9f499680047d13d7 100644 --- a/lib/rapi/rlib2.py +++ b/lib/rapi/rlib2.py @@ -86,23 +86,6 @@ class R_2_info(baserlib.R_Generic): return ganeti.cli.SubmitOpCode(op) -class R_2_tags(baserlib.R_Generic): - """/2/tags resource. - - Manages cluster tags. - - """ - DOC_URI = "/2/tags" - - def GET(self): - """Returns a list of all cluster tags. - - Example: ["tag1", "tag2", "tag3"] - - """ - return baserlib._Tags_GET(constants.TAG_CLUSTER) - - class R_2_os(baserlib.R_Generic): """/2/os resource. @@ -455,43 +438,86 @@ class R_2_instances_name_shutdown(baserlib.R_Generic): return job_id -class R_2_instances_name_tags(baserlib.R_Generic): - """/2/instances/[instance_name]/tags resource. +class _R_Tags(baserlib.R_Generic): + """ Quasiclass for tagging resources - Manages per-instance tags. + Manages tags. Inheriting this class you suppose to define DOC_URI and + TAG_LEVEL for it. """ - DOC_URI = "/2/instances/[instance_name]/tags" + + def __init__(self, items, queryargs, req): + """A tag resource constructor. + + We have to override the default to sort out cluster naming case. + + """ + baserlib.R_Generic.__init__(self, items, queryargs, req) + + if self.TAG_LEVEL != constants.TAG_CLUSTER: + self.name = items[0] + else: + self.name = "" def GET(self): - """Returns a list of instance tags. + """Returns a list of tags. Example: ["tag1", "tag2", "tag3"] """ - return baserlib._Tags_GET(constants.TAG_INSTANCE, name=self.items[0]) + return baserlib._Tags_GET(self.TAG_LEVEL, name=self.name) def PUT(self): - """Add a set of tags to the instance. + """Add a set of tags. The request as a list of strings should be PUT to this URI. And you'll have back a job id. """ - return baserlib._Tags_PUT(constants.TAG_INSTANCE, - self.req.request_post_data, name=self.items[0]) + return baserlib._Tags_PUT(self.TAG_LEVEL, + self.req.request_post_data, name=self.name) def DELETE(self): """Delete a tag. - In order to delete a set of tags from a instance, the DELETE + In order to delete a set of tags, the DELETE request should be addressed to URI like: - /2/instances/[instance_name]/tags?tag=[tag]&tag=[tag] + /tags?tag=[tag]&tag=[tag] """ if 'tag' not in self.queryargs: - # no we not gonna delete all tags from an instance + # no we not gonna delete all tags raise http.HttpNotImplemented() - return baserlib._Tags_DELETE(constants.TAG_INSTANCE, + return baserlib._Tags_DELETE(self.TAG_LEVEL, self.queryargs['tag'], - name=self.items[0]) + name=self.name) + + +class R_2_instances_name_tags(_R_Tags): + """ /2/instances/[instance_name]/tags resource. + + Manages per-instance tags. + + """ + DOC_URI = "/2/instances/[instance_name]/tags" + TAG_LEVEL = constants.TAG_INSTANCE + + +class R_2_nodes_name_tags(_R_Tags): + """ /2/nodes/[node_name]/tags resource. + + Manages per-node tags. + + """ + DOC_URI = "/2/nodes/[node_name]/tags" + TAG_LEVEL = constants.TAG_NODE + + +class R_2_tags(_R_Tags): + """ /2/instances/tags resource. + + Manages cluster tags. + + """ + DOC_URI = "/2/tags" + TAG_LEVEL = constants.TAG_CLUSTER