]> git.proxmox.com Git - mirror_ovs.git/blame - xenserver/opt_xensource_libexec_interface-reconfigure
stream-ssl: Log protocol details at DBG level.
[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):
064af421 207
0b8870d4 208 if pif_is_vlan(pif):
b3080599 209 pif = pif_get_vlan_slave(pif)
064af421 210
b3080599
IC
211 if pif_is_bond(pif):
212 pifs = pif_get_bond_slaves(pif)
0b8870d4 213 else:
b3080599 214 pifs = [pif]
0b8870d4 215
b3080599
IC
216 for pif in pifs:
217 netdev_remap_name(pif)
0b8870d4
IC
218
219#
220# IP device configuration
221#
064af421 222
0b8870d4
IC
223def ipdev_configure_static_routes(interface, oc, f):
224 """Open a route-<interface> file for static routes.
225
226 Opens the static routes configuration file for interface and writes one
227 line for each route specified in the network's other config "static-routes" value.
228 E.g. if
229 interface ( RO): xenbr1
230 other-config (MRW): static-routes: 172.16.0.0/15/192.168.0.3,172.18.0.0/16/192.168.0.4;...
231
232 Then route-xenbr1 should be
233 172.16.0.0/15 via 192.168.0.3 dev xenbr1
234 172.18.0.0/16 via 192.168.0.4 dev xenbr1
235 """
0b8870d4
IC
236 if oc.has_key('static-routes'):
237 # The key is present - extract comma seperates entries
238 lines = oc['static-routes'].split(',')
239 else:
240 # The key is not present, i.e. there are no static routes
241 lines = []
242
64ddb6fe 243 child = ConfigurationFile("%s/etc/sysconfig/network-scripts/route-%s" % (root_prefix(), interface))
0b8870d4
IC
244 child.write("# DO NOT EDIT: This file (%s) was autogenerated by %s\n" % \
245 (os.path.basename(child.path()), os.path.basename(sys.argv[0])))
246
247 try:
248 for l in lines:
249 network, masklen, gateway = l.split('/')
250 child.write("%s/%s via %s dev %s\n" % (network, masklen, gateway, interface))
251
252 f.attach_child(child)
253 child.close()
254
255 except ValueError, e:
256 log("Error in other-config['static-routes'] format for network %s: %s" % (interface, e))
064af421 257
0b8870d4
IC
258def ipdev_open_ifcfg(pif):
259 ipdev = pif_ipdev_name(pif)
c87d1024 260
0b8870d4
IC
261 log("Writing network configuration for %s" % ipdev)
262
64ddb6fe 263 f = ConfigurationFile("%s/etc/sysconfig/network-scripts/ifcfg-%s" % (root_prefix(), ipdev))
0b8870d4
IC
264
265 f.write("# DO NOT EDIT: This file (%s) was autogenerated by %s\n" % \
266 (os.path.basename(f.path()), os.path.basename(sys.argv[0])))
267 f.write("XEMANAGED=yes\n")
268 f.write("DEVICE=%s\n" % ipdev)
269 f.write("ONBOOT=no\n")
270
271 return f
272
b3080599 273def ipdev_configure_network(pif, dp):
0b8870d4
IC
274 """Write the configuration file for a network.
275
276 Writes configuration derived from the network object into the relevant
277 ifcfg file. The configuration file is passed in, but if the network is
278 bridgeless it will be ifcfg-<interface>, otherwise it will be ifcfg-<bridge>.
279
280 This routine may also write ifcfg files of the networks corresponding to other PIFs
281 in order to maintain consistency.
282
283 params:
284 pif: Opaque_ref of pif
b3080599 285 dp: Datapath object
0b8870d4
IC
286 """
287
b3080599 288 pifrec = db().get_pif_record(pif)
9a2b1175
IC
289 nw = pifrec['network']
290 nwrec = db().get_network_record(nw)
0b8870d4
IC
291
292 ipdev = pif_ipdev_name(pif)
293
294 f = ipdev_open_ifcfg(pif)
295
296 mode = pifrec['ip_configuration_mode']
297 log("Configuring %s using %s configuration" % (ipdev, mode))
298
299 oc = None
300 if pifrec.has_key('other_config'):
301 oc = pifrec['other_config']
302
b3080599
IC
303 dp.configure_ipdev(f)
304
064af421 305 if pifrec['ip_configuration_mode'] == "DHCP":
0b8870d4
IC
306 f.write("BOOTPROTO=dhcp\n")
307 f.write("PERSISTENT_DHCLIENT=yes\n")
064af421 308 elif pifrec['ip_configuration_mode'] == "Static":
0b8870d4
IC
309 f.write("BOOTPROTO=none\n")
310 f.write("NETMASK=%(netmask)s\n" % pifrec)
311 f.write("IPADDR=%(IP)s\n" % pifrec)
312 f.write("GATEWAY=%(gateway)s\n" % pifrec)
064af421 313 elif pifrec['ip_configuration_mode'] == "None":
0b8870d4 314 f.write("BOOTPROTO=none\n")
064af421 315 else:
0b8870d4
IC
316 raise Error("Unknown ip-configuration-mode %s" % pifrec['ip_configuration_mode'])
317
318 if nwrec.has_key('other_config'):
319 settings,offload = ethtool_settings(nwrec['other_config'])
320 if len(settings):
321 f.write("ETHTOOL_OPTS=\"%s\"\n" % str.join(" ", settings))
322 if len(offload):
323 f.write("ETHTOOL_OFFLOAD_OPTS=\"%s\"\n" % str.join(" ", offload))
324
0b8870d4
IC
325 ipdev_configure_static_routes(ipdev, nwrec['other_config'], f)
326
9a2b1175
IC
327 mtu = mtu_setting(nw, "Network", nwrec['other_config'])
328 if mtu:
329 f.write("MTU=%s\n" % mtu)
330
331
0b8870d4
IC
332 if pifrec.has_key('DNS') and pifrec['DNS'] != "":
333 ServerList = pifrec['DNS'].split(",")
334 for i in range(len(ServerList)): f.write("DNS%d=%s\n" % (i+1, ServerList[i]))
335 if oc and oc.has_key('domain'):
336 f.write("DOMAIN='%s'\n" % oc['domain'].replace(',', ' '))
337
b3080599 338 # There can be only one DNSDEV and one GATEWAYDEV in /etc/sysconfig/network.
0b8870d4
IC
339 #
340 # The peerdns pif will be the one with
341 # pif::other-config:peerdns=true, or the mgmt pif if none have
342 # this set.
343 #
344 # The gateway pif will be the one with
345 # pif::other-config:defaultroute=true, or the mgmt pif if none
346 # have this set.
347
b3080599
IC
348 # Work out which pif on this host should be the DNSDEV and which
349 # should be the GATEWAYDEV
0b8870d4 350 #
b3080599 351 # Note: we prune out the bond master pif (if it exists). This is
0b8870d4
IC
352 # because when we are called to bring up an interface with a bond
353 # master, it is implicit that we should bring down that master.
0b8870d4 354
b3080599 355 pifs_on_host = [p for p in db().get_all_pifs() if not p in pif_get_bond_masters(pif)]
0b8870d4
IC
356
357 # loop through all the pifs on this host looking for one with
358 # other-config:peerdns = true, and one with
359 # other-config:default-route=true
b3080599
IC
360 peerdns_pif = None
361 defaultroute_pif = None
0b8870d4 362 for __pif in pifs_on_host:
b3080599 363 __pifrec = db().get_pif_record(__pif)
0b8870d4
IC
364 __oc = __pifrec['other_config']
365 if __oc.has_key('peerdns') and __oc['peerdns'] == 'true':
366 if peerdns_pif == None:
367 peerdns_pif = __pif
368 else:
369 log('Warning: multiple pifs with "peerdns=true" - choosing %s and ignoring %s' % \
b3080599 370 (db().get_pif_record(peerdns_pif)['device'], __pifrec['device']))
0b8870d4
IC
371 if __oc.has_key('defaultroute') and __oc['defaultroute'] == 'true':
372 if defaultroute_pif == None:
373 defaultroute_pif = __pif
374 else:
375 log('Warning: multiple pifs with "defaultroute=true" - choosing %s and ignoring %s' % \
b3080599 376 (db().get_pif_record(defaultroute_pif)['device'], __pifrec['device']))
0b8870d4
IC
377
378 # If no pif is explicitly specified then use the mgmt pif for
379 # peerdns/defaultroute.
380 if peerdns_pif == None:
381 peerdns_pif = management_pif
382 if defaultroute_pif == None:
383 defaultroute_pif = management_pif
384
b3080599
IC
385 is_dnsdev = peerdns_pif == pif
386 is_gatewaydev = defaultroute_pif == pif
387
388 if is_dnsdev or is_gatewaydev:
64ddb6fe 389 fnetwork = ConfigurationFile(root_prefix() + "/etc/sysconfig/network")
b3080599
IC
390 for line in fnetwork.readlines():
391 if is_dnsdev and line.lstrip().startswith('DNSDEV='):
392 fnetwork.write('DNSDEV=%s\n' % ipdev)
393 is_dnsdev = False
394 elif is_gatewaydev and line.lstrip().startswith('GATEWAYDEV='):
395 fnetwork.write('GATEWAYDEV=%s\n' % ipdev)
396 is_gatewaydev = False
397 else:
398 fnetwork.write(line)
064af421 399
b3080599
IC
400 if is_dnsdev:
401 fnetwork.write('DNSDEV=%s\n' % ipdev)
402 if is_gatewaydev:
403 fnetwork.write('GATEWAYDEV=%s\n' % ipdev)
0b8870d4 404
b3080599
IC
405 fnetwork.close()
406 f.attach_child(fnetwork)
064af421 407
b3080599 408 return f
064af421 409
0b8870d4 410#
b3080599 411# Toplevel actions
0b8870d4 412#
064af421 413
b3080599
IC
414def action_up(pif, force):
415 pifrec = db().get_pif_record(pif)
0b8870d4 416
b3080599 417 ipdev = pif_ipdev_name(pif)
823c5699 418 dp = DatapathFactory()(pif)
0b8870d4 419
b3080599 420 log("action_up: %s" % ipdev)
0b8870d4 421
b3080599 422 f = ipdev_configure_network(pif, dp)
0b8870d4 423
b3080599 424 dp.preconfigure(f)
0b8870d4 425
b3080599 426 f.close()
0b8870d4 427
b3080599 428 pif_rename_physical_devices(pif)
0b8870d4 429
b3080599
IC
430 # if we are not forcing the interface up then attempt to tear down
431 # any existing devices which might interfere with brinign this one
432 # up.
433 if not force:
434 ifdown(ipdev)
0b8870d4 435
b3080599 436 dp.bring_down_existing()
0b8870d4 437
064af421
BP
438 try:
439 f.apply()
0b8870d4 440
b3080599 441 dp.configure()
0b8870d4
IC
442
443 ifup(ipdev)
444
b3080599 445 dp.post()
0b8870d4
IC
446
447 # Update /etc/issue (which contains the IP address of the management interface)
64ddb6fe 448 os.system(root_prefix() + "/sbin/update-issue")
0b8870d4 449
064af421
BP
450 f.commit()
451 except Error, e:
0b8870d4 452 log("failed to apply changes: %s" % e.msg)
064af421
BP
453 f.revert()
454 raise
455
0b8870d4 456def action_down(pif):
0b8870d4 457 ipdev = pif_ipdev_name(pif)
823c5699 458 dp = DatapathFactory()(pif)
0b8870d4 459
b3080599 460 log("action_down: %s" % ipdev)
0b8870d4 461
b3080599 462 ifdown(ipdev)
0b8870d4 463
b3080599 464 dp.bring_down()
064af421 465
823c5699
IC
466def action_rewrite():
467 DatapathFactory().rewrite()
468
b3080599
IC
469# This is useful for reconfiguring the mgmt interface after having lost connectivity to the pool master
470def action_force_rewrite(bridge, config):
471 def getUUID():
472 import subprocess
473 uuid,_ = subprocess.Popen(['uuidgen'], stdout = subprocess.PIPE).communicate()
474 return uuid.strip()
064af421 475
b3080599
IC
476 # Notes:
477 # 1. that this assumes the interface is bridged
478 # 2. If --gateway is given it will make that the default gateway for the host
064af421 479
b3080599 480 # extract the configuration
0b8870d4 481 try:
b3080599
IC
482 mode = config['mode']
483 mac = config['mac']
484 interface = config['device']
485 except:
486 raise Usage("Please supply --mode, --mac and --device")
064af421 487
b3080599
IC
488 if mode == 'static':
489 try:
490 netmask = config['netmask']
491 ip = config['ip']
492 except:
493 raise Usage("Please supply --netmask and --ip")
494 try:
495 gateway = config['gateway']
496 except:
497 gateway = None
498 elif mode != 'dhcp':
499 raise Usage("--mode must be either static or dhcp")
064af421 500
b3080599
IC
501 if config.has_key('vlan'):
502 is_vlan = True
503 vlan_slave, vlan_vid = config['vlan'].split('.')
504 else:
505 is_vlan = False
506
507 if is_vlan:
508 raise Error("Force rewrite of VLAN not implemented")
509
510 log("Configuring %s using %s configuration" % (bridge, mode))
511
64ddb6fe 512 f = ConfigurationFile(root_prefix() + dbcache_file)
b3080599
IC
513
514 pif_uuid = getUUID()
515 network_uuid = getUUID()
516
517 f.write('<?xml version="1.0" ?>\n')
518 f.write('<xenserver-network-configuration>\n')
519 f.write('\t<pif ref="OpaqueRef:%s">\n' % pif_uuid)
520 f.write('\t\t<network>OpaqueRef:%s</network>\n' % network_uuid)
521 f.write('\t\t<management>True</management>\n')
522 f.write('\t\t<uuid>%sPif</uuid>\n' % interface)
523 f.write('\t\t<bond_slave_of>OpaqueRef:NULL</bond_slave_of>\n')
524 f.write('\t\t<bond_master_of/>\n')
525 f.write('\t\t<VLAN_slave_of/>\n')
526 f.write('\t\t<VLAN_master_of>OpaqueRef:NULL</VLAN_master_of>\n')
527 f.write('\t\t<VLAN>-1</VLAN>\n')
528 f.write('\t\t<device>%s</device>\n' % interface)
529 f.write('\t\t<MAC>%s</MAC>\n' % mac)
530 f.write('\t\t<other_config/>\n')
531 if mode == 'dhcp':
532 f.write('\t\t<ip_configuration_mode>DHCP</ip_configuration_mode>\n')
533 f.write('\t\t<IP></IP>\n')
534 f.write('\t\t<netmask></netmask>\n')
535 f.write('\t\t<gateway></gateway>\n')
536 f.write('\t\t<DNS></DNS>\n')
537 elif mode == 'static':
538 f.write('\t\t<ip_configuration_mode>Static</ip_configuration_mode>\n')
539 f.write('\t\t<IP>%s</IP>\n' % ip)
540 f.write('\t\t<netmask>%s</netmask>\n' % netmask)
541 if gateway is not None:
542 f.write('\t\t<gateway>%s</gateway>\n' % gateway)
543 f.write('\t\t<DNS></DNS>\n')
544 else:
545 raise Error("Unknown mode %s" % mode)
546 f.write('\t</pif>\n')
547
548 f.write('\t<network ref="OpaqueRef:%s">\n' % network_uuid)
549 f.write('\t\t<uuid>InitialManagementNetwork</uuid>\n')
550 f.write('\t\t<PIFs>\n')
551 f.write('\t\t\t<PIF>OpaqueRef:%s</PIF>\n' % pif_uuid)
552 f.write('\t\t</PIFs>\n')
553 f.write('\t\t<bridge>%s</bridge>\n' % bridge)
554 f.write('\t\t<other_config/>\n')
555 f.write('\t</network>\n')
556 f.write('</xenserver-network-configuration>\n')
064af421 557
064af421 558 f.close()
b3080599 559
064af421
BP
560 try:
561 f.apply()
562 f.commit()
563 except Error, e:
564 log("failed to apply changes: %s" % e.msg)
565 f.revert()
566 raise
567
064af421 568def main(argv=None):
b3080599 569 global management_pif
0b8870d4 570
064af421
BP
571 session = None
572 pif_uuid = None
573 pif = None
574
575 force_interface = None
576 force_management = False
0b8870d4 577
064af421
BP
578 if argv is None:
579 argv = sys.argv
580
581 try:
582 try:
583 shortops = "h"
b3080599 584 longops = [ "pif=", "pif-uuid=",
064af421
BP
585 "session=",
586 "force=",
587 "force-interface=",
588 "management",
b3080599 589 "mac=", "device=", "mode=", "ip=", "netmask=", "gateway=",
64ddb6fe 590 "root-prefix=",
b63fadcf 591 "no-syslog",
064af421
BP
592 "help" ]
593 arglist, args = getopt.gnu_getopt(argv[1:], shortops, longops)
594 except getopt.GetoptError, msg:
595 raise Usage(msg)
596
597 force_rewrite_config = {}
0b8870d4 598
064af421 599 for o,a in arglist:
b3080599 600 if o == "--pif":
064af421
BP
601 pif = a
602 elif o == "--pif-uuid":
603 pif_uuid = a
604 elif o == "--session":
605 session = a
606 elif o == "--force-interface" or o == "--force":
607 force_interface = a
608 elif o == "--management":
609 force_management = True
b3080599 610 elif o in ["--mac", "--device", "--mode", "--ip", "--netmask", "--gateway"]:
064af421 611 force_rewrite_config[o[2:]] = a
64ddb6fe
BP
612 elif o == "--root-prefix":
613 set_root_prefix(a)
b63fadcf
BP
614 elif o == "--no-syslog":
615 set_log_destination("stderr")
064af421
BP
616 elif o == "-h" or o == "--help":
617 print __doc__ % {'command-name': os.path.basename(argv[0])}
618 return 0
619
b63fadcf
BP
620 if get_log_destination() == "syslog":
621 syslog.openlog(os.path.basename(argv[0]))
622 log("Called as " + str.join(" ", argv))
b3080599 623
064af421
BP
624 if len(args) < 1:
625 raise Usage("Required option <action> not present")
626 if len(args) > 1:
627 raise Usage("Too many arguments")
628
629 action = args[0]
fa2bec94
IC
630
631 if not action in ["up", "down", "rewrite", "rewrite-configuration"]:
632 raise Usage("Unknown action \"%s\"" % action)
633
064af421
BP
634 # backwards compatibility
635 if action == "rewrite-configuration": action = "rewrite"
0b8870d4 636
064af421
BP
637 if ( session or pif ) and pif_uuid:
638 raise Usage("--session/--pif and --pif-uuid are mutually exclusive.")
639 if ( session and not pif ) or ( not session and pif ):
640 raise Usage("--session and --pif must be used together.")
641 if force_interface and ( session or pif or pif_uuid ):
642 raise Usage("--force is mutually exclusive with --session, --pif and --pif-uuid")
643 if len(force_rewrite_config) and not (force_interface and action == "rewrite"):
644 raise Usage("\"--force rewrite\" needed for --device, --mode, --ip, --netmask, and --gateway")
b3080599
IC
645 if (action == "rewrite") and (pif or pif_uuid ):
646 raise Usage("rewrite action does not take --pif or --pif-uuid")
647
064af421
BP
648 global db
649 if force_interface:
650 log("Force interface %s %s" % (force_interface, action))
651
652 if action == "rewrite":
653 action_force_rewrite(force_interface, force_rewrite_config)
fa2bec94 654 elif action in ["up", "down"]:
b3080599
IC
655 db_init_from_cache(dbcache_file)
656 pif = db().get_pif_by_bridge(force_interface)
657 management_pif = db().get_management_pif()
064af421
BP
658
659 if action == "up":
b3080599 660 action_up(pif, True)
064af421
BP
661 elif action == "down":
662 action_down(pif)
fa2bec94
IC
663 else:
664 raise Error("Unknown action %s" % action)
064af421 665 else:
b3080599 666 db_init_from_xenapi(session)
064af421
BP
667
668 if pif_uuid:
b3080599 669 pif = db().get_pif_by_uuid(pif_uuid)
064af421 670
b3080599 671 if action == "rewrite":
823c5699 672 action_rewrite()
064af421 673 else:
057fed2b
BP
674 if not pif:
675 raise Usage("No PIF given")
064af421 676
057fed2b 677 if force_management:
0b8870d4 678 # pif is going to be the management pif
057fed2b
BP
679 management_pif = pif
680 else:
681 # pif is not going to be the management pif.
682 # Search DB cache for pif on same host with management=true
b3080599
IC
683 pifrec = db().get_pif_record(pif)
684 management_pif = db().get_management_pif()
064af421 685
057fed2b 686 log_pif_action(action, pif)
064af421 687
057fed2b
BP
688 if not check_allowed(pif):
689 return 0
690
691 if action == "up":
b3080599 692 action_up(pif, False)
057fed2b
BP
693 elif action == "down":
694 action_down(pif)
057fed2b 695 else:
fa2bec94 696 raise Error("Unknown action %s" % action)
064af421
BP
697
698 # Save cache.
b3080599 699 db().save(dbcache_file)
0b8870d4 700
064af421
BP
701 except Usage, err:
702 print >>sys.stderr, err.msg
703 print >>sys.stderr, "For help use --help."
704 return 2
705 except Error, err:
706 log(err.msg)
707 return 1
064af421 708
0b8870d4 709 return 0
064af421 710
064af421
BP
711if __name__ == "__main__":
712 rc = 1
713 try:
714 rc = main()
715 except:
716 ex = sys.exc_info()
717 err = traceback.format_exception(*ex)
718 for exline in err:
719 log(exline)
720
b3080599 721 syslog.closelog()
0b8870d4 722
064af421 723 sys.exit(rc)