Python实现网络出口带宽自动巡检

  • 数据获取
  • 1.eSitht介绍
  • 2.eSight API
  • 3.获取openid
  • 4.获取接口数据
  • 数据解析
  • 1.获取最值与均值
  • 2.按照单位排序
  • 代码整理



今天跟大家分享一个多职场网络出口带宽自动巡检的实例,话不多说,先看一下效果:

windows python 巡检脚本 python网络巡检_网络


windows python 巡检脚本 python网络巡检_运维_02


实现的流程步骤大致如下,最后设置定时任务即可实现定时自动巡检,省心省事~


windows python 巡检脚本 python网络巡检_windows python 巡检脚本_03


由于整体涉及的内容较多,今天我们挑核心部分进行分享:

  • 数据获取 — 通过eSight API获取接口历史数据
  • 数据解析 — 解析数据获取最大值与平均值


数据获取

1.eSitht介绍

eSight :大华为的一款网络监控系统,用于对网络设备进行监管。

提供存储、服务器、应用、交换机、路由器、防火墙、WLAN、PON网络、无线宽带集群设备、视频监控、IP话机、视讯设备等多种设备的统一管理,支持多厂商设备统一视图、资源,拓扑、故障、性能以及智能配置功能,同时为客户提供第三方设备的定制能力与告警北向接口,帮助客户打造专属的统一管理系统,降低运维成本,提升运维效率。

瞄一眼界面(我不是来打广告的…)

windows python 巡检脚本 python网络巡检_API_04


windows python 巡检脚本 python网络巡检_网络_05


windows python 巡检脚本 python网络巡检_网络_06


windows python 巡检脚本 python网络巡检_API_07

2.eSight API

此实例中,我们需要获取的目标数据是指定设备指定接口指定时间段的所有历史数据,官方文档提供的API中,如下API可实现我们的需求:

/rest/openapi/pm/historyByIndexKeys

需要使用POST请求,请求头与数据信息格式如下:

windows python 巡检脚本 python网络巡检_python_08


API文档链接:https://support.huawei.com/hedex/hdx.do?docid=EDOC1000184141&id=ZH-CN_TOPIC_0080904630&lang=zh

windows python 巡检脚本 python网络巡检_python_09


可以看到在POST请求的Headers属性中有个必选项openid,此属性类似cookie,在我们进行请求时可免认证,获取该属性的请求方法为另一API:

/rest/openapi/sm/session

windows python 巡检脚本 python网络巡检_python_10


API文档链接:https://support.huawei.com/hedex/pages/EDOC1000184141AZH01028/17/EDOC1000184141AZH01028/17/resources/api/SemiXML(0016119902)/p_openapi_start.html

3.获取openid

我们按照官方文档的要求构建PUT请求获取openid,代码:

import json
import requests
requests.packages.urllib3.disable_warnings()
url = 'https://10.0.12.100:32102/rest/openapi/sm/session'
data = {
    'userid': 'Username',
    'value': 'Password',
}
response = requests.put(url=url, json=data, verify=False)
result = response.text
content = json.loads(result)
openid = content['data']
print(openid)

输出看一下,大致长这样:

e4a86c579cefedfea3edabec8688a44453d6b98d78c16ad

4.获取接口数据

得到openid后,我们可以正式获取接口历史数据了,按照上述提到的API和参数说明准备对应的参数值:

/rest/openapi/pm/historyByIndexKeys

windows python 巡检脚本 python网络巡检_API_11


请求头参数:

openid:用于登录,通过指定API获取

mos:网元信息,包含{dn,displayValue}

  • dn:网元设备编号,可在eSight中点击对应设备获取
  • displayValue:测量对象名称,对应性能数据页面测量对象列。对于接口和单板而言一般是接口名称或者单板名称。

indexKeys:指标对象集合,包含{resourceType,measUnitKey,measTypeKey}

  • resourceType:资源类型
  • measUnitKey:指标组
  • measTypeKey:指标
  • 如上信息可参考性能指标列表

beginTime:起始时间戳 UTC 精确到毫秒
endTime:结束时间戳 UTC 精确到毫秒

由于需要指定开始和结束的时间戳,我们先构造一个生成对应时间戳的方法,用来请求过去某天0点的时间戳,如下:

import time
from datetime import datetime, timedelta
def get_time(day):
    yesterday = datetime.today().date() - timedelta(days=day)
    starttime = int(time.mktime(time.strptime(str(yesterday), '%Y-%m-%d')))
    return starttime * 1000

准备就绪后,可以开始构造POST请求获取接口历史数据,代码如下:

import requests
requests.packages.urllib3.disable_warnings()
url = 'https://10.0.12.100:32102/rest/openapi/pm/historyByIndexKeys'
header = {
    'openid': 'e4a86c579cefedfea3edabec8688a44453d6b98d78c16ad',
}
data = {
    'mos': [{
        'dn': 'NE=34614106',
        'displayValue': 'XGigabitEthernet1/1/0/44',
    }],
    'indexKeys': [{
        "resourceType": "interface",
        "measUnitKey": "ifXTrafficStat",
        "measTypeKey": "ifHCInOctetsSpeed"
    }],
    'beginTime': get_time(1),
    'endTime': get_time(0),
}
response = requests.post(url=url, headers=header, json=data, verify=False)
result = response.text
content = json.loads(result)
print(content)

成功获取接口历史数据,结果输出如下:

windows python 巡检脚本 python网络巡检_API_12

数据解析

1.获取最值与均值

如下红框内数据为我们需要的接口流量历史数据,eSight采集的时间间隔为1分钟,所以一个接口一天产生的值为24*60个,我们先将数据采集到指定列表中:

windows python 巡检脚本 python网络巡检_python_13


代码如下:

value_list = []
for resultData in content['data']['resultData']:
    for value in resultData['indexValues']:
        value_list.append(float(value['indexValue']))

对纯浮点型元素的列表取最大值和平均值,那就是信手拈来的事啦
取最大值:

max = sorted(value_list)[-1]

最平均值:

import numpy as np
ave = np.mean(value_list)

2.按照单位排序

按照上面的步骤,我们已经取出了一个接口的最值与均值,但是细心的同学可以看到,我们获取的数据是有带单位的,而且单位是按照数值自适应,无法在API请求时进行指定的,如下:

windows python 巡检脚本 python网络巡检_API_14


我们的出口设备一般都有做HA,且单台设备也可能有冗余接口,如果我们按照上面的方法对一台设备所有接口进行取值与排序,有可能会出现主业务口最大值1.80Gbps,备用接口最大值70.23Kbps的情况,这在我们后续结合所有接口计算设备总体最大值时,会出现数据异常的问题。为解决这个问题,我们将所有数据统一换算成中间单位Mbps进行计算:

unit = content['data']['resultData'][0]['indexUnit']
if unit == 'Gbps':
    print(max * 1000, round(ave * 1000, 2))
elif unit == 'Mbps':
    print(max, round(ave, 2))
elif unit == 'Kbps':
    print(round(max / 1000, 2), round(ave / 1000, 2))
else:
    print('数据异常')

代码整理

上面零碎的方法已经实现了我们的需求,现在要做的就是将代码进行整理,封装成类,方便后续调用:

#eSight接口类
class eSightAPI:
    #初始化
    def __init__(self, IP, dn, location, interface):
        '''
        :param IP: eSight管理IP
        :param dn: 网元DN
        :param location: 职场描述
        :param interface: 需查询的设备接口
        '''
        self.host = '{}:32102'.format(IP)
        self.username = 'Username'
        self.passwd = 'Password'
        self.session = requests.session()
        self.dn = dn
        self.interface = interface
        self.location = location

    #获取openid
    def get_openid(self):
        #PUT请求
        requests.packages.urllib3.disable_warnings()
        url = 'https://' + self.host + '/rest/openapi/sm/session'
        data = {
            'userid': self.username,
            'value': self.passwd,
        }
        try:
            response = self.session.put(url=url, json=data, verify=False)
            result = response.text
            content = json.loads(result)
            openid = content['data']
            # print(content)
            return openid
        except:
            print(traceback.print_exc())


    #获取与当天相隔day天的0点时间戳
    def get_time(self, day):
        yesterday = datetime.today().date() - timedelta(days=day)
        starttime = int(time.mktime(time.strptime(str(yesterday), '%Y-%m-%d')))
        return starttime * 1000


    #获取指定时间段接口信息
    def get_data(self):
        #POST请求
        try:
            requests.packages.urllib3.disable_warnings()
            url = 'https://' + self.host + '/rest/openapi/pm/historyByIndexKeys'
            header = {
                'openid': self.get_openid(),
            }
            # inter_list = []
            # for dn in self.dn:
            # for inter in self.interface:
            # inter_list.append({'dn': dn, 'displayValue': inter})
            data = {
                # 'mos': inter_list,
                'mos': [{
                    'dn': self.dn,
                    'displayValue': self.interface,
                }],
                'indexKeys':[{
                    "resourceType" : "interface",
                    "measUnitKey": "ifXTrafficStat",
                    "measTypeKey": "ifHCInOctetsSpeed"
                }],
                'beginTime': self.get_time(1),
                'endTime': self.get_time(0),
            }
            response = requests.post(url=url, headers=header, json=data, verify=False)
            result = response.text
            content = json.loads(result)
            return content
        except:
            return None


    #解析接口信息,返回最大值与平均值
    def get_value(self):
        content = self.get_data()
        if content == None:
            des = '{} 接口:{} 数据获取异常,请检查!'.format(self.location, self.interface)
            return None, des
        value_list = []
        for resultData in content['data']['resultData']:
            for value in resultData['indexValues']:
                # print(value['indexValue'])
                value_list.append(float(value['indexValue']))
        unit = content['data']['resultData'][0]['indexUnit']
        max = sorted(value_list)[-1]
        ave = np.mean(value_list)
        # print(self.location, max, ave, unit)
        if unit == 'Gbps':
            return max * 1000, round(ave * 1000, 2)
        elif unit == 'Mbps':
            return max, round(ave, 2)
        elif unit == 'Kbps':
            return round(max / 1000, 2), round(ave / 1000, 2)
        else:
            return 0, 0

后续再加上多线程和邮件功能就能实现开头演示的效果啦~



以上是本期的所有内容,感谢您的阅读~