b21cf46d2bd4734e843500b623eae510a92a3d82
[cascardo/ovs.git] / xenserver / etc_xapi.d_plugins_vswitch-cfg-update
1 #!/usr/bin/env python
2 #
3 # xapi plugin script to update the cache of configuration items in the
4 # ovs-vswitchd configuration file that are managed in the xapi database
5 # when integrated with Citrix management tools.
6
7 # Copyright (C) 2009 Nicira Networks, Inc.
8 #
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22 # TBD: - error handling needs to be improved.  Currently this can leave
23 # TBD:   the system in a bad state if anything goes wrong.
24
25 import logging
26 log = logging.getLogger("vswitch-cfg-update")
27 logging.basicConfig(filename="/var/log/vswitch-cfg-update.log", level=logging.DEBUG)
28
29 import XenAPIPlugin
30 import XenAPI
31 import subprocess
32
33 cfg_mod="/root/vswitch/bin/ovs-cfg-mod"
34 vswitchd_cfg_filename="/etc/ovs-vswitchd.conf"
35
36 def update(session, args):
37     pools = session.xenapi.pool.get_all()
38     # We assume there is only ever one pool...
39     if len(pools) == 0:
40         log.error("No pool for host.")
41         raise XenAPIPlugin.Failure("NO_POOL_FOR_HOST", [])
42     if len(pools) > 1:
43         log.error("More than one pool for host.")
44         raise XenAPIPlugin.Failure("MORE_THAN_ONE_POOL_FOR_HOST", [])
45     pool = session.xenapi.pool.get_record(pools[0])
46     try:
47         controller = pool["other_config"]["vSwitchController"]
48     except KeyError, e:
49         controller = ""
50     currentController = vswitchCurrentController()
51     if controller == "" and currentController != "":
52         log.debug("Removing controller configuration.")
53         removeControllerCfg()
54         return "Successfully removed controller config"
55     elif controller != currentController:
56         if len(controller) == 0:
57             log.debug("Setting controller to: %s" % (controller))
58         else:
59             log.debug("Changing controller from %s to %s" % (currentController, controller))
60         setControllerCfg(controller)
61         return "Successfully set controller to " + controller
62     else:
63         log.debug("No change to controller configuration required.")
64     return "No change to configuration"
65         
66 def vswitchCurrentController():
67     controller = vswitchCfgQuery("mgmt.controller")
68     if controller == "":
69         return controller
70     if len(controller) < 4 or controller[0:4] != "ssl:":
71         log.warning("Controller does not specify ssl connection type, returning entire string.")
72         return controller
73     else:
74         return controller[4:]
75
76 def removeControllerCfg():
77     vswitchCfgMod(["--del-match", "mgmt.controller=*",
78                    "--del-match", "ssl.bootstrap-ca-cert=*",
79                    "--del-match", "ssl.ca-cert=*",
80                    "--del-match", "ssl.private-key=*",
81                    "--del-match", "ssl.certificate=*"])
82                                        
83 def setControllerCfg(controller):
84     vswitchCfgMod(["--del-match", "mgmt.controller=*",
85                    "--del-match", "ssl.bootstrap-ca-cert=*",
86                    "--del-match", "ssl.ca-cert=*",
87                    "--del-match", "ssl.private-key=*",
88                    "--del-match", "ssl.certificate=*",
89                    "-a", "mgmt.controller=ssl:" + controller,
90                    "-a", "ssl.bootstrap-ca-cert=true",
91                    "-a", "ssl.ca-cert=/etc/ovs-vswitchd.cacert",
92                    "-a", "ssl.private-key=/etc/xensource/xapi-ssl.pem",
93                    "-a", "ssl.certificate=/etc/xensource/xapi-ssl.pem"])
94
95 def vswitchCfgQuery(key):
96     cmd = [cfg_mod, "--config-file=" + vswitchd_cfg_filename, "-q", key]
97     output = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()
98     if len(output) == 0 or output[0] == None:
99         output = ""
100     else:
101         output = output[0].strip()
102     return output
103
104 def vswitchCfgMod(action_args):
105     cmd = [cfg_mod, "-vANY:console:emer",
106            "--config-file=" + vswitchd_cfg_filename] + action_args
107     exitcode = subprocess.call(cmd)
108     if exitcode != 0:
109         log.error("ovs-cfg-mod failed with exit code "
110                   + str(exitcode) + " for " + repr(action_args))
111         raise XenAPIPlugin.Failure("VSWITCH_CONFIG_MOD_FAILURE",
112                                    [ str(exitcode) , str(action_args) ])
113     vswitchReload()
114     
115 def vswitchReload():
116     exitcode = subprocess.call(["/sbin/service", "vswitch", "reload"])
117     if exitcode != 0:
118         log.error("vswitch reload failed with exit code " + str(exitcode))
119         raise XenAPIPlugin.Failure("VSWITCH_CFG_RELOAD_FAILURE", [ str(exitcode) ])
120     
121
122 if __name__ == "__main__":
123     XenAPIPlugin.dispatch({"update": update})