接上篇博文


尝试添加一张主机表,用于管理主机信息

无非表的内容是host,那么肯定是在schema中建立,直接写描述即可

schema 填入id,id默认是1,name对应的是host

这里虚拟表所对应的东西是1,描述的字段还暂时没有

如下所示:

MariaDB [cmdb]> insert into `schema`(name) values('hosts');
MariaDB [cmdb]> select * from `schema`;
+----+-------+------+
| id | name  | desc |
+----+-------+------+
|  1 | hosts | NULL |
+----+-------+------+
1 row in set (0.00 sec)

描述字段

通过filed表中添加两个字段 hostname,schema_id 这俩字段与host与关,其实就是与id与关联

这样自增的话,会产生第一个索引,那如果再进行添加ip 的话,则id是2

MariaDB [cmdb]> insert into `field` (name,schema_id) value ('hostname',1);
MariaDB [cmdb]> insert into `field` (name,schema_id) value ('ip',1);
MariaDB [cmdb]> select * from field;
+----+----------+------+-----------+
| id | name     | meta | schema_id |
+----+----------+------+-----------+
|  1 | hostname | NULL |         1 |
|  5 | ip       | NULL |         1 |
+----+----------+------+-----------+
2 rows in set (0.00 sec)

如上,这里value对应的schema_id 都是1,也就是找到schema表中与id=1对应相关的表,也就是属hosts所管辖

MariaDB [cmdb]> select * from `schema`;
+----+-------+------+
| id | name  | desc |
+----+-------+------+
|  1 | hosts | NULL |
+----+-------+------+

这样创建假设自增的话,产生第一个主键

查询

查出对应的虚拟表所有的字段,只要指定schemaid就可以查出当前信息

MariaDB [cmdb]> select * from `schema`,`field` where 1 = 1 and `field`.schema_id = `schema`.id and `schema`.id = 1;
+----+-------+------+----+----------+------+-----------+
| id | name  | desc | id | name     | meta | schema_id |
+----+-------+------+----+----------+------+-----------+
|  1 | hosts | NULL |  1 | hostname | NULL |         1 |
|  1 | hosts | NULL |  5 | ip       | NULL |         1 |
+----+-------+------+----+----------+------+-----------+
2 rows in set (0.00 sec)

查出它所有字段,只要能知名schema id 相当于虚拟表已经被查出


记录一个主机信息,entity

MariaDB [cmdb]> insert into entity (id,`key`,schema_id) values(1,'0123123',1);

对value表填入数据

当前entity 的值是1,那么对应entity_id = 1就可以了,字段id是

MariaDB [cmdb]>  insert into `value`(entity_id,filed_id,`value`) values(1,1,'webserver');
MariaDB [cmdb]> insert into `value`(entity_id,filed_id,`value`) values(1,2,'182.168.1.1');MariaDB [cmdb]> select * from value;
+----+-------------+----------+-----------+
| id | value       | field_id | entity_id |
+----+-------------+----------+-----------+
|  1 | webser      |        1 |         1 |
|  2 | 182.168.1.1 |        2 |         1 |
+----+-------------+----------+-----------+
2 rows in set (0.01 sec)

可以看到其field对应的表字段

MariaDB [cmdb]> select * from field;
+----+----------+------+-----------+
| id | name     | meta | schema_id |
+----+----------+------+-----------+
|  1 | hostname | NULL |         1 |
|  2 | ip       | NULL |         1 |
+----+----------+------+-----------+
2 rows in set (0.00 sec)

插入第二个主机信息:

通过唯一key来区别主机,以及还需要对entity 进行添加行进行id对应

MariaDB [cmdb]> insert into entity(`key`,schema_id) values ('0456456',1);
Query OK, 1 row affected, 1 warning (0.00 sec)
MariaDB [cmdb]> select * from entity;
+----+---------+-----------+
| id | key     | schema_id |
+----+---------+-----------+
|  0 | 0456456 |         1 |
|  1 | 0123123 |         1 |
+----+---------+-----------+
2 rows in set (0.00 sec)

插入数据 ,对应entity 第二个id

insert into `value`(entity_id,filed_id,`value`) VALUES (1,1,'DBser');
insert into `value`(entity_id,filed_id,`value`) VALUES (1,2,'127.0.0.1');

以上存入了两个主机信息

查看

select entity.id as entity_id,entity.`key`, entity.schema_id,
`schema`.`name`, field.id,field.`name` as fname,
`value`.`value` FROM entity
INNER JOIN `value` on `value`.entity_id = entity_id
INNER JOIN `schema` on `value`.schema_id = `schema`.id
INNER JOIN field  on `value`.field_id = field_id

利与弊

好处:之前每个类都会生成一个表,现在无非是在scaehma添加一行记录而已

坏处:关系复杂、表结构复杂,多长关系表组成的关系链,复杂的同时带来了灵活性,ORM不识别这样的表,只能自己封装进行实现

可否在value 的value段用约束进行?

比如记录ip,那么ip不允许重复如何去写?

这样相当于所有表都互相干扰了,所以不允许加唯一键约束

可否建立一个ip 池的表,如果存放的主机信息的,对于资产管理,将所有的服务配置,那么就肯定涉及到ip

如果互不干扰的话,那么可否通过sechma id进行判断,需要考虑重复的时候判断问题,那么无非是插入的时候判断

单独写类型非常有限,既然类型不合适,那么ip地址肯定不合适,总需要方法来解决这些

那么可否通过正则表达式,但是比较难掌握

通过meta进行限制,meta是text类型,是否可以使用json?

将json中的字符串转为python代码,通过反射动态加载运行,这样实现的话需要约定好调用的接口

考虑的问题点:

1. 如何存放?如何描述?描述什么?

2. 如果用到反射的话,那可否存放一个类名,一个模块名 直接加载它 直接调用这个方法

开发


设计一个类 ,通过反射来判断这个值,进行字段类型来验证

存储之前通过类转为特殊类型转为字符串,来进行校验,如果校验成功则存入数据库

建立约束类型,目录结构如下:

建立基类,用于校验,功能方法冗余性全部在基类中实现,子类用于增强

校验字符合法性

class BaseType:def stringify(self,value):raise NotImplementedError()def destringify(self,value):raise NotImplementedError()
class Int(BaseType):def stringify(self,value):str(int(value))def destringify(self,value):passclass Int(BaseType):def stringify(self,value):return str(int(value))def destringify(self,value):pass

ip地址校验

通过ipaddress 模块进行校验ip地址合法性
import ipaddress
class BaseType:def stringify(self,value):raise NotImplementedError()def destringify(self,value):raise NotImplementedError()
class Int(BaseType):def stringify(self,value):return int(str(value))def destringify(self,value):return value
class IP(BaseType):def stringify(self,value):return str(ipaddress.ip_address(value))def destringify(self,value):return value

反射


既然拿到了类型和值了,接下来如何操作?

通过getattr反射进行找到对应的方法

通过name返回object属性值,当属性不存在,将使用default返回,如果没有默认,则抛出AttributeError

通过getattr进行反射

当前模块还未导入,而且字符串还没被分段

import json
jsonstr = """
{"type":"cmdb.types.Int","value":300
}
"""
obj = json.loads(jsonstr)
print(obj)
m,c = obj['type'].rsplit('.',maxsplit=1)
print(m,c)
# 返回如下
{'type': 'cmdb.types.Int', 'value': 300}
types.Int cmdb

导入模块importlib

通过获取的值进行反射,这里m对应的是cmdb.types, 正是init.py,将其导入

我们看到看init是类方法,那么需要扔一个值进去

进行实例化,传入一个参数,那么这个值是value

# 导入cmdb.types
mod = importlib.import_module(m)
cls = getattr(mod,c)
cls().stringify(obj['value'])
# 返回如下
{'value': 300, 'type': 'cmdb.types.Int'}
cmdb.types Int

校验IP

一般要求分4段式

这里用于测试 value 不应该写在这里,切记

抽象函数

一般抽象的时候都将其返回一个对象为止,所以需要改进如下:

import json
import importlib
jsonstr = """
{"type":"cmdb.types.IP","value":"10.10.10.1"
}
"""
obj = json.loads(jsonstr)
def get_instance(type:str):# 这里要约定好,不然无法判断m,c = type.rsplit('.',maxsplit=1)mod = importlib.import_module(m)cls = getattr(mod,c)return cls()
print(get_instance(obj['type']).stringify(obj['value']))

给予一个类模块取出,将类加载起来之后返回类的实例

调用它的方法,将函数get_instance导入到init中
import ipaddress
import importlib
def get_instance(type:str):m,c = type.rsplit('.',maxsplit=1)mod = importlib.import_module(m)cls = getattr(mod,c)return cls()
class BaseType:def stringify(self,value):raise NotImplementedError()def destringify(self,value):raise NotImplementedError()
class Int(BaseType):def stringify(self,value):return int(str(value))def destringify(self,value):return value
class IP(BaseType):def stringify(self,value):return str(ipaddress.ip_address(value))def destringify(self,value):return value

这样就可以完美解决数据类型的问题,通过传递进来的json串来找到对应方法并解析,从而进行判断类型并return

转载于:https://blog.51cto.com/yijiu/2314395

CMDB 设计(二)实现host、ip存储相关推荐

  1. 浅析单一冗余校验RAID缺陷--云存储环境下IP存储设备组建策略

    浅析单一冗余校验RAID缺陷--云存储环境下IP存储设备组建策略 前面的话 摘要 一.当前常见阵列组建模式及云存储环境下IP存储设备特点 1.只求容量及读写性能的RAID0: 2.为了数据安全宁可牺牲 ...

  2. Glide核心设计二:缓存管理

    原文链接:Glide核心设计二:缓存管理 引言 Glide作为一个优秀的图片加载框架,缓存管理是必不可少的一部分,这篇文章主要通过各个角度.从整体设计到代码实现,深入的分析Glide的缓存管理模块,力 ...

  3. 利用ISCSI存储技术构建IP存储网络(概念篇)

    一.iSCSI的概念iSCSI是一种在Internet协议上,特别是以太网上进行数据块传输的标准,它是一种基于IP Storage理论的新型存储技术,该技术是将存储行业广泛应用的SCSI接口技术与IP ...

  4. (原创)基于ZedBoard的Webcam设计(二):USB摄像头图片采集+QT显示

    在(原创基于ZedBoard的Webcam设计(一):Zedboard上的USB摄像头(V4L2接口)的图片采集中,我们完成了ZedBoard上USB摄像头的单幅图片采集,采集到的图片是存储在文件系统 ...

  5. 【vSphere系列二】安装 Openfiler 存储

    参考 http://tech.ddvip.com/2013-03/1362159819191307.html 一. Openfiler简介 Openfiler 能把标准x86/64架构的系统变成一个强 ...

  6. 计算机网络抓包参考文献,计算机网络课程设计二(网络抓包与分析)

    <计算机网络课程设计二(网络抓包与分析)>由会员分享,可在线阅读,更多相关<计算机网络课程设计二(网络抓包与分析)(9页珍藏版)>请在人人文库网上搜索. 1.课程设计课程名称: ...

  7. 存储专家论IP存储现实可行性

    媒体们喜欢iSCSI(注:实际上,我们也很喜欢iSCSI,主要的理由与Charlie所说基本相同):iSCSI的部署成本不高,而且可以为DAS(直连式存储)或NAS(网络附加存储)带来许多优势.本期存 ...

  8. 基于ZedBoard的Webcam设计(二):USB摄像头图片采集+QT显示

    在(原创基于ZedBoard的Webcam设计(一):Zedboard上的USB摄像头(V4L2接口)的图片采集中,我们完成了ZedBoard上USB摄像头的单幅图片采集,采集到的图片是存储在文件系统 ...

  9. 基于阿里云的基础架构设施保障(二)IAAS云存储

    1. 云硬盘 HDD(普通云盘) 特征: 性能一般, IOPS大概在数百左右. 应用场景: 数据不被经常访问或者低I/O负载的应用场景,需要低成本并且有随机读写I/O的应用环境. 混合HDD(高效云盘 ...

  10. (王爽)汇编语言-课程设计二完整版

    王爽汇编语言-课程设计二 前言 特别感谢 实验结果 实验思路 如何优化调试流程以节省时间 源码 未完成部分 前言 刚刚把lab2调试完,2021年10月12日 16:26:36,本来是打算在oneno ...

最新文章

  1. Udacity机器人软件工程师课程笔记(一)-样本搜索和找回-基于漫游者号模拟器
  2. hive lock命令的使用
  3. Python学习笔记十 IO编程
  4. mysql怎样修改my ini_mysql通过修改my.ini设置系统变量
  5. 数据链路层介质访问控制——信道划分、随机访问和轮询访问
  6. spring jmx_JMX和Spring –第2部分
  7. python按行读取文件取消空白行_python去掉空白行的多种实现代码
  8. 工作流实战_24_flowable 全局监听
  9. 【收藏】ASP.NET英文技术文章推荐[10/28 – 11/3]
  10. Linux 命令(5)—— shutdown 命令
  11. C#基础1:输入输出+变量定义
  12. python制作一个桌面小工具
  13. 什么是CMMI资质认证?
  14. 算法笔记练习 题解合集
  15. ISG2014 Writeups
  16. opencv 运动检测 三帧差法
  17. matlab求常微分方程组,matlab常微分方程组求解
  18. 2021年新年元旦,新年开篇两首毛泽东诗词——沁园春:恰同学少年,风华正茂。书生意气,挥斥方遒……...
  19. 键盘切换不出中文输入法的解决方法
  20. 为什么苹果文件连接服务器没反应,苹果手机连接电脑没反应,教您苹果手机连接电脑没反应具体解决方法...

热门文章

  1. JButton 圆角_昆明圆角灯箱哪家好
  2. cordova打开文件_Cordova开发App入门(四)打开及下载第三方App
  3. kafka学习_《从0到1学习Flink》—— Flink 读取 Kafka 数据写入到 RabbitMQ
  4. android中按钮间隔,Android布局有2个均匀间隔的按钮
  5. java中thread实例_Java多线程2:Thread中的实例方法
  6. jieba如何空文本记录
  7. 最小二乘法与最大似然函数的区别
  8. python官网下载哪个版本好玩_Python官网不同版本的下载
  9. python实现将文件内容按照某一列内容的大小值重新排序_Python数据分析入门教程(四):数值操作...
  10. ue的xml格式转换_VCARD格式