Revision 846baef9

b/lib/cli.py
32 32
from ganeti import errors
33 33
from ganeti import mcpu
34 34
from ganeti import constants
35
from ganeti import opcodes
35 36

  
36 37
from optparse import (OptionParser, make_option, TitledHelpFormatter,
37 38
                      Option, OptionValueError, SUPPRESS_HELP)
......
39 40
__all__ = ["DEBUG_OPT", "NOHDR_OPT", "SEP_OPT", "GenericMain", "SubmitOpCode",
40 41
           "cli_option", "GenerateTable", "AskUser",
41 42
           "ARGS_NONE", "ARGS_FIXED", "ARGS_ATLEAST", "ARGS_ANY", "ARGS_ONE",
42
           "USEUNITS_OPT", "FIELDS_OPT", "FORCE_OPT"]
43
           "USEUNITS_OPT", "FIELDS_OPT", "FORCE_OPT",
44
           "ListTags", "AddTags", "RemoveTags",
45
           ]
46

  
47

  
48
def _ExtractTagsObject(opts, args):
49
  """Extract the tag type object.
50

  
51
  Note that this function will modify its args parameter.
52

  
53
  """
54
  if not hasattr(opts, "tag_type"):
55
    raise errors.ProgrammerError("tag_type not passed to _ExtractTagsObject")
56
  kind = opts.tag_type
57
  if kind == constants.TAG_CLUSTER:
58
    retval = kind, kind
59
  elif kind == constants.TAG_NODE or kind == constants.TAG_INSTANCE:
60
    if not args:
61
      raise errors.OpPrereq("no arguments passed to the command")
62
    name = args.pop(0)
63
    retval = kind, name
64
  else:
65
    raise errors.ProgrammerError("Unhandled tag type '%s'" % kind)
66
  return retval
67

  
68

  
69
def ListTags(opts, args):
70
  """List the tags on a given object.
71

  
72
  This is a generic implementation that knows how to deal with all
73
  three cases of tag objects (cluster, node, instance). The opts
74
  argument is expected to contain a tag_type field denoting what
75
  object type we work on.
76

  
77
  """
78
  kind, name = _ExtractTagsObject(opts, args)
79
  op = opcodes.OpGetTags(kind=kind, name=name)
80
  result = SubmitOpCode(op)
81
  result = list(result)
82
  result.sort()
83
  for tag in result:
84
    print tag
85

  
86

  
87
def AddTags(opts, args):
88
  """Add tags on a given object.
89

  
90
  This is a generic implementation that knows how to deal with all
91
  three cases of tag objects (cluster, node, instance). The opts
92
  argument is expected to contain a tag_type field denoting what
93
  object type we work on.
94

  
95
  """
96
  kind, name = _ExtractTagsObject(opts, args)
97
  if not args:
98
    raise errors.OpPrereqError("No tags to be added")
99
  op = opcodes.OpAddTags(kind=kind, name=name, tags=args)
100
  SubmitOpCode(op)
101

  
102

  
103
def RemoveTags(opts, args):
104
  """Remove tags from a given object.
105

  
106
  This is a generic implementation that knows how to deal with all
107
  three cases of tag objects (cluster, node, instance). The opts
108
  argument is expected to contain a tag_type field denoting what
109
  object type we work on.
110

  
111
  """
112
  kind, name = _ExtractTagsObject(opts, args)
113
  if not args:
114
    raise errors.OpPrereqError("No tags to be removed")
115
  op = opcodes.OpDelTags(kind=kind, name=name, tags=args)
116
  SubmitOpCode(op)
117

  
43 118

  
44 119
DEBUG_OPT = make_option("-d", "--debug", default=False,
45 120
                        action="store_true",
......
68 143
_LOCK_OPT = make_option("--lock-retries", default=None,
69 144
                        type="int", help=SUPPRESS_HELP)
70 145

  
71

  
72 146
def ARGS_FIXED(val):
73 147
  """Macro-like function denoting a fixed number of arguments"""
74 148
  return -val
b/scripts/gnt-cluster
263 263
              "Runs a command on all (or only some) nodes"),
264 264
  'info': (ShowClusterConfig, ARGS_NONE, [DEBUG_OPT],
265 265
                 "", "Show cluster configuration"),
266
  'list-tags': (ListTags, ARGS_NONE,
267
                [DEBUG_OPT], "", "List the tags of the cluster"),
268
  'add-tags': (AddTags, ARGS_ANY, [DEBUG_OPT],
269
               "tag...", "Add tags to the cluster"),
270
  'remove-tags': (RemoveTags, ARGS_ANY, [DEBUG_OPT],
271
                  "tag...", "Remove tags from the cluster"),
266 272
  }
267 273

  
268 274
if __name__ == '__main__':
269
  sys.exit(GenericMain(commands))
275
  sys.exit(GenericMain(commands, override={"tag_type": constants.TAG_CLUSTER}))
b/scripts/gnt-instance
754 754
  'deactivate-disks': (DeactivateDisks, ARGS_ONE, [DEBUG_OPT],
755 755
                       "<instance>",
756 756
                       "Deactivate an instance's disks"),
757
  'list-tags': (ListTags, ARGS_ONE, [DEBUG_OPT],
758
                "<node_name>", "List the tags of the given instance"),
759
  'add-tags': (AddTags, ARGS_ATLEAST(1), [DEBUG_OPT],
760
               "<node_name> tag...", "Add tags to the given instance"),
761
  'remove-tags': (RemoveTags, ARGS_ATLEAST(1), [DEBUG_OPT],
762
                  "<node_name> tag...", "Remove tags from given instance"),
757 763
  }
758 764

  
759 765
if __name__ == '__main__':
760
  sys.exit(GenericMain(commands))
766
  sys.exit(GenericMain(commands,
767
                       override={"tag_type": constants.TAG_INSTANCE}))
b/scripts/gnt-node
26 26
from ganeti import opcodes
27 27
from ganeti import logger
28 28
from ganeti import utils
29
from ganeti import constants
29 30

  
30 31

  
31 32
def AddNode(opts, args):
......
180 181
  'volumes': (ListVolumes, ARGS_ANY,
181 182
              [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT],
182 183
              "[<node_name>...]", "List logical volumes on node(s)"),
184
  'list-tags': (ListTags, ARGS_ONE, [DEBUG_OPT],
185
                "<node_name>", "List the tags of the given node"),
186
  'add-tags': (AddTags, ARGS_ATLEAST(1), [DEBUG_OPT],
187
               "<node_name> tag...", "Add tags to the given node"),
188
  'remove-tags': (RemoveTags, ARGS_ATLEAST(1), [DEBUG_OPT],
189
                  "<node_name> tag...", "Remove tags from the given node"),
183 190
  }
184 191

  
185 192

  
186 193
if __name__ == '__main__':
187
  sys.exit(GenericMain(commands))
194
  sys.exit(GenericMain(commands, override={"tag_type": constants.TAG_NODE}))

Also available in: Unified diff