Add the backend for the create_vlan() API

Change-Id: I26995ed803e5dd42a56de07a8e5070dc10b41554
diff --git a/util.py b/util.py
index 3aa9018..c24f564 100644
--- a/util.py
+++ b/util.py
@@ -178,7 +178,8 @@
             else:
                 raise InputError("Unknown query command \"%s\"" % command)
 
-        except InputError:
+        except InputError as e:
+            print 'got error %s' % e
             raise
 
         except:
@@ -187,3 +188,82 @@
         return ret
 
 
+    # Complex call
+    # 1. create the VLAN in the DB
+    # 2. Iterate through all switches:
+    #   a. Create the VLAN
+    #   b. Add the VLAN to all trunk ports (if needed)
+    #
+    # The VLAN may already exist on some of the switches, that's
+    # fine.
+    def create_vlan(self, state, command, data):
+
+        print 'create_vlan'
+        db = state.db
+        config = state.config
+
+        name = data['name']
+        tag = int(data['tag'])
+        is_base_vlan = data['is_base_vlan']
+
+        # 1. Database record first
+        try:
+            print 'Adding DB record first: name %s, tag %d, is_base_vlan %d' % (name, tag, is_base_vlan)
+            vlan_id = db.create_vlan(name, tag, is_base_vlan)
+            print 'Added VLAN tag %d, name %s to the database, created VLAN ID %d' % (tag, name, vlan_id)
+        except InputError:
+            print 'DB creation failed'
+            raise
+
+        # 2. Now the switches
+        try:
+            for switch in sorted(config.switches):
+                trunk_ports = []
+                try:
+                    print 'Adding new VLAN to switch %s' % switch
+                    # Get the right driver
+                    s = self.get_switch_driver(switch, config)
+                    s.switch_connect(config.switches[switch].username, config.switches[switch].password)
+
+                    # 2a. Create the VLAN on the switch
+                    s.vlan_create(tag)
+                    s.vlan_set_name(tag, name)
+                    print 'Added VLAN tag %d, name %s to switch %s' % (tag, name, switch)
+
+                    # 2b. 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:
+                        print 'Added VLAN tag %d, name %s to switch %s' % (tag, name, switch)
+                        s.port_add_trunk_to_vlan(port, tag)
+
+                    # Save switch config so it will stay across reboots
+                    s.switch_save_running_config()
+
+                    # 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.
+            # Undo the database change
+            print 'Switch access failed. Deleting the new VLAN entry in the database'
+            db.delete_vlan(vlan_id)
+            raise
+
+        return vlan_id # If we're successful
+