]>
Commit | Line | Data |
---|---|---|
064af421 BP |
1 | #!/usr/bin/env python |
2 | # | |
3 | # xapi plugin script to update the cache of configuration items in the | |
bc391960 JP |
4 | # ovs-vswitchd configuration that are managed in the xapi database when |
5 | # integrated with Citrix management tools. | |
064af421 | 6 | |
939e5a1b | 7 | # Copyright (C) 2009, 2010, 2011 Nicira Networks, Inc. |
064af421 | 8 | # |
a14bc59f BP |
9 | # Licensed under the Apache License, Version 2.0 (the "License"); |
10 | # you may not use this file except in compliance with the License. | |
11 | # You may obtain a copy of the License at: | |
064af421 | 12 | # |
a14bc59f | 13 | # http://www.apache.org/licenses/LICENSE-2.0 |
064af421 | 14 | # |
a14bc59f BP |
15 | # Unless required by applicable law or agreed to in writing, software |
16 | # distributed under the License is distributed on an "AS IS" BASIS, | |
17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
18 | # See the License for the specific language governing permissions and | |
19 | # limitations under the License. | |
064af421 BP |
20 | |
21 | # TBD: - error handling needs to be improved. Currently this can leave | |
22 | # TBD: the system in a bad state if anything goes wrong. | |
23 | ||
064af421 BP |
24 | import XenAPIPlugin |
25 | import XenAPI | |
7e40e21d | 26 | import os |
064af421 | 27 | import subprocess |
7730bd8f | 28 | import syslog |
064af421 | 29 | |
f95c85e2 | 30 | vsctl="/usr/bin/ovs-vsctl" |
bc391960 | 31 | cacert_filename="/etc/openvswitch/vswitchd.cacert" |
7e40e21d JP |
32 | |
33 | # Delete the CA certificate, so that we go back to boot-strapping mode | |
34 | def delete_cacert(): | |
35 | try: | |
36 | os.remove(cacert_filename) | |
37 | except OSError: | |
38 | # Ignore error if file doesn't exist | |
39 | pass | |
064af421 BP |
40 | |
41 | def update(session, args): | |
bc31db1f | 42 | # Refresh bridge network UUIDs in case this host joined or left a pool. |
9575eae3 | 43 | script = "/opt/xensource/libexec/interface-reconfigure" |
bc31db1f | 44 | try: |
9575eae3 | 45 | retval = subprocess.call([script, "rewrite"]) |
bc31db1f BP |
46 | if retval != 0: |
47 | syslog.syslog("%s exited with status %d" % (script, retval)) | |
48 | except OSError, e: | |
49 | syslog.syslog("%s: failed to execute (%s)" % (script, e.strerror)) | |
50 | ||
064af421 BP |
51 | pools = session.xenapi.pool.get_all() |
52 | # We assume there is only ever one pool... | |
53 | if len(pools) == 0: | |
064af421 BP |
54 | raise XenAPIPlugin.Failure("NO_POOL_FOR_HOST", []) |
55 | if len(pools) > 1: | |
064af421 BP |
56 | raise XenAPIPlugin.Failure("MORE_THAN_ONE_POOL_FOR_HOST", []) |
57 | pool = session.xenapi.pool.get_record(pools[0]) | |
58 | try: | |
80854880 JP |
59 | try: |
60 | controller = pool["vswitch_controller"] | |
61 | except KeyError: | |
62 | # On systems older than XenServer 5.6.0, we needed to store | |
63 | # the key in "other_config". | |
64 | controller = pool["other_config"]["vSwitchController"] | |
064af421 BP |
65 | except KeyError, e: |
66 | controller = "" | |
939e5a1b | 67 | ret_str = "" |
064af421 BP |
68 | currentController = vswitchCurrentController() |
69 | if controller == "" and currentController != "": | |
7e40e21d | 70 | delete_cacert() |
59a81d82 JP |
71 | try: |
72 | emergency_reset(session, None) | |
73 | except: | |
74 | pass | |
064af421 | 75 | removeControllerCfg() |
939e5a1b | 76 | ret_str += "Successfully removed controller config. " |
064af421 | 77 | elif controller != currentController: |
7e40e21d | 78 | delete_cacert() |
59a81d82 JP |
79 | try: |
80 | emergency_reset(session, None) | |
81 | except: | |
82 | pass | |
064af421 | 83 | setControllerCfg(controller) |
939e5a1b EJ |
84 | ret_str += "Successfully set controller to %s. " % controller |
85 | ||
86 | try: | |
2dd26837 | 87 | pool_fail_mode = pool["other_config"]["vswitch-controller-fail-mode"] |
939e5a1b | 88 | except KeyError, e: |
2dd26837 | 89 | pool_fail_mode = None |
939e5a1b | 90 | |
2dd26837 EJ |
91 | bton = {} |
92 | ||
93 | for n in session.xenapi.network.get_all(): | |
94 | rec = session.xenapi.network.get_record(n) | |
95 | try: | |
96 | bton[rec['bridge']] = rec | |
97 | except KeyError: | |
98 | pass | |
939e5a1b EJ |
99 | |
100 | fail_mode_changed = False | |
75fca0a4 EJ |
101 | for bridge in vswitchCfgQuery(['list-br']).split(): |
102 | bridge = vswitchCfgQuery(['br-to-parent', bridge]) | |
939e5a1b EJ |
103 | bridge_fail_mode = vswitchCfgQuery(["get", "Bridge", |
104 | bridge, "fail_mode"]).strip('[]"') | |
105 | ||
2dd26837 EJ |
106 | try: |
107 | fail_mode = bton[bridge]["other_config"]["vswitch-controller-fail-mode"] | |
108 | except KeyError, e: | |
109 | fail_mode = None | |
110 | ||
111 | if fail_mode not in ['secure', 'standalone']: | |
112 | fail_mode = pool_fail_mode | |
113 | ||
114 | if fail_mode != 'secure': | |
115 | fail_mode = 'standalone' | |
116 | ||
939e5a1b EJ |
117 | if bridge_fail_mode != fail_mode: |
118 | vswitchCfgMod(['--', 'set', 'Bridge', bridge, | |
119 | "fail_mode=%s" % fail_mode]) | |
120 | fail_mode_changed = True | |
121 | ||
122 | if fail_mode_changed: | |
2dd26837 | 123 | ret_str += "Updated fail_mode. " |
939e5a1b EJ |
124 | |
125 | if ret_str != '': | |
126 | return ret_str | |
064af421 | 127 | else: |
5990cd46 | 128 | return "No change to configuration" |
83497018 | 129 | |
064af421 | 130 | def vswitchCurrentController(): |
7e67d10d BP |
131 | controller = vswitchCfgQuery(["get", "Open_vSwitch", |
132 | ".", "managers"]).strip('[]"') | |
064af421 BP |
133 | if controller == "": |
134 | return controller | |
135 | if len(controller) < 4 or controller[0:4] != "ssl:": | |
064af421 BP |
136 | return controller |
137 | else: | |
5a9e7099 | 138 | return controller.split(':')[1] |
064af421 BP |
139 | |
140 | def removeControllerCfg(): | |
5a9e7099 | 141 | vswitchCfgMod(["--", "clear", "Open_vSwitch", ".", "managers", |
f95c85e2 | 142 | "--", "del-ssl"]) |
83497018 | 143 | |
064af421 | 144 | def setControllerCfg(controller): |
88b56f29 BP |
145 | # /etc/xensource/xapi-ssl.pem is mentioned twice below because it |
146 | # contains both the private key and the certificate. | |
5a9e7099 | 147 | vswitchCfgMod(["--", "clear", "Open_vSwitch", ".", "managers", |
f95c85e2 JP |
148 | "--", "del-ssl", |
149 | "--", "--bootstrap", "set-ssl", | |
150 | "/etc/xensource/xapi-ssl.pem", | |
90056dc0 | 151 | "/etc/xensource/xapi-ssl.pem", |
bc391960 | 152 | cacert_filename, |
5a9e7099 JP |
153 | "--", "set", "Open_vSwitch", ".", |
154 | 'managers="ssl:' + controller + ':6632"']) | |
064af421 | 155 | |
7e67d10d | 156 | def vswitchCfgQuery(action_args): |
6b7b9d34 | 157 | cmd = [vsctl, "--timeout=5", "-vANY:console:emer"] + action_args |
064af421 BP |
158 | output = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate() |
159 | if len(output) == 0 or output[0] == None: | |
160 | output = "" | |
161 | else: | |
162 | output = output[0].strip() | |
163 | return output | |
164 | ||
165 | def vswitchCfgMod(action_args): | |
6b7b9d34 | 166 | cmd = [vsctl, "--timeout=5", "-vANY:console:emer"] + action_args |
064af421 BP |
167 | exitcode = subprocess.call(cmd) |
168 | if exitcode != 0: | |
064af421 BP |
169 | raise XenAPIPlugin.Failure("VSWITCH_CONFIG_MOD_FAILURE", |
170 | [ str(exitcode) , str(action_args) ]) | |
7730bd8f JP |
171 | |
172 | def emergency_reset(session, args): | |
6b7b9d34 | 173 | cmd = [vsctl, "--timeout=5", "emer-reset"] |
59a81d82 JP |
174 | exitcode = subprocess.call(cmd) |
175 | if exitcode != 0: | |
176 | raise XenAPIPlugin.Failure("VSWITCH_EMER_RESET_FAILURE", | |
177 | [ str(exitcode) ]) | |
178 | ||
179 | return "Successfully reset configuration" | |
064af421 | 180 | |
064af421 | 181 | if __name__ == "__main__": |
7730bd8f JP |
182 | XenAPIPlugin.dispatch({"update": update, |
183 | "emergency_reset": emergency_reset}) |