]>
git.proxmox.com Git - ovs.git/blob - xenserver/etc_xapi.d_plugins_openvswitch-cfg-update
0668b39d66fb4567e5528a5c17c3fd4ce8f9edc8
3 # xapi plugin script to update the cache of configuration items in the
4 # ovs-vswitchd configuration that are managed in the xapi database when
5 # integrated with Citrix management tools.
7 # Copyright (C) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
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:
13 # http://www.apache.org/licenses/LICENSE-2.0
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.
21 # TBD: - error handling needs to be improved. Currently this can leave
22 # TBD: the system in a bad state if anything goes wrong.
30 vsctl
= '/usr/bin/ovs-vsctl'
31 ofctl
= '/usr/bin/ovs-ofctl'
32 cacert_filename
= '/etc/openvswitch/vswitchd.cacert'
35 # Delete the CA certificate, so that we go back to boot-strapping mode
38 os
.remove(cacert_filename
)
40 # Ignore error if file doesn't exist
44 def update(session
, args
):
45 # Refresh bridge network UUIDs in case this host joined or left a pool.
46 script
= '/opt/xensource/libexec/interface-reconfigure'
48 retval
= subprocess
.call([script
, 'rewrite'])
50 syslog
.syslog('%s exited with status %d' % (script
, retval
))
52 syslog
.syslog('%s: failed to execute (%s)' % (script
, e
.strerror
))
54 pools
= session
.xenapi
.pool
.get_all()
55 # We assume there is only ever one pool...
57 raise XenAPIPlugin
.Failure('NO_POOL_FOR_HOST', [])
59 raise XenAPIPlugin
.Failure('MORE_THAN_ONE_POOL_FOR_HOST', [])
60 new_controller
= False
61 pool
= session
.xenapi
.pool
.get_record(pools
[0])
62 controller
= pool
.get('vswitch_controller')
64 currentControllers
= vswitchCurrentControllers()
66 if not controller
and currentControllers
:
69 emergency_reset(session
, None)
73 ret_str
+= 'Successfully removed controller config. '
74 elif controller
not in currentControllers
:
77 emergency_reset(session
, None)
80 setControllerCfg(controller
)
82 ret_str
+= 'Successfully set controller to %s. ' % controller
85 pool_fail_mode
= pool
['other_config']['vswitch-controller-fail-mode']
91 for rec
in session
.xenapi
.network
.get_all_records().values():
93 bton
[rec
['bridge']] = rec
97 # If new controller, get management MAC addresses from XAPI now
98 # in case fail_mode set to secure which may affect XAPI access
101 host_mgmt_device
= None
104 query
= 'field "management"="true"'
105 recs
= session
.xenapi
.PIF
.get_all_records_where(query
)
106 for rec
in recs
.itervalues():
107 pool_mgmt_macs
[rec
.get('MAC')] = rec
.get('device')
110 fail_mode_changed
= False
111 for bridge
in vswitchCfgQuery(['list-br']).split():
112 network
= bton
[bridge
]
113 bridge
= vswitchCfgQuery(['br-to-parent', bridge
])
115 xapi_dib
= network
['other_config'].get('vswitch-disable-in-band')
119 ovs_dib
= vswitchCfgQuery(['--', '--if-exists', 'get', 'Bridge',
121 'other_config:disable-in-band']).strip('"')
123 # Do nothing if setting is invalid, and warn the user.
124 if xapi_dib
not in ['true', 'false', '']:
125 ret_str
+= '"' + xapi_dib
+ '"' + \
126 ' is an invalid value for vswitch-disable-in-band on ' + \
129 # Change bridge disable-in-band option if XAPI and OVS states differ.
130 elif xapi_dib
!= ovs_dib
:
133 vswitchCfgMod(['--', 'set', 'Bridge', bridge
,
134 'other_config:disable-in-band=' + xapi_dib
])
137 vswitchCfgMod(['--', 'remove', 'Bridge', bridge
,
138 'other_config', 'disable-in-band'])
141 # Change bridge fail_mode if XAPI state differs from OVS state.
142 bridge_fail_mode
= vswitchCfgQuery(['get', 'Bridge',
143 bridge
, 'fail_mode']).strip('[]"')
146 other_config
= bton
[bridge
]['other_config']
147 fail_mode
= other_config
['vswitch-controller-fail-mode']
151 if fail_mode
not in ['secure', 'standalone']:
152 fail_mode
= pool_fail_mode
154 if fail_mode
!= 'secure':
155 fail_mode
= 'standalone'
157 if bridge_fail_mode
!= fail_mode
:
158 vswitchCfgMod(['--', 'set', 'Bridge', bridge
,
159 'fail_mode=%s' % fail_mode
])
160 fail_mode_changed
= True
162 # Determine local mgmt MAC address if host being added to secure
163 # pool so we can add default flows to allow management traffic
164 if new_controller
and fail_mode_changed
and pool_fail_mode
== 'secure':
165 oc
= vswitchCfgQuery(['get', 'Bridge', bridge
, 'other-config'])
166 m
= re
.match('.*hwaddr="([0-9a-fA-F:].*)".*', oc
)
167 if m
and m
.group(1) in pool_mgmt_macs
.keys():
169 host_mgmt_mac
= m
.group(1)
170 host_mgmt_device
= pool_mgmt_macs
[host_mgmt_mac
]
172 if (host_mgmt_mac
is not None and mgmt_bridge
is not None and
173 host_mgmt_device
is not None):
174 tp
= 'idle_timeout=0,priority=0'
175 port
= vswitchCfgQuery(['get', 'interface', host_mgmt_device
,
178 addFlow(mgmt_bridge
, '%s,in_port=%s,arp,nw_proto=1,actions=local' %
180 addFlow(mgmt_bridge
, '%s,in_port=local,arp,dl_src=%s,actions=%s' %
181 (tp
, host_mgmt_mac
, port
))
182 addFlow(mgmt_bridge
, '%s,in_port=%s,dl_dst=%s,actions=local' %
183 (tp
, port
, host_mgmt_mac
))
184 addFlow(mgmt_bridge
, '%s,in_port=local,dl_src=%s,actions=%s' %
185 (tp
, host_mgmt_mac
, port
))
188 ret_str
+= 'Updated in-band management. '
189 if fail_mode_changed
:
190 ret_str
+= 'Updated fail_mode. '
195 return 'No change to configuration'
198 def vswitchCurrentControllers():
199 controllers
= vswitchCfgQuery(['get-manager'])
201 def parse_controller(controller
):
202 if controller
.startswith('ssl:'):
203 return controller
.split(':')[1]
205 return controller
.split(':')[0]
207 return [parse_controller(controller
)
208 for controller
in controllers
.split('\n')
212 def removeControllerCfg():
213 vswitchCfgMod(['--', 'del-manager',
217 def setControllerCfg(controller
):
218 # /etc/xensource/xapi-ssl.pem is mentioned twice below because it
219 # contains both the private key and the certificate.
220 vswitchCfgMod(['--', 'del-manager',
222 '--', '--bootstrap', 'set-ssl',
223 '/etc/xensource/xapi-ssl.pem',
224 '/etc/xensource/xapi-ssl.pem',
226 '--', 'set-manager', 'ssl:' + controller
+ ':6632'])
229 def vswitchCfgQuery(action_args
):
230 cmd
= [vsctl
, '-vconsole:off'] + action_args
231 output
= subprocess
.Popen(cmd
, stdout
=subprocess
.PIPE
).communicate()
232 if len(output
) == 0 or output
[0] is None:
235 output
= output
[0].strip()
239 def vswitchCfgMod(action_args
):
240 cmd
= [vsctl
, '--timeout=5', '-vconsole:off'] + action_args
241 exitcode
= subprocess
.call(cmd
)
243 raise XenAPIPlugin
.Failure('VSWITCH_CONFIG_MOD_FAILURE',
244 [str(exitcode
), str(action_args
)])
247 def emergency_reset(session
, args
):
248 cmd
= [vsctl
, '--timeout=5', 'emer-reset']
249 exitcode
= subprocess
.call(cmd
)
251 raise XenAPIPlugin
.Failure('VSWITCH_EMER_RESET_FAILURE',
254 return 'Successfully reset configuration'
257 def addFlow(switch
, flow
):
258 cmd
= [ofctl
, 'add-flow', switch
, flow
]
259 exitcode
= subprocess
.call(cmd
)
261 raise XenAPIPlugin
.Failure('VSWITCH_ADD_FLOW_FAILURE',
262 [str(exitcode
), str(switch
), str(flow
)])
265 if __name__
== '__main__':
266 XenAPIPlugin
.dispatch({'update': update
,
267 'emergency_reset': emergency_reset
})