33、主机资产管理--启动
资产编号,ip, 主机名,使用者,os,mem,cpu, 上架时间,过保时间,
增、删、改、查
添加:
人工手工录入
ssh ip
hostname
cat /proc/cpuinfo
cat /proc/meminfo
主机内部安装了程序 agent =>server 上报数据(ip,hostname,os,mem,cpu)
扫描ip范围:ip,hostname,os
自动远程获取
text/csv/excel/xml =>导入ip,hostname,os,mem,cpu
其他第三方系统 => 调用API导入
删除:
人工删除
自动删除(与第三方系统结合)
改:
人工改
自动查
查:
自己查
提供数据 => API
查询、删除 => 人工
添加、删除 => 自动
修改 => 人工
model => table
资产编号,ip,主机名,使用者,os,arch,mem,cpu,disk,上架时间,过保时间,在线状态
机制
推:每周三所有人将作业发给我, agent=>sever V
拉:每周三我找所有人要, 扫描(ansible)
1、创建app
python manage.py startapp asset
2、启用app
settings INSTALLED_APPS 'asset.apps.AssetConfig',
3、app urls.py
app_name = 'asset'
urlpatterns = [
# path('index/', views.index, name='index'),
]
4、根路由配置 相关的url(/assert/)分发给app
path('asset/', include('asset.urls')),
5、models.py
#encoding: utf-8 from django.db import models from django.utils import timezone from django.core.exceptions import ObjectDoesNotExist class Host(models.Model): name = models.CharField(max_length=128, null=False, default='') ip = models.GenericIPAddressField(null=False, default='0.0.0.0') mac = models.CharField(max_length=32, null=False, default='') os = models.CharField(max_length=64, null=False, default='') arch = models.CharField(max_length=16, null=False, default='') mem = models.BigIntegerField(null=False, default=0) cpu = models.IntegerField(null=False, default=0) disk = models.CharField(max_length=512, null=False, default='{}') sn = models.CharField(max_length=128, null=False, default='') user = models.CharField(max_length=128, null=False, default='') remark = models.TextField(null=False, default='') purchase_time = models.DateTimeField(null=False) over_insurance_time = models.DateTimeField(null=False) create_time = models.DateTimeField(null=False, auto_now_add=True) last_time = models.DateTimeField(null=False)
6、迁移数据库
python manage.py makemigrations
python manage.py migrate
验证:mysql -uroot -pXXX -e "use cmdb_user;show create table asset_host;"
34、主机资产管理--Django command方法调用
创建Python包,怎么判断?下面必须存在__init__.py文件。
command => script.py
runserver
makemigrations
migrate
check
1、commands
app/management/commands/__init__.py
2、script.py
F:\py3proj\07\cmdb\asset\management\commands\collect_host.py
#encoding: utf-8
from django.core.management import BaseCommand
class Command(BaseCommand):
def handle(self, *args, **options):
print('test..')
执行 python manage.py 查看可运行的命令
python manage.py collect_host 查看运行结果。如下截图。
34、主机资产管理--ansible安装配置
win 7下载ssh客户端:https://www.mls-software.com/opensshd.html
win 7下载ansible:https://www.cnblogs.com/yuzhouliu/p/16459075.html
因win上面运行ansible可用度不高,需要转到Linux上面操作。
[root@www ~]# python3 -m venv py36django2
[root@www ~]# cd cmdb/kk/
[root@www kk]# source /root/py36django2/bin/activate
(py36django2) [root@www kk]# pip freeze
(py36django2) [root@www kk]# pip list
(py36django2) [root@www kk]# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
(py36django2) [root@www kk]# pip install Django==2.0.5
拷贝代码到Linux环境
本地备份的代码:“cmdb0904-que-ansible.zip”
(py36django2) [root@www cmdb]# yum install gcc gcc-c++ python3-devel mysql-devel python-devel
(py36django2) [root@www cmdb]# pip install mysqlclient
(py36django2) [root@www cmdb]# python manage.py runserver 0.0.0.0:8080
因跟本地使用的数据库信息一致,故不需要在数据库这块下功夫,只需要安装基本的就好。
访问验证:http://192.168.1.118:8080/user/index/, 使用正常。
(py36django2) [root@www cmdb]# yum install ansible -y
(py36django2) [root@www cmdb]# cat etc/hosts 创建并编辑文件
localhost ansible_ssh_pass=Sunny@123
test ansible_host=192.168.1.106 ansible_user=root ansible_ssh_pass=Sunny@123
(py36django2) [root@www cmdb]# ansible all -i etc/hosts --list-hosts
(py36django2) [root@www cmdb]# ssh localhost
(py36django2) [root@www cmdb]# ansible all -m ping -i etc/hosts
(py36django2) [root@www cmdb]# ansible all -m setup -i etc/hosts >test.txt 全部信息
控制器 =>ssh =>受控主机
ansible --> inventory剧本
a、调用系统命令 output
b、系统命令工具 => Python封装 => python 3rd
c、python 3rd
hosts => 剧本 ansible_connection ansible_host ansible_user ansible_ssh_pass
ansible => -m module 任务 和 playbook 剧本
ansible python api
mysql/ansible/es/阿里云 =>第三方工具
python 3rd mysqlclient、ansible、pyes、requests
python使用
34、ansible--Python api
Python API ansible:https://docs.ansible.com/ansible/2.4/dev_guide/developing_api.html
(py36django2) [root@www etc]# pip install --upgrade pip
(py36django2) [root@www etc]# pip install ansible
(py36django2) [root@www etc]# pip uninstall cryptography
(py36django2) [root@www etc]# pip install -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com cryptography==36.0.2
(py36django2) [root@www pycharm_project_827]# cat etc/hosts
localhost ansible_ssh_pass=Sunny@123
test ansible_host=192.168.1.106 ansible_user=root ansible_ssh_pass=Sunny@123
(py36django2) [root@www pycharm_project_827]# ansible all -i etc/hosts -m ping
(py36django2) [root@www etc]# ssh-keygen -b 4096
(py36django2) [root@www etc]# ssh-copy-id -i ~/.ssh/id_rsa.pub localhost
(py36django2) [root@www etc]# ssh-copy-id -i ~/.ssh/id_rsa.pub 192.168.1.106
调整ansible位置,
(py36django2) [root@www pycharm_project_827]# cat etc/hosts
localhost
test ansible_host=192.168.1.106 ansible_user=root
(py36django2) [root@www pycharm_project_827]# ansible all -i etc/hosts -m ping
[root@www pycharm_project_827]# ansible -i etc/hosts all -m setup
[root@www pycharm_project_827]# ansible -i etc/hosts all -m setup -a "filter=ansible_os_family"
[root@www pycharm_project_827]# ansible -i etc/hosts all -m setup -a "filter=ansible_all_ipv4_addresses"
[root@www pycharm_project_827]# ansible --version
[root@www pycharm_project_827]# ansible-doc -l
[root@www pycharm_project_827]# ansible-doc -s setup
(py36django2) [root@www pycharm_project_827]# cat etc/test.py 创建api测试接口。
#!/usr/bin/env python
#encoding: utf-8
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import json
import shutil
from collections import namedtuple
import ansible.constants as C
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.inventory.manager import InventoryManager
from ansible.parsing.dataloader import DataLoader
from ansible.playbook.play import Play
from ansible.plugins.callback import CallbackBase
from ansible.vars.manager import VariableManager
""""回调"""
class ResultCallback(CallbackBase):
def v2_runner_on_ok(self, result, **kwargs):
host = result._host
print(dir())
print(result.task_name)
print(json.dumps({host.name: result._result}, indent=4))
Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check','diff'])
options = Options(connection='smart', module_path=[], forks=10, become=None,become_method=None, become_user=None,check=False, diff=False)
loader = DataLoader() # Takes care of finding and reading yaml, json and ini files
passwords = {}
results_callback = ResultCallback()
inventory = InventoryManager(loader=loader, sources='hosts') #剧本文件 sources='hosts'
variable_manager = VariableManager(loader=loader, inventory=inventory)
play_source = {
"name": "test",
"hosts": 'all', # 在哪些主机上运行。
"gather_facts": 'no',
"tasks": [{ # 执行的任务列表
"name": 'fact', # 任务名称
'setup': '' # 任务模块
}
]
}
play = Play().load(play_source, variable_manager=variable_manager, loader=loader)
tqm = None
try:
tqm = TaskQueueManager(
inventory=inventory,
variable_manager=variable_manager,
loader=loader,
options=options,
passwords=passwords,
stdout_callback=results_callback
)
result = tqm.run(play)
finally:
if tqm is not None:
tqm.cleanup()
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
(py36django2) [root@www etc]# python test.py
/root/py36django2/lib64/python3.6/site-packages/ansible/parsing/vault/__init__.py:44: CryptographyDeprecationWarning: Python 3.6 is no longer supported by the Python core team. Therefore, support for it is deprecated in cryptography and will be removed in a future release.
from cryptography.exceptions import InvalidSignature
Traceback (most recent call last):
File "test.py", line 55, in <module>
stdout_callback=results_callback
TypeError: __init__() got an unexpected keyword argument 'options'
解决方法:严格注意Python包版本,安装低版本的包,解决问题。
(py36django2) [root@www etc]# pip uninstall cryptography
(py36django2) [root@www etc]# pip uninstall ansible==2.9.27
(py36django2) [root@www etc]# pip install ansible==2.4.2.0
(py36django2) [root@www etc]# pip install cryptography==36.0.2
(py36django2) [root@www etc]# cd /tmp/pycharm_project_827/etc
(py36django2) [root@www etc]# python test.py 可以输出整个ansible信息。
将api指向model服务。
...
last_time = models.DateTimeField(null=False)
@classmethod
def create_or_replace(cls,ip,name,mac,os,arch,mem,cpu,disk):
obj = None
try:
obj = cls.objects.get(ip=ip)
except ObjectDoesNotExist as e:
obj = cls()
obj.ip = ip
obj.purchase_time = timezone.now()
obj.over_insurance_time = timezone.now()
obj.name = name
obj.mac = mac
obj.os = os
obj.arch = arch
obj.mem = mem
obj.cpu = cpu
obj.disk = disk
obj.last_time = timezone.now()
obj.save()
return obj
编辑脚本collect_host.py服务,
#encoding: utf-8
from django.core.management import BaseCommand
import json
import os
from django.conf import settings
import shutil
from collections import namedtuple
import ansible.constants as C
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.inventory.manager import InventoryManager
from ansible.parsing.dataloader import DataLoader
from ansible.playbook.play import Play
from ansible.plugins.callback import CallbackBase
from ansible.vars.manager import VariableManager
from asset.models import Host
class ResultCallback(CallbackBase):
def v2_runner_on_ok(self, result, **kwargs):
if result.task_name == 'collect_host':
self.collect_host(result._result)
def collect_host(self, result):
facts = result.get('ansible_facts', {})
ip = facts.get('ansible_default_ipv4', {}).get('address', '')
name = facts.get('ansible_nodename', '')
mac = facts.get('ansible_default_ipv4', {}).get('macaddress', '')
os = facts.get('ansible_os_family', '')
arch = facts.get('ansible_architecture', '')
mem = facts.get('ansible_memtotal_mb', '')
cpu = facts.get('ansible_processor_vcpus', '')
disk = [{'name': i.get('device'), 'total': int(i.get('size_total'))/1024/1024} for i in facts.get('ansible_mounts', [])]
Host.create_or_replace(ip, name, mac, os, arch, mem, cpu, json.dumps(disk))
class Command(BaseCommand):
def handle(self, *args, **options):
AnsibleOptions = namedtuple('AnsibleOptions',['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check','diff'])
ansibleoptions = AnsibleOptions(connection='smart', module_path=[], forks=10, become=None, become_method=None,become_user=None, check=False, diff=False)
loader = DataLoader() # Takes care of finding and reading yaml, json and ini files
passwords = {}
results_callback = ResultCallback()
inventory = InventoryManager(loader=loader, sources=os.path.join(settings.BASE_DIR, 'etc', 'hosts')) # 剧本文件 sources='hosts'
variable_manager = VariableManager(loader=loader, inventory=inventory)
# ansible all -i etc/hosts -m setup
play_source = {
"name": "cmdb",
"hosts": 'all', # 在哪些主机上运行。
"gather_facts": 'no',
"tasks": [{ # 执行的任务列表
"name": 'collect_host', # 任务名称
'setup': '' # 任务模块
}
]
}
play = Play().load(play_source, variable_manager=variable_manager, loader=loader)
tqm = None
try:
tqm = TaskQueueManager(
inventory=inventory,
variable_manager=variable_manager,
loader=loader,
options=ansibleoptions,
passwords=passwords,
stdout_callback=results_callback
)
result = tqm.run(play)
finally:
if tqm is not None:
tqm.cleanup()
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
(py36django2) [root@www pycharm_project_827]# cd /tmp/pycharm_project_827
(py36django2) [root@www pycharm_project_827]# python manage.py collect_host 执行脚本,查看数据库有记录。
(py36django2) [root@www etc]# mysql -uroot -pSunny@123 -e 'use cmdb_user;select * from asset_host;' 查看有记录
(py36django2) [root@www etc]# mysql -uroot -pSunny@123 -e 'use cmdb_user;select count(1) from asset_host;'