Docker技术实践

该代码实现了一个Docker虚拟机管理系统,包括创建、查看、启动、停止和删除虚拟机的功能。系统通过SSH连接宿主机,使用SFTP传输文件,并通过Docker API管理分布在不同节点上的容器。同时,它能根据容器的网络信息动态生成MPI配置文件。
摘要由CSDN通过智能技术生成
import docker
import subprocess
import tkinter
import tkinter.messagebox
import random
import paramiko
import tkinter.font as tkFont
from PIL import Image, ImageTk
from tkinter import ttk
import webbrowser
import os

# 将mpi配置写入本地文件,再由本地通过sftp上传到宿主机挂在目录
unload_path = './mpi_config/servers'
# 容器挂载的宿主机目录
host_share = '/mpi_config'
# 容器中的mpi配置,与host_share共享文件
docker_file = '/mpich/mpi_config'
volumes = {}
temp_volumes = {}
temp_volumes['bind'] = docker_file
temp_volumes['mode'] = 'rw'
# 挂载文件夹
volumes[host_share] = temp_volumes

# 连接宿主机
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname="192.168.43.56", port=22, username="root", password="a000401.")

# 文件传输stfp
sftp_client = paramiko.Transport(("192.168.43.56", 22))
sftp_client.connect(username="root", password="a000401.")
sftp = paramiko.SFTPClient.from_transport(sftp_client)

ip1 = '192.168.43.56'
ip2 = '192.168.43.66'
ip3 = '192.168.43.60'

# docker images配置好的mpi映像
docker_images = '802140ebb05d'
connect1 = ip1 + ':2375'
connect2 = ip2 + ':2375'
connect3 = ip3 + ':2375'

client1 = docker.DockerClient(base_url=connect1, use_ssh_client=True)
client2 = docker.DockerClient(base_url=connect2, use_ssh_client=True)
client3 = docker.DockerClient(base_url=connect3, use_ssh_client=True)

# 设置网络模式为桥接
network1 = client1.networks.get('my_network')
network2 = client2.networks.get('my_network')
network3 = client3.networks.get('my_network')
CPU_1 = 4
CPU_2 = 4
CPU_3 = 4

# mpi配置文件写到本地的目录中
def write_config():
    # 有问题,系统自动运行windows的文件系统
    file_address = '.' + host_share + '/servers'
    containers1 = client1.containers.list()
    containers2 = client2.containers.list()
    containers3 = client3.containers.list()

    containers_ip1 = network1.attrs['Containers']
    containers_ip2 = network2.attrs['Containers']
    containers_ip3 = network3.attrs['Containers']
    ips = []
    # 读容器ip添加到ips中
    with open(file_address, mode='w', encoding='utf-8') as file_obj:
        for container in containers1:
            for container_ip in containers_ip1:
                key = container_ip
                value = containers_ip1[key]
                if value['Name'] == container.name:
                    ip = value['IPv4Address'][:-3]
                    if value['Name'] == 'master_1':
                        file_obj.write(ip + ':' + str(1) + '\n')
                    else:
                        ips.append(ip)

        for container in containers2:
            for container_ip in containers_ip2:
                key = container_ip
                value = containers_ip2[key]
                if value['Name'] == container.name:
                    ip = value['IPv4Address'][:-3]
                    if value['Name'] == 'master_2':
                        file_obj.write(ip + ':' + str(1) + '\n')
                    else:
                        ips.append(ip)

        for container in containers3:
            for container_ip in containers_ip3:
                key = container_ip
                value = containers_ip3[key]
                if value['Name'] == container.name:
                    ip = value['IPv4Address'][:-3]
                    if value['Name'] == 'master_3':
                        file_obj.write(ip + ':' + str(1) + '\n')
                    else:
                        ips.append(ip)

        # 将ip写入servers文件
        for i in range(len(ips)):
            file_obj.write(ips[i] + ':' + str(1) + '\n')

# 创建虚拟机
def create():
    create_one = tkinter.Toplevel()
    frame_main = tkinter.Frame(create_one, bg="WhiteSmoke")
    frame_main.propagate(False)
    frame_main.pack(expand=tkinter.YES, fill=tkinter.BOTH)
    create_one.title('创建虚拟机')
    create_one.geometry('800x600')  # 窗体大小
    global memory, CPU_number, docker_name, docker_place

    number3 = tkinter.StringVar()
    memory = ttk.Combobox(create_one, width=20, textvariable=number3)
    memory['values'] = ('1', '2', '3', '4', '5', '6', '7', '8')
    memory.place(x=500, y=100, width=250, height=20)
    memory.current(0)
    memory_label = tkinter.Label(create_one, text='请输入最大内存(单位GB)(范围1-8)', bg='white')
    memory_label.place(x=20, y=100, width=400, height=20)

    number1 = tkinter.StringVar()
    CPU_number = ttk.Combobox(create_one, width=12, textvariable=number1)
    CPU_number['values'] = ('0', '1', '2', '3', '4')
    CPU_number.place(x=500, y=150, width=250, height=20)
    CPU_number.current(0)
    CPU_number_label = tkinter.Label(create_one, text='请输入CPU核数目(范围0-4)', bg='white')
    CPU_number_label.place(x=20, y=150, width=400, height=20)

    docker_name = tkinter.Entry(create_one)
    docker_name.place(x=500, y=200, width=250, height=20)
    docker_name_label = tkinter.Label(create_one, text='请输入虚拟机名字', width=80, bg='white')
    docker_name_label.place(x=20, y=200, width=400, height=20)

    number2 = tkinter.StringVar()
    docker_place = ttk.Combobox(create_one, width=12, textvariable=number2)
    docker_place['values'] = ('1', '2', '3')
    docker_place.place(x=500, y=250, width=250, height=20)
    docker_place.current(0)
    docker_place_label = tkinter.Label(create_one, text='请选择在那一台物理机上创建docker:', bg='white')
    docker_place_label.place(x=20, y=250, width=400, height=20)
    # 选择一切容器参数后,调用docker_create()函数
    button2 = tkinter.Button(create_one, text='创建虚拟机', command=docker_create, font=('Arial', 12), width=50, height=2)
    button2.place(x=170, y=400)

# 查看虚拟机状态
def check():
    write_config()
    # 上传至服务器
    sftp.put(unload_path, host_share + '/servers')
    webbrowser.open("http://{:}:4040".format(ip1), new=0)


def start():
    create_three = tkinter.Toplevel()
    frame_main = tkinter.Frame(create_three, bg="WhiteSmoke")
    frame_main.propagate(False)
    frame_main.pack(expand=tkinter.YES, fill=tkinter.BOTH)
    create_three.title('开启虚拟机')
    create_three.geometry('800x600')  # 窗体大小
    global name2, docker_place2

    number2 = tkinter.StringVar()
    name2 = ttk.Combobox(create_three, width=12, textvariable=number2)

    containers1 = client1.containers.list(all=True)
    containers2 = client2.containers.list(all=True)
    containers3 = client3.containers.list(all=True)

    containers1_run = client1.containers.list()
    containers2_run = client2.containers.list()
    containers3_run = client3.containers.list()

    list_temp = []
    for container in containers1:
        if container not in containers1_run:
            list_temp.append(container.name)
    for container in containers2:
        if container not in containers2_run:
            list_temp.append(container.name)
    for container in containers3:
        if container not in containers3_run:
            list_temp.append(container.name)


    if len(list_temp) == 0:
        list_temp.append('所有的docker容器都已经开启')
    name2['values'] = tuple(list_temp)
    name2.place(width=250, x=500, y=70, height=20)
    name2.current(0)
    name2_label = tkinter.Label(create_three, text='请输入要开启的虚拟机名字', bg='white')
    name2_label.place(x=20, y=70, width=400, height=20)

    number1 = tkinter.StringVar()
    docker_place2 = ttk.Combobox(create_three, width=12, textvariable=number1)
    docker_place2['values'] = ('1', '2', '3')
    docker_place2.place(width=250, x=500, y=170, height=20)
    docker_place2.current(0)
    docker_place2_label1 = tkinter.Label(create_three, text='请选择在那一台物理机上开启docker:', bg='white')
    docker_place2_label1.place(x=20, y=170, width=400, height=20)

    button1 = tkinter.Button(create_three, text='开启虚拟机', command=start_container, font=('Arial', 12), width=50,
                             height=2)
    button1.place(x=170, y=300)


def remove():
    create_four = tkinter.Toplevel()
    frame_main = tkinter.Frame(create_four, bg="WhiteSmoke")
    frame_main.propagate(False)
    frame_main.pack(expand=tkinter.YES, fill=tkinter.BOTH)
    create_four.title('删除虚拟机')
    create_four.geometry('800x600')  # 窗体大小
    global name1, docker_place1

    number1 = tkinter.StringVar()
    name1 = ttk.Combobox(create_four, width=12, textvariable=number1)
    containers1 = client1.containers.list(all=True)
    containers2 = client2.containers.list(all=True)
    containers3 = client3.containers.list(all=True)

    list_temp = []
    for container in containers1:
        list_temp.append(container.name)
    for container in containers2:
        list_temp.append(container.name)
    for container in containers3:
        list_temp.append(container.name)

    name1['values'] = tuple(list_temp)
    name1.place(width=250, x=500, y=70, height=20)
    name1.current(0)
    name1_label = tkinter.Label(create_four, text='请输入要删除的虚拟机名字', bg='white')
    name1_label.place(x=20, y=70, width=400, height=20)

    number2 = tkinter.StringVar()
    docker_place1 = ttk.Combobox(create_four, width=12, textvariable=number2)
    docker_place1['values'] = ('1', '2' ,'3')
    docker_place1.place(width=250, x=500, y=170, height=20)
    docker_place1.current(0)
    docker_place_label1 = tkinter.Label(create_four, text='请选择在那一台物理机上删除docker:', bg='white')
    docker_place_label1.place(x=20, y=170, width=400, height=20)

    button1 = tkinter.Button(create_four, text='删除虚拟机', bg='white', command=remove_container, font=('Arial', 12), width=50,
                             height=2)
    button1.place(x=170, y=300)


def stop():
    create_five = tkinter.Toplevel()
    frame_main = tkinter.Frame(create_five, bg="WhiteSmoke")
    frame_main.propagate(False)
    frame_main.pack(expand=tkinter.YES, fill=tkinter.BOTH)
    create_five.title('停止虚拟机')
    create_five.geometry('800x600')  # 窗体大小
    global name3, docker_place3

    number1 = tkinter.StringVar()
    name3 = ttk.Combobox(create_five, width=12, textvariable=number1)
    containers1 = client1.containers.list()
    containers2 = client2.containers.list()
    containers3 = client3.containers.list()

    list_temp = []
    for container in containers1:
        list_temp.append(container.name)
    for container in containers2:
        list_temp.append(container.name)
    for container in containers3:
        list_temp.append(container.name)

    name3['values'] = tuple(list_temp)
    name3.place(width=250, x=500, y=70, height=20)
    name3.current(0)
    name3_label = tkinter.Label(create_five, text='请输入要停止的虚拟机名字', bg='white')
    name3_label.place(x=20, y=70, width=400, height=20)

    number2 = tkinter.StringVar()
    docker_place3 = ttk.Combobox(create_five, width=12, textvariable=number2)
    docker_place3['values'] = ('1', '2' ,'3')
    docker_place3.place(width=250, x=500, y=170, height=20)
    docker_place3.current(0)
    docker_place_label3 = tkinter.Label(create_five, text='请选择在哪一台物理机上停止docker:', bg='white')
    docker_place_label3.place(x=20, y=170, width=400, height=20)

    button3 = tkinter.Button(create_five, text='停止虚拟机', command=stop_container, font=('Arial', 12), width=50, height=2)
    button3.place(x=170, y=300)


def remove_container():
    position = docker_place1.get()
    name = name1.get()
    if position == "1":
        client = client1
    elif position == '2':
        client = client2
    elif position == '3':
        client = client3
    if position != '1' and position != '2' and position != '3':
        tkinter.messagebox.showwarning("提示", '虚拟机参数输入错误')
        return

    name_list = []
    containers = client.containers.list(all=True)
    for container in containers:
        name_list.append(container.name)
    if name not in name_list:
        tkinter.messagebox.showwarning("提示", '要删除的虚拟机不存在')
        return

    container = client.containers.get(name)
    container.stop()
    container.remove()
    tkinter.messagebox.showwarning("提示", '成功删除虚拟机')


def start_container():
    position = docker_place2.get()
    name = name2.get()
    if position == "1":
        client = client1
    elif position == '2':
        client = client2
    elif position == '3':
        client = client3
    if position != '1' and position != '2' and position != '3':
        tkinter.messagebox.showwarning("提示", '虚拟机参数输入错误')
        return

    name_list = []
    containers = client.containers.list(all=True)
    for container in containers:
        name_list.append(container.name)
    if name not in name_list:
        tkinter.messagebox.showwarning("提示", '要开启的虚拟机不存在')
        return

    container = client.containers.get(name)
    container.start()
    tkinter.messagebox.showwarning("提示", '成功开启虚拟机')


def stop_container():
    position = docker_place3.get()
    name = name3.get()
    if position ==  '1':
        client = client1
    elif position == '2':
        client = client2
    elif position == '3':
        client = client3
    if position != '1' and position != '2' and position != '3':
        tkinter.messagebox.showwarning("提示", '虚拟机参数输入错误')
        return

    name_list = []
    containers = client.containers.list()
    for container in containers:
        name_list.append(container.name)
    if name not in name_list:
        tkinter.messagebox.showwarning("提示", '要停止的虚拟机不存在')
        return

    container = client.containers.get(name)
    container.stop()
    tkinter.messagebox.showwarning("提示", '成功停止虚拟机')

def docker_create():
    position = docker_place.get()
    if position == '1':
        client = client1
        CPU_number_limit = CPU_1
    elif position == '2':
        client = client2
        CPU_number_limit = CPU_2
    elif position == '3':
        client = client3
        CPU_number_limit = CPU_3

    if position != '1' and position != '2' and position != '3':
        tkinter.messagebox.showwarning("提示", '虚拟机参数输入错误')
        return

    name = docker_name.get()
    memory_number = int(eval(memory.get()))
    if memory_number > 8:
        tkinter.messagebox.showwarning("提示", '虚拟机超过主机最大内存容量')
        return

    mem_limit = memory.get() + 'g'
    number = int(eval(CPU_number.get()))
    if number > CPU_number_limit:
        tkinter.messagebox.showwarning("提示", '虚拟机超过最大CPU核数目')
        return

    CPU_list = []
    CPU_str = ''
    while len(CPU_list) < number:
        i = random.randint(0, 3)
        if i not in CPU_list:
            CPU_list.append(i)
            CPU_str += str(i)
            CPU_str += ','
    CPU_str = CPU_str[:-1]
    print(CPU_str)
    print(CPU_list)
    # 参数:image-镜像id号 name-容器名 mem_limit-分配最大内存 tty
    # privileged-授予此容器扩展权限 detach-在后台运行容器并返回一个容器对象
    # stdin_open-即使没有连接,也要保持STDIN打开。
    #  network-网络模式
    client.containers.run(image=docker_images, name=name, mem_limit=mem_limit, tty=True, privileged=True,
                                       detach=True, stdin_open=True, network='my_network', cpuset_cpus=CPU_str,
                                       volumes=volumes)
    tkinter.messagebox.showwarning("提示", '虚拟机创建成功')
    client1.close()
    client2.close()
    client3.close()


root = tkinter.Tk()
root.title('docker虚拟机管理系统')  # 标题
root.geometry('800x700')  # 窗体大小

frame_top = tkinter.Frame(root, bg="SkyBlue")
frame_top.pack(fill=tkinter.X)

lbl_image = tkinter.Label(frame_top, width=150, height=80)
lbl_image.pack(side=tkinter.LEFT)
imgtop = Image.open(r'docker.jpg')
img1 = imgtop.resize((150, 80), Image.ANTIALIAS)
tk_img = ImageTk.PhotoImage(img1)
lbl_image.image = tk_img
lbl_image.config(image=tk_img)

tkinter.Label(frame_top, text="云计算课程设计", bg='SkyBlue',
              font=tkFont.Font(family="微软雅黑", size=12, weight=tkFont.NORMAL)).pack(side=tkinter.LEFT, padx=20)
tkinter.Label(frame_top, text="制作成员:刘涛 罗继睿 刘皓轩", bg="SkyBlue", height=2,
              font=tkFont.Font(family="微软雅黑", size=12, weight=tkFont.NORMAL)).pack(side=tkinter.RIGHT, padx=100)

frame_main = tkinter.Frame(root, bg="LightBlue")
frame_main.propagate(False)
frame_main.pack(expand=tkinter.YES, fill=tkinter.BOTH)

frame_maintop = tkinter.Frame(frame_main, bg="SkyBlue", width=800,height=10)
frame_maintop.pack(fill=tkinter.X, padx=20, pady=10)
imagetop = tkinter.Label(frame_maintop, width=800, height=40)
tkinter.Label(frame_maintop, text="虚拟机管理器", bg="SkyBlue", fg='black', height=2,
              font=tkFont.Font(family="微软雅黑", size=18, weight=tkFont.BOLD)).pack(side=tkinter.LEFT, padx=300)

frame_mainleft = tkinter.Frame(frame_main, width=800, height=40,bg="SkyBlue")
frame_mainleft.pack(side=tkinter.RIGHT, fill=tkinter.Y, padx=30)
tkinter.Label(frame_mainleft, text="  主要功能", bg="SkyBlue", fg='black', height=2,
              font=tkFont.Font(family="微软雅黑", size=18, weight=tkFont.BOLD)).pack(anchor=tkinter.W, padx=300, pady=5)
frame_mainleft.propagate(False)

button1 = tkinter.Button(frame_mainleft, text='创建虚拟机', command=create, font=tkFont.Font(family="微软雅黑", size=11),
                         width=50, height=2, bg='white').pack(padx=10, pady=5)
button2 = tkinter.Button(frame_mainleft, text='查看虚拟机状态', command=check, font=tkFont.Font(family="微软雅黑", size=11),
                         width=50, height=2, bg='white').pack(padx=10, pady=5)
button3 = tkinter.Button(frame_mainleft, text='开启虚拟机', command=start, font=tkFont.Font(family="微软雅黑", size=11),
                         width=50, height=2, bg='white').pack(padx=10, pady=5)
button5 = tkinter.Button(frame_mainleft, text='停止虚拟机', command=stop, font=tkFont.Font(family="微软雅黑", size=11), width=50,
                         height=2, bg='white').pack(padx=10, pady=5)
button4 = tkinter.Button(frame_mainleft, text='删除虚拟机', command=remove, font=tkFont.Font(family="微软雅黑", size=11),
                         width=50, height=2, bg='white').pack(padx=10, pady=5)

root.mainloop()
ssh.close()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liamhh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值