]> git.proxmox.com Git - mirror_ovs.git/blame - xenserver/opt_xensource_libexec_interface-reconfigure
ofproto-dpif: Revalidate flows after "fdb/flush".
[mirror_ovs.git] / xenserver / opt_xensource_libexec_interface-reconfigure
CommitLineData
064af421
BP
1#!/usr/bin/python
2#
c4b1912e 3# Copyright (c) 2008,2009 Citrix Systems, Inc.
064af421 4#
c4b1912e
IC
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU Lesser General Public License as published
7# by the Free Software Foundation; version 2.1 only. with the special
8# exception on linking described in file LICENSE.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU Lesser General Public License for more details.
14#
064af421
BP
15"""Usage:
16
057fed2b
BP
17 %(command-name)s <PIF> up
18 %(command-name)s <PIF> down
b3080599 19 %(command-name)s rewrite
057fed2b
BP
20 %(command-name)s --force <BRIDGE> up
21 %(command-name)s --force <BRIDGE> down
b3080599 22 %(command-name)s --force <BRIDGE> rewrite --device=<INTERFACE> --mac=<MAC-ADDRESS> <CONFIG>
064af421 23
057fed2b
BP
24 where <PIF> is one of:
25 --session <SESSION-REF> --pif <PIF-REF>
26 --pif-uuid <PIF-UUID>
27 and <CONFIG> is one of:
28 --mode=dhcp
29 --mode=static --ip=<IPADDR> --netmask=<NM> [--gateway=<GW>]
064af421
BP
30
31 Options:
b3080599 32 --session A session reference to use to access the xapi DB
057fed2b
BP
33 --pif A PIF reference within the session.
34 --pif-uuid The UUID of a PIF.
35 --force An interface name.
64ddb6fe 36 --root-prefix=DIR Use DIR as alternate root directory (for testing).
b63fadcf 37 --no-syslog Write log messages to stderr instead of system log.
064af421
BP
38"""
39
064af421
BP
40# Notes:
41# 1. Every pif belongs to exactly one network
42# 2. Every network has zero or one pifs
43# 3. A network may have an associated bridge, allowing vifs to be attached
44# 4. A network may be bridgeless (there's no point having a bridge over a storage pif)
45
b3080599
IC
46from InterfaceReconfigure import *
47
48import os, sys, getopt
064af421
BP
49import syslog
50import traceback
064af421 51import re
2bb451b6 52import random
064af421 53
064af421
BP
54management_pif = None
55
1fa5a105 56dbcache_file = "/var/xapi/network.dbcache"
064af421 57
0b8870d4 58#
b3080599 59# Logging.
0b8870d4
IC
60#
61
0b8870d4 62def log_pif_action(action, pif):
b3080599 63 pifrec = db().get_pif_record(pif)
0b8870d4
IC
64 rec = {}
65 rec['uuid'] = pifrec['uuid']
66 rec['ip_configuration_mode'] = pifrec['ip_configuration_mode']
67 rec['action'] = action
68 rec['pif_netdev_name'] = pif_netdev_name(pif)
69 rec['message'] = "Bring %(action)s PIF %(uuid)s" % rec
70 log("%(message)s: %(pif_netdev_name)s configured as %(ip_configuration_mode)s" % rec)
71
0b8870d4
IC
72#
73# Exceptions.
74#
75
064af421
BP
76class Usage(Exception):
77 def __init__(self, msg):
78 Exception.__init__(self)
79 self.msg = msg
80
0b8870d4
IC
81#
82# Boot from Network filesystem or device.
83#
064af421 84
0b8870d4
IC
85def check_allowed(pif):
86 """Determine whether interface-reconfigure should be manipulating this PIF.
064af421 87
0b8870d4
IC
88 Used to prevent system PIFs (such as network root disk) from being interfered with.
89 """
6dd3fad4 90
b3080599 91 pifrec = db().get_pif_record(pif)
0b8870d4 92 try:
64ddb6fe 93 f = open(root_prefix() + "/proc/ardence")
0b8870d4
IC
94 macline = filter(lambda x: x.startswith("HWaddr:"), f.readlines())
95 f.close()
96 if len(macline) == 1:
97 p = re.compile(".*\s%(MAC)s\s.*" % pifrec, re.IGNORECASE)
98 if p.match(macline[0]):
99 log("Skipping PVS device %(device)s (%(MAC)s)" % pifrec)
100 return False
101 except IOError:
102 pass
103 return True
064af421 104
0b8870d4
IC
105#
106# Bare Network Devices -- network devices without IP configuration
107#
064af421 108
0b8870d4
IC
109def netdev_remap_name(pif, already_renamed=[]):
110 """Check whether 'pif' exists and has the correct MAC.
111 If not, try to find a device with the correct MAC and rename it.
112 'already_renamed' is used to avoid infinite recursion.
113 """
b3080599 114
0b8870d4
IC
115 def read1(name):
116 file = None
117 try:
118 file = open(name, 'r')
119 return file.readline().rstrip('\n')
120 finally:
121 if file != None:
122 file.close()
064af421 123
0b8870d4
IC
124 def get_netdev_mac(device):
125 try:
64ddb6fe 126 return read1("%s/sys/class/net/%s/address" % (root_prefix(), device))
0b8870d4
IC
127 except:
128 # Probably no such device.
129 return None
064af421 130
0b8870d4
IC
131 def get_netdev_tx_queue_len(device):
132 try:
64ddb6fe 133 return int(read1("%s/sys/class/net/%s/tx_queue_len" % (root_prefix(), device)))
0b8870d4
IC
134 except:
135 # Probably no such device.
136 return None
064af421 137
0b8870d4 138 def get_netdev_by_mac(mac):
64ddb6fe 139 for device in os.listdir(root_prefix() + "/sys/class/net"):
0b8870d4
IC
140 dev_mac = get_netdev_mac(device)
141 if (dev_mac and mac.lower() == dev_mac.lower() and
142 get_netdev_tx_queue_len(device)):
143 return device
144 return None
064af421 145
0b8870d4
IC
146 def rename_netdev(old_name, new_name):
147 log("Changing the name of %s to %s" % (old_name, new_name))
148 run_command(['/sbin/ifconfig', old_name, 'down'])
149 if not run_command(['/sbin/ip', 'link', 'set', old_name, 'name', new_name]):
150 raise Error("Could not rename %s to %s" % (old_name, new_name))
064af421 151
b3080599 152 pifrec = db().get_pif_record(pif)
2bb451b6
BP
153 device = pifrec['device']
154 mac = pifrec['MAC']
155
156 # Is there a network device named 'device' at all?
0b8870d4 157 device_exists = netdev_exists(device)
2bb451b6
BP
158 if device_exists:
159 # Yes. Does it have MAC 'mac'?
160 found_mac = get_netdev_mac(device)
161 if found_mac and mac.lower() == found_mac.lower():
162 # Yes, everything checks out the way we want. Nothing to do.
163 return
164 else:
165 log("No network device %s" % device)
166
167 # What device has MAC 'mac'?
168 cur_device = get_netdev_by_mac(mac)
169 if not cur_device:
170 log("No network device has MAC %s" % mac)
171 return
172
173 # First rename 'device', if it exists, to get it out of the way
174 # for 'cur_device' to replace it.
175 if device_exists:
176 rename_netdev(device, "dev%d" % random.getrandbits(24))
177
178 # Rename 'cur_device' to 'device'.
179 rename_netdev(cur_device, device)
180
0b8870d4
IC
181#
182# IP Network Devices -- network devices with IP configuration
183#
064af421 184
0b8870d4
IC
185def ifdown(netdev):
186 """Bring down a network interface"""
0b8870d4
IC
187 if not netdev_exists(netdev):
188 log("ifdown: device %s does not exist, ignoring" % netdev)
189 return
64ddb6fe 190 if not os.path.exists("%s/etc/sysconfig/network-scripts/ifcfg-%s" % (root_prefix(), netdev)):
b3080599
IC
191 log("ifdown: device %s exists but ifcfg-%s does not" % (netdev,netdev))
192 run_command(["/sbin/ifconfig", netdev, 'down'])
193 return
0b8870d4 194 run_command(["/sbin/ifdown", netdev])
064af421 195
0b8870d4
IC
196def ifup(netdev):
197 """Bring up a network interface"""
64ddb6fe 198 if not os.path.exists(root_prefix() + "/etc/sysconfig/network-scripts/ifcfg-%s" % netdev):
0b8870d4
IC
199 raise Error("ifup: device %s exists but ifcfg-%s does not" % (netdev,netdev))
200 run_command(["/sbin/ifup", netdev])
201
202#
b3080599 203#
0b8870d4 204#
064af421 205
b3080599 206def pif_rename_physical_devices(pif):
92e906e4
IC
207 if pif_is_tunnel(pif):
208 return
064af421 209
0b8870d4 210 if pif_is_vlan(pif):
b3080599 211 pif = pif_get_vlan_slave(pif)
064af421 212
b3080599
IC
213 if pif_is_bond(pif):
214 pifs = pif_get_bond_slaves(pif)
0b8870d4 215 else:
b3080599 216 pifs = [pif]
0b8870d4 217
b3080599
IC
218 for pif in pifs:
219 netdev_remap_name(pif)
0b8870d4
IC
220
221#
222# IP device configuration
223#
064af421 224
0b8870d4
IC
225def ipdev_configure_static_routes(interface, oc, f):
226 """Open a route-<interface> file for static routes.
227
228 Opens the static routes configuration file for interface and writes one
229 line for each route specified in the network's other config "static-routes" value.
230 E.g. if
231 interface ( RO): xenbr1
232 other-config (MRW): static-routes: 172.16.0.0/15/192.168.0.3,172.18.0.0/16/192.168.0.4;...
233
234 Then route-xenbr1 should be
235 172.16.0.0/15 via 192.168.0.3 dev xenbr1
236 172.18.0.0/16 via 192.168.0.4 dev xenbr1
237 """
0b8870d4
IC
238 if oc.has_key('static-routes'):
239 # The key is present - extract comma seperates entries
240 lines = oc['static-routes'].split(',')
241 else:
242 # The key is not present, i.e. there are no static routes
243 lines = []
244
64ddb6fe 245 child = ConfigurationFile("%s/etc/sysconfig/network-scripts/route-%s" % (root_prefix(), interface))
0b8870d4
IC
246 child.write("# DO NOT EDIT: This file (%s) was autogenerated by %s\n" % \
247 (os.path.basename(child.path()), os.path.basename(sys.argv[0])))
248
249 try:
250 for l in lines:
251 network, masklen, gateway = l.split('/')
252 child.write("%s/%s via %s dev %s\n" % (network, masklen, gateway, interface))
253
254 f.attach_child(child)
255 child.close()
256
257 except ValueError, e:
258 log("Error in other-config['static-routes'] format for network %s: %s" % (interface, e))
064af421 259
0b8870d4
IC
260def ipdev_open_ifcfg(pif):
261 ipdev = pif_ipdev_name(pif)
c87d1024 262
0b8870d4
IC
263 log("Writing network configuration for %s" % ipdev)
264
64ddb6fe 265 f = ConfigurationFile("%s/etc/sysconfig/network-scripts/ifcfg-%s" % (root_prefix(), ipdev))
0b8870d4
IC
266
267 f.write("# DO NOT EDIT: This file (%s) was autogenerated by %s\n" % \
268 (os.path.basename(f.path()), os.path.basename(sys.argv[0])))
269 f.write("XEMANAGED=yes\n")
270 f.write("DEVICE=%s\n" % ipdev)
271 f.write("ONBOOT=no\n")
272
273 return f
274
b3080599 275def ipdev_configure_network(pif, dp):
0b8870d4
IC
276 """Write the configuration file for a network.
277
278 Writes configuration derived from the network object into the relevant
279 ifcfg file. The configuration file is passed in, but if the network is
280 bridgeless it will be ifcfg-<interface>, otherwise it will be ifcfg-<bridge>.
281
282 This routine may also write ifcfg files of the networks corresponding to other PIFs
283 in order to maintain consistency.
284
285 params:
286 pif: Opaque_ref of pif
b3080599 287 dp: Datapath object
0b8870d4
IC
288 """
289
b3080599 290 pifrec = db().get_pif_record(pif)
9a2b1175
IC
291 nw = pifrec['network']
292 nwrec = db().get_network_record(nw)
0b8870d4
IC
293
294 ipdev = pif_ipdev_name(pif)
295
296 f = ipdev_open_ifcfg(pif)
297
298 mode = pifrec['ip_configuration_mode']
299 log("Configuring %s using %s configuration" % (ipdev, mode))
300
301 oc = None
302 if pifrec.has_key('other_config'):
303 oc = pifrec['other_config']
304
b3080599
IC
305 dp.configure_ipdev(f)
306
064af421 307 if pifrec['ip_configuration_mode'] == "DHCP":
0b8870d4
IC
308 f.write("BOOTPROTO=dhcp\n")
309 f.write("PERSISTENT_DHCLIENT=yes\n")
064af421 310 elif pifrec['ip_configuration_mode'] == "Static":
0b8870d4
IC
311 f.write("BOOTPROTO=none\n")
312 f.write("NETMASK=%(netmask)s\n" % pifrec)
313 f.write("IPADDR=%(IP)s\n" % pifrec)
314 f.write("GATEWAY=%(gateway)s\n" % pifrec)
064af421 315 elif pifrec['ip_configuration_mode'] == "None":
0b8870d4 316 f.write("BOOTPROTO=none\n")
064af421 317 else:
0b8870d4
IC
318 raise Error("Unknown ip-configuration-mode %s" % pifrec['ip_configuration_mode'])
319
320 if nwrec.has_key('other_config'):
321 settings,offload = ethtool_settings(nwrec['other_config'])
322 if len(settings):
323 f.write("ETHTOOL_OPTS=\"%s\"\n" % str.join(" ", settings))
324 if len(offload):
325 f.write("ETHTOOL_OFFLOAD_OPTS=\"%s\"\n" % str.join(" ", offload))
326
0b8870d4
IC
327 ipdev_configure_static_routes(ipdev, nwrec['other_config'], f)
328
9a2b1175
IC
329 mtu = mtu_setting(nw, "Network", nwrec['other_config'])
330 if mtu:
331 f.write("MTU=%s\n" % mtu)
332
333
0b8870d4
IC
334 if pifrec.has_key('DNS') and pifrec['DNS'] != "":
335 ServerList = pifrec['DNS'].split(",")
336 for i in range(len(ServerList)): f.write("DNS%d=%s\n" % (i+1, ServerList[i]))
337 if oc and oc.has_key('domain'):
338 f.write("DOMAIN='%s'\n" % oc['domain'].replace(',', ' '))
339
b3080599 340 # There can be only one DNSDEV and one GATEWAYDEV in /etc/sysconfig/network.
0b8870d4
IC
341 #
342 # The peerdns pif will be the one with
343 # pif::other-config:peerdns=true, or the mgmt pif if none have
344 # this set.
345 #
346 # The gateway pif will be the one with
347 # pif::other-config:defaultroute=true, or the mgmt pif if none
348 # have this set.
349
b3080599
IC
350 # Work out which pif on this host should be the DNSDEV and which
351 # should be the GATEWAYDEV
0b8870d4 352 #
b3080599 353 # Note: we prune out the bond master pif (if it exists). This is
0b8870d4
IC
354 # because when we are called to bring up an interface with a bond
355 # master, it is implicit that we should bring down that master.
0b8870d4 356
b3080599 357 pifs_on_host = [p for p in db().get_all_pifs() if not p in pif_get_bond_masters(pif)]
0b8870d4
IC
358
359 # loop through all the pifs on this host looking for one with
360 # other-config:peerdns = true, and one with
361 # other-config:default-route=true
b3080599
IC
362 peerdns_pif = None
363 defaultroute_pif = None
0b8870d4 364 for __pif in pifs_on_host:
b3080599 365 __pifrec = db().get_pif_record(__pif)
0b8870d4
IC
366 __oc = __pifrec['other_config']
367 if __oc.has_key('peerdns') and __oc['peerdns'] == 'true':
368 if peerdns_pif == None:
369 peerdns_pif = __pif
370 else:
371 log('Warning: multiple pifs with "peerdns=true" - choosing %s and ignoring %s' % \
b3080599 372 (db().get_pif_record(peerdns_pif)['device'], __pifrec['device']))
0b8870d4
IC
373 if __oc.has_key('defaultroute') and __oc['defaultroute'] == 'true':
374 if defaultroute_pif == None:
375 defaultroute_pif = __pif
376 else:
377 log('Warning: multiple pifs with "defaultroute=true" - choosing %s and ignoring %s' % \
b3080599 378 (db().get_pif_record(defaultroute_pif)['device'], __pifrec['device']))
0b8870d4
IC
379
380 # If no pif is explicitly specified then use the mgmt pif for
381 # peerdns/defaultroute.
382 if peerdns_pif == None:
383 peerdns_pif = management_pif
384 if defaultroute_pif == None:
385 defaultroute_pif = management_pif
386
b3080599
IC
387 is_dnsdev = peerdns_pif == pif
388 is_gatewaydev = defaultroute_pif == pif
389
390 if is_dnsdev or is_gatewaydev:
64ddb6fe 391 fnetwork = ConfigurationFile(root_prefix() + "/etc/sysconfig/network")
b3080599
IC
392 for line in fnetwork.readlines():
393 if is_dnsdev and line.lstrip().startswith('DNSDEV='):
394 fnetwork.write('DNSDEV=%s\n' % ipdev)
395 is_dnsdev = False
396 elif is_gatewaydev and line.lstrip().startswith('GATEWAYDEV='):
397 fnetwork.write('GATEWAYDEV=%s\n' % ipdev)
398 is_gatewaydev = False
399 else:
400 fnetwork.write(line)
064af421 401
b3080599
IC
402 if is_dnsdev:
403 fnetwork.write('DNSDEV=%s\n' % ipdev)
404 if is_gatewaydev:
405 fnetwork.write('GATEWAYDEV=%s\n' % ipdev)
0b8870d4 406
b3080599
IC
407 fnetwork.close()
408 f.attach_child(fnetwork)
064af421 409
b3080599 410 return f
064af421 411
0b8870d4 412#
b3080599 413# Toplevel actions
0b8870d4 414#
064af421 415
b3080599
IC
416def action_up(pif, force):
417 pifrec = db().get_pif_record(pif)
0b8870d4 418
b3080599 419 ipdev = pif_ipdev_name(pif)
823c5699 420 dp = DatapathFactory()(pif)
0b8870d4 421
b3080599 422 log("action_up: %s" % ipdev)
0b8870d4 423
b3080599 424 f = ipdev_configure_network(pif, dp)
0b8870d4 425
b3080599 426 dp.preconfigure(f)
0b8870d4 427
b3080599 428 f.close()
0b8870d4 429
b3080599 430 pif_rename_physical_devices(pif)
0b8870d4 431
b3080599
IC
432 # if we are not forcing the interface up then attempt to tear down
433 # any existing devices which might interfere with brinign this one
434 # up.
435 if not force:
436 ifdown(ipdev)
0b8870d4 437
b3080599 438 dp.bring_down_existing()
0b8870d4 439
064af421
BP
440 try:
441 f.apply()
0b8870d4 442
b3080599 443 dp.configure()
0b8870d4
IC
444
445 ifup(ipdev)
446
b3080599 447 dp.post()
0b8870d4
IC
448
449 # Update /etc/issue (which contains the IP address of the management interface)
64ddb6fe 450 os.system(root_prefix() + "/sbin/update-issue")
0b8870d4 451
064af421
BP
452 f.commit()
453 except Error, e:
0b8870d4 454 log("failed to apply changes: %s" % e.msg)
064af421
BP
455 f.revert()
456 raise
457
0b8870d4 458def action_down(pif):
0b8870d4 459 ipdev = pif_ipdev_name(pif)
823c5699 460 dp = DatapathFactory()(pif)
0b8870d4 461
b3080599 462 log("action_down: %s" % ipdev)
0b8870d4 463
b3080599 464 ifdown(ipdev)
0b8870d4 465
b3080599 466 dp.bring_down()
064af421 467
823c5699
IC
468def action_rewrite():
469 DatapathFactory().rewrite()
470
b3080599
IC
471# This is useful for reconfiguring the mgmt interface after having lost connectivity to the pool master
472def action_force_rewrite(bridge, config):
473 def getUUID():
474 import subprocess
475 uuid,_ = subprocess.Popen(['uuidgen'], stdout = subprocess.PIPE).communicate()
476 return uuid.strip()
064af421 477
b3080599
IC
478 # Notes:
479 # 1. that this assumes the interface is bridged
480 # 2. If --gateway is given it will make that the default gateway for the host
064af421 481
b3080599 482 # extract the configuration
0b8870d4 483 try:
b3080599
IC
484 mode = config['mode']
485 mac = config['mac']
486 interface = config['device']
487 except:
488 raise Usage("Please supply --mode, --mac and --device")
064af421 489
b3080599
IC
490 if mode == 'static':
491 try:
492 netmask = config['netmask']
493 ip = config['ip']
494 except:
495 raise Usage("Please supply --netmask and --ip")
496 try:
497 gateway = config['gateway']
498 except:
499 gateway = None
500 elif mode != 'dhcp':
501 raise Usage("--mode must be either static or dhcp")
064af421 502
b3080599
IC
503 if config.has_key('vlan'):
504 is_vlan = True
505 vlan_slave, vlan_vid = config['vlan'].split('.')
506 else:
507 is_vlan = False
508
509 if is_vlan:
510 raise Error("Force rewrite of VLAN not implemented")
511
512 log("Configuring %s using %s configuration" % (bridge, mode))
513
64ddb6fe 514 f = ConfigurationFile(root_prefix() + dbcache_file)
b3080599
IC
515
516 pif_uuid = getUUID()
517 network_uuid = getUUID()
518
519 f.write('<?xml version="1.0" ?>\n')
520 f.write('<xenserver-network-configuration>\n')
521 f.write('\t<pif ref="OpaqueRef:%s">\n' % pif_uuid)
522 f.write('\t\t<network>OpaqueRef:%s</network>\n' % network_uuid)
523 f.write('\t\t<management>True</management>\n')
524 f.write('\t\t<uuid>%sPif</uuid>\n' % interface)
525 f.write('\t\t<bond_slave_of>OpaqueRef:NULL</bond_slave_of>\n')
526 f.write('\t\t<bond_master_of/>\n')
527 f.write('\t\t<VLAN_slave_of/>\n')
528 f.write('\t\t<VLAN_master_of>OpaqueRef:NULL</VLAN_master_of>\n')
529 f.write('\t\t<VLAN>-1</VLAN>\n')
404c1692
AE
530 f.write('\t\t<tunnel_access_PIF_of/>\n')
531 f.write('\t\t<tunnel_transport_PIF_of/>\n')
b3080599
IC
532 f.write('\t\t<device>%s</device>\n' % interface)
533 f.write('\t\t<MAC>%s</MAC>\n' % mac)
534 f.write('\t\t<other_config/>\n')
535 if mode == 'dhcp':
536 f.write('\t\t<ip_configuration_mode>DHCP</ip_configuration_mode>\n')
537 f.write('\t\t<IP></IP>\n')
538 f.write('\t\t<netmask></netmask>\n')
539 f.write('\t\t<gateway></gateway>\n')
540 f.write('\t\t<DNS></DNS>\n')
541 elif mode == 'static':
542 f.write('\t\t<ip_configuration_mode>Static</ip_configuration_mode>\n')
543 f.write('\t\t<IP>%s</IP>\n' % ip)
544 f.write('\t\t<netmask>%s</netmask>\n' % netmask)
545 if gateway is not None:
546 f.write('\t\t<gateway>%s</gateway>\n' % gateway)
547 f.write('\t\t<DNS></DNS>\n')
548 else:
549 raise Error("Unknown mode %s" % mode)
550 f.write('\t</pif>\n')
551
552 f.write('\t<network ref="OpaqueRef:%s">\n' % network_uuid)
553 f.write('\t\t<uuid>InitialManagementNetwork</uuid>\n')
554 f.write('\t\t<PIFs>\n')
555 f.write('\t\t\t<PIF>OpaqueRef:%s</PIF>\n' % pif_uuid)
556 f.write('\t\t</PIFs>\n')
557 f.write('\t\t<bridge>%s</bridge>\n' % bridge)
558 f.write('\t\t<other_config/>\n')
559 f.write('\t</network>\n')
560 f.write('</xenserver-network-configuration>\n')
064af421 561
064af421 562 f.close()
b3080599 563
064af421
BP
564 try:
565 f.apply()
566 f.commit()
567 except Error, e:
568 log("failed to apply changes: %s" % e.msg)
569 f.revert()
570 raise
571
064af421 572def main(argv=None):
b3080599 573 global management_pif
0b8870d4 574
064af421
BP
575 session = None
576 pif_uuid = None
577 pif = None
578
579 force_interface = None
580 force_management = False
0b8870d4 581
064af421
BP
582 if argv is None:
583 argv = sys.argv
584
585 try:
586 try:
587 shortops = "h"
b3080599 588 longops = [ "pif=", "pif-uuid=",
064af421
BP
589 "session=",
590 "force=",
591 "force-interface=",
592 "management",
b3080599 593 "mac=", "device=", "mode=", "ip=", "netmask=", "gateway=",
64ddb6fe 594 "root-prefix=",
b63fadcf 595 "no-syslog",
064af421
BP
596 "help" ]
597 arglist, args = getopt.gnu_getopt(argv[1:], shortops, longops)
598 except getopt.GetoptError, msg:
599 raise Usage(msg)
600
601 force_rewrite_config = {}
0b8870d4 602
064af421 603 for o,a in arglist:
b3080599 604 if o == "--pif":
064af421
BP
605 pif = a
606 elif o == "--pif-uuid":
607 pif_uuid = a
608 elif o == "--session":
609 session = a
610 elif o == "--force-interface" or o == "--force":
611 force_interface = a
612 elif o == "--management":
613 force_management = True
b3080599 614 elif o in ["--mac", "--device", "--mode", "--ip", "--netmask", "--gateway"]:
064af421 615 force_rewrite_config[o[2:]] = a
64ddb6fe
BP
616 elif o == "--root-prefix":
617 set_root_prefix(a)
b63fadcf
BP
618 elif o == "--no-syslog":
619 set_log_destination("stderr")
064af421
BP
620 elif o == "-h" or o == "--help":
621 print __doc__ % {'command-name': os.path.basename(argv[0])}
622 return 0
623
b63fadcf
BP
624 if get_log_destination() == "syslog":
625 syslog.openlog(os.path.basename(argv[0]))
626 log("Called as " + str.join(" ", argv))
b3080599 627
064af421
BP
628 if len(args) < 1:
629 raise Usage("Required option <action> not present")
630 if len(args) > 1:
631 raise Usage("Too many arguments")
632
633 action = args[0]
fa2bec94
IC
634
635 if not action in ["up", "down", "rewrite", "rewrite-configuration"]:
636 raise Usage("Unknown action \"%s\"" % action)
637
064af421
BP
638 # backwards compatibility
639 if action == "rewrite-configuration": action = "rewrite"
0b8870d4 640
064af421
BP
641 if ( session or pif ) and pif_uuid:
642 raise Usage("--session/--pif and --pif-uuid are mutually exclusive.")
643 if ( session and not pif ) or ( not session and pif ):
644 raise Usage("--session and --pif must be used together.")
645 if force_interface and ( session or pif or pif_uuid ):
646 raise Usage("--force is mutually exclusive with --session, --pif and --pif-uuid")
647 if len(force_rewrite_config) and not (force_interface and action == "rewrite"):
648 raise Usage("\"--force rewrite\" needed for --device, --mode, --ip, --netmask, and --gateway")
b3080599
IC
649 if (action == "rewrite") and (pif or pif_uuid ):
650 raise Usage("rewrite action does not take --pif or --pif-uuid")
651
064af421
BP
652 global db
653 if force_interface:
654 log("Force interface %s %s" % (force_interface, action))
655
656 if action == "rewrite":
657 action_force_rewrite(force_interface, force_rewrite_config)
fa2bec94 658 elif action in ["up", "down"]:
b3080599
IC
659 db_init_from_cache(dbcache_file)
660 pif = db().get_pif_by_bridge(force_interface)
661 management_pif = db().get_management_pif()
064af421
BP
662
663 if action == "up":
b3080599 664 action_up(pif, True)
064af421
BP
665 elif action == "down":
666 action_down(pif)
fa2bec94
IC
667 else:
668 raise Error("Unknown action %s" % action)
064af421 669 else:
b3080599 670 db_init_from_xenapi(session)
064af421
BP
671
672 if pif_uuid:
b3080599 673 pif = db().get_pif_by_uuid(pif_uuid)
064af421 674
b3080599 675 if action == "rewrite":
823c5699 676 action_rewrite()
064af421 677 else:
057fed2b
BP
678 if not pif:
679 raise Usage("No PIF given")
064af421 680
057fed2b 681 if force_management:
0b8870d4 682 # pif is going to be the management pif
057fed2b
BP
683 management_pif = pif
684 else:
685 # pif is not going to be the management pif.
686 # Search DB cache for pif on same host with management=true
b3080599
IC
687 pifrec = db().get_pif_record(pif)
688 management_pif = db().get_management_pif()
064af421 689
057fed2b 690 log_pif_action(action, pif)
064af421 691
057fed2b
BP
692 if not check_allowed(pif):
693 return 0
694
695 if action == "up":
b3080599 696 action_up(pif, False)
057fed2b
BP
697 elif action == "down":
698 action_down(pif)
057fed2b 699 else:
fa2bec94 700 raise Error("Unknown action %s" % action)
064af421
BP
701
702 # Save cache.
b3080599 703 db().save(dbcache_file)
0b8870d4 704
064af421
BP
705 except Usage, err:
706 print >>sys.stderr, err.msg
707 print >>sys.stderr, "For help use --help."
708 return 2
709 except Error, err:
710 log(err.msg)
711 return 1
064af421 712
0b8870d4 713 return 0
064af421 714
064af421
BP
715if __name__ == "__main__":
716 rc = 1
717 try:
718 rc = main()
719 except:
720 ex = sys.exc_info()
721 err = traceback.format_exception(*ex)
722 for exline in err:
723 log(exline)
724
b3080599 725 syslog.closelog()
0b8870d4 726
064af421 727 sys.exit(rc)