From 8646b8d62cf4ca7b6bccae537a0c9e72ba45eab3 Mon Sep 17 00:00:00 2001 From: Harry Huang Date: Fri, 17 Nov 2017 14:53:44 +0800 Subject: Merge compass-tasks-osa and compass-tasks-k8s JIRA: COMPASS-568 rename compass-tasks to compass-tasks-base. add both osa and k8s support in compass-tasks Change-Id: I438f5b17e509d4cb751ced0ffe640ec70899882f Signed-off-by: Harry Huang --- compass-tasks-base/hdsdiscovery/SNMP_CONFIG.md | 33 +++ compass-tasks-base/hdsdiscovery/__init__.py | 13 + compass-tasks-base/hdsdiscovery/base.py | 185 +++++++++++++ compass-tasks-base/hdsdiscovery/error.py | 26 ++ compass-tasks-base/hdsdiscovery/hdmanager.py | 171 ++++++++++++ compass-tasks-base/hdsdiscovery/utils.py | 289 +++++++++++++++++++++ .../hdsdiscovery/vendors/__init__.py | 13 + .../hdsdiscovery/vendors/appliance/__init__.py | 0 .../hdsdiscovery/vendors/appliance/appliance.py | 34 +++ .../vendors/appliance/plugins/__init__.py | 0 .../hdsdiscovery/vendors/appliance/plugins/mac.py | 48 ++++ .../hdsdiscovery/vendors/arista/__init__.py | 13 + .../hdsdiscovery/vendors/arista/arista.py | 33 +++ .../vendors/arista/plugins/__init__.py | 13 + .../hdsdiscovery/vendors/arista/plugins/mac.py | 24 ++ .../hdsdiscovery/vendors/hp/__init__.py | 13 + compass-tasks-base/hdsdiscovery/vendors/hp/hp.py | 33 +++ .../hdsdiscovery/vendors/hp/plugins/__init__.py | 13 + .../hdsdiscovery/vendors/hp/plugins/mac.py | 23 ++ .../hdsdiscovery/vendors/huawei/__init__.py | 13 + .../hdsdiscovery/vendors/huawei/huawei.py | 33 +++ .../vendors/huawei/plugins/__init__.py | 13 + .../hdsdiscovery/vendors/huawei/plugins/mac.py | 63 +++++ .../hdsdiscovery/vendors/ovswitch/__init__.py | 13 + .../hdsdiscovery/vendors/ovswitch/ovswitch.py | 76 ++++++ .../vendors/ovswitch/plugins/__init__.py | 13 + .../hdsdiscovery/vendors/ovswitch/plugins/mac.py | 87 +++++++ .../hdsdiscovery/vendors/pica8/__init__.py | 13 + .../hdsdiscovery/vendors/pica8/pica8.py | 33 +++ .../hdsdiscovery/vendors/pica8/plugins/__init__.py | 13 + .../hdsdiscovery/vendors/pica8/plugins/mac.py | 24 ++ 31 files changed, 1371 insertions(+) create mode 100644 compass-tasks-base/hdsdiscovery/SNMP_CONFIG.md create mode 100644 compass-tasks-base/hdsdiscovery/__init__.py create mode 100644 compass-tasks-base/hdsdiscovery/base.py create mode 100644 compass-tasks-base/hdsdiscovery/error.py create mode 100644 compass-tasks-base/hdsdiscovery/hdmanager.py create mode 100644 compass-tasks-base/hdsdiscovery/utils.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/__init__.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/appliance/__init__.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/appliance/appliance.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/appliance/plugins/__init__.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/appliance/plugins/mac.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/arista/__init__.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/arista/arista.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/arista/plugins/__init__.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/arista/plugins/mac.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/hp/__init__.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/hp/hp.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/hp/plugins/__init__.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/hp/plugins/mac.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/huawei/__init__.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/huawei/huawei.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/huawei/plugins/__init__.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/huawei/plugins/mac.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/ovswitch/__init__.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/ovswitch/ovswitch.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/ovswitch/plugins/__init__.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/ovswitch/plugins/mac.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/pica8/__init__.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/pica8/pica8.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/pica8/plugins/__init__.py create mode 100644 compass-tasks-base/hdsdiscovery/vendors/pica8/plugins/mac.py (limited to 'compass-tasks-base/hdsdiscovery') diff --git a/compass-tasks-base/hdsdiscovery/SNMP_CONFIG.md b/compass-tasks-base/hdsdiscovery/SNMP_CONFIG.md new file mode 100644 index 0000000..337b542 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/SNMP_CONFIG.md @@ -0,0 +1,33 @@ +Install & Config Prerequisite Packages: + +1. Net-Snmp: + a. #apt-get install -y snmpd snmp libsnmp-python + b. #apt-get install -y snmp-mibs-downloader + For Centos: + # yum install net-snmp net-snmp-utils + + c. create vendor's mibs directory(for example): + - #mkdir -p /root/.snmp/mibs/huawei + - #vim /etc/snmp/snmp.conf (if not exists, create snmp.conf file) + * add vendor;s mibs directory: + mibdirs +/root/.snmp/mibs/huawei + * comment the line: + #mibs: + d. copy vendor's mibs to that directory + e. #vim /etc/default/snmpd + * modify the directive from + TRAPDRUN=no --> TRAPDRUN=yes + For Centos: + # vim /etc/sysconfig/snmpd + * modify into or add the directive + TRAPDRUN=yes + + f. #vim /etc/snmp/snmpd.conf + * add the following line, where $ip is the ip address of manager machine: + com2sec mynetwork $ip/24 public + g. #service snmpd restart + + Note: net-snmp-config is used to see default configuration + +2. paramiko: + #apt-get install python-paramiko diff --git a/compass-tasks-base/hdsdiscovery/__init__.py b/compass-tasks-base/hdsdiscovery/__init__.py new file mode 100644 index 0000000..4ee55a4 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/compass-tasks-base/hdsdiscovery/base.py b/compass-tasks-base/hdsdiscovery/base.py new file mode 100644 index 0000000..77b3b0b --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/base.py @@ -0,0 +1,185 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Base class extended by specific vendor in vendors directory. +A vendor needs to implement abstract methods of base class. +""" +import logging +import re + +from abc import ABCMeta + +from compass.hdsdiscovery.error import TimeoutError +from compass.hdsdiscovery import utils + + +class BaseVendor(object): + """Basic Vendor object.""" + __metaclass__ = ABCMeta + + def is_this_vendor(self, sys_info, **kwargs): + """Determine if the host is associated with this vendor. + + This function must be implemented by vendor itself + """ + raise NotImplementedError + + +class BaseSnmpVendor(BaseVendor): + """Base SNMP-based vendor plugin. + + .. note:: + It uses MIB-II sysDescr value to determine the vendor of the switch. + """ + + def __init__(self, matched_names): + super(BaseSnmpVendor, self).__init__() + self._matched_names = matched_names + + def is_this_vendor(self, sys_info, **kwargs): + """Determine if the switch belongs to this vendor. + + Matching the system information retrieved from the switch. + :param str sys_info: the system information retrieved from a switch + Return True + """ + if sys_info: + for name in self._matched_names: + if re.search(r"\b" + re.escape(name) + r"\b", sys_info, + re.IGNORECASE): + return True + return False + + +class BasePlugin(object): + """Extended by vendor's plugin. + + This plugin processes request and retrieve info directly from the switch. + """ + __metaclass__ = ABCMeta + + def process_data(self, oper='SCAN', **kwargs): + """Each vendors will have some plugins to do some operations. + + Plugin will process request data and return expected result. + + :param oper: operation function name. + :param kwargs: key-value pairs of arguments + """ + raise NotImplementedError + + # At least one of these three functions below must be implemented. + def scan(self, **kwargs): + """Get multiple records at once.""" + pass + + def set(self, **kwargs): + """Set value to desired variable.""" + pass + + def get(self, **kwargs): + """Get one record from a host.""" + pass + + +class BaseSnmpMacPlugin(BasePlugin): + """Base snmp plugin.""" + + def __init__(self, host, credential, oid='BRIDGE-MIB::dot1dTpFdbPort', + vlan_oid='Q-BRIDGE-MIB::dot1qPvid'): + super(BaseSnmpMacPlugin, self).__init__() + self.host = host + self.credential = credential + self.oid = oid + self.port_oid = 'ifName' + self.vlan_oid = vlan_oid + + def process_data(self, oper='SCAN', **kwargs): + """progress data.""" + func_name = oper.lower() + return getattr(self, func_name)(**kwargs) + + def scan(self, **kwargs): + """scan.""" + results = None + try: + results = utils.snmpwalk_by_cl(self.host, self.credential, + self.oid) + except TimeoutError as error: + logging.debug("PluginMac:scan snmpwalk_by_cl failed: %s", + error.message) + return None + + mac_list = [] + for entity in results: + if_index = entity['value'] + if entity and int(if_index): + tmp = {} + mac_numbers = entity['iid'].split('.') + tmp['mac'] = self.get_mac_address(mac_numbers) + tmp['port'] = self.get_port(if_index) + tmp['vlan'] = self.get_vlan_id(if_index) + mac_list.append(tmp) + + return mac_list + + def get_vlan_id(self, port): + """Get vlan Id.""" + if not port: + return None + + oid = '.'.join((self.vlan_oid, port)) + vlan_id = None + result = None + try: + result = utils.snmpget_by_cl(self.host, self.credential, oid) + except TimeoutError as error: + logging.debug("[PluginMac:get_vlan_id snmpget_by_cl failed: %s]", + error.message) + return None + + vlan_id = result.split()[-1] + return vlan_id + + def get_port(self, if_index): + """Get port number.""" + + if_name = '.'.join((self.port_oid, if_index)) + result = None + try: + result = utils.snmpget_by_cl(self.host, self.credential, if_name) + except TimeoutError as error: + logging.debug("[PluginMac:get_port snmpget_by_cl failed: %s]", + error.message) + return None + + # A result may be like "Value: FasterEthernet1/2/34 + port = result.split()[-1].split('/')[-1] + return port + + def convert_to_hex(self, value): + """Convert the integer from decimal to hex.""" + + return "%0.2x" % int(value) + + def get_mac_address(self, mac_numbers): + """Assemble mac address from the list.""" + if len(mac_numbers) != 6: + logging.error("[PluginMac:get_mac_address] MAC address must be " + "6 digitals") + return None + + mac_in_hex = [self.convert_to_hex(num) for num in mac_numbers] + return ":".join(mac_in_hex) diff --git a/compass-tasks-base/hdsdiscovery/error.py b/compass-tasks-base/hdsdiscovery/error.py new file mode 100644 index 0000000..5bcf1a2 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/error.py @@ -0,0 +1,26 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""hdsdiscovery module errors.""" + + +class TimeoutError(Exception): + """Timeout error.""" + + def __init__(self, message): + super(TimeoutError, self).__init__(message) + self.message = message + + def __str__(self): + return repr(self.message) diff --git a/compass-tasks-base/hdsdiscovery/hdmanager.py b/compass-tasks-base/hdsdiscovery/hdmanager.py new file mode 100644 index 0000000..028d444 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/hdmanager.py @@ -0,0 +1,171 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Manage hdsdiscovery functionalities.""" +import logging +import os +import re + +from compass.hdsdiscovery.error import TimeoutError +from compass.hdsdiscovery import utils +from compass.utils import setting_wrapper as setting +from compass.utils import util + + +UNREACHABLE = 'unreachable' +NOTSUPPORTED = 'notsupported' +ERROR = 'error' +REPOLLING = 'repolling' + + +class HDManager(object): + """Process a request.""" + + def __init__(self): + base_dir = os.path.dirname(os.path.realpath(__file__)) + self.vendors_dir = os.path.join(base_dir, 'vendors') + self.vendor_plugins_dir = os.path.join(self.vendors_dir, '?/plugins') + self.snmp_sysdescr = 'sysDescr.0' + + def learn(self, host, credential, vendor, req_obj, oper="SCAN", **kwargs): + """Insert/update record of switch_info. + + Get expected results from switch according to sepcific operation. + + :param req_obj: the object of a machine + :param host: switch IP address + :param credientials: credientials to access switch + :param oper: operations of the plugin (SCAN, GETONE, SET) + :param kwargs(optional): key-value pairs + """ + plugin_dir = self.vendor_plugins_dir.replace('?', vendor) + if not os.path.exists(plugin_dir): + logging.error('No such directory: %s', plugin_dir) + return None + + plugin = utils.load_module(req_obj, plugin_dir, host, credential) + if not plugin: + # No plugin found! + # TODO(Grace): add more code to catch excpetion or unexpected state + logging.error('no plugin %s to load from %s', req_obj, plugin_dir) + return None + + return plugin.process_data(oper, **kwargs) + + def is_valid_vendor(self, host, credential, vendor): + """Check if vendor is associated with this host and credential + + :param host: switch ip + :param credential: credential to access switch + :param vendor: the vendor of switch + """ + vendor_dir = os.path.join(self.vendors_dir, vendor) + if not os.path.exists(vendor_dir): + logging.error('no such directory: %s', vendor_dir) + return False + + sys_info, err = self.get_sys_info(host, credential) + if not sys_info: + logging.debug("[hdsdiscovery][hdmanager][is_valid_vendor]" + "failded to get sys information: %s", err) + return False + + instance = utils.load_module(vendor, vendor_dir) + if not instance: + logging.debug("[hdsdiscovery][hdmanager][is_valid_vendor]" + "No such vendor found!") + return False + + if instance.is_this_vendor(sys_info): + logging.info("[hdsdiscovery][hdmanager][is_valid_vendor]" + "vendor %s is correct!", vendor) + return True + + return False + + def get_vendor(self, host, credential): + """Check and get vendor of the switch. + + :param host: switch ip: + :param credential: credential to access switch + :return a tuple (vendor, switch_state, error) + """ + + switch_lists = util.load_configs(setting.MACHINE_LIST_DIR) + switch_list = [] + for items in switch_lists: + for item in items['MACHINE_LIST']: + for k, v in item.items(): + switch_list.append(k) + if host in switch_list: + return ("appliance", "Found", "") + + # TODO(grace): Why do we need to have valid IP? + # a hostname should also work. + if not utils.valid_ip_format(host): + logging.error("host '%s' is not valid IP address!", host) + return (None, ERROR, "Invalid IP address %s!" % host) + + if not utils.is_valid_snmp_v2_credential(credential): + logging.debug("******The credential %s of host %s cannot " + "be used for either SNMP v2 or SSH*****", + credential, host) + return (None, ERROR, "Invalid credential") + + sys_info, err = self.get_sys_info(host, credential) + if not sys_info: + return (None, UNREACHABLE, err) + + # List all vendors in vendors directory -- a directory but hidden + # under ../vendors + all_vendors = [o for o in os.listdir(self.vendors_dir) + if os.path.isdir(os.path.join(self.vendors_dir, o)) + and re.match(r'^[^\.]', o)] + + logging.debug("[get_vendor][available vendors]: %s ", all_vendors) + logging.debug("[get_vendor] System Information is [%s]", sys_info) + + # TODO(grace): should not conver to lower. The vendor impl can choose + # to do case-insensitive match + # sys_info = sys_info.lower() + vendor = None + for vname in all_vendors: + vpath = os.path.join(self.vendors_dir, vname) + instance = utils.load_module(vname, vpath) + if not instance: + logging.error('no instance %s load from %s', vname, vpath) + continue + + if instance.is_this_vendor(sys_info): + logging.info("[get_vendor]****Found vendor '%s'****", vname) + vendor = vname + break + + if not vendor: + logging.debug("[get_vendor] No vendor found! <==================") + return (None, NOTSUPPORTED, "Not supported switch vendor!") + + return (vendor, REPOLLING, "") + + def get_sys_info(self, host, credential): + """get sys info.""" + sys_info = None + try: + sys_info = utils.snmpget_by_cl(host, + credential, + self.snmp_sysdescr) + except TimeoutError as error: + return (None, error.message) + + return (sys_info, "") diff --git a/compass-tasks-base/hdsdiscovery/utils.py b/compass-tasks-base/hdsdiscovery/utils.py new file mode 100644 index 0000000..72adb0a --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/utils.py @@ -0,0 +1,289 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Utility functions + Including functions of get/getbulk/walk/set of snmp for three versions +""" +import imp +import logging +import re +import subprocess + +from compass.hdsdiscovery.error import TimeoutError + + +def load_module(mod_name, path, host=None, credential=None): + """Load a module instance. + + :param str mod_name: module name + :param str path: directory of the module + :param str host: switch ip address + :param str credential: credential used to access switch + """ + try: + mod_file, path, descr = imp.find_module(mod_name, [path]) + if mod_file: + mod = imp.load_module(mod_name, mod_file, path, descr) + if host and credential: + instance = getattr(mod, mod.CLASS_NAME)(host, credential) + else: + instance = getattr(mod, mod.CLASS_NAME)() + + return instance + except ImportError as exc: + logging.error('No such module found: %s', mod_name) + logging.exception(exc) + return None + + +def ssh_remote_execute(host, username, password, cmd): + """SSH to execute script on remote machine + + :param host: ip of the remote machine + :param username: username to access the remote machine + :param password: password to access the remote machine + :param cmd: command to execute + """ + try: + import paramiko + if not cmd: + logging.error("[hdsdiscovery][utils][ssh_remote_execute] command" + "is None! Failed!") + return None + + client = paramiko.SSHClient() + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + client.connect(host, username=username, password=password, timeout=15) + stdin, stdout, stderr = client.exec_command(cmd) + result = stdout.readlines() + return result + + except ImportError as exc: + logging.error("[hdsdiscovery][utils][ssh_remote_execute] failed to" + "load module 'paramiko', donnot exist!") + logging.exception(exc) + return None + + except Exception as exc: + logging.error("[hdsdiscovery][utils][ssh_remote_execute] failed: %s", + cmd) + logging.exception(exc) + return None + + finally: + stdin.close() + stdout.close() + stderr.close() + client.close() + + +def valid_ip_format(ip_address): + """Valid the format of an Ip address.""" + + if not re.match(r'^((([0-2]?\d{0,2}\.){3}([0-2]?\d{0,2}))' + r'|(([\da-fA-F]{1,4}:){7}([\da-fA-F]{1,4})))$', + ip_address): + # check IP's format is match ipv4 or ipv6 by regex + return False + + return True + +################################################################# +# Implement snmpwalk and snmpget funtionality +# The structure of returned dictionary will by tag/iid/value/type +################################################################# +AUTH_VERSIONS = { + '1': 1, + '2c': 2, + '3': 3 +} + + +def snmp_walk(host, credential, *args, **kwargs): + """Impelmentation of snmpwalk functionality + + :param host: switch ip + :param credential: credential to access switch + :param args: OIDs + :param kwargs: key-value pairs + """ + try: + import netsnmp + + except ImportError: + logging.error("Module 'netsnmp' do not exist! Please install it first") + return None + + if 'version' not in credential or 'community' not in credential: + logging.error("[utils] missing 'version' and 'community' in %s", + credential) + return None + + version = None + if credential['version'] in AUTH_VERSIONS: + version = AUTH_VERSIONS[credential['version']] + + varbind_list = [] + for arg in args: + varbind = netsnmp.Varbind(arg) + varbind_list.append(varbind) + + var_list = netsnmp.VarList(*varbind_list) + + netsnmp.snmpwalk(var_list, + DestHost=host, + Version=version, + Community=credential['community'], + **kwargs) + + result = [] + if not var_list: + logging.error("[hsdiscovery][utils][snmp_walk] retrived no record!") + return result + + for var in var_list: + response = {} + response['elem_name'] = var.tag + response['iid'] = var.iid + response['value'] = var.val + response['type'] = var.type + result.append(response) + + return result + + +def snmp_get(host, credential, object_type, **kwargs): + """Impelmentation of snmp get functionality + + :param object_type: mib object + :param host: switch ip + :param credential: the dict of credential to access switch + """ + try: + import netsnmp + + except ImportError: + logging.error("Module 'netsnmp' do not exist! Please install it first") + return None + + if 'version' not in credential or 'community' not in credential: + logging.error('[uitls][snmp_get] missing keywords in %s for %s', + credential, host) + return None + + version = None + if credential['version'] in AUTH_VERSIONS: + version = AUTH_VERSIONS[credential['version']] + + varbind = netsnmp.Varbind(object_type) + res = netsnmp.snmpget(varbind, + DestHost=host, + Version=version, + Community=credential['community'], + **kwargs) + if res and res[0]: + return res[0] + + logging.info('no result found for %s %s', host, credential) + return None + + +SSH_CREDENTIALS = {"username": "", "password": ""} +SNMP_V2_CREDENTIALS = {"version": "", "community": ""} + + +def is_valid_snmp_v2_credential(credential): + """check if credential is valid snmp v2 credential.""" + if credential.keys() != SNMP_V2_CREDENTIALS.keys(): + return False + if credential['version'] != '2c': + logging.error("The value of version in credential is not '2c'!") + return False + return True + + +def is_valid_ssh_credential(credential): + """check if credential is valid ssh credential.""" + if credential.keys() != SSH_CREDENTIALS.keys(): + return False + return True + + +def snmpget_by_cl(host, credential, oid, timeout=8, retries=3): + """snmpget by credential.""" + if not is_valid_snmp_v2_credential(credential): + logging.error("[utils][snmpget_by_cl] Credential %s cannot be used " + "for SNMP request!", credential) + return None + + version = credential['version'] + community = credential['community'] + cmd = "snmpget -v %s -c %s -Ob -r %s -t %s %s %s" % ( + version, community, retries, timeout, host, oid) + + returncode, output, err = exec_command(cmd) + + if returncode and err: + logging.error("[snmpget_by_cl] %s", err) + raise TimeoutError(err.strip('\n')) + + return output.strip('\n') + + +def snmpwalk_by_cl(host, credential, oid, timeout=5, retries=3): + """snmpwalk by credential.""" + if not is_valid_snmp_v2_credential(credential): + logging.error("[utils][snmpwalk_by_cl] Credential %s cannot be used " + "for SNMP request!", credential) + return None + + version = credential['version'] + community = credential['community'] + cmd = "snmpwalk -v %s -c %s -Cc -r %s -t %s -Ob %s %s" % ( + version, community, retries, timeout, host, oid) + + returncode, output, err = exec_command(cmd) + + if returncode and err: + logging.debug("[snmpwalk_by_cl] %s ", err) + raise TimeoutError(err) + + result = [] + if not output: + return result + + output = output.split('\n') + for line in output: + if not line: + continue + temp = {} + arr = line.split(" ") + temp['iid'] = arr[0].split('.', 1)[-1] + temp['value'] = arr[-1] + result.append(temp) + + return result + + +def exec_command(command): + """Execute command. + + Return a tuple: returncode, output and error message(None if no error). + """ + sub_p = subprocess.Popen(command, + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + output, err_msg = sub_p.communicate() + return (sub_p.returncode, output, err_msg) diff --git a/compass-tasks-base/hdsdiscovery/vendors/__init__.py b/compass-tasks-base/hdsdiscovery/vendors/__init__.py new file mode 100644 index 0000000..4ee55a4 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/compass-tasks-base/hdsdiscovery/vendors/appliance/__init__.py b/compass-tasks-base/hdsdiscovery/vendors/appliance/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/compass-tasks-base/hdsdiscovery/vendors/appliance/appliance.py b/compass-tasks-base/hdsdiscovery/vendors/appliance/appliance.py new file mode 100644 index 0000000..3d66f4e --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/appliance/appliance.py @@ -0,0 +1,34 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +"""Vendor: Compass Appliance""" +from compass.hdsdiscovery import base + + +# Vendor_loader will load vendor instance by CLASS_NAME +CLASS_NAME = 'Appliance' + + +class Appliance(base.BaseSnmpVendor): + """Fake SNMP object for compass appliance.""" + + def __init__(self): + base.BaseSnmpVendor.__init__(self, ['appliance']) + self.__name = 'appliance' + + @property + def name(self): + """Get 'name' proptery.""" + return self.__name diff --git a/compass-tasks-base/hdsdiscovery/vendors/appliance/plugins/__init__.py b/compass-tasks-base/hdsdiscovery/vendors/appliance/plugins/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/compass-tasks-base/hdsdiscovery/vendors/appliance/plugins/mac.py b/compass-tasks-base/hdsdiscovery/vendors/appliance/plugins/mac.py new file mode 100644 index 0000000..cc14881 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/appliance/plugins/mac.py @@ -0,0 +1,48 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Compass Appliance Mac module.""" +from compass.hdsdiscovery import base +from compass.utils import setting_wrapper as setting +from compass.utils import util + +import logging + + +CLASS_NAME = "Mac" + + +class Mac(base.BaseSnmpMacPlugin): + """Processes MAC address.""" + + def __init__(self, host, credential): + self.host = host + # self.credential = credential + # return + + def scan(self): + """Implemnets the scan method in BasePlugin class. + + .. note:: + Dummy scan function for compass appliance. + Returns fixed mac addresses. + """ + mac_list = None + machine_lists = util.load_configs(setting.MACHINE_LIST_DIR) + for items in machine_lists: + for item in items['MACHINE_LIST']: + for k, v in item.items(): + if k == self.host: + mac_list = v + return mac_list diff --git a/compass-tasks-base/hdsdiscovery/vendors/arista/__init__.py b/compass-tasks-base/hdsdiscovery/vendors/arista/__init__.py new file mode 100644 index 0000000..4ee55a4 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/arista/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/compass-tasks-base/hdsdiscovery/vendors/arista/arista.py b/compass-tasks-base/hdsdiscovery/vendors/arista/arista.py new file mode 100644 index 0000000..5eacea1 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/arista/arista.py @@ -0,0 +1,33 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Vendor: Arista.""" +from compass.hdsdiscovery import base + + +# Vendor_loader will load vendor instance by CLASS_NAME +CLASS_NAME = 'Arista' + + +class Arista(base.BaseSnmpVendor): + """Arista Network switch object.""" + + def __init__(self): + base.BaseSnmpVendor.__init__(self, ['arista']) + self._name = 'arista' + + @property + def name(self): + """Get 'name' proptery.""" + return self._name diff --git a/compass-tasks-base/hdsdiscovery/vendors/arista/plugins/__init__.py b/compass-tasks-base/hdsdiscovery/vendors/arista/plugins/__init__.py new file mode 100644 index 0000000..4ee55a4 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/arista/plugins/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/compass-tasks-base/hdsdiscovery/vendors/arista/plugins/mac.py b/compass-tasks-base/hdsdiscovery/vendors/arista/plugins/mac.py new file mode 100644 index 0000000..ed2f331 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/arista/plugins/mac.py @@ -0,0 +1,24 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Pica8 Switch Mac module.""" +from compass.hdsdiscovery.base import BaseSnmpMacPlugin + + +CLASS_NAME = 'Mac' + + +class Mac(BaseSnmpMacPlugin): + """Process MAC address by Arista switch.""" + pass diff --git a/compass-tasks-base/hdsdiscovery/vendors/hp/__init__.py b/compass-tasks-base/hdsdiscovery/vendors/hp/__init__.py new file mode 100644 index 0000000..4ee55a4 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/hp/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/compass-tasks-base/hdsdiscovery/vendors/hp/hp.py b/compass-tasks-base/hdsdiscovery/vendors/hp/hp.py new file mode 100644 index 0000000..7ddc5e9 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/hp/hp.py @@ -0,0 +1,33 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Vendor: HP.""" +from compass.hdsdiscovery import base + + +# Vendor_loader will load vendor instance by CLASS_NAME +CLASS_NAME = 'Hp' + + +class Hp(base.BaseSnmpVendor): + """Hp switch object.""" + + def __init__(self): + base.BaseSnmpVendor.__init__(self, ['hp', 'procurve']) + self.names = ['hp', 'procurve'] + + @property + def name(self): + """Get 'name' proptery.""" + return self.names[0] diff --git a/compass-tasks-base/hdsdiscovery/vendors/hp/plugins/__init__.py b/compass-tasks-base/hdsdiscovery/vendors/hp/plugins/__init__.py new file mode 100644 index 0000000..4ee55a4 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/hp/plugins/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/compass-tasks-base/hdsdiscovery/vendors/hp/plugins/mac.py b/compass-tasks-base/hdsdiscovery/vendors/hp/plugins/mac.py new file mode 100644 index 0000000..3bc81f4 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/hp/plugins/mac.py @@ -0,0 +1,23 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""HP Switch Mac module.""" +from compass.hdsdiscovery.base import BaseSnmpMacPlugin + +CLASS_NAME = 'Mac' + + +class Mac(BaseSnmpMacPlugin): + """Process MAC address by HP switch.""" + pass diff --git a/compass-tasks-base/hdsdiscovery/vendors/huawei/__init__.py b/compass-tasks-base/hdsdiscovery/vendors/huawei/__init__.py new file mode 100644 index 0000000..4ee55a4 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/huawei/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/compass-tasks-base/hdsdiscovery/vendors/huawei/huawei.py b/compass-tasks-base/hdsdiscovery/vendors/huawei/huawei.py new file mode 100644 index 0000000..19fd043 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/huawei/huawei.py @@ -0,0 +1,33 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Huawei Switch.""" +from compass.hdsdiscovery import base + + +# Vendor_loader will load vendor instance by CLASS_NAME +CLASS_NAME = "Huawei" + + +class Huawei(base.BaseSnmpVendor): + """Huawei switch.""" + + def __init__(self): + base.BaseSnmpVendor.__init__(self, ["huawei"]) + self.__name = "huawei" + + @property + def name(self): + """Return switch name.""" + return self.__name diff --git a/compass-tasks-base/hdsdiscovery/vendors/huawei/plugins/__init__.py b/compass-tasks-base/hdsdiscovery/vendors/huawei/plugins/__init__.py new file mode 100644 index 0000000..4ee55a4 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/huawei/plugins/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/compass-tasks-base/hdsdiscovery/vendors/huawei/plugins/mac.py b/compass-tasks-base/hdsdiscovery/vendors/huawei/plugins/mac.py new file mode 100644 index 0000000..49d3863 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/huawei/plugins/mac.py @@ -0,0 +1,63 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Huawei Switch Mac module.""" +import logging + +from compass.hdsdiscovery.base import BaseSnmpMacPlugin +from compass.hdsdiscovery import utils + + +CLASS_NAME = "Mac" + + +class Mac(BaseSnmpMacPlugin): + """Processes MAC address.""" + + def __init__(self, host, credential): + super(Mac, self).__init__( + host, credential, + 'HUAWEI-L2MAM-MIB::hwDynFdbPort') + + def scan(self): + """Implemnets the scan method in BasePlugin class. + + .. note:: + In this mac module, mac addesses were retrieved by + snmpwalk commandline. + """ + results = utils.snmpwalk_by_cl(self.host, self.credential, self.oid) + + if not results: + logging.info("[Huawei][mac] No results returned from SNMP walk!") + return None + + mac_list = [] + + for entity in results: + # The format of 'iid' is like '248.192.1.214.34.15.31.1.48' + # The first 6 numbers will be the MAC address + # The 7th number is its vlan ID + numbers = entity['iid'].split('.') + mac = self.get_mac_address(numbers[:6]) + vlan = numbers[6] + port = self.get_port(entity['value']) + + tmp = {} + tmp['port'] = port + tmp['mac'] = mac + tmp['vlan'] = vlan + mac_list.append(tmp) + + return mac_list diff --git a/compass-tasks-base/hdsdiscovery/vendors/ovswitch/__init__.py b/compass-tasks-base/hdsdiscovery/vendors/ovswitch/__init__.py new file mode 100644 index 0000000..4ee55a4 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/ovswitch/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/compass-tasks-base/hdsdiscovery/vendors/ovswitch/ovswitch.py b/compass-tasks-base/hdsdiscovery/vendors/ovswitch/ovswitch.py new file mode 100644 index 0000000..4d03328 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/ovswitch/ovswitch.py @@ -0,0 +1,76 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Open Vswitch module.""" +import logging +import re + +from compass.hdsdiscovery import base +from compass.hdsdiscovery import utils + + +# Vendor_loader will load vendor instance by CLASS_NAME +CLASS_NAME = "OVSwitch" + + +class OVSwitch(base.BaseVendor): + """Open Vswitch.""" + def __init__(self): + self.__name = "Open vSwitch" + + def is_this_vendor(self, sys_info, host=None, credential=None, **kwargs): + """Determine if the hostname is accociated witH this vendor. + + :param host: swtich's IP address + :param credential: credential to access switch + """ + result = sys_info + if host and credential: + if utils.is_valid_ssh_credential(credential): + user = credential['username'] + pwd = credential['password'] + + else: + msg = ("[OVSwitch]The format of credential %r is not for SSH " + "or incorrect Keywords! " % credential) + logging.info(msg) + return False + + cmd = "ovs-vsctl -V" + result = None + try: + result = utils.ssh_remote_execute(host, user, pwd, cmd) + logging.debug('%s result for %s is %s', cmd, host, result) + if not result: + return False + except Exception as exc: + logging.error("No vendor or connection failed to run %s", cmd) + logging.exception(exc) + return False + + if isinstance(result, str): + result = [result] + + for line in result: + if not line: + continue + if re.search(r"\b" + re.escape(self.__name) + r"\b", line): + return True + + return False + + @property + def name(self): + """Open Vswitch name.""" + return self.__name diff --git a/compass-tasks-base/hdsdiscovery/vendors/ovswitch/plugins/__init__.py b/compass-tasks-base/hdsdiscovery/vendors/ovswitch/plugins/__init__.py new file mode 100644 index 0000000..4ee55a4 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/ovswitch/plugins/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/compass-tasks-base/hdsdiscovery/vendors/ovswitch/plugins/mac.py b/compass-tasks-base/hdsdiscovery/vendors/ovswitch/plugins/mac.py new file mode 100644 index 0000000..5f497a0 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/ovswitch/plugins/mac.py @@ -0,0 +1,87 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Open Vswitch Mac address module.""" +import logging + +from compass.hdsdiscovery import base +from compass.hdsdiscovery import utils + + +CLASS_NAME = "Mac" + + +class Mac(base.BasePlugin): + """Open Vswitch MAC address module.""" + def __init__(self, host, credential): + self.host = host + self.credential = credential + + def process_data(self, oper="SCAN", **kwargs): + """Dynamically call the function according 'oper' + + :param oper: operation of data processing + """ + func_name = oper.lower() + return getattr(self, func_name)(**kwargs) + + def scan(self, **kwargs): + """Implemnets the scan method in BasePlugin class. + + .. note:: + In this module, mac addesses were retrieved by ssh. + """ + try: + user = self.credential['username'] + pwd = self.credential['password'] + except KeyError: + logging.error("Cannot find username and password in credential") + return None + + cmd = ("BRIDGES=$(ovs-vsctl show |grep Bridge |cut -f 2 -d '\"');" + "for br in $BRIDGES; do" + "PORTS=$(ovs-ofctl show $br |grep addr |cut -f 1 -d ':' " + "|egrep -v 'eth|wlan|LOCAL'|awk -F '(' '{print $1}');" + "for port in $PORTS; do" + "RESULT=$(ovs-appctl fdb/show $br |" + "awk '$1 == '$port' {print $1" "$2" "$3}');" + "echo '$RESULT'" + "done;" + "done;") + output = None + try: + output = utils.ssh_remote_execute(self.host, user, pwd, cmd) + except Exception as error: + logging.exception(error) + return None + + logging.debug("[scan][output] output is %s", output) + if not output: + return None + + fields_arr = ['port', 'vlan', 'mac'] + + result = [] + for line in output: + if not line or line == '\n': + continue + + values_arr = line.split() + temp = {} + for field, value in zip(fields_arr, values_arr): + temp[field] = value + + result.append(temp.copy()) + + return result diff --git a/compass-tasks-base/hdsdiscovery/vendors/pica8/__init__.py b/compass-tasks-base/hdsdiscovery/vendors/pica8/__init__.py new file mode 100644 index 0000000..4ee55a4 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/pica8/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/compass-tasks-base/hdsdiscovery/vendors/pica8/pica8.py b/compass-tasks-base/hdsdiscovery/vendors/pica8/pica8.py new file mode 100644 index 0000000..856817e --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/pica8/pica8.py @@ -0,0 +1,33 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Vendor: Pica8.""" +from compass.hdsdiscovery import base + + +# Vendor_loader will load vendor instance by CLASS_NAME +CLASS_NAME = 'Pica8' + + +class Pica8(base.BaseSnmpVendor): + """Pica8 switch object.""" + + def __init__(self): + base.BaseSnmpVendor.__init__(self, ['pica8']) + self._name = 'pica8' + + @property + def name(self): + """Get 'name' proptery.""" + return self._name diff --git a/compass-tasks-base/hdsdiscovery/vendors/pica8/plugins/__init__.py b/compass-tasks-base/hdsdiscovery/vendors/pica8/plugins/__init__.py new file mode 100644 index 0000000..4ee55a4 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/pica8/plugins/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/compass-tasks-base/hdsdiscovery/vendors/pica8/plugins/mac.py b/compass-tasks-base/hdsdiscovery/vendors/pica8/plugins/mac.py new file mode 100644 index 0000000..d5ccfc0 --- /dev/null +++ b/compass-tasks-base/hdsdiscovery/vendors/pica8/plugins/mac.py @@ -0,0 +1,24 @@ +# Copyright 2014 Huawei Technologies Co. Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Pica8 Switch Mac module.""" +from compass.hdsdiscovery.base import BaseSnmpMacPlugin + + +CLASS_NAME = 'Mac' + + +class Mac(BaseSnmpMacPlugin): + """Process MAC address by Pica8 switch.""" + pass -- cgit 1.2.3-korg