From feb6452857669cd2ef85bfcdd4cf6576a7f464e5 Mon Sep 17 00:00:00 2001 From: Steve McIntyre Date: Fri, 19 Dec 2014 18:53:02 +0000 Subject: Implemented the backend for delete_vlan() Change-Id: Ie70408c6ce52e8a520df86c77194a96ae196ef89 --- util.py | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/util.py b/util.py index 1d1a935..7652037 100644 --- a/util.py +++ b/util.py @@ -291,3 +291,113 @@ class VlanUtil: return vlan_id # If we're successful + # Complex call + # 1. Check in the DB if there are any ports on the VLAN. Bail if so + # 2. Iterate through all switches: + # a. Remove the VLAN from all trunk ports (if needed) + # b. Remove the VLAN + # 3. If all went OK, save config on the switches + # 4. Remove the VLAN in the DB + # + # If things fail, we attempt to roll back by rebooting switches. + def delete_vlan(self, state, command, data): + + print 'delete_vlan' + db = state.db + config = state.config + + vlan_id = int(data['vlan_id']) + + # 1. Check for database records first + print 'Checking for ports using VLAN id %d' % vlan_id + vlan = db.get_vlan_by_id(vlan_id) + if vlan is None: + raise InputError("VLAN ID %d does not exist" % vlan_id) + vlan_tag = vlan.tag + ports = db.get_ports_by_current_vlan(vlan_id) + if ports is not None: + raise InputError("Cannot delete VLAN ID %d when it still has %d ports" % + (vlan_id, len(ports))) + ports = db.get_ports_by_base_vlan(vlan_id) + if ports is not None: + raise InputError("Cannot delete VLAN ID %d when it still has %d ports" % + (vlan_id, len(ports))) + + # Keep track of which switches we've configured, for later use + switches_done = [] + + # 2. Now the switches + try: + for switch in sorted(config.switches): + trunk_ports = [] + try: + # Get the right driver + s = self.get_switch_driver(switch, config) + s.switch_connect(config.switches[switch].username, config.switches[switch].password) + + # Mark this switch as one we've touched, for + # either config saving or rollback below + switches_done.append(switch) + + # 2a. Do we need to worry about trunk ports on this switch? + if 'TrunkWildCardVlans' in s.switch_get_capabilities(): + print 'This switch does not need special trunk port handling' + else: + print 'This switch needs special trunk port handling' + switch_id = db.get_switch_id_by_name(switch) + trunk_ports = db.get_trunk_port_names_by_switch(switch_id) + if trunk_ports is None: + print "But it has no trunk ports defined" + trunk_ports = [] + else: + print 'Found %d trunk_ports that need adjusting' % len(trunk_ports) + + # Modify any trunk ports as needed + for port in trunk_ports: + s.port_remove_trunk_from_vlan(port, tag) + print 'Removed VLAN tag %d from switch %s port %s' % (vlan_tag, switch, port) + + # 2b. Remove the VLAN from the switch + print 'Removing VLAN tag %d from switch %s' % (vlan_tag, switch) + s.vlan_destroy(vlan_tag) + print 'Removed VLAN tag %d from switch %s' % (vlan_tag, switch) + + # And now we're done with this switch + s.switch_disconnect() + del s + + except IOError: + raise + + except IOError: + # Bugger. Looks like one of the switch calls above + # failed. To undo the changes safely, we'll need to reset + # all the switches we managed to configure. This could + # take some time! + for switch in switches_done: + s = self.get_switch_driver(switch, config) + s.switch_connect(config.switches[switch].username, config.switches[switch].password) + s.switch_restart() # Will implicitly also close the connection + del s + + # 3. If we've got this far, things were successful. Save + # config on all the switches so it will persist across reboots + for switch in switches_done: + s = self.get_switch_driver(switch, config) + s.switch_connect(config.switches[switch].username, config.switches[switch].password) + s.switch_save_running_config() + s.switch_disconnect() + del s + + # 4. Finally, remove the VLAN in the DB + try: + print 'Removing DB record: VLAN id %d' % vlan_id + vlan_id = db.delete_vlan(vlan_id) + print 'Removed VLAN id %d from the database OK' % vlan_id + except InputError: + print 'DB deletion failed' + raise + + return vlan_id # If we're successful + + -- cgit v1.2.3