- bridge = bridge_name(pif)
- interface = interface_name(pif)
- ipdev = ipdev_name(pif)
- datapath = datapath_name(pif)
- physdevs = physdev_names(pif)
- vlan_slave = None
- if pifrec['VLAN'] != '-1':
- vlan_slave = get_vlan_slave_of_pif(pif)
- if vlan_slave and is_bond_pif(vlan_slave):
- bond_master = vlan_slave
- elif is_bond_pif(pif):
- bond_master = pif
- else:
- bond_master = None
- if bond_master:
- bond_slaves = get_bond_slaves_of_pif(bond_master)
- else:
- bond_slaves = []
- bond_masters = get_bond_masters_of_pif(pif)
-
- # Support "rpm -e vswitch" gracefully by keeping Centos configuration
- # files up-to-date, even though we don't use them or need them.
- f = configure_pif(pif)
- mode = pifrec['ip_configuration_mode']
- if bridge:
- log("Configuring %s using %s configuration" % (bridge, mode))
- br = open_network_ifcfg(pif)
- configure_network(pif, br)
- br.close()
- f.attach_child(br)
- else:
- log("Configuring %s using %s configuration" % (interface, mode))
- configure_network(pif, f)
- f.close()
- for master in bond_masters:
- master_bridge = bridge_name(master)
- removed = unconfigure_pif(master)
- f.attach_child(removed)
- if master_bridge:
- removed = open_network_ifcfg(master)
- log("Unlinking stale file %s" % removed.path())
- removed.unlink()
- f.attach_child(removed)
-
- # /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)
- br.write("VLAN_SLAVE=%s\n" % datapath)
- br.write("VLAN_VID=%s\n" % pifrec['VLAN'])
- br.close()
- f.attach_child(br)
-
- # Update all configuration files (both ours and Centos's).
- f.apply()
- f.commit()
-
- # "ifconfig down" the network device and delete its IP address, etc.
- down_netdev(ipdev)
- for physdev in physdevs:
- down_netdev(physdev)
-
- # If we are bringing up a bond, remove IP addresses from the
- # slaves (because we are implicitly being asked to take them down).
- #
- # Conversely, if we are bringing up an interface that has bond
- # masters, remove IP addresses from the bond master (because we
- # are implicitly being asked to take it down).
- for bond_pif in bond_slaves + bond_masters:
- run_command(["/sbin/ifconfig", ipdev_name(bond_pif), '0.0.0.0'])
-
- # Remove all keys related to pif and any bond masters linked to PIF.
- del_ports = [ipdev] + physdevs + bond_masters
- if vlan_slave and bond_master:
- del_ports += [interface_name(bond_master)]
-
- # What ports do we need to add to the datapath?
- #
- # We definitely need the ipdev, and ordinarily we want the
- # physical devices too, but for bonds we need the bond as bridge
- # port.
- add_ports = [ipdev, datapath]
- if not bond_master:
- add_ports += physdevs
- else:
- add_ports += [interface_name(bond_master)]
-
- # What ports do we need to delete?
- #
- # - All the ports that we add, to avoid duplication and to drop
- # them from another datapath in case they're misassigned.
- #
- # - The physical devices, since they will either be in add_ports
- # or added to the bonding device (see below).
- #
- # - The bond masters for pif. (Ordinarily pif shouldn't have any
- # bond masters. If it does then interface-reconfigure is
- # implicitly being asked to take them down.)
- del_ports = add_ports + physdevs + bond_masters
-
- # What networks does this datapath carry?
- #
- # - The network corresponding to the datapath's PIF.
- #
- # - The networks corresponding to any VLANs attached to the
- # datapath's PIF.
- network_uuids = []
- for nwpif in db.get_pifs_by_record({'device': pifrec['device'],
- 'host': pifrec['host']}):
- net = db.get_pif_record(nwpif)['network']
- network_uuids += [db.get_network_record(net)['uuid']]
-
- # Bring up bond slaves early, because ovs-vswitchd initially
- # enables or disables bond slaves based on whether carrier is
- # detected when they are added, and a network device that is down
- # always reports "no carrier".
- bond_slave_physdevs = []
- for slave in bond_slaves:
- bond_slave_physdevs += physdev_names(slave)
- for slave_physdev in bond_slave_physdevs:
- up_netdev(slave_physdev)
-
- # Now modify the ovs-vswitchd config file.
- argv = []
- for port in set(del_ports):
- argv += interface_deconfigure_commands(port)
- for port in set(add_ports):
- argv += ['--add=bridge.%s.port=%s' % (datapath, port)]
- if vlan_slave:
- argv += ['--add=vlan.%s.tag=%s' % (ipdev, pifrec['VLAN'])]
- argv += ['--add=iface.%s.internal=true' % (ipdev)]
-
- # xapi creates a bridge by the name of the ipdev and requires
- # that the IP address will be on it. We need to delete this
- # bridge because we need that device to be a member of our
- # datapath.
- argv += ['--del-match=bridge.%s.[!0-9]*' % ipdev]
-
- # xapi insists that its attempts to create the bridge succeed,
- # so force that to happen.
- argv += ['--add=iface.%s.fake-bridge=true' % (ipdev)]
- else:
- try:
- os.unlink("%s/br-%s" % (vswitch_config_dir, bridge))
- except OSError:
- pass
- argv += ['--del-match=bridge.%s.xs-network-uuids=*' % datapath]
- argv += ['--add=bridge.%s.xs-network-uuids=%s' % (datapath, uuid)
- for uuid in set(network_uuids)]
- if bond_master:
- argv += configure_bond(bond_master)
- modify_config(argv)
-
- # Configure network devices.
- configure_netdev(pif)
-
- # Bring up VLAN slave, plus physical devices other than bond
- # slaves (which we brought up earlier).
- if vlan_slave:
- up_netdev(ipdev_name(vlan_slave))
- for physdev in set(physdevs) - set(bond_slave_physdevs):
- up_netdev(physdev)
-
- # Update /etc/issue (which contains the IP address of the management interface)
- os.system("/sbin/update-issue")
-
- if bond_slaves:
- # There seems to be a race somewhere: without this sleep, using
- # XenCenter to create a bond that becomes the management interface
- # fails with "The underlying connection was closed: A connection that
- # was expected to be kept alive was closed by the server." on every
- # second or third try, even though /var/log/messages doesn't show
- # anything unusual.
- #
- # The race is probably present even without vswitch, but bringing up a
- # bond without vswitch involves a built-in pause of 10 seconds or more
- # to wait for the bond to transition from learning to forwarding state.
- time.sleep(5)
-
-def action_down(pif):
- rec = db.get_pif_record(pif)
- interface = interface_name(pif)
- bridge = bridge_name(pif)
- ipdev = ipdev_name(pif)
-
- # Support "rpm -e vswitch" gracefully by keeping Centos configuration
- # files up-to-date, even though we don't use them or need them.
- f = unconfigure_pif(pif)
- if bridge:
- br = open_network_ifcfg(pif)
- log("Unlinking stale file %s" % br.path())
- br.unlink()
- f.attach_child(br)
- try:
- f.apply()
- f.commit()
- except Error, e:
- log("action_down failed to apply changes: %s" % e.msg)
- f.revert()
- raise
-
- argv = []
- if rec['VLAN'] != '-1':
- # Get rid of the VLAN device itself.
- down_netdev(ipdev)
- argv += interface_deconfigure_commands(ipdev)
-
- # If the VLAN's slave is attached, stop here.
- slave = get_vlan_slave_of_pif(pif)
- if db.get_pif_record(slave)['currently_attached']:
- log("VLAN slave is currently attached")
- modify_config(argv)
- return
-
- # If the VLAN's slave has other VLANs that are attached, stop here.
- masters = get_vlan_masters_of_pif(slave)
- for m in masters:
- if m != pif and db.get_pif_record(m)['currently_attached']:
- log("VLAN slave has other master %s" % interface_naem(m))
- modify_config(argv)
- return
-
- # Otherwise, take down the VLAN's slave too.
- log("No more masters, bring down vlan slave %s" % interface_name(slave))
- pif = slave
- else:
- # Stop here if this PIF has attached VLAN masters.
- vlan_masters = get_vlan_masters_of_pif(pif)
- 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']:
- log("Leaving %s up due to currently attached VLAN master %s" % (interface, interface_name(m)))
- return
-
- # pif is now either a bond or a physical device which needs to be
- # brought down. pif might have changed so re-check all its attributes.
- rec = db.get_pif_record(pif)
- interface = interface_name(pif)
- bridge = bridge_name(pif)
- ipdev = ipdev_name(pif)