python脚本:连接Linux """ paramiko,pywinrm实现windows/linux脚本调用 linux下脚本语法错误,或者命令不存在等没有通过stderr变量接收到,只能添加判断条件; windows下可以接收到错误信息并作出判
python脚本:连接Linux
"""paramiko, pywinrm实现windows/linux脚本调用
linux下脚本语法错误,或者命令不存在等没有通过stderr变量接收到,只能添加判断条件;
windows下可以接收到错误信息并作出判断;
"""
import paramiko
import winrm
import socket
import requests
import datetime
from winrm.exceptions import WinRMTransportError, WinRMOperationTimeoutError, WinRMError
from requests.exceptions import ConnectionError
###############################################################
# 为实现 WINDOWS下执行脚本时长超时设置,对wimrm中相关类进行重写。#
###############################################################
# 重写Protocol类
class Protocol(winrm.protocol.Protocol):
def get_command_output(self, shell_id, command_id):
"""
Get the Output of the given shell and command
@param string shell_id: The shell id on the remote machine.
See #open_shell
@param string command_id: The command id on the remote machine.
See #run_command
#@return [Hash] Returns a Hash with a key :exitcode and :data.
Data is an Array of Hashes where the cooresponding key
# is either :stdout or :stderr. The reason it is in an Array so so
we can get the output in the order it ocurrs on
# the console.
"""
stdout_buffer, stderr_buffer = [], []
command_done = False
############################################################################
# 限时6*60s #
# 程序反复查看相应,如果相应成功,且在超时时限内则命令成功,否则报超时异常。 #
# 获取响应的时长较长。 #
############################################################################
return_code = -1
limited_seconds = 6 * 60
start_time = datetime.datetime.now()
while not command_done:
print('get the response from windows...')
try:
stdout, stderr, return_code, command_done = \
self._raw_get_command_output(shell_id, command_id)
stdout_buffer.append(stdout)
stderr_buffer.append(stderr)
except WinRMOperationTimeoutError as e:
# this is an expected error when waiting for a long-running process, just silently retry
pass
end_time = datetime.datetime.now()
delta_time = end_time - start_time
total_seconds = delta_time.total_seconds()
if total_seconds > limited_seconds:
raise WinRMOperationTimeoutError()
return b''.join(stdout_buffer), b''.join(stderr_buffer), return_code
# 重写Session类
class Session(winrm.Session):
# TODO implement context manager methods
def __init__(self, target, auth, **kwargs):
username, password = auth
self.url = self._build_url(target, kwargs.get('transport', 'plaintext'))
self.protocol = Protocol(self.url,
username=username, password=password, **kwargs)
class ServerByPara(object):
def __init__(self, cmd, host, user, password, system_choice):
self.cmd = cmd
self.client = paramiko.SSHClient()
self.host = host
self.user = user
self.pwd = password
self.system_choice = system_choice
def exec_linux_cmd(self, succeedtext, linux_timeout, port=22):
data_init = ''
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
self.client.connect(hostname=self.host, username=self.user, password=self.pwd, timeout=5, port=port)
except (socket.timeout, paramiko.ssh_exception.SSHException) as e:
print("连接服务器失败")
return {
"exec_tag": 1,
"data": "连接服务器失败 {0}".format(e),
"log": "连接服务器失败",
}
try:
stdin, stdout, stderr = self.client.exec_command(self.cmd, get_pty=True, timeout=linux_timeout)
if stderr.read():
exec_tag = 1
data_init = str(stderr.read(), encoding='utf-8')
# for data in stderr.readlines():
# data_init += data
log = ""
else:
exec_tag = 0
log = ""
try:
data_init = str(stdout.read(), encoding='utf-8')
if data_init:
data_init = " ".join(data_init.split("\r\n"))
if "command not found" in data_init: # 命令不存在
exec_tag = 1
log = "命令不存在"
elif "syntax error" in data_init: # 语法错误
exec_tag = 1
log = "语法错误"
elif "No such file or directory" in data_init: # 脚本不存在
exec_tag = 1
log = "脚本不存在"
elif succeedtext is not None:
if succeedtext not in data_init:
exec_tag = 1
log = "未匹配"
except Exception as e:
print(e)
exec_tag = 0 # 不抛错
log = "编码错误"
data_init = "编码错误"
except socket.timeout as e:
print("脚本执行超时")
return {
"exec_tag": 1,
"data": "脚本执行超时",
"log": "脚本执行超时",
}
return {
"exec_tag": exec_tag,
"data": data_init,
"log": log,
}
def exec_win_cmd(self, succeedtext):
data_init = ""
log = ""
try:
s = Session(self.host, auth=(self.user, self.pwd))
ret = s.run_cmd(self.cmd)
except (ConnectionError, WinRMOperationTimeoutError, WinRMTransportError, WinRMError) as e:
if type(e) == WinRMOperationTimeoutError:
print("脚本执行超时")
exec_tag = 1
data = "脚本执行超时 {0}".format(e)
log = "脚本执行超时"
elif type(e) in [ConnectionError, WinRMTransportError]:
print("连接windows失败")
exec_tag = 1
data = "连接windows失败 {0}".format(e)
log = "连接windows失败"
else:
print("执行windows脚本发生异常错误")
exec_tag = 1
data = "执行windows脚本发生异常错误 {0}".format(e)
log = "执行windows脚本发生异常错误"
return {
"exec_tag": exec_tag,
"data": data,
"log": log,
}
else:
if ret.std_err:
data_init = str(ret.std_err, encoding='gbk')
exec_tag = 1
# for data in ret.std_err.decode().split("\r\n"):
# data_init += data
log = ""
else:
exec_tag = 0
try:
data_init = str(ret.std_out, encoding='gbk')
if data_init:
data_init = "".join(data_init.split("\r\n"))
# for data in ret.std_out.decode().split("\r\n"):
# data_init += data
except Exception as e:
print(e)
exec_tag = 0 # 不抛错
log = "编码错误"
data_init = "编码错误"
else:
if succeedtext is not None:
if succeedtext not in data_init:
exec_tag = 1
log = "未匹配"
return {
"exec_tag": exec_tag,
"data": data_init,
"log": log,
}
def run(self, succeedtext,linux_timeout=6* 60):
if self.system_choice == "Linux":
result = self.exec_linux_cmd(succeedtext, linux_timeout)
if self.client:
self.client.close()
elif self.system_choice == "AIX":
result = self.exec_linux_cmd(succeedtext, linux_timeout, port=22)
if self.client:
self.client.close()
else:
result = self.exec_win_cmd(succeedtext)
# print(result)
return result
if __name__ == '__main__':
# server_obj = ServerByPara(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])
# server_obj = ServerByPara(r"C:\Users\Administrator\Desktop\test_python.bat", "192.168.100.151", "administrator","tesunet@2017", "Windows")
server_obj = ServerByPara(r"echo 中文 > C:\Users\Administrator\Desktop\test.bat",
"192.168.100.154", "administrator", "tesunet@2017", "Windows")
# linux_temp_script_file = r"/tmp/drm/954/tmp_script_6486.sh&&/tmp/drm/954/tmp_script_6486.sh"
# cmd = r"sed -i 's/\r$//' {0}&&{0}".format(linux_temp_script_file)
# print(cmd) # sed -i 's/\r$//' /tmp/drm/954/tmp_script_6486.sh&&/tmp/drm/954/tmp_script_6486.sh
# server_obj = ServerByPara("mkdir -p /tmp/drm/957",
# "10.64.7.43", "root", "qtdl2003", "Linux")
# server_obj = ServerByPara("echo 中文",
# "192.168.184.66", "root", "password", "Linux")
# server_obj = ServerByPara(r"echo '你好你好你好你好你好你好你好';echo '你好你好你好你好你好你好你好';echo '你好你好你好你好你好你好你好'", "192.168.184.66", "root","password", "Linux")
server_obj.run("")
print(11111111111111)
python脚本:操作kvm虚拟机,进行kvm虚拟机开机、关机、克隆、快照等。
from drm import remotefrom lxml import etree
import time
import json
class KVMApi():
def __init__(self, credit):
self.ip = credit['KvmHost']
self.username = credit['KvmUser']
self.password = credit['KvmPasswd']
self.system_tag = credit['SystemType']
def remote_linux(self, exe_cmd):
rm_obj = remote.ServerByPara(exe_cmd, self.ip, self.username, self.password, self.system_tag)
result = rm_obj.run(succeedtext='', linux_timeout=12 * 60)
return result
def list_of_groups(self, list_info, per_list_len):
"""
list_info: 列表元素
per_list_len: 每个小列表的长度
"""
list_of_group = zip(*(iter(list_info),) * per_list_len)
end_list = [list(i) for i in list_of_group]
count = len(list_info) % per_list_len
end_list.append(list_info[-count:]) if count != 0 else end_list
return end_list
def domstate(self, kvm_name):
# 获取虚拟机的状态
exe_cmd = r'virsh domstate {0}'.format(kvm_name)
result = self.remote_linux(exe_cmd)
result = result['data'].strip()
return result
def kvm_all_list(self):
# 获取所有kvm虚拟机
exe_cmd = r'virsh list --all'
result = self.remote_linux(exe_cmd)
kvm_list = [x for x in result['data'].split(' ') if x]
del kvm_list[0:4]
kvm_list_filter = []
for i in kvm_list:
if i == 'shut':
continue
if i == 'off':
i = '关闭'
if i == 'running':
i = '运行中'
if i == 'paused':
i = '暂停'
kvm_list_filter.append(i)
end_list = self.list_of_groups(kvm_list_filter, 3)
kvm_all_list_dict = []
for item in end_list:
data = {}
data['id'] = item[0]
data['name'] = item[1]
data['state'] = item[2]
kvm_all_list_dict.append(data)
return kvm_all_list_dict
def kvm_exclude_copy_list(self):
# 获取除实例之外所有kvm虚拟机
exe_cmd = r'virsh list --all'
result = self.remote_linux(exe_cmd)
kvm_list = [x for x in result['data'].split(' ') if x]
del kvm_list[0:4]
kvm_list_filter = []
for i in kvm_list:
if i == 'shut':
continue
if i == 'off':
i = '关闭'
if i == 'running':
i = '运行中'
if i == 'paused':
i = '暂停'
kvm_list_filter.append(i)
end_list = self.list_of_groups(kvm_list_filter, 3)
kvm_all_list_dict = []
for item in end_list:
data = {}
if '@' not in item[1]:
data['id'] = item[0]
data['name'] = item[1]
data['state'] = item[2]
kvm_all_list_dict.append(data)
return kvm_all_list_dict
def kvm_include_copy_list(self, kvm_copy_name):
# 获取所有实例虚拟机
exe_cmd = r'virsh list --all'
result = self.remote_linux(exe_cmd)
kvm_list = [x for x in result['data'].split(' ') if x]
del kvm_list[0:4]
kvm_list_filter = []
for i in kvm_list:
if i == 'shut':
continue
if i == 'off':
i = '关闭'
if i == 'running':
i = '运行中'
if i == 'paused':
i = '暂停'
kvm_list_filter.append(i)
end_list = self.list_of_groups(kvm_list_filter, 3)
kvm_all_list_dict = []
for item in end_list:
data = {}
copyname = kvm_copy_name + '@'
if copyname in item[1]:
data['id'] = item[0]
data['name'] = item[1]
data['state'] = item[2]
kvm_all_list_dict.append(data)
return kvm_all_list_dict
def kvm_run_list(self):
# 获取正在运行的虚拟机
exe_cmd = r'virsh list'
result = self.remote_linux(exe_cmd)
kvm_list = [x for x in result['data'].split(' ') if x]
del kvm_list[0:3]
end_list = self.list_of_groups(kvm_list, 3)
kvm_all_list_dict = []
for item in end_list:
data = {}
data['id'] = item[0]
data['name'] = item[1]
data['state'] = item[2]
kvm_all_list_dict.append(data)
return kvm_all_list_dict
def kvm_start(self, kvm_state, kvm_name):
# 开启虚拟机:是关闭的状态(shut off/关闭)
if kvm_state == 'shut off' or kvm_state == '关闭':
exe_cmd = r'virsh start {0}'.format(kvm_name)
result = self.remote_linux(exe_cmd)
if result['data'].strip() == 'Domain {0} started'.format(kvm_name) or \
result['data'].strip() == '域 {0} 已开始'.format(kvm_name):
result = '开机成功。'
else:
result = '开机失败。'
else:
result = '虚拟机已开启。'
return result
def kvm_shutdown(self, kvm_state, kvm_name):
# 关闭虚拟机:是开启的状态(running)
if kvm_state == 'running' or kvm_state == '运行中':
exe_cmd = r'virsh shutdown {0}'.format(kvm_name)
result = self.remote_linux(exe_cmd)
if result['data'].strip() == 'Domain {0} is being shutdown'.format(kvm_name) or \
result['data'].strip() == '域 {0} 被关闭'.format(kvm_name):
time.sleep(5)
state = self.domstate(kvm_name)
if state == 'shut off' or state == '关闭':
result = '关闭成功。'
else:
result = '关闭失败。'
else:
result = '关闭失败。'
elif kvm_state == '暂停' or kvm_state == 'paused':
result = '虚拟机未运行。'
else:
result = '虚拟机未开启。'
return result
def kvm_destroy(self, kvm_state, kvm_name):
# 断电虚拟机:是开启的状态(running)或者是暂停状态(pasued)
if kvm_state == 'running' or kvm_state == '运行中' or kvm_state == 'paused' or kvm_state == '暂停':
exe_cmd = r'virsh destroy {0}'.format(kvm_name)
result = self.remote_linux(exe_cmd)
if result['data'].strip() == 'Domain {0} destroyed'.format(kvm_name) or \
result['data'].strip() == '域 {0} 被删除'.format(kvm_name):
result = '断电成功。'
else:
result = '断电失败。'
else:
result = '虚拟机未开启。'
return result
def filesystem_del(self, filesystem):
try:
exe_cmd = r'zfs destroy {0}'.format(filesystem)
result = self.remote_linux(exe_cmd)
if result['data'] == '':
result = '删除文件系统成功。'
else:
result = '删除文件系统成功。'
except Exception as e:
print(e)
result = '删除文件系统失败。'
return result
def undefine(self, kvm_name, state):
"""
删除虚拟机
停止主机:virsh shutdown linux65
删除主机定义:virsh undefine linux65
删除KVM虚拟机文件系统: zfs destroy tank/CentOS-7@test3
"""
# 这里需要先判断虚拟机的状态
# 如果是关闭(shut off)的虚拟机直接删除,然后删除磁盘文件,如果是开启(running)的虚拟机,先关闭再删除虚拟机,在删除磁盘文件
# 如果虚拟机中创建了快照,虚拟机是无法删除的,需要删除所有的快照,然后在执行删除虚拟机操作
if state == 'shut off' or state == '关闭':
snapshot_list = self.snapshot_list(kvm_name)
if not snapshot_list:
try:
exe_cmd = r'virsh undefine {0}'.format(kvm_name)
result = self.remote_linux(exe_cmd)
if result['data'].strip() == 'Domain {0} has been undefined'.format(kvm_name) or \
result['data'].strip() == '域 {0} 已经被取消定义'.format(kvm_name):
result = '取消定义成功。'
else:
result = '取消定义失败。'
except Exception as e:
print(e)
result = '取消定义失败。'
else:
result = '虚拟机已创建快照,无法删除。'
else:
result = '虚拟机未关闭。'
return result
def kvm_suspend(self, kvm_state, kvm_name):
"""
暂停虚机:开启(ruuning)/暂停(paused)的状态,关闭状态提醒错误。
"""
if kvm_state == 'running' or kvm_state == '运行中' or kvm_state == 'paused' or kvm_state == '暂停':
exe_cmd = r'virsh suspend {0}'.format(kvm_name)
result = self.remote_linux(exe_cmd)
if result['data'].strip() == 'Domain {0} suspended'.format(kvm_name) or \
result['data'].strip() == '域 {0} 被挂起'.format(kvm_name):
result = '暂停成功。'
else:
result = '暂停失败。'
else:
result = '虚拟机未开启。'
return result
def kvm_resume(self, kvm_state, kvm_name):
"""
恢复暂停的虚机:必须是暂停(paused)状态的虚拟机才可以执行恢复操作
"""
if kvm_state == 'paused' or kvm_state == '暂停':
exe_cmd = r'virsh resume {0}'.format(kvm_name)
result = self.remote_linux(exe_cmd)
if result['data'].strip() == 'Domain {0} resumed'.format(kvm_name) or \
result['data'].strip() == '域 {0} 被重新恢复'.format(kvm_name):
result = '运行成功。'
else:
result = '运行失败。'
else:
result = '虚拟机非暂停状态,无法执行此操作。'
return result
def kvm_reboot(self, kvm_state, kvm_name):
"""
重启虚机:必须是开启(running)/暂停(paused)状态的虚拟机才可以执行重启操作
"""
if kvm_state == 'running' or kvm_state == '运行中' or kvm_state == '暂停' or kvm_state == 'paused':
exe_cmd = r'virsh reboot {0}'.format(kvm_name)
result = self.remote_linux(exe_cmd)
if result['data'].strip() == 'Domain {0} is being rebooted'.format(kvm_name) or \
result['data'].strip() == '域 {0} 正在被重新启动'.format(kvm_name):
result = '重启成功。'
else:
result = '重启失败。'
else:
result = '虚拟机未开启。'
return result
def kvm_clone(self, kvm_state, kvm_name, kvm_name_clone, filesystem):
"""
克隆虚拟机:需要在关机或者暂停的状态下才可以进行克隆
克隆出错:ERROR Domain with devices to clone must be paused or shutoff.
克隆成功:Allocating 'Test-3.qcow2' | 80 GB 00:02 Clone 'Test-3' created successfully.
virt-clone -o win2k16 -n Test-1 -f /var/lib/libvirt/images/Test—1.qcow2
注:-o:original 后面跟要克隆的虚拟机名字
-n:name 克隆后虚拟机的名字
-f:file 指定镜像存放的路径:默认路径:/var/lib/libvirt/images
新的虚拟机存在报错:ERROR Invalid name for new guest: Guest name 'Test-3' is already in use.
"""
# 判断虚拟机的状态
disk_path = '/' + filesystem + '/' + kvm_name_clone + '.qcow2'
if kvm_state == 'shut off' or kvm_state == 'paused' or kvm_state == '关闭' or kvm_state == '暂停':
exe_cmd = r'virt-clone -o {0} -n {1} -f {2}'.format(kvm_name, kvm_name_clone, disk_path)
result = self.remote_linux(exe_cmd)
if "Clone '{0}' created successfully.".format(kvm_name_clone) or \
"成功克隆 '{0}'".format(kvm_name_clone) in result['data']:
result = '克隆成功。'
else:
result = '克隆失败。'
else:
result = '虚拟机未关闭。'
return result
def kvm_info_data(self, kvm_name):
# 获取虚拟机cpu、内存、系统类型、磁盘
exe_cmd = r'cat /etc/libvirt/qemu/{0}.xml'.format(kvm_name)
result = self.remote_linux(exe_cmd)
config = etree.XML(result['data'])
kvm_cpu = config.xpath("//vcpu")[0]
kvm_memory = config.xpath("//memory")[0]
kvm_os = config.xpath("//os/type")[0]
kvm_diskpath = config.xpath("//disk/source")[0]
kvm_os = kvm_os.text
kvm_cpu = int(kvm_cpu.text)
kvm_memory = int(int(kvm_memory.text)/1024)
kvm_disk = kvm_diskpath.attrib['file']
kvm_info = {
'kvm_os': kvm_os,
'kvm_disk': kvm_disk,
'kvm_cpu': kvm_cpu,
'kvm_memory': kvm_memory
}
return kvm_info
def snapshot_create(self, kvm_name):
# 创建快照
# 创建成功提示信息:Domain snapshot 1596685828 created
exe_cmd = r'virsh snapshot-create {0}'.format(kvm_name)
result = self.remote_linux(exe_cmd)
if 'created' in result['data'] or '已生成域快照' in result['data']:
result = '虚拟机{0}创建快照成功。'.format(kvm_name)
else:
result = '虚拟机{0}创建快照失败。'.format(kvm_name)
return result
def snapshot_list(self, kvm_name):
# 查看快照列表
exe_cmd = r'virsh snapshot-list {0}'.format(kvm_name)
result = self.remote_linux(exe_cmd)
list = [x for x in result['data'].split(' ') if x]
del list[0:4]
end_list = self.list_of_groups(list, 5)
snapshot_list_dict = []
for item in end_list:
data = {}
data['name'] = item[0]
snapshot_list_dict.append(data)
"""
[{'name': '1596684491'},
{'name': '1596685828'}]
"""
return snapshot_list_dict
def snapshot_del(self, kvm_name, snapshotname):
# 删除快照
exe_cmd = r'virsh snapshot-delete {0} --snapshotname {1}'.format(kvm_name, snapshotname)
result = self.remote_linux(exe_cmd)
if result['data'] == 'Domain snapshot {0} deleted'.format(snapshotname) or result['data'] == '已删除域快照':
result = '快照{0}删除成功。'.format(snapshotname)
else:
result = '快照{0}删除失败。'.format(snapshotname)
return result
def snapshot_revert(self, kvm_name, snapshotname):
# 恢复快照:虚拟机是关机的状态
state = self.domstate(kvm_name)
if state == 'shut off':
exe_cmd = r'virsh snapshot-revert {0} --snapshotname {1}'.format(kvm_name, snapshotname)
self.remote_linux(exe_cmd)
result = '恢复到快照{0}成功。'.format(snapshotname)
else:
result = '请先关闭虚拟机,再执行恢复操作。'.format(kvm_name)
return result
def zfs_kvm_filesystem(self):
exe_cmd = r'ls /data/vmdata'.format()
result = self.remote_linux(exe_cmd)
kvm_filesystem = [x.replace('\t', '') for x in result['data'].split(' ') if x]
return kvm_filesystem
def create_filesystem(self, filesystem):
"""
为每一台虚拟机分别创建一个文件系统
tank/kvm_1
tank/kvm_2
tank/kvm_3
zfs创建文件系统:zfs create tank/kvm_1
zfs_pool_data:文件系统路径
"""
try:
exe_cmd = r'zfs create {0}'.format(filesystem)
result = self.remote_linux(exe_cmd)
if result['data'] == '':
result = '文件系统创建成功。'
else:
result = '文件系统创建失败。'
except:
result = '文件系统创建失败。'
return result
def zfs_create_snapshot(self, snapshot_name):
"""
创建快照:zfs snapshot tank/kvm_1@2020-07-28
kvm_name:虚拟机
zfs_snapshot_name:快照名字
"""
try:
exe_cmd = r'zfs snapshot {0}'.format(snapshot_name)
result = self.remote_linux(exe_cmd)
if result['data'] == '':
info = '创建成功。'
else:
info = '创建失败。'
except:
info = '创建失败。'
return info
def zfs_snapshot_list(self, filesystem):
"""
查看zfs快照:zfs list -t snapshot -r tank/kvm_1
"""
exe_cmd = r'zfs list -t snapshot -r {0}'.format(filesystem)
result = self.remote_linux(exe_cmd)
snapshot_list = [x for x in result['data'].split(' ') if x]
del snapshot_list[0:5]
end_list = self.list_of_groups(snapshot_list, 5)
zfs_snapshot_list_dict = []
for item in end_list:
data = {}
item = item[0].split('@')
data['name'] = item[1]
zfs_snapshot_list_dict.append(data)
return zfs_snapshot_list_dict
def zfs_snapshot_del(self, snapshot_name):
"""
删除快照:zfs destroy mypool/data@2020-07-28
"""
try:
exe_cmd = r'zfs destroy {0}'.format(snapshot_name)
result = self.remote_linux(exe_cmd)
if result['data'] == '':
info = '删除快照成功。'
else:
info = '删除快照失败。'
except:
info = '快照已挂载,删除失败。'
return info
def zfs_clone_snapshot(self, snapshot_name, filesystem_name):
"""
克隆快照:zfs clone tank/kvm_1@2020-08-20 tank/kvm_1@2020-08-20
kvm_name
kvm_snapshot_name
kvm_snapshot_clone_name
"""
try:
exe_cmd = r'zfs clone {0} {1}'.format(snapshot_name, filesystem_name)
result = self.remote_linux(exe_cmd)
if result['data'] == '':
info = '克隆成功。'
else:
info = '克隆失败。'
except:
info = '克隆失败。'
return info
def create_kvm_xml(self, kvm_machine, snapshotname, copyname, copycpu, copymemory):
"""
读取文件,修改文件,追加到新文件
kvm_name = 'Test-1 老虚拟机
kvm_name_new = 'kvm_1 新虚拟机
kvm_disk_path = '/tank/kvm_1@kvm_1/Test-1.qcow2' 新虚拟机磁盘
"""
try:
exe_cmd = r'cat /etc/libvirt/qemu/{0}.xml'.format(kvm_machine)
snapshot_clone_name = snapshotname.replace('@', '-')
kvm_disk_path = '/' + snapshot_clone_name + '/' + kvm_machine + '.qcow2'
result = self.remote_linux(exe_cmd)
# 解析xml文件找出要修改的name、uuid、disk_path、mac、cpu、memory
config = etree.XML(result['data'])
kvm_name = config.xpath("//name")[0]
kvm_diskpath = config.xpath("//disk/source")[0]
kvm_uuid = config.xpath("//uuid")[0]
kvm_interface = config.xpath("//interface")[0]
kvm_mac = config.xpath("//mac")[0]
if copycpu != '' and copymemory != '':
copymemory = int(copymemory) * 1024
kvm_cpu = config.xpath("//vcpu")[0]
kvm_cpu.text = copycpu
kvm_memory = config.xpath("//memory")[0]
kvm_currentmemory = config.xpath("//currentMemory")[0]
kvm_memory.text = str(copymemory)
kvm_currentmemory.text = str(copymemory)
elif copycpu != '' and copymemory == '':
kvm_cpu = config.xpath("//vcpu")[0]
kvm_cpu.text = copycpu
elif copycpu == '' and copymemory != '':
copymemory = int(copymemory) * 1024
kvm_memory = config.xpath("//memory")[0]
kvm_currentmemory = config.xpath("//currentMemory")[0]
kvm_memory.text = str(copymemory)
kvm_currentmemory.text = str(copymemory)
# 修改名字、修改磁盘路径、删除uuid、删除mac
kvm_name.text = copyname
kvm_diskpath.attrib['file'] = kvm_disk_path
config.remove(kvm_uuid)
kvm_interface.remove(kvm_mac)
xml_content = etree.tounicode(config)
xml_path = '/etc/libvirt/qemu/{0}.xml'.format(copyname)
exe_cmd = r'cat > {0} << \EOH'.format(xml_path) + '\n' + xml_content + '\nEOH'
self.remote_linux(exe_cmd)
info = '生成成功。'
except:
info = '生成失败。'
return info
def define_kvm(self, copy_name):
"""
通过xml文件定义虚拟机
virsh define /etc/libvirt/qemu/kvm_1.xml
"""
xml_path = '/etc/libvirt/qemu/{0}.xml'.format(copy_name)
exe_cmd = r'virsh define {0}'.format(xml_path)
result = self.remote_linux(exe_cmd) # 定义域 CentOS-7@test4(从 /etc/libvirt/qemu/CentOS-7@test4.xml)
if result['data'].strip() == 'Domain {0} defined from {1}'.format(copy_name, xml_path) or \
result['data'].strip() == '定义域 {0}(从 {1})'.format(copy_name, xml_path):
result = '定义成功。'
else:
result = '定义失败。'
return result
def guestmount(self, kvm_machine, filesystem):
"""
guestmount -a /data/vmdata/CentOS-7-2020-09-14/CentOS-7.qcow2 -i /etc/libvirt/kvm_mount
/data/vmdata/CentOS-7-2020-09-14/CentOS-7.qcow2 磁盘路径
/etc/libvirt/kvm_mount 要挂载的目录
"""
try:
# filesystem: data/vmdata/CentOS-7-2020-09-14
kvm_disk_path = '/' + filesystem + '/' + kvm_machine + '.qcow2'
kvm_mount = '/etc/libvirt/kvm_mount'
exe_cmd = r'guestmount -a {0} -i {1} && sleep 1'.format(kvm_disk_path, kvm_mount)
self.remote_linux(exe_cmd)
result = '挂载成功。'
except Exception as e:
print(e)
result = '挂载失败。'
return result
def alert_ip_hostname(self, copy_ip, copy_hostname):
"""
sed -i "/IPADDR/s/=.*/=192.168.1.180/" /etc/libvirt/kvm_mount/etc/sysconfig/network-scripts/ifcfg-eth0 修改ip
sed -i '/HWADDR/d' /etc/libvirt/kvm_mount/etc/sysconfig/network-scripts/ifcfg-eth0 删除MAC地址
echo CentOS-7@test5 > /etc/libvirt/kvm_mount/etc/hostname 修改主机名
"""
try:
exe_cmd_ip = 'sed -i "/IPADDR/s/=.*/={0}/" /etc/libvirt/kvm_mount/etc/sysconfig/network-scripts/ifcfg-eth0'.format(copy_ip)
exe_cmd_mac = 'sed -i "/HWADDR/d" /etc/libvirt/kvm_mount/etc/sysconfig/network-scripts/ifcfg-eth0'
exe_cmd_hostname = 'echo {0} > /etc/libvirt/kvm_mount/etc/hostname'.format(copy_hostname)
exe_cmd = r'{0} && {1} && {2}'.format(exe_cmd_ip, exe_cmd_mac, exe_cmd_hostname)
result = self.remote_linux(exe_cmd)
if result['data'] == '':
result = '修改成功。'
else:
result = '修改失败。'
except Exception as e:
print(e)
result = '修改失败。'
return result
def umount(self):
"""
取消挂载:umount /etc/libvirt/kvm_mount
"""
try:
exe_cmd = r'umount /etc/libvirt/kvm_mount'
result = self.remote_linux(exe_cmd)
if result['data'] == '':
result = '取消挂载成功。'
else:
result = '取消挂载失败'
except Exception as e:
print(e)
result = '取消挂载失败。'
return result
def kvm_disk_space(self):
"""
获取kvm文件系统磁盘使用情况:zfs list
"""
exe_cmd = r'zfs list'
result = self.remote_linux(exe_cmd)
kvm_space_list = [x for x in result['data'].split(' ') if x]
del kvm_space_list[0:5]
end_list = self.list_of_groups(kvm_space_list, 5)
data = {}
for item in end_list:
if 'data' == item[0]:
data['used_total'] = float(item[1].replace('G', ''))
data['size_total'] = float(item[2].replace('G', ''))
data['used_percent'] = round(float(item[1].replace('G', ''))/float(item[2].replace('G', '')), 2)*100
return data
def memory_disk_cpu_data(self):
"""
宿主机查看内存使用率:cat /proc/meminfo
查看cpu使用率
查看磁盘使用率
查看操作系统
查看主机名
"""
data = ''
try:
# 内存
exe_cmd = r'cat /proc/meminfo'
result = self.remote_linux(exe_cmd)
memory_info = [x for x in result['data'].split(' ') if x]
end_list = self.list_of_groups(memory_info, 3)[0:5]
memtotal = end_list[0][1] # 总内存
memfree = end_list[1][1] # 空闲内存
buffers = end_list[3][1] # 给文件缓存大小
cached = end_list[4][1] # 高速缓冲存储器使用的大小
free_mem = int(memfree) + int(buffers) + int(cached)
used_mem = int(memtotal) - free_mem
memory_usage = round(100 * used_mem / float(memtotal), 2)
# 磁盘
exe_cmd = r'df'
result = self.remote_linux(exe_cmd)
disk_info = [x for x in result['data'].split(' ') if x]
del disk_info[0:6]
end_list = self.list_of_groups(disk_info, 6)
disk_info_list = []
for item in end_list:
data = {}
data['name'] = item[0]
data['total'] = item[1]
data['used'] = item[2]
data['mount'] = item[5]
disk_info_list.append(data)
total = 0
used = 0
for i in disk_info_list:
if i['mount'] == '/' or i['mount'] == '/data' or i['mount'] == '/boot':
total += int(i['total'])
used += int(i['used'])
disk_usage = round(used / total * 100, 2)
# cpu使用率
exe_cmd = r"top -n1 | awk '/Cpu/{print $2}'"
result = self.remote_linux(exe_cmd)
cpu_usage = float(result['data'])
# cpu个数
exe_cmd = r'cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l'
result = self.remote_linux(exe_cmd)
cpu_count = result['data']
# 操作系统
exe_cmd = r"cat /etc/centos-release"
result = self.remote_linux(exe_cmd)
os = result['data']
# 主机名
exe_cmd = r"cat /etc/hostname"
result = self.remote_linux(exe_cmd)
hostname = result['data']
data = {
'mem_total': round(int(memtotal) / 1024 / 1024, 2),
'mem_used': round(used_mem / 1024 / 1024, 2),
'memory_usage': memory_usage,
'disk_total': round(total / 1024 / 1024, 2),
'disk_used': round(used / 1024 / 1024, 2),
'disk_usage': disk_usage,
'cpu_usage': cpu_usage,
'cpu_count': cpu_count,
'os': os,
'hostname': hostname
}
except Exception as e:
print(e)
return data
def kvm_cpu_mem_usage(self, kvm_id):
kvm_mem_usage = ''
kvm_cpu_usage = ''
try:
# 获取内存使用信息
exe_cmd = r"./test5.py {0}".format(kvm_id)
result = self.remote_linux(exe_cmd)
kvm_mem_usage = result['data']
# 获取cpu使用信息
exe_cmd = r"./test4.py {0}".format(kvm_id)
result = self.remote_linux(exe_cmd)
kvm_cpu_usage = result['data']
except Exception as e:
print(e)
kvm_mem_usage = json.loads(kvm_mem_usage)
kvm_cpu_usage = json.loads(kvm_cpu_usage)
data = {
"kvm_mem_usage": kvm_mem_usage,
"kvm_cpu_usage": kvm_cpu_usage,
}
return data
def kvm_disk_usage(self, kvm_name):
kvm_disk_usage = ''
try:
# 获取磁盘使用信息
exe_cmd = r'virt-df -d {0}'.format(kvm_name)
result = self.remote_linux(exe_cmd)
kvm_disk_list = [x for x in result['data'].split(' ') if x]
del kvm_disk_list[0:5]
# ['CentOS-7:/dev/sda1', '10474496', '1004380', '9470116', '10%']
kvm_disk_usage = {
'kvm_name': kvm_disk_list[0].split(':')[0],
'disk_filesystem': kvm_disk_list[0],
'disk_total': round(int(kvm_disk_list[1]) / 1024 / 1024, 2),
'disk_used': round(int(kvm_disk_list[2]) / 1024 / 1024, 2),
'disk_usage': kvm_disk_list[4]
}
except Exception as e:
print(e)
data = {"kvm_disk_usage": kvm_disk_usage}
return data
def kvm_template(self):
# kvm虚拟机模板文件: cd /home/images
try:
exe_cmd = r'ls /home/images'
result = self.remote_linux(exe_cmd)
result = [x.replace('\t', ' ').split(' ') for x in result['data'].split(' ') if x][0]
except Exception as e:
print(e)
result = '查找kvm模板文件失败。'
return result
def copy_disk(self, kvm_template_path, filesystem):
try:
exe_cmd = r'cp {0} {1}'.format(kvm_template_path, filesystem)
result = self.remote_linux(exe_cmd)
if result['data'] == '':
result = '拷贝磁盘文件成功。'
else:
result = '拷贝磁盘文件失败。'
except Exception as e:
print(e)
result = '拷贝磁盘文件失败。'
return result
def create_new_xml(self, kvm_xml, kvm_disk_path, kvmname):
try:
exe_cmd = r'cat /home/xml/{0}'.format(kvm_xml)
result = self.remote_linux(exe_cmd)
# 解析xml文件找出要修改的name、uuid、disk_path、mac、
config = etree.XML(result['data'])
kvm_name = config.xpath("//name")[0]
kvm_diskpath = config.xpath("//disk/source")[0]
kvm_uuid = config.xpath("//uuid")[0]
kvm_interface = config.xpath("//interface")[0]
kvm_mac = config.xpath("//mac")[0]
# 修改名字、修改磁盘路径、删除uuid、删除mac
kvm_name.text = kvmname
kvm_diskpath.attrib['file'] = kvm_disk_path
config.remove(kvm_uuid)
kvm_interface.remove(kvm_mac)
xml_content = etree.tounicode(config)
xml_path = '/etc/libvirt/qemu/{0}.xml'.format(kvmname)
exe_cmd = r'cat > {0} << \EOH'.format(xml_path) + '\n' + xml_content + '\nEOH'
self.remote_linux(exe_cmd)
info = '生成成功。'
except:
info = '生成失败。'
return info
linuxserver_credit = {
'KvmHost': '192.168.1.61',
'KvmUser': 'root',
'KvmPasswd': '******',
'SystemType': 'Linux',
}
# result = KVMApi(linuxserver_credit).kvm_all_list()
# result = KVMApi(linuxserver_credit).clone('Test-1', 'Test-3')
# result = KVMApi(linuxserver_credit).zfs_create_filesystem('kvm_1')
# result = KVMApi(linuxserver_credit).copy_kvm_disk('kvm_1', 'Test-1')
# result = KVMApi(linuxserver_credit).zfs_create_snapshot('kvm_1', '2020-08-20')
# result = KVMApi(linuxserver_credit).zfs_snapshot_list('tank/CentOS-7')
# result = KVMApi(linuxserver_credit).zfs_clone_snapshot('tank/CentOS-7@2020-08-25')
# result = KVMApi(linuxserver_credit).create_kvm_xml('CentOS-7@test3', 'tank/CentOS-7@2020-08-28', 'CentOS-7@2020-08-28', '2', '1024')
# result = KVMApi(linuxserver_credit).define('kvm_1')
# result = KVMApi(linuxserver_credit).start('CentOS-7@2020-08-30')
# result = KVMApi(linuxserver_credit).shutdown('Test-1')
# result = KVMApi(linuxserver_credit).zfs_list()
# result = KVMApi(linuxserver_credit).zfs_kvm_filesystem()
# result = KVMApi(linuxserver_credit).snapshot_list('Test-1')
# print(result)
# result = KVMApi(linuxserver_credit).guestmount('CentOS-7', 'tank/CentOS-7@test1')
# result = KVMApi(linuxserver_credit).alert_ip('192.168.1.180')
# result = KVMApi(linuxserver_credit).alert_hostname('CentOS-7@test5')
# result = KVMApi(linuxserver_credit).guestmount_umount()
# result = KVMApi(linuxserver_credit).alert_ip_hostname_sh('CentOS-7', 'tank/CentOS-7-test2', '192.168.1.197', 'CentOS-7-test2')
# print(result)
# result = KVMApi(linuxserver_credit).kvm_disk_space()
# result = KVMApi(linuxserver_credit).kvm_info_data('Test-1')
# result = KVMApi(linuxserver_credit).kvm_include_copy_list('CentOS-7')
# result = KVMApi(linuxserver_credit).zfs_kvm_filesystem()
# result = KVMApi(linuxserver_credit).kvm_template()
# print(result)
附:
kvm虚拟机cpu使用率(正在运行的kvm虚拟机)
#! /bin/pythonimport libvirt
import time
conn = libvirt.open("qemu:///system")
import sys
import json
info = {}
id = int(sys.argv[1])
dom = conn.lookupByID(id)
name = dom.name()
t1 = time.time()
c1 = int (dom.info()[4])
time.sleep(3)
t2 = time.time();
c2 = int (dom.info()[4])
c_nums = int (dom.info()[3])
cpu_usage = round((c2-c1)*100/((t2-t1)*c_nums*1e9), 2)
info['cpu_usage'] = cpu_usage
print(json.dumps(info))
test4.py
kvm虚拟机内存使用率(正在运行的kvm虚拟机)
#!/usr/bin/pythonimport libvirt
conn = libvirt.open("qemu:///system")
import json
import sys
id = int(sys.argv[1])
info = {}
dom = conn.lookupByID(id)
infos = dom.info()
name = dom.name()
mem = infos[1]
dom.setMemoryStatsPeriod(10)
meminfo = dom.memoryStats()
free_mem = float(meminfo['unused'])
total_mem = float(meminfo['available'])
used_mem = total_mem-free_mem
mem_usage = round(((total_mem-free_mem) / total_mem)*100, 2)
info['mem_usage'] = mem_usage
info['mem_used'] = round(used_mem/1024/1024,2)
info['mem_total'] = round(total_mem/1024/1024,2)
info['mem_free'] = round(free_mem/1024/1024,2)
print(json.dumps(info))
test4.py