compass-core/compass/hdsdiscovery/utils.py
grace.yu 65d9d18c74 Fixed hdsdiscover utils.py bug and updated networking validation
Change-Id: I44488ed2f52f3c1fe9a56050e383176d117ca97f
2014-03-24 17:13:17 -07:00

289 lines
8.7 KiB
Python

# 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)