Add port numbers and a port_map_name_to_number() mapping function

The names that switches use internally to describe their ports often
have very little obvious overlap with the labels written externally
on the switches, and the latter labels are what people are likely to
be feeding into VLANd when trying to use it, e.g. with LAVA.

Add a simple mapping from the internal port name to port number, which
should be *something* approximating to the visible labels. Some
switches (e.g. the Catalyst 3750) can be very difficult to deal with
here, and we'll document that for users too.

Change-Id: Ia52a20b533c748462a8d7487028ea7bde4076f1b
diff --git a/drivers/common.py b/drivers/common.py
index 1405f88..6832f3b 100644
--- a/drivers/common.py
+++ b/drivers/common.py
@@ -52,6 +52,7 @@
     _allowed_port_modes = [ "trunk", "access" ]
     _ports = []
     _port_modes = {}
+    _port_numbers = {}
     _prompt_name = ''
     _username = ''
     _password = ''
@@ -90,6 +91,7 @@
         self.connection.close(True)
         self._ports = []
         self._port_modes.clear()
+        self._port_numbers.clear()
         self._prompt_name = ''
         self._systemdata = []
         del(self)
@@ -140,6 +142,12 @@
             logging.debug("port_get_mode: found mode %s for port %s, adding to cache", self._port_modes[port], port)
             return mode
 
+    def port_map_name_to_number(self, port_name):
+        if not self._is_port_name_valid(port_name):
+            raise InputError("Port name %s not recognised" % port_name)
+        logging.debug("port_map_name_to_number: returning %d for port_name %s", self._port_numbers[port_name], port_name)
+        return self._port_numbers[port_name]
+
     # Wrappers to adapt logging for pexpect when we've configured on a
     # switch.
     # This will be the method called by the pexpect object to write a