1"""
2Name server control tool.
3
4Pyro - Python Remote Objects.  Copyright by Irmen de Jong (irmen@razorvine.net).
5"""
6
7from __future__ import print_function
8import sys
9import os
10import warnings
11from Pyro4 import errors, naming
12
13if sys.version_info < (3, 0):
14    input = raw_input
15
16
17def handleCommand(nameserver, options, args):
18    def printListResult(resultdict, title=""):
19        print("--------START LIST %s" % title)
20        for name, (uri, metadata) in sorted(resultdict.items()):
21            print("%s --> %s" % (name, uri))
22            if metadata:
23                print("    metadata:", metadata)
24        print("--------END LIST %s" % title)
25
26    def cmd_ping():
27        nameserver.ping()
28        print("Name server ping ok.")
29
30    def cmd_listprefix():
31        if len(args) == 1:
32            printListResult(nameserver.list(return_metadata=True))
33        else:
34            printListResult(nameserver.list(prefix=args[1], return_metadata=True), "- prefix '%s'" % args[1])
35
36    def cmd_listregex():
37        if len(args) != 2:
38            raise SystemExit("requires one argument: pattern")
39        printListResult(nameserver.list(regex=args[1], return_metadata=True), "- regex '%s'" % args[1])
40
41    def cmd_lookup():
42        if len(args) != 2:
43            raise SystemExit("requires one argument: name")
44        uri, metadata = nameserver.lookup(args[1], return_metadata=True)
45        print(uri)
46        if metadata:
47            print("metadata:", metadata)
48
49    def cmd_register():
50        if len(args) != 3:
51            raise SystemExit("requires two arguments: name uri")
52        nameserver.register(args[1], args[2], safe=True)
53        print("Registered %s" % args[1])
54
55    def cmd_remove():
56        if len(args) != 2:
57            raise SystemExit("requires one argument: name")
58        count = nameserver.remove(args[1])
59        if count > 0:
60            print("Removed %s" % args[1])
61        else:
62            print("Nothing removed")
63
64    def cmd_removeregex():
65        if len(args) != 2:
66            raise SystemExit("requires one argument: pattern")
67        sure = input("Potentially removing lots of items from the Name server. Are you sure (y/n)?").strip()
68        if sure in ('y', 'Y'):
69            count = nameserver.remove(regex=args[1])
70            print("%d items removed." % count)
71
72    def cmd_setmeta():
73        if len(args) < 2:
74            raise SystemExit("requires at least 2 arguments: uri and zero or more meta tags")
75        metadata = set(args[2:])
76        nameserver.set_metadata(args[1], metadata)
77        if metadata:
78            print("Metadata updated")
79        else:
80            print("Metadata cleared")
81
82    def cmd_listmeta_all():
83        if len(args) < 2:
84            raise SystemExit("requires at least one metadata tag argument")
85        metadata = set(args[1:])
86        printListResult(nameserver.list(metadata_all=metadata, return_metadata=True), " - searched by metadata")
87
88    def cmd_listmeta_any():
89        if len(args) < 2:
90            raise SystemExit("requires at least one metadata tag argument")
91        metadata = set(args[1:])
92        printListResult(nameserver.list(metadata_any=metadata, return_metadata=True), " - searched by metadata")
93
94    commands = {
95        "ping": cmd_ping,
96        "list": cmd_listprefix,
97        "listmatching": cmd_listregex,
98        "listmeta_all": cmd_listmeta_all,
99        "listmeta_any": cmd_listmeta_any,
100        "lookup": cmd_lookup,
101        "register": cmd_register,
102        "remove": cmd_remove,
103        "removematching": cmd_removeregex,
104        "setmeta": cmd_setmeta
105    }
106    try:
107        commands[args[0]]()
108    except Exception as x:
109        print("Error: %s - %s" % (type(x).__name__, x))
110
111
112def main(args=None):
113    from optparse import OptionParser
114    usage = "usage: %prog [options] command [arguments]\nCommands: " \
115            "register remove removematching lookup list listmatching\n          listmeta_all listmeta_any setmeta ping"
116    parser = OptionParser(usage=usage)
117    parser.add_option("-n", "--host", dest="host", help="hostname of the NS")
118    parser.add_option("-p", "--port", dest="port", type="int",
119                      help="port of the NS (or bc-port if host isn't specified)")
120    parser.add_option("-u", "--unixsocket", help="Unix domain socket name of the NS")
121    parser.add_option("-k", "--key", help="the HMAC key to use (deprecated)")
122    parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="verbose output")
123    options, args = parser.parse_args(args)
124    if options.key:
125        warnings.warn("using -k to supply HMAC key on the command line is a security problem "
126                      "and is deprecated since Pyro 4.72. See the documentation for an alternative.")
127    if "PYRO_HMAC_KEY" in os.environ:
128        if options.key:
129            raise SystemExit("error: don't use -k and PYRO_HMAC_KEY at the same time")
130        options.key = os.environ["PYRO_HMAC_KEY"]
131    if not args or args[0] not in ("register", "remove", "removematching", "list", "listmatching", "lookup",
132                                   "listmeta_all", "listmeta_any", "setmeta", "ping"):
133        parser.error("invalid or missing command")
134    if options.verbose:
135        print("Locating name server...")
136    if options.unixsocket:
137        options.host = "./u:" + options.unixsocket
138    try:
139        nameserver = naming.locateNS(options.host, options.port, hmac_key=options.key)
140    except errors.PyroError as x:
141        print("Error: %s" % x)
142        return
143    if options.verbose:
144        print("Name server found: %s" % nameserver._pyroUri)
145    handleCommand(nameserver, options, args)
146    if options.verbose:
147        print("Done.")
148
149
150if __name__ == "__main__":
151    main()
152