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


今天跟大家分享一个多职场网络出口带宽自动巡检的实例,话不多说,先看一下效果: 自动巡检
在这里插入图片描述
实现的流程步骤大致如下,最后设置定时任务即可实现定时自动巡检,省心省事~
在这里插入图片描述
由于整体涉及的内容较多,今天我们挑核心部分进行分享:

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


数据获取

1.eSitht介绍

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

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

瞄一眼界面(我不是来打广告的…)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.eSight API

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

/rest/openapi/pm/historyByIndexKeys

需要使用POST请求,请求头与数据信息格式如下:
在这里插入图片描述
API文档链接:https://support.huawei.com/hedex/hdx.do?docid=EDOC1000184141&id=ZH-CN_TOPIC_0080904630&lang=zh
在这里插入图片描述
可以看到在POST请求的Headers属性中有个必选项openid,此属性类似cookie,在我们进行请求时可免认证,获取该属性的请求方法为另一API:

/rest/openapi/sm/session

在这里插入图片描述
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

在这里插入图片描述
请求头参数:
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)

成功获取接口历史数据,结果输出如下:
在这里插入图片描述

数据解析

1.获取最值与均值

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

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请求时进行指定的,如下:
在这里插入图片描述
我们的出口设备一般都有做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

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



以上是本期的所有内容,感谢您的阅读~
希望每个看完本文的您都能有所收获,如果您觉得本文不错,可以点一波关注或者关注一下我的公众号~
您的支持是我最大的动力!
在这里插入图片描述

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值