python: Break unixctl implementation into registry, client, and server.
[sliver-openvswitch.git] / python / ovs / unixctl / __init__.py
1 # Copyright (c) 2011, 2012 Nicira, Inc.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at:
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 import types
16
17 import ovs.util
18
19 commands = {}
20 strtypes = types.StringTypes
21
22
23 class _UnixctlCommand(object):
24     def __init__(self, usage, min_args, max_args, callback, aux):
25         self.usage = usage
26         self.min_args = min_args
27         self.max_args = max_args
28         self.callback = callback
29         self.aux = aux
30
31
32 def _unixctl_help(conn, unused_argv, unused_aux):
33     reply = "The available commands are:\n"
34     command_names = sorted(commands.keys())
35     for name in command_names:
36         reply += "  "
37         usage = commands[name].usage
38         if usage:
39             reply += "%-23s %s" % (name, usage)
40         else:
41             reply += name
42         reply += "\n"
43     conn.reply(reply)
44
45
46 def command_register(name, usage, min_args, max_args, callback, aux):
47     """ Registers a command with the given 'name' to be exposed by the
48     UnixctlServer. 'usage' describes the arguments to the command; it is used
49     only for presentation to the user in "help" output.
50
51     'callback' is called when the command is received.  It is passed a
52     UnixctlConnection object, the list of arguments as unicode strings, and
53     'aux'.  Normally 'callback' should reply by calling
54     UnixctlConnection.reply() or UnixctlConnection.reply_error() before it
55     returns, but if the command cannot be handled immediately, then it can
56     defer the reply until later.  A given connection can only process a single
57     request at a time, so a reply must be made eventually to avoid blocking
58     that connection."""
59
60     assert isinstance(name, strtypes)
61     assert isinstance(usage, strtypes)
62     assert isinstance(min_args, int)
63     assert isinstance(max_args, int)
64     assert isinstance(callback, types.FunctionType)
65
66     if name not in commands:
67         commands[name] = _UnixctlCommand(usage, min_args, max_args, callback,
68                                          aux)
69
70 def socket_name_from_target(target):
71     assert isinstance(target, strtypes)
72
73     if target.startswith("/"):
74         return 0, target
75
76     pidfile_name = "%s/%s.pid" % (ovs.dirs.RUNDIR, target)
77     pid = ovs.daemon.read_pidfile(pidfile_name)
78     if pid < 0:
79         return -pid, "cannot read pidfile \"%s\"" % pidfile_name
80
81     return 0, "%s/%s.%d.ctl" % (ovs.dirs.RUNDIR, target, pid)
82
83 command_register("help", "", 0, 0, _unixctl_help, None)