可能用到的参考链接:
1. prettytable模块讲解:https://finthon.com/python-prettytable/
2. re正则表达式模块:https://www.runoob.com/python/python-reg-expressions.html
3. csv模块: https://docs.python.org/zh-cn/3/library/csv.html
4. Windows如何永久修改镜像源:https://www.cnblogs.com/eosclover/p/11254378.html
需求:
1. 云主机的属性包括:主机名,IP地址, CPU, 内存, 磁盘类型,磁盘大小,运行状态
2. 云主机的方法包括: 开机,关机,重启
3. 请支持云主机的(增)删改(查)操作,查看云主机信息时,请支持表格查看
4. 支持存储云主机到csv文件中,也支持加载csv文件的云主机信息
分析:
以上需求可以抽象出云主机类(属性+方法), 云主机管理类(属性+方法)
data/machines.csv内需要有表头
hostname,IP
import re
import time
import prettytable as pt
import pandas as pd
FILENAME = 'data/machines.csv'
class Machine:
"""
云主机类
1. 云主机的属性包括:主机名,IP地址, CPU, 内存, 磁盘类型,磁盘大小,运行状态
2. 云主机的方法包括: 开机,关机,重启
"""
def __init__(self, hostname: str, IP: str, CPU: int = 2, memeory: int = 4,
diskCategory: str = '普通云盘', diskSize: int = 40, status: str = 'Running', **kwargs):
# 将对象self和属性封装在一起
self.hostname = hostname
self.IP = IP
self.CPU = CPU
self.memory = memeory
self.diskCategory = diskCategory
self.diskSize = diskSize
self.status = status
def isRunning(self):
return self.status == 'Running'
def isStopped(self):
return self.status == 'Stopped'
def start(self):
if self.isRunning():
return '已开机'
else:
print(f'云主机{self.IP}正在开机')
time.sleep(0.3)
return '开机成功'
def stop(self):
if self.isStopped():
return '已关机'
else:
print(f'云主机{self.IP}正在关机')
time.sleep(0.3)
return '关机成功'
def reboot(self):
self.stop()
self.start()
return '重启成功'
def to_dict(self):
"""
将machine对象转成自定义的字典格式
:return:
"""
return {
'hostname': self.hostname,
'IP': self.IP,
'CPU': self.CPU,
'memory': self.memory,
'diskCategory': self.diskCategory,
'diskSize': self.diskSize,
'status': self.status
}
def __str__(self):
"""将对象转成字符串时,自动执行该方法"""
return f'Machine-<{self.hostname}>'
def __repr__(self):
"""将对象转成字符串时,自动执行该方法"""
return f'Machine-<{self.hostname}>'
class MachineManager:
def __init__(self, filename=None):
self.machines = []
if filename:
self.read_csv(filename=filename)
def is_ip_valid(self, ip: str) -> bool:
'判断IP是否合法'
items = re.findall(r'\d+', ip) # '172.25.17.8' --> ['172', '25', '17', '8']
# 合法的IP由4段数字组成,如果不是,则返回False
if len(items) != 4: return False
# 扩展知识:
# 1. all(list), 列表里的每一个元素全部为True的时候,返回True
# 2. any(list), 列表里的每一个元素全部为False的时候,返回False
# 3. 列表生成式:
return all([0 <= int(item) <= 255 for item in items])
def append(self, hostname: str, IP: str, CPU: int = 2, memeory: int = 4,
diskCategory: str = '普通云盘', diskSize: int = 40, status: str = 'Running', **kwargs):
"""添加云主机"""
if not self.is_ip_valid(IP):
raise Exception(f'云主机ip={IP}不合法')
m = Machine(hostname, IP, CPU, memeory, diskCategory, diskSize, status)
self.machines.append(m)
def find_machine(self, IP) -> int:
"""根据ip去寻找指定云主机的索引,如果没找到抛出异常,如果找到则返回索引"""
index = 0
for machine in self.machines:
if machine.IP == IP:
return index
index += 1
else:
raise Exception(f'云主机{IP}不存在')
def update(self, IP, key=None, value=None):
"""更新云主机"""
index = self.find_machine(IP)
m = self.machines[index]
if hasattr(m, key):
setattr(m, key, value)
else:
raise Exception(f'Machine类不存在{key}属性')
def delete(self, IP):
"""删除云主机"""
index = self.find_machine(IP)
self.machines.pop(index)
def reterive(self, IP):
"""查看指定云主机信息"""
index = self.find_machine(IP)
return self.machines[index].to_dict()
def list_all(self):
"""列出所有的云主机"""
print(self.machines)
def prettytable_list_all(self):
"""使用美化的表格去展示"""
# 实例化表格对象并指定表头
table = pt.PrettyTable(field_names=["主机名", "IP地址", "CPU", "内存(单位:G)", "磁盘类型", "磁盘大小(单位:G)", "运行状态"])
# 遍历所有云主机,将云主机信息添加到table对象中。
for machine in self.machines:
table.add_row([machine.hostname, machine.IP, machine.CPU,
machine.memory, machine.diskCategory, machine.diskSize, machine.status])
# 打印表格
print(table)
def to_csv(self, filename='machines.csv'):
"""
将云主机信息存储到csv文件中
:return:
"""
# machines数据结构是列表里面嵌套字典, [{'hostname':'xxx', 'IP':'xxx', xxx}, {'hostname':'xxx', 'IP':'xxx', xxx}]
machines = []
for m in self.machines:
# m.to_dict()是Machine的一个方法,用于将machine对象转成字典格式
machines.append(m.to_dict())
# 将数据转成dataframe对象
df = pd.DataFrame(machines)
df.to_csv(filename)
print(f'存储到文件{filename}成功')
def read_csv(self, filename='machines.csv'):
"""
加载文件中的云主机信息到内存中self.machines
:param filename:
:return:
"""
df = pd.read_csv(filename)
machines = df.T.to_dict().values() # {0: {'name': 'hello1', 'age': 18, 'score': 100}, 1: {'name': 'hello2', 'age': 19, 'score': 99}}
# **machine做解包的操作,将获取machine的值依次传给Machine的构造方法。
self.machines = [Machine(**machine) for machine in machines]
print('加载数据库的信息成功....')
def main():
menu = """
云主机管理系统
1). 添加云主机
2). 更新云主机
3). 查看云主机
4). 删除云主机
5). 持久化存储云主机
6). 退出
请输入你的选择:"""
manager = MachineManager(filename=FILENAME)
while True:
"""
hostname: str, IP: str, CPU: int = 2, memeory: int = 4,
diskCategory: str = '普通云盘', diskSize: int = 40, status: str = 'Running'
"""
choice = input(menu)
if choice == '1':
print('添加云主机'.center(50, '*'))
hostname = input('hostname:')
IP = input('IP:')
CPU = int(input('CPU:'))
memeory = int(input('memeory(默认单位 G):'))
diskCategory = input('diskCategory(可选:普通云盘,高效云盘):')
diskSize = int(input('diskSize(默认单位 G):'))
status = input('status(可选:Running,Stopped):')
# 异常捕获机制
try:
manager.append(hostname=hostname, IP=IP, CPU=CPU, memeory=memeory,
diskCategory=diskCategory, diskSize=diskSize, status=status)
except Exception as e:
print(f'添加云主机{IP}失败,原因:{str(e)}')
else:
print(f'添加云主机{IP}成功')
elif choice == '2':
print('更新云主机'.center(50, '*'))
IP = input('更新的云主机IP:')
try:
manager.find_machine(IP)
key = input('更新的属性名:')
value = input('更新的属性值:')
manager.update(IP, key, value)
except Exception as e:
print(f'更新云主机{IP}失败,原因:{str(e)}')
else:
print(f'更新云主机{IP}成功')
elif choice == '3':
print('查看云主机'.center(50, '*'))
manager.prettytable_list_all()
elif choice == '4':
print('删除云主机'.center(50, '*'))
IP = input('更新的云主机IP:')
try:
manager.delete(IP)
except Exception as e:
print(f'删除云主机{IP}失败,原因:{str(e)}')
else:
print(f'删除云主机{IP}成功')
elif choice == '5':
print('持久化存储云主机'.center(50, '*'))
manager.to_csv(FILENAME)
elif choice == '6':
print()
print('退出云主机管理系统'.center(50, '*'))
exit(0)
else:
print('请输入正确的选择')
if __name__ == '__main__':
main()
m1 = Machine(hostname='westos1', IP='172.25.254.1')
print(m1.start())
print(m1.stop())
print(m1.reboot())
manager = MachineManager(filename='data/machines.csv')
manager.prettytable_list_all()
manager.to_csv(filename='data/machines.csv')
for i in [1, 2, 3, 6, 7]: # i=0, 1, 2, 3, 4
manager.append(hostname=f'westos{i}', IP=f'172.25.254.{i}')
manager.list_all()
manager.prettytable_list_all()
manager.to_csv('data/machines.csv')
manager.read_csv('data/machines.csv')
manager.prettytable_list_all()