Commit 73415719 authored by Iustin Pop's avatar Iustin Pop
Browse files

Implement tag searching

This patch adds a search command for locating tags on all objects of the
cluster using a regex pattern.

Reviewed-by: aat
parent 830da270
......@@ -4141,6 +4141,42 @@ class LUGetTags(TagsLU):
return self.target.GetTags()
class LUSearchTags(NoHooksLU):
"""Searches the tags for a given pattern.
"""
_OP_REQP = ["pattern"]
def CheckPrereq(self):
"""Check prerequisites.
This checks the pattern passed for validity by compiling it.
"""
try:
self.re = re.compile(self.op.pattern)
except re.error, err:
raise errors.OpPrereqError("Invalid search pattern '%s': %s" %
(self.op.pattern, err))
def Exec(self, feedback_fn):
"""Returns the tag list.
"""
cfg = self.cfg
tgts = [("/cluster", cfg.GetClusterInfo())]
ilist = [cfg.GetInstanceInfo(name) for name in cfg.GetInstanceList()]
tgts.extend([("/instances/%s" % i.name, i) for i in ilist])
nlist = [cfg.GetNodeInfo(name) for name in cfg.GetNodeList()]
tgts.extend([("/nodes/%s" % n.name, n) for n in nlist])
results = []
for path, target in tgts:
for tag in target.GetTags():
if self.re.search(tag):
results.append((path, tag))
return results
class LUAddTags(TagsLU):
"""Sets a tag on a given object.
......
......@@ -80,6 +80,7 @@ class Processor(object):
opcodes.OpExportInstance: cmdlib.LUExportInstance,
# tags lu
opcodes.OpGetTags: cmdlib.LUGetTags,
opcodes.OpSearchTags: cmdlib.LUSearchTags,
opcodes.OpAddTags: cmdlib.LUAddTags,
opcodes.OpDelTags: cmdlib.LUDelTags,
}
......
......@@ -263,6 +263,12 @@ class OpGetTags(OpCode):
__slots__ = ["kind", "name"]
class OpSearchTags(OpCode):
"""Searches the tags in the cluster for a given pattern."""
OP_ID = "OP_TAGS_SEARCH"
__slots__ = ["pattern"]
class OpAddTags(OpCode):
"""Add a list of tags on a given object."""
OP_ID = "OP_TAGS_SET"
......
......@@ -301,6 +301,42 @@
</para>
</refsect2>
<refsect2>
<title>SEARCH-TAGS</title>
<cmdsynopsis>
<command>search-tags</command>
<arg choice="req"><replaceable>pattern</replaceable></arg>
</cmdsynopsis>
<para>
Searches the tags on all objects in the cluster (the cluster
itself, the nodes and the instances) for a given pattern. The
pattern is interpreted as a regular expression and a search
will be done on it (i.e. the given pattern is not anchored to
the beggining of the string; if you want that, prefix the
pattern with <literal>^</literal>).
</para>
<para>
If no tags are matching the pattern, the exit code of the
command will be one. If there is at least one match, the exit
code will be zero. Each match is listed on one line, the
object and the tag separated by a space. The cluster will be
listed as <filename>/cluster</filename>, a node will be listed
as
<filename>/nodes/<replaceable>name</replaceable></filename>,
and an instance as
<filename>/instances/<replaceable>name</replaceable></filename>.
Example:
</para>
<screen>
# gnt-cluster search time
/cluster ctime:2007-09-01
/nodes/node1.example.com mtime:2007-10-04
</screen>
</refsect2>
<refsect2>
<title>VERIFY</title>
......
......@@ -193,6 +193,20 @@ def MasterFailover(opts, args):
SubmitOpCode(op)
def SearchTags(opts, args):
"""Searches the tags on all the cluster.
"""
op = opcodes.OpSearchTags(pattern=args[0])
result = SubmitOpCode(op)
if not result:
return 1
result = list(result)
result.sort()
for path, tag in result:
print "%s %s" % (path, tag)
# this is an option common to more than one command, so we declare
# it here and reuse it
node_option = make_option("-n", "--node", action="append", dest="nodes",
......@@ -269,6 +283,9 @@ commands = {
"tag...", "Add tags to the cluster"),
'remove-tags': (RemoveTags, ARGS_ANY, [DEBUG_OPT, TAG_SRC_OPT],
"tag...", "Remove tags from the cluster"),
'search-tags': (SearchTags, ARGS_ONE,
[DEBUG_OPT], "", "Searches the tags on all objects on"
" the cluster for a given pattern (regex)"),
}
if __name__ == '__main__':
......
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