Commit 846baef9 authored by Iustin Pop's avatar Iustin Pop

Implement command-line tags support

This patch adds generic functions for tag manipulations to cli.py and
modifies gnt-{cluster,node,instance} to export {list,add,remove}-tags
commands that use those.

Reviewed-by: imsnah
parent f27302fa
...@@ -32,6 +32,7 @@ from ganeti import logger ...@@ -32,6 +32,7 @@ from ganeti import logger
from ganeti import errors from ganeti import errors
from ganeti import mcpu from ganeti import mcpu
from ganeti import constants from ganeti import constants
from ganeti import opcodes
from optparse import (OptionParser, make_option, TitledHelpFormatter, from optparse import (OptionParser, make_option, TitledHelpFormatter,
Option, OptionValueError, SUPPRESS_HELP) Option, OptionValueError, SUPPRESS_HELP)
...@@ -39,7 +40,81 @@ from optparse import (OptionParser, make_option, TitledHelpFormatter, ...@@ -39,7 +40,81 @@ from optparse import (OptionParser, make_option, TitledHelpFormatter,
__all__ = ["DEBUG_OPT", "NOHDR_OPT", "SEP_OPT", "GenericMain", "SubmitOpCode", __all__ = ["DEBUG_OPT", "NOHDR_OPT", "SEP_OPT", "GenericMain", "SubmitOpCode",
"cli_option", "GenerateTable", "AskUser", "cli_option", "GenerateTable", "AskUser",
"ARGS_NONE", "ARGS_FIXED", "ARGS_ATLEAST", "ARGS_ANY", "ARGS_ONE", "ARGS_NONE", "ARGS_FIXED", "ARGS_ATLEAST", "ARGS_ANY", "ARGS_ONE",
"USEUNITS_OPT", "FIELDS_OPT", "FORCE_OPT"] "USEUNITS_OPT", "FIELDS_OPT", "FORCE_OPT",
"ListTags", "AddTags", "RemoveTags",
]
def _ExtractTagsObject(opts, args):
"""Extract the tag type object.
Note that this function will modify its args parameter.
"""
if not hasattr(opts, "tag_type"):
raise errors.ProgrammerError("tag_type not passed to _ExtractTagsObject")
kind = opts.tag_type
if kind == constants.TAG_CLUSTER:
retval = kind, kind
elif kind == constants.TAG_NODE or kind == constants.TAG_INSTANCE:
if not args:
raise errors.OpPrereq("no arguments passed to the command")
name = args.pop(0)
retval = kind, name
else:
raise errors.ProgrammerError("Unhandled tag type '%s'" % kind)
return retval
def ListTags(opts, args):
"""List the tags on a given object.
This is a generic implementation that knows how to deal with all
three cases of tag objects (cluster, node, instance). The opts
argument is expected to contain a tag_type field denoting what
object type we work on.
"""
kind, name = _ExtractTagsObject(opts, args)
op = opcodes.OpGetTags(kind=kind, name=name)
result = SubmitOpCode(op)
result = list(result)
result.sort()
for tag in result:
print tag
def AddTags(opts, args):
"""Add tags on a given object.
This is a generic implementation that knows how to deal with all
three cases of tag objects (cluster, node, instance). The opts
argument is expected to contain a tag_type field denoting what
object type we work on.
"""
kind, name = _ExtractTagsObject(opts, args)
if not args:
raise errors.OpPrereqError("No tags to be added")
op = opcodes.OpAddTags(kind=kind, name=name, tags=args)
SubmitOpCode(op)
def RemoveTags(opts, args):
"""Remove tags from a given object.
This is a generic implementation that knows how to deal with all
three cases of tag objects (cluster, node, instance). The opts
argument is expected to contain a tag_type field denoting what
object type we work on.
"""
kind, name = _ExtractTagsObject(opts, args)
if not args:
raise errors.OpPrereqError("No tags to be removed")
op = opcodes.OpDelTags(kind=kind, name=name, tags=args)
SubmitOpCode(op)
DEBUG_OPT = make_option("-d", "--debug", default=False, DEBUG_OPT = make_option("-d", "--debug", default=False,
action="store_true", action="store_true",
...@@ -68,7 +143,6 @@ FORCE_OPT = make_option("-f", "--force", dest="force", action="store_true", ...@@ -68,7 +143,6 @@ FORCE_OPT = make_option("-f", "--force", dest="force", action="store_true",
_LOCK_OPT = make_option("--lock-retries", default=None, _LOCK_OPT = make_option("--lock-retries", default=None,
type="int", help=SUPPRESS_HELP) type="int", help=SUPPRESS_HELP)
def ARGS_FIXED(val): def ARGS_FIXED(val):
"""Macro-like function denoting a fixed number of arguments""" """Macro-like function denoting a fixed number of arguments"""
return -val return -val
......
...@@ -263,7 +263,13 @@ commands = { ...@@ -263,7 +263,13 @@ commands = {
"Runs a command on all (or only some) nodes"), "Runs a command on all (or only some) nodes"),
'info': (ShowClusterConfig, ARGS_NONE, [DEBUG_OPT], 'info': (ShowClusterConfig, ARGS_NONE, [DEBUG_OPT],
"", "Show cluster configuration"), "", "Show cluster configuration"),
'list-tags': (ListTags, ARGS_NONE,
[DEBUG_OPT], "", "List the tags of the cluster"),
'add-tags': (AddTags, ARGS_ANY, [DEBUG_OPT],
"tag...", "Add tags to the cluster"),
'remove-tags': (RemoveTags, ARGS_ANY, [DEBUG_OPT],
"tag...", "Remove tags from the cluster"),
} }
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(GenericMain(commands)) sys.exit(GenericMain(commands, override={"tag_type": constants.TAG_CLUSTER}))
...@@ -754,7 +754,14 @@ commands = { ...@@ -754,7 +754,14 @@ commands = {
'deactivate-disks': (DeactivateDisks, ARGS_ONE, [DEBUG_OPT], 'deactivate-disks': (DeactivateDisks, ARGS_ONE, [DEBUG_OPT],
"<instance>", "<instance>",
"Deactivate an instance's disks"), "Deactivate an instance's disks"),
'list-tags': (ListTags, ARGS_ONE, [DEBUG_OPT],
"<node_name>", "List the tags of the given instance"),
'add-tags': (AddTags, ARGS_ATLEAST(1), [DEBUG_OPT],
"<node_name> tag...", "Add tags to the given instance"),
'remove-tags': (RemoveTags, ARGS_ATLEAST(1), [DEBUG_OPT],
"<node_name> tag...", "Remove tags from given instance"),
} }
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(GenericMain(commands)) sys.exit(GenericMain(commands,
override={"tag_type": constants.TAG_INSTANCE}))
...@@ -26,6 +26,7 @@ from ganeti.cli import * ...@@ -26,6 +26,7 @@ from ganeti.cli import *
from ganeti import opcodes from ganeti import opcodes
from ganeti import logger from ganeti import logger
from ganeti import utils from ganeti import utils
from ganeti import constants
def AddNode(opts, args): def AddNode(opts, args):
...@@ -180,8 +181,14 @@ commands = { ...@@ -180,8 +181,14 @@ commands = {
'volumes': (ListVolumes, ARGS_ANY, 'volumes': (ListVolumes, ARGS_ANY,
[DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT], [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT],
"[<node_name>...]", "List logical volumes on node(s)"), "[<node_name>...]", "List logical volumes on node(s)"),
'list-tags': (ListTags, ARGS_ONE, [DEBUG_OPT],
"<node_name>", "List the tags of the given node"),
'add-tags': (AddTags, ARGS_ATLEAST(1), [DEBUG_OPT],
"<node_name> tag...", "Add tags to the given node"),
'remove-tags': (RemoveTags, ARGS_ATLEAST(1), [DEBUG_OPT],
"<node_name> tag...", "Remove tags from the given node"),
} }
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(GenericMain(commands)) sys.exit(GenericMain(commands, override={"tag_type": constants.TAG_NODE}))
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment