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