#
"""Usage:
- %(command-name)s --session <SESSION-REF> --pif <PIF-REF> [up|down|rewrite]
- %(command-name)s --force <BRIDGE> [up|down|rewrite <CONFIG>]
+ %(command-name)s <PIF> up
+ %(command-name)s <PIF> down
+ %(command-name)s [<PIF>] rewrite
+ %(command-name)s --force <BRIDGE> up
+ %(command-name)s --force <BRIDGE> down
+ %(command-name)s --force <BRIDGE> rewrite --device=<INTERFACE> <CONFIG>
%(command-name)s --force all down
- where,
- <CONFIG> = --device=<INTERFACE> --mode=dhcp
- <CONFIG> = --device=<INTERFACE> --mode=static --ip=<IPADDR> --netmask=<NM> [--gateway=<GW>]
+ 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.
- --force-interface An interface name. Mutually exclusive with --session/--pif.
-
- Either both --session and --pif or just --pif-uuid.
-
- <ACTION> is either "up" or "down" or "rewrite"
+ --pif A PIF reference within the session.
+ --pif-uuid The UUID of a PIF.
+ --force An interface name.
"""
#
#
# --output-directory=<DIR> Write configuration to <DIR>. Also disables actually
# raising/lowering the interfaces
-# --pif-uuid A PIF UUID, use instead of --session/--pif.
#
#
#
# 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)
-# XXX: --force-interface=all down
-
-# XXX: --force-interface rewrite
-
-# XXX: Sometimes this leaves "orphaned" datapaths, e.g. a datapath whose
-# only port is the local port. Should delete those.
-
-# XXX: This can leave crud in ovs-vswitchd.conf in this scenario:
-# - Create bond in XenCenter.
-# - Create VLAN on bond in XenCenter.
-# - Attempt to delete bond in XenCenter (this will fail because there
-# is a VLAN on the bond, although the error may not be reported
-# until the next step)
-# - Delete VLAN in XenCenter.
-# - Delete bond in XenCenter.
-# At this point there will still be some configuration data for the bond
-# or the VLAN in ovs-vswitchd.conf.
-
import XenAPI
import os, sys, getopt, time, signal
import syslog
db = None
management_pif = None
-dbcache_file = "/etc/ovs-vswitch.dbcache"
-vswitch_config_dir = "/etc/openvswitch"
+vswitch_state_dir = "/var/lib/openvswitch/"
+dbcache_file = vswitch_state_dir + "dbcache"
class Usage(Exception):
def __init__(self, msg):
'MAC': (str_to_xml,str_from_xml),
'other_config': (lambda x, p, t, v: otherconfig_to_xml(x, p, v, PIF_OTHERCONFIG_ATTRS),
lambda n: otherconfig_from_xml(n, PIF_OTHERCONFIG_ATTRS)),
+
+ # Special case: We write the current value
+ # PIF.currently-attached to the cache but since it will
+ # not be valid when we come to use the cache later
+ # (i.e. after a reboot) we always read it as False.
+ 'currently_attached': (bool_to_xml, lambda n: False),
}
PIF_OTHERCONFIG_ATTRS = [ 'domain', 'peerdns', 'defaultroute', 'mtu', 'static-routes' ] + \
rec = session.xenapi.network.get_record(n)
self.__networks[n] = {}
for f in NETWORK_ATTRS:
- self.__networks[n][f] = rec[f]
+ if f == "PIFs":
+ # drop PIFs on other hosts
+ self.__networks[n][f] = [p for p in rec[f] if self.__pif_on_host(p)]
+ else:
+ self.__networks[n][f] = rec[f]
self.__networks[n]['other_config'] = {}
for f in NETWORK_OTHERCONFIG_ATTRS:
if not rec['other_config'].has_key(f): continue
pifrec = db.get_pif_record(pif)
if pifrec['VLAN'] != '-1':
- return [get_vlan_slave_of_pif(pif)]
+ return get_physdev_pifs(get_vlan_slave_of_pif(pif))
elif len(pifrec['bond_master_of']) != 0:
return get_bond_slaves_of_pif(pif)
else:
rec['ip_configuration_mode'] = pifrec['ip_configuration_mode']
rec['action'] = action
rec['interface-name'] = interface_name(pif)
- if action == "rewrite":
- rec['message'] = "Rewrite PIF %(uuid)s configuration" % rec
- else:
- rec['message'] = "Bring %(action)s PIF %(uuid)s" % rec
+ rec['message'] = "Bring %(action)s PIF %(uuid)s" % rec
log("%(message)s: %(interface-name)s configured as %(ip_configuration_mode)s" % rec)
def get_bond_masters_of_pif(pif):
run_ethtool(device, oc)
def modify_config(commands):
- run_command(['/root/vswitch/bin/ovs-cfg-mod', '-vANY:console:emer',
+ run_command(['/usr/bin/ovs-cfg-mod', '-vANY:console:emer',
'-F', '/etc/ovs-vswitchd.conf']
+ commands + ['-c'])
run_command(['/sbin/service', 'vswitch', 'reload'])
# /etc/xensource/scripts/vif needs to know where to add VIFs.
if vlan_slave:
- if not os.path.exists(vswitch_config_dir):
- os.mkdir(vswitch_config_dir)
- br = ConfigurationFile("br-%s" % bridge, vswitch_config_dir)
+ if not os.path.exists(vswitch_state_dir):
+ os.mkdir(vswitch_state_dir)
+ br = ConfigurationFile("br-%s" % bridge, vswitch_state_dir)
br.write("VLAN_SLAVE=%s\n" % datapath)
br.write("VLAN_VID=%s\n" % pifrec['VLAN'])
br.close()
# - The networks corresponding to any VLANs attached to the
# datapath's PIF.
network_uuids = []
- for nwpif in db.get_pifs_by_device({'device': pifrec['device']}):
+ for nwpif in db.get_pifs_by_device(pifrec['device']):
net = db.get_pif_record(nwpif)['network']
network_uuids += [db.get_network_record(net)['uuid']]
argv += ['--add=iface.%s.fake-bridge=true' % (ipdev)]
else:
try:
- os.unlink("%s/br-%s" % (vswitch_config_dir, bridge))
+ os.unlink("%s/br-%s" % (vswitch_state_dir, bridge))
except OSError:
pass
argv += ['--del-match=bridge.%s.xs-network-uuids=*' % datapath]
# Bring up VLAN slave, plus physical devices other than bond
# slaves (which we brought up earlier).
+ # XXX need to bring up bond itself.
+ # XXX need to set MAC address on fake bridge
if vlan_slave:
up_netdev(ipdev_name(vlan_slave))
for physdev_pif in set(physdev_pifs) - set(bond_slave_physdev_pifs):
log("VLAN masters of %s - %s" % (rec['device'], [interface_name(m) for m in vlan_masters]))
for m in vlan_masters:
if db.get_pif_record(m)['currently_attached']:
+ # XXX remove IP address
log("Leaving %s up due to currently attached VLAN master %s" % (interface, interface_name(m)))
return
# We have no code of our own to run here.
pass
+def action_force_rewrite(interface, config):
+ raise Error("Force rewrite is not implemented yet.")
+
def main(argv=None):
global output_directory, management_pif
"force=",
"force-interface=",
"management",
- "test-mode",
"device=", "mode=", "ip=", "netmask=", "gateway=",
"help" ]
arglist, args = getopt.gnu_getopt(argv[1:], shortops, longops)
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"
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 force_interface == "all" and action != "down":
+ raise Usage("\"--force all\" only valid for down action")
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":
action_force_rewrite(force_interface, force_rewrite_config)
- else:
+ elif action in ["up", "down"]:
+ if action == "down" and force_interface == "all":
+ raise Error("Force all interfaces down not implemented yet")
+
db = DatabaseCache(cache_file=dbcache_file)
pif = db.get_pif_by_bridge(force_interface)
management_pif = db.get_management_pif()
action_up(pif)
elif action == "down":
action_down(pif)
- else:
- raise Usage("Unknown action %s" % action)
+ else:
+ raise Error("Unknown action %s" % action)
else:
db = DatabaseCache(session_ref=session)
if pif_uuid:
pif = db.get_pif_by_uuid(pif_uuid)
-
- if not pif:
- raise Usage("No PIF given")
- if force_management:
- # pif is going to be the management pif
- management_pif = pif
+ if action == "rewrite" and not pif:
+ pass
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()
+ if not pif:
+ raise Usage("No PIF given")
- log_pif_action(action, pif)
+ 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()
- if not check_allowed(pif):
- return 0
+ log_pif_action(action, pif)
- if action == "up":
- action_up(pif)
- elif action == "down":
- action_down(pif)
- elif action == "rewrite":
- action_rewrite(pif)
- else:
- raise Usage("Unknown action %s" % action)
+ if not check_allowed(pif):
+ return 0
+
+ if action == "up":
+ action_up(pif)
+ elif action == "down":
+ action_down(pif)
+ elif action == "rewrite":
+ action_rewrite(pif)
+ else:
+ raise Error("Unknown action %s" % action)
# Save cache.
- pifrec = db.get_pif_record(pif)
db.save(dbcache_file)
except Usage, err: