diff options
Diffstat (limited to 'Vland/drivers/common.py')
-rw-r--r-- | Vland/drivers/common.py | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/Vland/drivers/common.py b/Vland/drivers/common.py new file mode 100644 index 0000000..e564c9e --- /dev/null +++ b/Vland/drivers/common.py @@ -0,0 +1,167 @@ +#! /usr/bin/python + +# Copyright 2014-2015 Linaro Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. + +import time +import logging + +from errors import InputError, PExpectError + +class SwitchErrors: + """ Error logging and statistics class """ + + def __init__(self): + self.errors_in = 0 + self.errors_out = 0 + + def __repr__(self): + return "<SwitchErrors: errors_in: %d, errors_out: %d>" % (self.errors_in, self.errors_out) + + # For now, just count the error. Later on we might add stats and + # analysis + def log_error_in(self, text): + self.errors_in += 1 + + # For now, just count the error. Later on we might add stats and + # analysis + def log_error_out(self, text): + self.errors_out += 1 + +class SwitchDriver(object): + + connection = None + hostname = "" + serial_number = '' + + _allowed_port_modes = [ "trunk", "access" ] + _ports = [] + _port_modes = {} + _port_numbers = {} + _prompt_name = '' + _username = '' + _password = '' + _enable_password = '' + _systemdata = [] + + def __init__ (self, switch_hostname, debug): + + if debug: + # Configure logging for pexpect output if we have debug + # enabled + + # get the logger + self.logger = logging.getLogger(switch_hostname) + + # give the logger the methods required by pexpect + self.logger.write = self._log_write + self.logger.flush = self._log_do_nothing + + else: + self.logger = None + + self.hostname = switch_hostname + + # Connect to the switch and log in + def switch_connect(self, username, password, enablepassword): + self._username = username + self._password = password + self._enable_password = enablepassword + self._switch_connect() + + # Log out of the switch and drop the connection and all state + def switch_disconnect(self): + self._logout() + logging.debug("Closing connection to %s", self.hostname) + self._ports = [] + self._port_modes.clear() + self._port_numbers.clear() + self._prompt_name = '' + self._systemdata = [] + del(self) + + def dump_list(self, data): + i = 0 + for line in data: + print "%d: \"%s\"" % (i, line) + i += 1 + + def _delay(self): + time.sleep(0.5) + + # List the capabilities of the switch (and driver) - some things + # make no sense to abstract. Returns a dict of strings, each one + # describing an extra feature that that higher levels may care + # about + def switch_get_capabilities(self): + return self._capabilities + + # List the names of all the ports on the switch + def switch_get_port_names(self): + return self._ports + + def _is_port_name_valid(self, name): + for port in self._ports: + if name == port: + return True + return False + + def _is_port_mode_valid(self, mode): + for allowed in self._allowed_port_modes: + if allowed == mode: + return True + return False + + # Try to look up a port mode in our cache. If not there, go ask + # the switch and cache the result + def port_get_mode(self, port): + if not self._is_port_name_valid(port): + raise InputError("Port name %s not recognised" % port) + if port in self._port_modes: + logging.debug("port_get_mode: returning mode %s from cache for port %s", self._port_modes[port], port) + return self._port_modes[port] + else: + mode = self._port_get_mode(port) + self._port_modes[port] = mode + 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 + # log message + def _log_write(self, *args, **kwargs): + # ignore other parameters, pexpect only uses one arg + content = args[0] + + if content in [' ', '', '\n', '\r', '\r\n']: + return # don't log empty lines + + # Split the output into multiple lines so we get a + # well-formatted logfile + for line in content.split('\r\n'): + logging.info(line) + + # This is the flush method for pexpect + def _log_do_nothing(self): + pass |