mirror of
https://github.com/openvswitch/ovs
synced 2025-10-15 14:17:18 +00:00
Only the vswitch backend is able to implement CHIN. Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
726 lines
23 KiB
Python
Executable File
726 lines
23 KiB
Python
Executable File
#!/usr/bin/python
|
|
#
|
|
# Copyright (c) 2008,2009 Citrix Systems, Inc.
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU Lesser General Public License as published
|
|
# by the Free Software Foundation; version 2.1 only. with the special
|
|
# exception on linking described in file LICENSE.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Lesser General Public License for more details.
|
|
#
|
|
"""Usage:
|
|
|
|
%(command-name)s <PIF> up
|
|
%(command-name)s <PIF> down
|
|
%(command-name)s rewrite
|
|
%(command-name)s --force <BRIDGE> up
|
|
%(command-name)s --force <BRIDGE> down
|
|
%(command-name)s --force <BRIDGE> rewrite --device=<INTERFACE> --mac=<MAC-ADDRESS> <CONFIG>
|
|
|
|
where <PIF> is one of:
|
|
--session <SESSION-REF> --pif <PIF-REF>
|
|
--pif-uuid <PIF-UUID>
|
|
and <CONFIG> is one of:
|
|
--mode=dhcp
|
|
--mode=static --ip=<IPADDR> --netmask=<NM> [--gateway=<GW>]
|
|
|
|
Options:
|
|
--session A session reference to use to access the xapi DB
|
|
--pif A PIF reference within the session.
|
|
--pif-uuid The UUID of a PIF.
|
|
--force An interface name.
|
|
--root-prefix=DIR Use DIR as alternate root directory (for testing).
|
|
--no-syslog Write log messages to stderr instead of system log.
|
|
"""
|
|
|
|
# Notes:
|
|
# 1. Every pif belongs to exactly one network
|
|
# 2. Every network has zero or one pifs
|
|
# 3. A network may have an associated bridge, allowing vifs to be attached
|
|
# 4. A network may be bridgeless (there's no point having a bridge over a storage pif)
|
|
|
|
from InterfaceReconfigure import *
|
|
|
|
import os, sys, getopt
|
|
import syslog
|
|
import traceback
|
|
import re
|
|
import random
|
|
|
|
management_pif = None
|
|
|
|
dbcache_file = "/var/xapi/network.dbcache"
|
|
|
|
#
|
|
# Logging.
|
|
#
|
|
|
|
def log_pif_action(action, pif):
|
|
pifrec = db().get_pif_record(pif)
|
|
rec = {}
|
|
rec['uuid'] = pifrec['uuid']
|
|
rec['ip_configuration_mode'] = pifrec['ip_configuration_mode']
|
|
rec['action'] = action
|
|
rec['pif_netdev_name'] = pif_netdev_name(pif)
|
|
rec['message'] = "Bring %(action)s PIF %(uuid)s" % rec
|
|
log("%(message)s: %(pif_netdev_name)s configured as %(ip_configuration_mode)s" % rec)
|
|
|
|
#
|
|
# Exceptions.
|
|
#
|
|
|
|
class Usage(Exception):
|
|
def __init__(self, msg):
|
|
Exception.__init__(self)
|
|
self.msg = msg
|
|
|
|
#
|
|
# Boot from Network filesystem or device.
|
|
#
|
|
|
|
def check_allowed(pif):
|
|
"""Determine whether interface-reconfigure should be manipulating this PIF.
|
|
|
|
Used to prevent system PIFs (such as network root disk) from being interfered with.
|
|
"""
|
|
|
|
pifrec = db().get_pif_record(pif)
|
|
try:
|
|
f = open(root_prefix() + "/proc/ardence")
|
|
macline = filter(lambda x: x.startswith("HWaddr:"), f.readlines())
|
|
f.close()
|
|
if len(macline) == 1:
|
|
p = re.compile(".*\s%(MAC)s\s.*" % pifrec, re.IGNORECASE)
|
|
if p.match(macline[0]):
|
|
log("Skipping PVS device %(device)s (%(MAC)s)" % pifrec)
|
|
return False
|
|
except IOError:
|
|
pass
|
|
return True
|
|
|
|
#
|
|
# Bare Network Devices -- network devices without IP configuration
|
|
#
|
|
|
|
def netdev_remap_name(pif, already_renamed=[]):
|
|
"""Check whether 'pif' exists and has the correct MAC.
|
|
If not, try to find a device with the correct MAC and rename it.
|
|
'already_renamed' is used to avoid infinite recursion.
|
|
"""
|
|
|
|
def read1(name):
|
|
file = None
|
|
try:
|
|
file = open(name, 'r')
|
|
return file.readline().rstrip('\n')
|
|
finally:
|
|
if file != None:
|
|
file.close()
|
|
|
|
def get_netdev_mac(device):
|
|
try:
|
|
return read1("%s/sys/class/net/%s/address" % (root_prefix(), device))
|
|
except:
|
|
# Probably no such device.
|
|
return None
|
|
|
|
def get_netdev_tx_queue_len(device):
|
|
try:
|
|
return int(read1("%s/sys/class/net/%s/tx_queue_len" % (root_prefix(), device)))
|
|
except:
|
|
# Probably no such device.
|
|
return None
|
|
|
|
def get_netdev_by_mac(mac):
|
|
for device in os.listdir(root_prefix() + "/sys/class/net"):
|
|
dev_mac = get_netdev_mac(device)
|
|
if (dev_mac and mac.lower() == dev_mac.lower() and
|
|
get_netdev_tx_queue_len(device)):
|
|
return device
|
|
return None
|
|
|
|
def rename_netdev(old_name, new_name):
|
|
log("Changing the name of %s to %s" % (old_name, new_name))
|
|
run_command(['/sbin/ifconfig', old_name, 'down'])
|
|
if not run_command(['/sbin/ip', 'link', 'set', old_name, 'name', new_name]):
|
|
raise Error("Could not rename %s to %s" % (old_name, new_name))
|
|
|
|
pifrec = db().get_pif_record(pif)
|
|
device = pifrec['device']
|
|
mac = pifrec['MAC']
|
|
|
|
# Is there a network device named 'device' at all?
|
|
device_exists = netdev_exists(device)
|
|
if device_exists:
|
|
# Yes. Does it have MAC 'mac'?
|
|
found_mac = get_netdev_mac(device)
|
|
if found_mac and mac.lower() == found_mac.lower():
|
|
# Yes, everything checks out the way we want. Nothing to do.
|
|
return
|
|
else:
|
|
log("No network device %s" % device)
|
|
|
|
# What device has MAC 'mac'?
|
|
cur_device = get_netdev_by_mac(mac)
|
|
if not cur_device:
|
|
log("No network device has MAC %s" % mac)
|
|
return
|
|
|
|
# First rename 'device', if it exists, to get it out of the way
|
|
# for 'cur_device' to replace it.
|
|
if device_exists:
|
|
rename_netdev(device, "dev%d" % random.getrandbits(24))
|
|
|
|
# Rename 'cur_device' to 'device'.
|
|
rename_netdev(cur_device, device)
|
|
|
|
#
|
|
# IP Network Devices -- network devices with IP configuration
|
|
#
|
|
|
|
def ifdown(netdev):
|
|
"""Bring down a network interface"""
|
|
if not netdev_exists(netdev):
|
|
log("ifdown: device %s does not exist, ignoring" % netdev)
|
|
return
|
|
if not os.path.exists("%s/etc/sysconfig/network-scripts/ifcfg-%s" % (root_prefix(), netdev)):
|
|
log("ifdown: device %s exists but ifcfg-%s does not" % (netdev,netdev))
|
|
run_command(["/sbin/ifconfig", netdev, 'down'])
|
|
return
|
|
run_command(["/sbin/ifdown", netdev])
|
|
|
|
def ifup(netdev):
|
|
"""Bring up a network interface"""
|
|
if not os.path.exists(root_prefix() + "/etc/sysconfig/network-scripts/ifcfg-%s" % netdev):
|
|
raise Error("ifup: device %s exists but ifcfg-%s does not" % (netdev,netdev))
|
|
run_command(["/sbin/ifup", netdev])
|
|
|
|
#
|
|
#
|
|
#
|
|
|
|
def pif_rename_physical_devices(pif):
|
|
if pif_is_tunnel(pif):
|
|
return
|
|
|
|
if pif_is_vlan(pif):
|
|
pif = pif_get_vlan_slave(pif)
|
|
|
|
if pif_is_bond(pif):
|
|
pifs = pif_get_bond_slaves(pif)
|
|
else:
|
|
pifs = [pif]
|
|
|
|
for pif in pifs:
|
|
netdev_remap_name(pif)
|
|
|
|
#
|
|
# IP device configuration
|
|
#
|
|
|
|
def ipdev_configure_static_routes(interface, oc, f):
|
|
"""Open a route-<interface> file for static routes.
|
|
|
|
Opens the static routes configuration file for interface and writes one
|
|
line for each route specified in the network's other config "static-routes" value.
|
|
E.g. if
|
|
interface ( RO): xenbr1
|
|
other-config (MRW): static-routes: 172.16.0.0/15/192.168.0.3,172.18.0.0/16/192.168.0.4;...
|
|
|
|
Then route-xenbr1 should be
|
|
172.16.0.0/15 via 192.168.0.3 dev xenbr1
|
|
172.18.0.0/16 via 192.168.0.4 dev xenbr1
|
|
"""
|
|
if oc.has_key('static-routes'):
|
|
# The key is present - extract comma seperates entries
|
|
lines = oc['static-routes'].split(',')
|
|
else:
|
|
# The key is not present, i.e. there are no static routes
|
|
lines = []
|
|
|
|
child = ConfigurationFile("%s/etc/sysconfig/network-scripts/route-%s" % (root_prefix(), interface))
|
|
child.write("# DO NOT EDIT: This file (%s) was autogenerated by %s\n" % \
|
|
(os.path.basename(child.path()), os.path.basename(sys.argv[0])))
|
|
|
|
try:
|
|
for l in lines:
|
|
network, masklen, gateway = l.split('/')
|
|
child.write("%s/%s via %s dev %s\n" % (network, masklen, gateway, interface))
|
|
|
|
f.attach_child(child)
|
|
child.close()
|
|
|
|
except ValueError, e:
|
|
log("Error in other-config['static-routes'] format for network %s: %s" % (interface, e))
|
|
|
|
def ipdev_open_ifcfg(pif):
|
|
ipdev = pif_ipdev_name(pif)
|
|
|
|
log("Writing network configuration for %s" % ipdev)
|
|
|
|
f = ConfigurationFile("%s/etc/sysconfig/network-scripts/ifcfg-%s" % (root_prefix(), ipdev))
|
|
|
|
f.write("# DO NOT EDIT: This file (%s) was autogenerated by %s\n" % \
|
|
(os.path.basename(f.path()), os.path.basename(sys.argv[0])))
|
|
f.write("XEMANAGED=yes\n")
|
|
f.write("DEVICE=%s\n" % ipdev)
|
|
f.write("ONBOOT=no\n")
|
|
|
|
return f
|
|
|
|
def ipdev_configure_network(pif, dp):
|
|
"""Write the configuration file for a network.
|
|
|
|
Writes configuration derived from the network object into the relevant
|
|
ifcfg file. The configuration file is passed in, but if the network is
|
|
bridgeless it will be ifcfg-<interface>, otherwise it will be ifcfg-<bridge>.
|
|
|
|
This routine may also write ifcfg files of the networks corresponding to other PIFs
|
|
in order to maintain consistency.
|
|
|
|
params:
|
|
pif: Opaque_ref of pif
|
|
dp: Datapath object
|
|
"""
|
|
|
|
pifrec = db().get_pif_record(pif)
|
|
nw = pifrec['network']
|
|
nwrec = db().get_network_record(nw)
|
|
|
|
ipdev = pif_ipdev_name(pif)
|
|
|
|
f = ipdev_open_ifcfg(pif)
|
|
|
|
mode = pifrec['ip_configuration_mode']
|
|
log("Configuring %s using %s configuration" % (ipdev, mode))
|
|
|
|
oc = None
|
|
if pifrec.has_key('other_config'):
|
|
oc = pifrec['other_config']
|
|
|
|
dp.configure_ipdev(f)
|
|
|
|
if pifrec['ip_configuration_mode'] == "DHCP":
|
|
f.write("BOOTPROTO=dhcp\n")
|
|
f.write("PERSISTENT_DHCLIENT=yes\n")
|
|
elif pifrec['ip_configuration_mode'] == "Static":
|
|
f.write("BOOTPROTO=none\n")
|
|
f.write("NETMASK=%(netmask)s\n" % pifrec)
|
|
f.write("IPADDR=%(IP)s\n" % pifrec)
|
|
f.write("GATEWAY=%(gateway)s\n" % pifrec)
|
|
elif pifrec['ip_configuration_mode'] == "None":
|
|
f.write("BOOTPROTO=none\n")
|
|
else:
|
|
raise Error("Unknown ip-configuration-mode %s" % pifrec['ip_configuration_mode'])
|
|
|
|
if nwrec.has_key('other_config'):
|
|
settings,offload = ethtool_settings(nwrec['other_config'])
|
|
if len(settings):
|
|
f.write("ETHTOOL_OPTS=\"%s\"\n" % str.join(" ", settings))
|
|
if len(offload):
|
|
f.write("ETHTOOL_OFFLOAD_OPTS=\"%s\"\n" % str.join(" ", offload))
|
|
|
|
ipdev_configure_static_routes(ipdev, nwrec['other_config'], f)
|
|
|
|
mtu = mtu_setting(nw, "Network", nwrec['other_config'])
|
|
if mtu:
|
|
f.write("MTU=%s\n" % mtu)
|
|
|
|
|
|
if pifrec.has_key('DNS') and pifrec['DNS'] != "":
|
|
ServerList = pifrec['DNS'].split(",")
|
|
for i in range(len(ServerList)): f.write("DNS%d=%s\n" % (i+1, ServerList[i]))
|
|
if oc and oc.has_key('domain'):
|
|
f.write("DOMAIN='%s'\n" % oc['domain'].replace(',', ' '))
|
|
|
|
# There can be only one DNSDEV and one GATEWAYDEV in /etc/sysconfig/network.
|
|
#
|
|
# The peerdns pif will be the one with
|
|
# pif::other-config:peerdns=true, or the mgmt pif if none have
|
|
# this set.
|
|
#
|
|
# The gateway pif will be the one with
|
|
# pif::other-config:defaultroute=true, or the mgmt pif if none
|
|
# have this set.
|
|
|
|
# Work out which pif on this host should be the DNSDEV and which
|
|
# should be the GATEWAYDEV
|
|
#
|
|
# Note: we prune out the bond master pif (if it exists). This is
|
|
# because when we are called to bring up an interface with a bond
|
|
# master, it is implicit that we should bring down that master.
|
|
|
|
pifs_on_host = [p for p in db().get_all_pifs() if not p in pif_get_bond_masters(pif)]
|
|
|
|
# loop through all the pifs on this host looking for one with
|
|
# other-config:peerdns = true, and one with
|
|
# other-config:default-route=true
|
|
peerdns_pif = None
|
|
defaultroute_pif = None
|
|
for __pif in pifs_on_host:
|
|
__pifrec = db().get_pif_record(__pif)
|
|
__oc = __pifrec['other_config']
|
|
if __oc.has_key('peerdns') and __oc['peerdns'] == 'true':
|
|
if peerdns_pif == None:
|
|
peerdns_pif = __pif
|
|
else:
|
|
log('Warning: multiple pifs with "peerdns=true" - choosing %s and ignoring %s' % \
|
|
(db().get_pif_record(peerdns_pif)['device'], __pifrec['device']))
|
|
if __oc.has_key('defaultroute') and __oc['defaultroute'] == 'true':
|
|
if defaultroute_pif == None:
|
|
defaultroute_pif = __pif
|
|
else:
|
|
log('Warning: multiple pifs with "defaultroute=true" - choosing %s and ignoring %s' % \
|
|
(db().get_pif_record(defaultroute_pif)['device'], __pifrec['device']))
|
|
|
|
# If no pif is explicitly specified then use the mgmt pif for
|
|
# peerdns/defaultroute.
|
|
if peerdns_pif == None:
|
|
peerdns_pif = management_pif
|
|
if defaultroute_pif == None:
|
|
defaultroute_pif = management_pif
|
|
|
|
is_dnsdev = peerdns_pif == pif
|
|
is_gatewaydev = defaultroute_pif == pif
|
|
|
|
if is_dnsdev or is_gatewaydev:
|
|
fnetwork = ConfigurationFile(root_prefix() + "/etc/sysconfig/network")
|
|
for line in fnetwork.readlines():
|
|
if is_dnsdev and line.lstrip().startswith('DNSDEV='):
|
|
fnetwork.write('DNSDEV=%s\n' % ipdev)
|
|
is_dnsdev = False
|
|
elif is_gatewaydev and line.lstrip().startswith('GATEWAYDEV='):
|
|
fnetwork.write('GATEWAYDEV=%s\n' % ipdev)
|
|
is_gatewaydev = False
|
|
else:
|
|
fnetwork.write(line)
|
|
|
|
if is_dnsdev:
|
|
fnetwork.write('DNSDEV=%s\n' % ipdev)
|
|
if is_gatewaydev:
|
|
fnetwork.write('GATEWAYDEV=%s\n' % ipdev)
|
|
|
|
fnetwork.close()
|
|
f.attach_child(fnetwork)
|
|
|
|
return f
|
|
|
|
#
|
|
# Toplevel actions
|
|
#
|
|
|
|
def action_up(pif, force):
|
|
pifrec = db().get_pif_record(pif)
|
|
|
|
ipdev = pif_ipdev_name(pif)
|
|
dp = DatapathFactory()(pif)
|
|
|
|
log("action_up: %s" % ipdev)
|
|
|
|
f = ipdev_configure_network(pif, dp)
|
|
|
|
dp.preconfigure(f)
|
|
|
|
f.close()
|
|
|
|
pif_rename_physical_devices(pif)
|
|
|
|
# if we are not forcing the interface up then attempt to tear down
|
|
# any existing devices which might interfere with brinign this one
|
|
# up.
|
|
if not force:
|
|
ifdown(ipdev)
|
|
|
|
dp.bring_down_existing()
|
|
|
|
try:
|
|
f.apply()
|
|
|
|
dp.configure()
|
|
|
|
ifup(ipdev)
|
|
|
|
dp.post()
|
|
|
|
# Update /etc/issue (which contains the IP address of the management interface)
|
|
os.system(root_prefix() + "/sbin/update-issue")
|
|
|
|
f.commit()
|
|
except Error, e:
|
|
log("failed to apply changes: %s" % e.msg)
|
|
f.revert()
|
|
raise
|
|
|
|
def action_down(pif):
|
|
ipdev = pif_ipdev_name(pif)
|
|
dp = DatapathFactory()(pif)
|
|
|
|
log("action_down: %s" % ipdev)
|
|
|
|
ifdown(ipdev)
|
|
|
|
dp.bring_down()
|
|
|
|
def action_rewrite():
|
|
DatapathFactory().rewrite()
|
|
|
|
# This is useful for reconfiguring the mgmt interface after having lost connectivity to the pool master
|
|
def action_force_rewrite(bridge, config):
|
|
def getUUID():
|
|
import subprocess
|
|
uuid,_ = subprocess.Popen(['uuidgen'], stdout = subprocess.PIPE).communicate()
|
|
return uuid.strip()
|
|
|
|
# Notes:
|
|
# 1. that this assumes the interface is bridged
|
|
# 2. If --gateway is given it will make that the default gateway for the host
|
|
|
|
# extract the configuration
|
|
try:
|
|
mode = config['mode']
|
|
mac = config['mac']
|
|
interface = config['device']
|
|
except:
|
|
raise Usage("Please supply --mode, --mac and --device")
|
|
|
|
if mode == 'static':
|
|
try:
|
|
netmask = config['netmask']
|
|
ip = config['ip']
|
|
except:
|
|
raise Usage("Please supply --netmask and --ip")
|
|
try:
|
|
gateway = config['gateway']
|
|
except:
|
|
gateway = None
|
|
elif mode != 'dhcp':
|
|
raise Usage("--mode must be either static or dhcp")
|
|
|
|
if config.has_key('vlan'):
|
|
is_vlan = True
|
|
vlan_slave, vlan_vid = config['vlan'].split('.')
|
|
else:
|
|
is_vlan = False
|
|
|
|
if is_vlan:
|
|
raise Error("Force rewrite of VLAN not implemented")
|
|
|
|
log("Configuring %s using %s configuration" % (bridge, mode))
|
|
|
|
f = ConfigurationFile(root_prefix() + dbcache_file)
|
|
|
|
pif_uuid = getUUID()
|
|
network_uuid = getUUID()
|
|
|
|
f.write('<?xml version="1.0" ?>\n')
|
|
f.write('<xenserver-network-configuration>\n')
|
|
f.write('\t<pif ref="OpaqueRef:%s">\n' % pif_uuid)
|
|
f.write('\t\t<network>OpaqueRef:%s</network>\n' % network_uuid)
|
|
f.write('\t\t<management>True</management>\n')
|
|
f.write('\t\t<uuid>%sPif</uuid>\n' % interface)
|
|
f.write('\t\t<bond_slave_of>OpaqueRef:NULL</bond_slave_of>\n')
|
|
f.write('\t\t<bond_master_of/>\n')
|
|
f.write('\t\t<VLAN_slave_of/>\n')
|
|
f.write('\t\t<VLAN_master_of>OpaqueRef:NULL</VLAN_master_of>\n')
|
|
f.write('\t\t<VLAN>-1</VLAN>\n')
|
|
f.write('\t\t<device>%s</device>\n' % interface)
|
|
f.write('\t\t<MAC>%s</MAC>\n' % mac)
|
|
f.write('\t\t<other_config/>\n')
|
|
if mode == 'dhcp':
|
|
f.write('\t\t<ip_configuration_mode>DHCP</ip_configuration_mode>\n')
|
|
f.write('\t\t<IP></IP>\n')
|
|
f.write('\t\t<netmask></netmask>\n')
|
|
f.write('\t\t<gateway></gateway>\n')
|
|
f.write('\t\t<DNS></DNS>\n')
|
|
elif mode == 'static':
|
|
f.write('\t\t<ip_configuration_mode>Static</ip_configuration_mode>\n')
|
|
f.write('\t\t<IP>%s</IP>\n' % ip)
|
|
f.write('\t\t<netmask>%s</netmask>\n' % netmask)
|
|
if gateway is not None:
|
|
f.write('\t\t<gateway>%s</gateway>\n' % gateway)
|
|
f.write('\t\t<DNS></DNS>\n')
|
|
else:
|
|
raise Error("Unknown mode %s" % mode)
|
|
f.write('\t</pif>\n')
|
|
|
|
f.write('\t<network ref="OpaqueRef:%s">\n' % network_uuid)
|
|
f.write('\t\t<uuid>InitialManagementNetwork</uuid>\n')
|
|
f.write('\t\t<PIFs>\n')
|
|
f.write('\t\t\t<PIF>OpaqueRef:%s</PIF>\n' % pif_uuid)
|
|
f.write('\t\t</PIFs>\n')
|
|
f.write('\t\t<bridge>%s</bridge>\n' % bridge)
|
|
f.write('\t\t<other_config/>\n')
|
|
f.write('\t</network>\n')
|
|
f.write('</xenserver-network-configuration>\n')
|
|
|
|
f.close()
|
|
|
|
try:
|
|
f.apply()
|
|
f.commit()
|
|
except Error, e:
|
|
log("failed to apply changes: %s" % e.msg)
|
|
f.revert()
|
|
raise
|
|
|
|
def main(argv=None):
|
|
global management_pif
|
|
|
|
session = None
|
|
pif_uuid = None
|
|
pif = None
|
|
|
|
force_interface = None
|
|
force_management = False
|
|
|
|
if argv is None:
|
|
argv = sys.argv
|
|
|
|
try:
|
|
try:
|
|
shortops = "h"
|
|
longops = [ "pif=", "pif-uuid=",
|
|
"session=",
|
|
"force=",
|
|
"force-interface=",
|
|
"management",
|
|
"mac=", "device=", "mode=", "ip=", "netmask=", "gateway=",
|
|
"root-prefix=",
|
|
"no-syslog",
|
|
"help" ]
|
|
arglist, args = getopt.gnu_getopt(argv[1:], shortops, longops)
|
|
except getopt.GetoptError, msg:
|
|
raise Usage(msg)
|
|
|
|
force_rewrite_config = {}
|
|
|
|
for o,a in arglist:
|
|
if o == "--pif":
|
|
pif = a
|
|
elif o == "--pif-uuid":
|
|
pif_uuid = a
|
|
elif o == "--session":
|
|
session = a
|
|
elif o == "--force-interface" or o == "--force":
|
|
force_interface = a
|
|
elif o == "--management":
|
|
force_management = True
|
|
elif o in ["--mac", "--device", "--mode", "--ip", "--netmask", "--gateway"]:
|
|
force_rewrite_config[o[2:]] = a
|
|
elif o == "--root-prefix":
|
|
set_root_prefix(a)
|
|
elif o == "--no-syslog":
|
|
set_log_destination("stderr")
|
|
elif o == "-h" or o == "--help":
|
|
print __doc__ % {'command-name': os.path.basename(argv[0])}
|
|
return 0
|
|
|
|
if get_log_destination() == "syslog":
|
|
syslog.openlog(os.path.basename(argv[0]))
|
|
log("Called as " + str.join(" ", argv))
|
|
|
|
if len(args) < 1:
|
|
raise Usage("Required option <action> not present")
|
|
if len(args) > 1:
|
|
raise Usage("Too many arguments")
|
|
|
|
action = args[0]
|
|
|
|
if not action in ["up", "down", "rewrite", "rewrite-configuration"]:
|
|
raise Usage("Unknown action \"%s\"" % action)
|
|
|
|
# backwards compatibility
|
|
if action == "rewrite-configuration": action = "rewrite"
|
|
|
|
if ( session or pif ) and pif_uuid:
|
|
raise Usage("--session/--pif and --pif-uuid are mutually exclusive.")
|
|
if ( session and not pif ) or ( not session and pif ):
|
|
raise Usage("--session and --pif must be used together.")
|
|
if force_interface and ( session or pif or pif_uuid ):
|
|
raise Usage("--force is mutually exclusive with --session, --pif and --pif-uuid")
|
|
if len(force_rewrite_config) and not (force_interface and action == "rewrite"):
|
|
raise Usage("\"--force rewrite\" needed for --device, --mode, --ip, --netmask, and --gateway")
|
|
if (action == "rewrite") and (pif or pif_uuid ):
|
|
raise Usage("rewrite action does not take --pif or --pif-uuid")
|
|
|
|
global db
|
|
if force_interface:
|
|
log("Force interface %s %s" % (force_interface, action))
|
|
|
|
if action == "rewrite":
|
|
action_force_rewrite(force_interface, force_rewrite_config)
|
|
elif action in ["up", "down"]:
|
|
db_init_from_cache(dbcache_file)
|
|
pif = db().get_pif_by_bridge(force_interface)
|
|
management_pif = db().get_management_pif()
|
|
|
|
if action == "up":
|
|
action_up(pif, True)
|
|
elif action == "down":
|
|
action_down(pif)
|
|
else:
|
|
raise Error("Unknown action %s" % action)
|
|
else:
|
|
db_init_from_xenapi(session)
|
|
|
|
if pif_uuid:
|
|
pif = db().get_pif_by_uuid(pif_uuid)
|
|
|
|
if action == "rewrite":
|
|
action_rewrite()
|
|
else:
|
|
if not pif:
|
|
raise Usage("No PIF given")
|
|
|
|
if force_management:
|
|
# pif is going to be the management pif
|
|
management_pif = pif
|
|
else:
|
|
# pif is not going to be the management pif.
|
|
# Search DB cache for pif on same host with management=true
|
|
pifrec = db().get_pif_record(pif)
|
|
management_pif = db().get_management_pif()
|
|
|
|
log_pif_action(action, pif)
|
|
|
|
if not check_allowed(pif):
|
|
return 0
|
|
|
|
if action == "up":
|
|
action_up(pif, False)
|
|
elif action == "down":
|
|
action_down(pif)
|
|
else:
|
|
raise Error("Unknown action %s" % action)
|
|
|
|
# Save cache.
|
|
db().save(dbcache_file)
|
|
|
|
except Usage, err:
|
|
print >>sys.stderr, err.msg
|
|
print >>sys.stderr, "For help use --help."
|
|
return 2
|
|
except Error, err:
|
|
log(err.msg)
|
|
return 1
|
|
|
|
return 0
|
|
|
|
if __name__ == "__main__":
|
|
rc = 1
|
|
try:
|
|
rc = main()
|
|
except:
|
|
ex = sys.exc_info()
|
|
err = traceback.format_exception(*ex)
|
|
for exline in err:
|
|
log(exline)
|
|
|
|
syslog.closelog()
|
|
|
|
sys.exit(rc)
|