├── .gitignore ├── README.md ├── agent ├── VERSION ├── base.xml ├── client.py ├── constants.py ├── disk.xml ├── host.py ├── log.py ├── task.py ├── test │ ├── 1.xml │ ├── 111.qcow2 │ ├── 2.xml │ ├── build_host_hw.py │ ├── build_host_status.py │ ├── build_vm_conf.py │ ├── build_vm_status.py │ ├── cdrom_xml.py │ ├── cds.xml │ ├── cds222.xml │ ├── disk_xml.py │ ├── file1.py │ ├── hd_xml.py │ ├── host_getMaxVcpus.py │ ├── host_get_file_list.py │ ├── host_get_hw_info.py │ ├── host_get_iso.py │ ├── host_get_resource.py │ ├── host_get_sw_info.py │ ├── host_nodeinfo.py │ ├── path.py │ ├── prepare_img.py │ ├── snapshot_xml.py │ ├── task_action.py │ ├── task_create_snapshot.py │ ├── task_define.py │ ├── task_delete.py │ ├── task_delete_snapshot.py │ ├── task_download.py │ ├── task_edit.py │ ├── task_report.py │ ├── task_resume_snapshot.py │ ├── task_set_ip.py │ ├── test.py │ ├── threadpool_test.py │ ├── vm_define.py │ ├── vm_destroy.py │ ├── vm_edit_conf.py │ ├── vm_get_info.py │ ├── vm_get_os_version.py │ ├── vm_get_status.py │ ├── vm_judge_exist.py │ ├── vm_read_vm_file.py │ ├── vm_shutdown.py │ ├── vm_start.py │ ├── vm_start_from_cdrom.py │ ├── vm_undefine.py │ ├── vm_write_vm_file.py │ └── xingyu.xml ├── vm.py ├── vpe.conf └── xml_api.py ├── docs ├── libvirt-1.0-Libvirt_Application_Development_Guide_Using_Python-en-US.pdf ├── 接口设计文档.txt ├── 数据库设计.png └── 环境部署说明.txt ├── screenshots ├── 任务管理.jpg ├── 添加镜像模板.jpg ├── 登录页.jpg ├── 虚拟机列表.jpg ├── 虚拟机快照管理.jpg ├── 虚拟机总览.jpg ├── 虚拟机配置.jpg ├── 设备列表页.jpg └── 设备总览.jpg └── web ├── api ├── __init__.py ├── admin.py ├── apps.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_auto_20160608_1532.py │ ├── 0003_auto_20160608_1605.py │ └── __init__.py ├── models.py ├── tests.py └── views.py ├── manage.py ├── server ├── __init__.py ├── admin.py ├── apps.py ├── migrations │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── tests.py └── views.py ├── templates ├── 444.html ├── api_error.html ├── base.html ├── basic_modal.html ├── basic_task_modal.html ├── create_ins_modal.html ├── login.html ├── server │ ├── instances.html │ ├── logs.html │ ├── modal_add_iostemp.html │ ├── modal_add_vmfile.html │ ├── overview.html │ ├── packages.html │ ├── server_info.html │ ├── server_list.html │ ├── setting.html │ ├── tasks-all.html │ └── tasks.html └── side_base.html └── webkvmmgr ├── __init__.py ├── settings.py ├── static ├── css │ ├── bootstrap-switch.min.css │ ├── common.css │ ├── instance.css │ ├── login.css │ ├── server.css │ └── tasks.css ├── images │ ├── avatar.svg │ ├── bg.png │ ├── favicon.ico │ ├── logo.png │ ├── logofx.jpg │ ├── logofx.png │ ├── main.png │ ├── password.svg │ └── username.svg └── js │ ├── bootstrap-switch.min.js │ ├── common.js │ ├── echarts.min.js │ ├── instance.js │ ├── login.js │ └── server.js ├── urls.py └── wsgi.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Python template 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | env/ 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | nosetests.xml 46 | coverage.xml 47 | *,cover 48 | .hypothesis/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | 58 | # Flask stuff: 59 | instance/ 60 | .webassets-cache 61 | 62 | # Scrapy stuff: 63 | .scrapy 64 | 65 | # Sphinx documentation 66 | docs/_build/ 67 | 68 | # PyBuilder 69 | target/ 70 | 71 | # IPython Notebook 72 | .ipynb_checkpoints 73 | 74 | # pyenv 75 | .python-version 76 | 77 | # celery beat schedule file 78 | celerybeat-schedule 79 | 80 | # dotenv 81 | .env 82 | 83 | # virtualenv 84 | venv/ 85 | ENV/ 86 | 87 | # Spyder project settings 88 | .spyderproject 89 | 90 | # Rope project settings 91 | .ropeproject 92 | 93 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # webkvmmgr 2 | KVM Manager with Django 3 | 4 | ## Demo video 5 | [http://v.qq.com/page/w/7/1/w0313ztcu71.html](http://v.qq.com/page/w/7/1/w0313ztcu71.html) 6 | 7 | ## Requirements 8 | ### 宿主机 9 | 1. host目前选择版本: centos6.x 或 centos7 10 | 11 | 2. Host安装包: 12 | 13 | 1) kvm相关包: 14 | yum install qemu-kvm libvirt libvirt-python 15 | 16 | 2) python依赖包: 17 | requests、threadpool 18 | 19 | 3) 其它rpm包: 20 | ​​ util-linux 21 | 22 | 3. Disk配置: 23 | 24 | 1) 指定1块硬盘,例如/dev/sda,用来存放vm的系统盘; 25 | 26 | 2) 格式化,并挂载到/img/os目录; 27 | 28 | 3) 指定剩下的N-1块硬盘,用来存放vm的数据盘;(如果硬盘做了raid,则意味着,这个raid盘,用来存放vm的数据盘) 29 | 30 | 4) 格式化,并挂载到/img/dataN目录; 31 | 32 | 举例: 33 | ​例如一个host有5块盘,sda/sdb/sdc/sdd/sde,则: 34 | 35 | 1) 选择sda用来存放vm的系统盘; 36 | 37 | 2) 格式化并挂载: 38 | mkfs.ext4 /dev/sda && mount /dev/sda /img/os 39 | 40 | 3) 选择sdb/sdc/sdd/sde,用来存放vm的数据盘; 41 | 42 | 4) 格式化并挂载: 43 | ``` 44 | mkfs.ext4 /dev/sdb && mount /dev/sdb /img/data1 45 | mkfs.ext4 /dev/sdc && mount /dev/sdc /img/data2 46 | mkfs.ext4 /dev/sdd && mount /dev/sdd /img/data3 47 | mkfs.ext4 /dev/sde && mount /dev/sde /img/data4 48 | ``` 49 | 50 | 4. net配置: 51 | 创建一个名叫ovirtmgmt的网桥 52 | 53 | ### 虚拟机 54 | 1. 安装rpm包qemu-guest-agent: 55 | yum install qemu-guest-agent 56 | 57 | 2. 添加开机自启动程序: 58 | killall qemu-ga 59 | nohup qemu-ga -p /dev/virtio-ports/org.qemu.guest_agent.0 & 60 | 61 | ## Screenshot 62 | 63 | * 登录页 64 | 65 | 登录页 66 | 67 | * 设备列表页 68 | 69 | 设备列表页 70 | 71 | * 设备总览 72 | 73 | 设备总览 74 | 75 | * 虚拟机列表 76 | 77 | 虚拟机列表 78 | 79 | * 虚拟机总览 80 | 81 | 虚拟机总览 82 | 83 | * 虚拟机快照管理 84 | 85 | 虚拟机快照管理 86 | 87 | * 虚拟机配置 88 | 89 | 虚拟机配置 90 | 91 | 92 | * 添加镜像模板 93 | 94 | 添加镜像模板 95 | 96 | * 任务管理 97 | 98 | 任务管理 99 | 100 | 101 | ## Todo List 102 | * 重新组织agent代码, 现在代码还没有整理; 103 | * 完善文档; -------------------------------------------------------------------------------- /agent/VERSION: -------------------------------------------------------------------------------- 1 | 1.0.0 2 | -------------------------------------------------------------------------------- /agent/base.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 4 6 | 7 | hvm 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | destroy 17 | restart 18 | restart 19 | 20 | /usr/libexec/qemu-kvm 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /agent/client.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from log import logger 3 | import json 4 | import datetime 5 | from vm import vm 6 | from host import vmmhost 7 | import libvirt 8 | import constants 9 | import Queue 10 | import time 11 | import os 12 | 13 | """ 14 | url_up = 'http://192.168.1.136:8000/api/kvm' 15 | #headers = {'content-type': 'application/json'} 16 | payload = {'key1': 'value1', 'key2': 'value2'} 17 | r = requests.post(url_up, data=json.dumps(payload)) 18 | """ 19 | 20 | def get_now_str(): 21 | return datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') 22 | 23 | def build_vm_conf(sn, uri = "qemu:///system"): 24 | 25 | conn = None 26 | try: 27 | conn = libvirt.open(uri) 28 | except Exception, e: 29 | logger.exception(e) 30 | 31 | ret_dict = {} 32 | ret_dict['req'] = "vm.conf" 33 | ret_dict['sn'] = sn 34 | 35 | doms_info = [] 36 | chost = vmmhost(sn, conn) 37 | now_time = get_now_str() 38 | for name in chost.get_vmlist(): 39 | dom_info = {} 40 | dom_info['name'] = name 41 | dom_info['update_time'] = now_time 42 | dom_info['type'] = 0 43 | avm = vm(name) 44 | dom_info['os'] = avm.get_os_version() #todo: lsb_release -d 45 | dom_info['cpu_num'] = avm.get_cpu_num() 46 | dom_info['memory'] = avm.get_mem() 47 | dom_info['disk'] = avm.get_disk_info() 48 | dom_info['network'] = avm.get_net_info() 49 | snapshot_list = avm.get_snapshots() 50 | snapshot_list_info = [] 51 | for item in snapshot_list: 52 | snap_item = {} 53 | snap_item['name'] = item 54 | snap_item['create_time'] = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) #todo 55 | snap_item['comment'] = "xxxx" 56 | snapshot_list_info.append(snap_item) 57 | dom_info['snapshots'] = snapshot_list_info 58 | 59 | doms_info.append(dom_info) 60 | 61 | ret_dict['body'] = doms_info 62 | logger.debug('---------------------------------------------------') 63 | logger.debug(ret_dict) 64 | 65 | if conn: 66 | conn.close() 67 | 68 | return ret_dict 69 | 70 | def build_vm_status(sn, uri = "qemu:///system"): 71 | 72 | conn = None 73 | try: 74 | conn = libvirt.open(uri) 75 | except Exception, e: 76 | logger.exception(e) 77 | 78 | ret_dict = {} 79 | ret_dict['req'] = "vm.status" 80 | ret_dict['sn'] = sn 81 | 82 | doms_info = [] 83 | chost = vmmhost(sn, conn) 84 | now_time = get_now_str() 85 | for name in chost.get_vmlist(): 86 | print name 87 | dom_info = {} 88 | dom_info['name'] = name 89 | dom_info['update_time'] = now_time 90 | 91 | avm = vm(name) 92 | run_status = avm.get_status() 93 | dom_info['status'] = run_status['vm_status'] 94 | 95 | 96 | if dom_info['status'] == constants.vm_status_running: 97 | 98 | vm_info = avm.get_info() 99 | dom_info['cpu_idle'] = vm_info['cpu_idle'] 100 | dom_info['mem_usage'] = vm_info['mem_usage'] 101 | dom_info['disk'] = [] #todo 102 | net_item = {} 103 | net_item['name'] = "" 104 | dom_info['net'] = avm._get_network_interfaces() 105 | else: 106 | dom_info['cpu_idle'] = 100.00 107 | dom_info['mem_usage'] = 0.00 108 | dom_info['disk'] = [] 109 | dom_info['net'] = [] 110 | 111 | doms_info.append(dom_info) 112 | 113 | ret_dict['body'] = doms_info 114 | 115 | logger.debug(ret_dict) 116 | 117 | if conn: 118 | conn.close() 119 | 120 | return ret_dict 121 | 122 | def build_host_hw(sn, uri = "qemu:///system"): 123 | 124 | conn = None 125 | try: 126 | conn = libvirt.open(uri) 127 | except Exception, e: 128 | logger.exception(e) 129 | 130 | ret_dict = {} 131 | ret_dict['req'] = "host.hw" 132 | ret_dict['sn'] = sn 133 | 134 | chost = vmmhost(sn, conn) 135 | 136 | ret_dict['body'] = [ chost.get_hw_info() ] 137 | 138 | if conn: 139 | conn.close() 140 | 141 | return ret_dict 142 | 143 | def build_host_status(sn, uri = "qemu:///system"): 144 | 145 | conn = None 146 | try: 147 | conn = libvirt.open(uri) 148 | except Exception, e: 149 | logger.exception(e) 150 | 151 | ret_dict = {} 152 | ret_dict['req'] = "host.status" 153 | ret_dict['sn'] = sn 154 | 155 | chost = vmmhost(sn, conn) 156 | host_info = chost.get_sw_info() 157 | host_info['name'] = chost.get_hostname() 158 | host_info['status'] = 1 159 | host_info['update_time'] = get_now_str() 160 | host_info['task'] = [] #todo 161 | 162 | 163 | host_info['mem_usage'] = chost.get_memory_usage()['mem_usage'] 164 | host_info['cpu_idle'] = ("%.2f" % (100- float(chost.get_cpu_usage()['cpu_usage']))) 165 | host_info['disk'] = chost.get_disk_usage() 166 | host_info['net'] = chost.get_net_usage() 167 | #todo 168 | host_info['ip'] = str(chost.get_out_ip()) 169 | host_info['disk_usage'] = 20 #%.2f 170 | 171 | #todo: filter files by 'iso/ISO' 172 | vm_files = [] 173 | vm_file_item = {} 174 | 175 | for i in os.listdir(constants.iso_path): 176 | abs_path = os.path.join(constants.iso_path, i) 177 | if os.path.isfile(abs_path): 178 | vm_file_item={} 179 | vm_file_item['name'] = i 180 | vm_file_item['type'] = 0 181 | vm_file_item['size'] = os.path.getsize(abs_path) 182 | vm_file_item['path'] = constants.iso_path 183 | vm_files.append(vm_file_item) 184 | 185 | for i in os.listdir(constants.img_template_path): 186 | abs_path = os.path.join(constants.img_template_path, i) 187 | if os.path.isfile(abs_path): 188 | vm_file_item={} 189 | vm_file_item['name'] = i 190 | vm_file_item['type'] = 0 191 | vm_file_item['size'] = os.path.getsize(abs_path) 192 | vm_file_item['path'] = constants.img_template_path 193 | vm_files.append(vm_file_item) 194 | 195 | host_info['vm_files'] = vm_files 196 | 197 | ret_dict['body'] = [ host_info ] 198 | 199 | if conn: 200 | conn.close() 201 | 202 | logger.debug(ret_dict) 203 | return ret_dict 204 | 205 | 206 | def start(): 207 | sn = 'CAS1000000000' 208 | try: 209 | payload = build_host_hw(sn) 210 | logger.debug(json.dumps(payload)) 211 | r = requests.post(constants.url_status, data=json.dumps(payload)) 212 | except Exception, e: 213 | logger.exception(e) 214 | while 1: 215 | 216 | try: 217 | payload = build_host_status(sn) 218 | r = requests.post(constants.url_status, data=json.dumps(payload)) 219 | print r.status_code 220 | 221 | payload = build_vm_conf(sn) 222 | r = requests.post(constants.url_status, data=json.dumps(payload)) 223 | print r.status_code 224 | 225 | payload = build_vm_status(sn) 226 | r = requests.post(constants.url_status, data=json.dumps(payload)) 227 | print r.status_code 228 | except Exception, e: 229 | logger.exception(e) 230 | 231 | time.sleep(5) 232 | 233 | 234 | 235 | start() 236 | exit() 237 | 238 | """ 239 | 240 | _task_wait_list = [] 241 | _task_doing_list = [] 242 | 243 | def dispatch(): 244 | while 1: 245 | time.sleep(1) 246 | lock _task_wait_list 247 | if len(_task_wait_list) != 0: 248 | pop 249 | get thread to do task 250 | unlock _task_wait_list 251 | 252 | def get_task_status(): 253 | pass 254 | 255 | 256 | """ 257 | def task_is_expired(task_item): 258 | pass 259 | def task_handling(task_item): 260 | 261 | pass 262 | def task_done(task_item): 263 | pass 264 | 265 | #pool = threadpool.ThreadPool(10) 266 | #start() 267 | 268 | 269 | 270 | 271 | 272 | 273 | -------------------------------------------------------------------------------- /agent/constants.py: -------------------------------------------------------------------------------- 1 | #img_path = "/home/louzhengwei/test/sdb2/img/" 2 | 3 | 4 | img_root_path = "/img" 5 | img_os_path = "/img/os" 6 | img_data_path = "/img/data" 7 | img_template_path = "/img/template" 8 | iso_path = "/img/iso" 9 | 10 | vm_status_running = 1 11 | vm_status_shutoff = 5 12 | 13 | ERROR_MSG_EXPIRED = "task is expired" 14 | ERROR_MSG_TYPE_INVALID = "task type is invalid" 15 | ERROR_MSG_FORMAT_INVALID = "task format is invalid" 16 | ERROR_MSG_HANDLE = "task handle is invalid" 17 | 18 | url_status = 'http://192.168.1.107:8000/api/kvm/' 19 | url_task = 'http://192.168.1.107:8000/api/task/' 20 | -------------------------------------------------------------------------------- /agent/disk.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /agent/host.py: -------------------------------------------------------------------------------- 1 | import xml.etree.ElementTree as ET 2 | from log import logger 3 | import os, sys 4 | import libvirt 5 | import constants 6 | 7 | import subprocess 8 | import commands 9 | import time 10 | import urllib 11 | import re 12 | import urllib2 13 | 14 | 15 | class vmmhost: 16 | def __init__(self, sn, conn): 17 | self.conn = conn 18 | self.sn = sn 19 | 20 | def get_vmlist(self): 21 | dom_names = [] 22 | for dom in self.conn.listAllDomains(): 23 | dom_names.append(dom.name()) 24 | return dom_names 25 | 26 | def get_sw_info(self): 27 | ret = {} 28 | hv_ver = self.conn.getVersion() 29 | major = hv_ver / 1000000 30 | minor = hv_ver % 1000000 / 1000 31 | release = hv_ver % 1000 32 | hv_ver = str(major)+'.'+str(minor)+'.'+str(release) 33 | 34 | lib_ver = self.conn.getLibVersion() 35 | major = lib_ver / 1000000 36 | minor = lib_ver % 1000000 / 1000 37 | release = lib_ver % 1000 38 | lib_ver = str(major)+'.'+str(minor)+'.'+str(release) 39 | 40 | abspath = os.path.dirname(os.path.abspath(__file__)) 41 | cli_ver = open(abspath + "/VERSION").readline().rstrip('\r\n') 42 | 43 | cmd = "uname -r" 44 | os_ver = commands.getoutput(cmd) 45 | 46 | ret['version'] = cli_ver 47 | ret['libvirt_version'] = lib_ver 48 | ret['hv_version'] = hv_ver 49 | ret['os_version'] = os_ver 50 | return ret 51 | 52 | def get_out_ip(self): 53 | response = urllib2.urlopen('http://www.ip.cn') 54 | html = response.read() 55 | ip=re.search(r'code.(.*?)..code',html) 56 | return ip.group(1) 57 | 58 | def get_hw_info(self): 59 | ret = {} 60 | cmd = "lscpu | grep '^Arch' | awk '{print $2}'" 61 | result = commands.getoutput(cmd) 62 | ret['architecture'] = result 63 | 64 | cmd = "lscpu | grep '^CPU(s)' | awk '{print $2}'" 65 | result = commands.getoutput(cmd) 66 | ret['cpus'] = int(result) 67 | 68 | cmd = "lscpu | grep '^Model name' | awk -F: '{print $2}'" 69 | result = commands.getoutput(cmd) 70 | ret['cpu_name'] = result.strip() 71 | disk_size_cmd = "lsblk -b --output=NAME,SIZE | grep '^.d' | awk '{printf(\"%s\\n%s\\n\", $1,$2)}'" 72 | cmd_result = commands.getoutput(disk_size_cmd) 73 | disk_size = 0 74 | disk_num = 0 75 | disk_info = [] 76 | i = 0 77 | #for i < len(cmd_result): 78 | cmd_result_list = cmd_result.splitlines() 79 | while i < len(cmd_result_list): 80 | #for item in cmd_result.splitlines(): 81 | disk_item = {} 82 | disk_item['name'] = cmd_result_list[i] 83 | i += 1 84 | disk_item['size'] = cmd_result_list[i] 85 | i += 1 86 | disk_info.append(disk_item) 87 | disk_size += int(disk_item['size']) 88 | disk_num += 1 89 | ret['disk'] = disk_info 90 | ret['disk_size'] = disk_size 91 | ret['data_disk_num'] = disk_num 92 | 93 | nodeinfo = self.conn.getInfo() 94 | ''' 95 | print('Model: '+str(nodeinfo[0])) 96 | print('Memory size: '+str(nodeinfo[1])+'MB') 97 | print('Number of CPUs: '+str(nodeinfo[2])) 98 | print('MHz of CPUs: '+str(nodeinfo[3])) 99 | print('Number of NUMA nodes: '+str(nodeinfo[4])) 100 | print('Number of CPU sockets: '+str(nodeinfo[5])) 101 | print('Number of CPU cores per socket: '+str(nodeinfo[6])) 102 | print('Number of CPU threads per core: '+str(nodeinfo[7])) 103 | ''' 104 | ret['total_mem'] = int(nodeinfo[1])*1024*1024 105 | 106 | return ret 107 | 108 | def get_memory_usage(self): 109 | """ 110 | Function return memory usage on node. 111 | """ 112 | get_all_mem = self.conn.getInfo()[1] * 1048576 113 | get_freemem = self.conn.getMemoryStats(-1, 0) 114 | print get_freemem 115 | if type(get_freemem) == dict: 116 | free = (get_freemem.values()[0] + 117 | get_freemem.values()[2] + 118 | get_freemem.values()[3]) * 1024 119 | percent = ("%2.f" % (100 - ((free * 100 * 1.0) / get_all_mem))) 120 | usage = (get_all_mem - free) 121 | mem_usage = { 122 | 'mem_all': get_all_mem, 123 | 'mem_free': free, 124 | 'mem_usage': percent 125 | } 126 | else: 127 | mem_usage = None 128 | 129 | return mem_usage 130 | 131 | def get_cpu_usage(self): 132 | """ 133 | Function return cpu usage on node. 134 | """ 135 | prev_idle = 0 136 | prev_total = 0 137 | cpu = self.conn.getCPUStats(-1, 0) 138 | if type(cpu) == dict: 139 | for num in range(2): 140 | idle = self.conn.getCPUStats(-1, 0).values()[1] 141 | total = sum(self.conn.getCPUStats(-1, 0).values()) 142 | diff_idle = idle - prev_idle 143 | diff_total = total - prev_total 144 | diff_usage = ("%.2f" % ((1000 * (diff_total - diff_idle) * 1.0 / diff_total + 5) / 10)) 145 | prev_total = total 146 | prev_idle = idle 147 | if num == 0: 148 | time.sleep(1) 149 | else: 150 | if diff_usage < 0: 151 | diff_usage = 0 152 | else: 153 | return None 154 | return {'cpu_usage': diff_usage} 155 | 156 | def get_rx_tx(self, itface): 157 | try: 158 | cmd_rx = "cat /sys/class/net/%s/statistics/rx_bytes" % itface 159 | cmd_tx = "cat /sys/class/net/%s/statistics/tx_bytes" % itface 160 | data_rx_prev = commands.getoutput(cmd_rx) 161 | data_tx_prev = commands.getoutput(cmd_tx) 162 | 163 | time.sleep(1) 164 | data_rx_now = commands.getoutput(cmd_rx) 165 | data_tx_now = commands.getoutput(cmd_tx) 166 | 167 | rx = (float(data_rx_now) - float(data_rx_prev))/1024 168 | rx = ("%.2f" % rx) 169 | tx = (float(data_tx_now) - float(data_tx_prev))/1024 170 | tx = ("%.2f" % tx) 171 | 172 | except Exception, e: 173 | logger.exception(e) 174 | return None 175 | 176 | return {"in" : rx, "out" : tx} 177 | 178 | 179 | def get_net_usage(self, itfaces = ["ovirtmgmt"]): 180 | ret = [] 181 | 182 | for itface in itfaces: 183 | item = {} 184 | item['name'] = itface 185 | item['type'] = 'service' 186 | rx_tx = self.get_rx_tx(itface) 187 | if rx_tx is not None: 188 | item['in'] = rx_tx['in'] 189 | item['out'] = rx_tx['out'] 190 | 191 | ret.append(item) 192 | return ret 193 | 194 | def get_disk_usage(self): 195 | """ 196 | Function return cpu usage on node. 197 | """ 198 | ret_list = [] 199 | cmd = "df -l | grep -v ^Filesystem " 200 | result = commands.getoutput(cmd) 201 | for item in result.splitlines(): 202 | ret_list.append({}) 203 | 204 | col = ("source", "size", "avail", "pcent", "target") 205 | for item_col in col: 206 | i = 0 207 | cmd = "df -l --output=%s | awk 'NR>1 {print $0}'" % item_col 208 | result = commands.getoutput(cmd) 209 | for item in result.splitlines(): 210 | ret_list[i][item_col] = item.strip() 211 | i += 1 212 | 213 | logger.debug(ret_list) 214 | #delete tmpfs: delete the one that does not begin with '/' 215 | for index in range(len(ret_list)-1, -1, -1): 216 | if re.match('/', ret_list[index]["source"]) is None: 217 | del(ret_list[index]) 218 | else: 219 | #add column: util 220 | cmd = "iostat -x %s | grep -A1 util | tail -1 | awk '{print $NF}' " % ret_list[index]["source"] 221 | result = commands.getoutput(cmd) 222 | ret_list[index]['util'] = float(result)*100 223 | #delete character '%' 224 | ret_list[index]['pcent'] = ("%.2f" % float(ret_list[index]['pcent'][:-1])) 225 | 226 | return ret_list 227 | 228 | def get_hostname(self): 229 | return self.conn.getHostname() 230 | 231 | def get_resource_info(self): 232 | pass 233 | 234 | @staticmethod 235 | def get_file_list(path): 236 | ret_list = [] 237 | files = os.listdir(path) 238 | for fi in files: 239 | if os.path.isfile(os.path.join(path, fi)): 240 | ret_list.append(fi) 241 | 242 | return ret_list 243 | 244 | def download_res(self, url, checksum, save_to_path): 245 | i = 1 246 | percent = 0 247 | def report(count, blockSize, totalSize): 248 | percent = int(count*blockSize*100/totalSize) 249 | sys.stdout.write("\r %d %d %d%%" % (i, count, percent) + ' complete') 250 | sys.stdout.flush() 251 | filename = commands.getoutput('basename %s' % url) 252 | print '1111' 253 | urllib.urlretrieve(url, save_to_path + '/' + filename, reporthook=report) 254 | print '22222' 255 | pass 256 | 257 | @staticmethod 258 | def report(count, blockSize, totalSize): 259 | percent = int(count*blockSize*100/totalSize) 260 | sys.stdout.write("\r %d %d%%" % (count, percent) + ' complete') 261 | sys.stdout.flush() 262 | -------------------------------------------------------------------------------- /agent/log.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | #logging.config.fileConfig("logging.conf") 4 | logger = logging.getLogger() 5 | 6 | fh = logging.FileHandler('/tmp/test.log') 7 | ch = logging.StreamHandler() 8 | 9 | formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(threadName)s - %(filename)s:%(lineno)d:%(funcName)s - %(message)s') 10 | fh.setFormatter(formatter) 11 | ch.setFormatter(formatter) 12 | 13 | logger.addHandler(fh) 14 | logger.addHandler(ch) 15 | 16 | logger.setLevel(logging.DEBUG) 17 | 18 | 19 | -------------------------------------------------------------------------------- /agent/test/1.xml: -------------------------------------------------------------------------------- 1 | 2 | vm_name1 3 | 92b4e1bc-acbf-4873-9a1f-be17f7425aa9 4 | 2097152 5 | 2097152 6 | 16 7 | 8 | 1020 9 | 10 | 11 | 12 | oVirt 13 | oVirt Node 14 | 7-1.1503.el7.centos.2.8 15 | 16 | 17 | 18 | hvm 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | Nehalem 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | destroy 38 | restart 39 | destroy 40 | 41 | /usr/libexec/qemu-kvm 42 | 43 | 44 | 45 | 46 |
47 | 48 | 49 | 50 | 51 | 52 |
53 | 54 | 55 |
56 | 57 | 58 | 59 |
60 | 61 | 62 |
63 | 64 | 65 | 66 | 67 | 68 | 69 |
70 | 71 | 72 | 73 | 74 |
75 | 76 | 77 | 78 | 79 |
80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 |