一、设计

公司设备较多,有时需要匹配一些设备之间的关系。这里以NAS存储和主机之间的关联关系。存储都分了那些lun,给了哪些主机使用?理清这些关系如果全靠纯手工来做是比较繁琐的。这时候可以借助自动化工具+采集脚本,自动完成入库操作即可。定期的跑下任备就行了。

使用df -t nfs输出并排除首行的说明,内容如下:

1192.168.7.252:/HYMANAGER  197G  130G   68G  66% /logs
2192.168.7.253:/fs_hymanager  493G  241G  252G  49% /home/hymanager/share_files

数据库表设计:

 1CREATE TABLE `nas` (
 2  `id` int(11) NOT NULL AUTO_INCREMENT,
 3  `hostname` varchar(30) NOT NULL,
 4  `ipaddr` varchar(20) NOT NULL,
 5  `nasip` varchar(30) NOT NULL,
 6  `naslun` varchar(100) NOT NULL,
 7  `size` varchar(40) NOT NULL,
 8  `used` varchar(40) NOT NULL,
 9  `avail` varchar(40) NOT NULL,
10  `usepercent` varchar(10) NOT NULL,
11  `mounted` varchar(100) NOT NULL,
12  `upday` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
13  PRIMARY KEY (`id`)
14) ENGINE=InnoDB DEFAULT CHARSET=utf8;

表结构如下:

nas-tables
nas-tables

二、web api

表设计好了,也可以通过从主机上取数据了。接下来就写个API 主动可以接受入库数据。代码如下:

 1package main
 2import (
 3    "bytes"
 4    "database/sql"
 5    "fmt"
 6    "net/http"
 7    "github.com/gin-gonic/gin"
 8    _ "github.com/go-sql-driver/mysql"
 9)
10func main() {
11    db, err := sql.Open("mysql", "root:password@tcp(127.0.0.1:3306)/gotest")
12    if err != nil {
13        fmt.Print(err.Error())
14    }
15    defer db.Close()
16    // make sure connection is available
17    err = db.Ping()
18    if err != nil {
19        fmt.Print(err.Error())
20    }
21    router := gin.Default()
22    // POST new person details
23    router.POST("/nfs", func(c *gin.Context) {
24        hostname := c.PostForm("hostname")
25        ipaddr := c.PostForm("ipaddr")
26        nasip := c.PostForm("nasip")
27        naslun := c.PostForm("naslun")
28        size := c.PostForm("size")
29        used := c.PostForm("used")
30        avail := c.PostForm("avail")
31        usepercent := c.PostForm("usepercent")
32        mounted := c.PostForm("mounted")
33        stmt, err := db.Prepare("insert into nas (hostname,ipaddr,nasip,naslun,size,used,avail,usepercent,mounted) values(?,?,?,?,?,?,?,?,?);")
34        if err != nil {
35            fmt.Print(err.Error())
36        }
37        _, err = stmt.Exec(hostname, ipaddr, nasip, naslun, size, used, avail, usepercent, mounted)
38        if err != nil {
39            fmt.Print(err.Error())
40        }
41        // Fastest way to append strings
42        defer stmt.Close()
43        c.JSON(http.StatusOK, gin.H{
44            "message": fmt.Sprintf("successfully created"),
45        })
46    })
47    router.Run(":3000")
48}

此时通过curl 入库时会报错:error on parse multipart form array: invalid URL escape “%” ,查看发现是使用百分比一项,由于有特殊符号%号导致无法成功入库该项的值。

三、解决入库报错

这里有几种方法可借操作:1、将百分号去掉;2、使用xxd就是进行URLencode转换;3、使用curl自身的转码方式进行URLencode转码。

第一种方式实现代码如下:

1ipaddr=`curl http://10.212.149.204/myip`
2df -t nfs -hP|sed 's/[:%]/ /g'|awk 'NR>1{print $0}' | while read nasip naslun size used avail usepercent mounted
3do
4   curl -d  "hostname=$HOSTNAME&ipaddr=$ipaddr&nasip=$nasip&naslun=$naslun&size=$size&used=$used&avail=$avail&usepercent=$usepercent&mounted=$m
5ounted" http://10.212.52.14:3000/nfs
6done

第二种方式代码类似如下:

1ipaddr=`curl http://10.212.149.204/myip`
2df -t nfs -hP|sed 's/:/ /g'|awk 'NR>1{print $0}' | while read nasip naslun size used avail usepercent mounted
3do
4    percent=`echo "$usepercent" | tr -d '\n' | xxd -plain | sed 's/\(..\)/%\1/g'`
5    echo $percent
6    echo  "hostname=$HOSTNAME&ipaddr=$ipaddr&nasip=$nasip&naslun=$naslun&size=$size&used=$used&avail=$avail&usepercent=$percent&mounted=$mounted"
7    curl -d  "hostname=$HOSTNAME&ipaddr=$ipaddr&nasip=$nasip&naslun=$naslun&size=$size&used=$used&avail=$avail&usepercent=$percent&mounted=$mounted" http://10.212.52.14:3000/nfs
8done

第三种方式具体可以参考:

三种方式了我选择了第一种,好处就是便于进行百分比使用率查询。比如使用select 语名查询时,想要查询百分比使用大于多少或少于多少的,直接使用比较运算符就可以了。

结合现网的自动化工具,5分钟内就可以完成几千台数据的采集入库。入库完成后,再配合python pandas模块分容易的就可以通过查询数据库输出为excel文件

1from sqlalchemy import create_engine
2import time
3import pandas as pd
4today = time.strftime("%Y%m%d", time.localtime())
5engine = create_engine('mysql+pymysql://root:passwd@localhost:3306/gotest')
6sql = "select * from nas where upday=today";
7dsql=pd.read_sql(sql,con = engine)
8dsql.to_excel("nfs.xlsx",index=False)

再通过邮件定时更新该数据表。具体结果如下(点击图片看大图):

nfs-excel
nfs-excel