上篇博客中已经介绍过Django的安装和基本使用,如果大家还有不明白请参考我的博客
Python [4] Django的安装和基础运行环境简介
http://467754239.blog.51cto.com/4878013/1613612
这篇博客和大家聊聊Python结合Django实现IT资产管理
基础环境:
系统版本:CentOS 6.4 64bit Python版本:2.6 Django版本:1.6.5 ip地址:192.168.1.210
一、安装Django环境
# rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm # sed -i 's@^#@@' /etc/yum.repos.d/epel.repo # sed -i 's@mirrorlist@#mirrorlist@' /etc/yum.repos.d/epel.repo # yum -y install python-pip # pip install 'django==1.6.5'
二、创建工程和应用
[root@localhost ~]# django-admin.py startproject Simplecmdb [root@localhost ~]# cd Simplecmdb/ [root@localhost Simplecmdb]# django-admin.py startapp hostinfo [root@localhost Simplecmdb]# tree ./ ./ ├── hostinfo │ ├── admin.py │ ├── __init__.py │ ├── models.py │ ├── tests.py │ └── views.py ├── manage.py └── Simplecmdb ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py 2 directories, 10 files
三、配置应用
1、修改工程配置文件
[root@localhost Simplecmdb]# vim Simplecmdb/settings.py INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'hostinfo', #添加应用 ) MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', #'django.middleware.csrf.CsrfViewMiddleware',#注释此行(默认禁止第三方curl工具使用) 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ) LANGUAGE_CODE = 'zh-cn' #修改字符集 TIME_ZONE = 'Asia/Shanghai' #修改时区
2、添加应用的url访问
[root@localhost Simplecmdb]# cat Simplecmdb/urls.py from django.conf.urls import patterns, include, url from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', # Examples: # url(r'^$', 'Simplecmdb.views.home', name='home'), # url(r'^blog/', include('blog.urls')), url(r'^admin/', include(admin.site.urls)), url(r'^hostinfo$','hostinfo.views.index'), #访问的url路径 )
解释:hostinfo.views.index hostinfo:创建的应用和工程在同一级目录 views:视图文件,定义请求的响应就是由这个文件定义的 index:是视图文件中定义的一个函数名
3、定义搜集主机信息的数据模型(也就是字段名和数据类型)
[root@localhost Simplecmdb]# cat hostinfo/models.py from django.db import models # Create your models here. class Host(models.Model): hostname = models.CharField(max_length=50) ip = models.IPAddressField() osversion = models.CharField(max_length=50) memory = models.CharField(max_length=50) disk = models.CharField(max_length=50) vendor_id = models.CharField(max_length=50) model_name = models.CharField(max_length=50) cpu_core = models.CharField(max_length=50) product = models.CharField(max_length=50) Manufacturer = models.CharField(max_length=50) sn = models.CharField(max_length=50)
4、初始化模型数据库并生成数据库文件
[root@localhost Simplecmdb]# python manage.py syncdb Creating tables ... Creating table django_admin_log Creating table auth_permission Creating table auth_group_permissions Creating table auth_group Creating table auth_user_groups Creating table auth_user_user_permissions Creating table auth_user Creating table django_content_type Creating table django_session Creating table hostinfo_host You just installed Django's auth system, which means you don't have any superusers defined. Would you like to create one now? (yes/no): yes Username (leave blank to use 'root'): root Email address: [email protected] Password: #后台admin的登陆密码 Password (again): Superuser created successfully. Installing custom SQL ... Installing indexes ... Installed 0 object(s) from 0 fixture(s)
5、注册后台admin并显示注册信息
[root@localhost Simplecmdb]# vim hostinfo/admin.py #注册数据库 from django.contrib import admin from hostinfo.models import Host # Register your models here. class HostAdmin(admin.ModelAdmin): list_display = [ 'hostname', 'ip', 'osversion', 'memory', 'disk', 'vendor_id', 'model_name', 'cpu_core', 'product', 'Manufacturer', 'sn'] admin.site.register(Host,HostAdmin)
6、定义用户的响应请求
[root@localhost Simplecmdb]# vim hostinfo/views.py from django.shortcuts import render from django.http import HttpResponse from hostinfo.models import Host # Create your views here. def index(req): print req if req.method == 'POST': hostname = req.POST.get('hostname') ip = req.POST.get('ip') osversion = req.POST.get('osversion') memory = req.POST.get('memory') disk = req.POST.get('disk') vendor_id = req.POST.get('vendor_id') model_name = req.POST.get('model_name') cpu_core = req.POST.get('cpu_core') product = req.POST.get('product') Manufacturer = req.POST.get('Manufacturer') sn = req.POST.get('sn') host = Host() host.hostname = hostname host.ip = ip host.osversion = osversion host.memory = memory host.disk = disk host.vendor_id = vendor_id host.model_name = model_name host.cpu_core = cpu_core host.product = product host.Manufacturer = Manufacturer host.sn = sn host.save() return HttpResponse('ok') else: return HttpResponse('no data')
三、运行django的工程服务
[root@localhost ~]# cd /root/Simplecmdb/ [root@localhost Simplecmdb]# python manage.py runserver 0.0.0.0:80 Validating models... 0 errors found March 02, 2015 - 16:11:12 Django version 1.6.5, using settings 'Simplecmdb.settings' Starting development server at http://0.0.0.0:80/ Quit the server with CONTROL-C.
四、浏览器访问页面
1、访问主页面
因为我们没有传送任何数据,所以返回我们定义的字符串"no data"
注册的账号是root,密码为123456
五、以下是用Python实现对Linux主机的信息采集
搜集的信息主要包括:主机名、ip、系统版本、硬盘、内存、cpu的个数、cpu的厂商、序列号和生产商
[root@localhost ~]# cat post_hostinfo.py #!/usr/bin/env python #coding:utf8 #author:Allentuns #time:2015-02-14 from subprocess import Popen,PIPE import urllib,urllib2 import pickle import json import re ###[hostname message]##### def get_HostnameInfo(file): with open(file,'r') as fd: data = fd.read().split('\n') for line in data: if line.startswith('HOSTNAME'): hostname = line.split('=')[1] break return hostname #####[ipaddr message]##### def get_Ipaddr(): P = Popen(['ifconfig'],stdout=PIPE) data = P.stdout.read() list = [] str = '' option = False lines = data.split('\n') for line in lines: if not line.startswith(' '): list.append(str) str = line else: str += line while True: if '' in list: list.remove('') else: break r_devname = re.compile('(eth\d*|lo)') r_mac = re.compile('HWaddr\s([A-F0-9:]{17})') r_ip = re.compile('addr:([\d.]{7,15})') for line in list: devname = r_devname.findall(line) mac = r_mac.findall(line) ip = r_ip.findall(line) if mac: return ip[0] #####[osversion message]##### def get_OsVerion(file): with open(file) as fd: lines = fd.readlines() os_version = lines[0][:-8] return os_version #####[memory message]##### def get_MemoryInfo(file): with open(file) as fd: data_list = fd.read().split('\n') MemTotal_line = data_list[0] Memory_K = MemTotal_line.split()[1] Memory_G = float(Memory_K)/1000/1000 Memory_G2 = '%.2f' % Memory_G memory = Memory_G2 + 'G' return memory #####[disk message]##### def get_DiskInfo(): p = Popen(['fdisk','-l'],stdout=PIPE,stderr=PIPE) stdout,stderr = p.communicate() diskdata = stdout disk_initial_size = 0 re_disk_type = re.compile(r'Disk /dev/[shd]{1}.*:\s+[\d.\s\w]*,\s+([\d]+).*') disk_size_bytes = re_disk_type.findall(diskdata) for size in disk_size_bytes: disk_initial_size += int(size) disk_size_total_bytes = '%.2f' % (float(disk_initial_size)/1000/1000/1000) disk_size_total_G = disk_size_total_bytes + 'G' disk = disk_size_total_G return disk #####[cpu message]##### def get_CpuInfo(): p = Popen(['cat','/proc/cpuinfo'],stdout=PIPE,stderr=PIPE) stdout, stderr = p.communicate() cpudata = stdout.strip() cpu_dict = {} re_cpu_cores = re.compile(r'processor\s+:\s+([\d])') re_vendor_id = re.compile(r'vendor_id\s+:\s([\w]+)') re_model_name = re.compile(r'model name\s+:\s+(.*)') res_cpu_cores = re_cpu_cores.findall(cpudata) cpu_dict['Cpu_Cores'] = int(res_cpu_cores[-1]) + 1 res_vendor_id = re_vendor_id.findall(cpudata) cpu_dict['Vendor_Id'] = res_vendor_id[-1] res_model_name = re_model_name.findall(cpudata) cpu_dict['Model_Name'] = res_model_name[-1] return cpu_dict #####[Demi message]##### def get_dmidecode(): P = Popen(['dmidecode'],stdout=PIPE) data = P.stdout.read() lines = data.split('\n\n') dmidecode_line = lines[2] line = [i.strip() for i in dmidecode_line.split('\n') if i] Manufacturer = line[2].split(': ')[-1] product = line[3].split(': ')[-1] sn = line[5].split(': ')[-1] return Manufacturer,product,sn if __name__ == '__main__': #####[get data]##### hostname = get_HostnameInfo('/etc/sysconfig/network') ip = get_Ipaddr() osversion = get_OsVerion('/etc/issue') memory = get_MemoryInfo('/proc/meminfo') disk = get_DiskInfo() Vendor_Id = get_CpuInfo()['Vendor_Id'] Model_Name = get_CpuInfo()['Model_Name'] Cpu_Cores = get_CpuInfo()['Cpu_Cores'] Manufacturer,product,sn = get_dmidecode() #####[get dict]##### hostinfo = { 'hostname':hostname, 'ip':ip, 'osversion':osversion, 'memory':memory, 'disk':disk, 'vendor_id':Vendor_Id, 'model_name':Model_Name, 'cpu_core':Cpu_Cores, 'product':product, 'Manufacturer':Manufacturer, 'sn':sn, } data = urllib.urlencode(hostinfo) req = urllib2.urlopen('http://192.168.1.210:80/hostinfo',data)
此脚本需要注意两处:
1、脚本目前只能在CentOS系统上运行,非CentOS系统会报异常,比如文件找不到等
2、执行脚本前需要先安装一个包(demidecode),这个包可以搜集主机的部分信息
[root@localhost ~]# yum -y install dmidecode [root@localhost ~]# python post_hostinfo.py
然后刷新后台admin的页面
以上配置还有问题,就是不能保证主机的唯一性,如果反复执行上述脚本会得到以下结果
这个问题可以这样解决,用户执行脚本然后传递参数到服务器,服务器可以做个判断,如果传递的参数已经存在,那么我们不保存此信息,如果是更新,那么我们重新赋值并保存到数据库中
[root@localhost Simplecmdb]# cat hostinfo/views.py from django.shortcuts import render from django.http import HttpResponse from hostinfo.models import Host # Create your views here. def index(req): if req.method == 'POST': hostname = req.POST.get('hostname') ip = req.POST.get('ip') osversion = req.POST.get('osversion') memory = req.POST.get('memory') disk = req.POST.get('disk') vendor_id = req.POST.get('vendor_id') model_name = req.POST.get('model_name') cpu_core = req.POST.get('cpu_core') product = req.POST.get('product') Manufacturer = req.POST.get('Manufacturer') sn = req.POST.get('sn') try: #修改这一部分 host = Host.objects.get(hostname=hostname) #判断是否存在,存在报异常 except: host = Host() host.hostname = hostname host.ip = ip host.osversion = osversion host.memory = memory host.disk = disk host.vendor_id = vendor_id host.model_name = model_name host.cpu_core = cpu_core host.product = product host.Manufacturer = Manufacturer host.sn = sn host.save() return HttpResponse('ok') else: return HttpResponse('no data')
最终显示的效果如下:
六、主机分组
1、如下图所示:在web高可用集群中,多台服务器提供同一类服务是非常正常的,就比如web前端使用多台nginx和keepalived做高可用,后端应用比如tomcat提供用于的请求响应,像以上这两类我们可以单独进行分组划分。
2、修改配置文件定义主机组
首先在hostinfo应用中添加定义组的数据结构
[root@localhost Simplecmdb]# vim hostinfo/models.py from django.db import models # Create your models here. class Host(models.Model): hostname = models.CharField(max_length=50) ip = models.IPAddressField() osversion = models.CharField(max_length=50) memory = models.CharField(max_length=50) disk = models.CharField(max_length=50) vendor_id = models.CharField(max_length=50) model_name = models.CharField(max_length=50) cpu_core = models.CharField(max_length=50) product = models.CharField(max_length=50) Manufacturer = models.CharField(max_length=50) sn = models.CharField(max_length=50) #添加以下行 class HostGroup(models.Model): groupname = models.CharField(max_length=50) members = models.ManyToManyField(Host)
其次检查语法并同步数据库
[root@localhost Simplecmdb]# python manage.py validate 0 errors found [root@localhost Simplecmdb]# python manage.py syncdb Creating tables ... Creating table hostinfo_hostgroup_members Creating table hostinfo_hostgroup Installing custom SQL ... Installing indexes ...
最后注册admin并能在admin页面显示
[root@localhost Simplecmdb]# vim hostinfo/admin.py from django.contrib import admin from hostinfo.models import Host from hostinfo.models import HostGroup #添加此行 # Register your models here. class HostAdmin(admin.ModelAdmin): list_display = [ 'hostname', 'ip', 'osversion', 'memory', 'disk', 'vendor_id', 'model_name', 'cpu_core', 'product', 'Manufacturer', 'sn'] #添加以下行 class HostGroupAdmin(admin.ModelAdmin): list_display = ['groupname'] admin.site.register(Host,HostAdmin) admin.site.register(HostGroup,HostGroupAdmin)
浏览器访问admin页面
问题来了,怎么Member都显示的是Host object啊?其实原因出在这里
[root@localhost Simplecmdb]# vim hostinfo/models.py from django.db import models # Create your models here. class Host(models.Model): hostname = models.CharField(max_length=50) ip = models.IPAddressField() osversion = models.CharField(max_length=50) memory = models.CharField(max_length=50) disk = models.CharField(max_length=50) vendor_id = models.CharField(max_length=50) model_name = models.CharField(max_length=50) cpu_core = models.CharField(max_length=50) product = models.CharField(max_length=50) Manufacturer = models.CharField(max_length=50) sn = models.CharField(max_length=50) class HostGroup(models.Model): groupname = models.CharField(max_length=50) members = models.ManyToManyField(Host)
Host和HostGroup都是类,而HostGroup中的members引用上面的Host类,返回值就是一个对象,我们应该在Host类中添加定义一个函数,然后返回我们想要的值就Ok啦
修改代码如下:
[root@localhost Simplecmdb]# vim hostinfo/models.py from django.db import models # Create your models here. class Host(models.Model): hostname = models.CharField(max_length=50) ip = models.IPAddressField() osversion = models.CharField(max_length=50) memory = models.CharField(max_length=50) disk = models.CharField(max_length=50) vendor_id = models.CharField(max_length=50) model_name = models.CharField(max_length=50) cpu_core = models.CharField(max_length=50) product = models.CharField(max_length=50) Manufacturer = models.CharField(max_length=50) sn = models.CharField(max_length=50) def __str__(self): return self.hostname class HostGroup(models.Model): groupname = models.CharField(max_length=50) members = models.ManyToManyField(Host)
然后同步数据库
[root@localhost Simplecmdb]# python manage.py syncdb Creating tables ... Installing custom SQL ... Installing indexes ... Installed 0 object(s) from 0 fixture(s)
再次刷新之前的页面
3、定义组名和添加组成员
上述所涉及到的还存在一定的问题:我们总不能手动一个个上传此Python脚本到各个客户机,然后在执行此脚本,显然不符合自动化的要求;按自动化的思路来讲,我们应该主动发现同网段的所有主机,然后自动加主机加入到同一个新组中,然后对这个组进行执行上传、执行脚本的工作。这样就省去了很多的麻烦,后续也会继续补上此类的脚本。
Python[6] IT资产管理(下)
http://467754239.blog.51cto.com/4878013/1616806