云计算–基于docker+swarm集群的奇偶交换排序
c++代码:mpi部分
sort.cpp
#include<iostream>
#include<fstream>
#include<algorithm>
#include <iomanip>
#include<random>
#include<time.h>
#include"mpi.h"
#define N 1000 //待排序的整型数量
using namespace std;
int load()
{
int temp;
ifstream fp("temp.txt");
fp >> temp;
fp.close();
return temp;
}
/*该函数用来获得某个阶段,某个进程的通信伙伴*/
int Get_Partner(int my_rank, int phase) {
// 偶通信阶段,偶数为通信双方的较小进程
if (phase % 2 == 0) {
if (my_rank % 2 == 0) {
return my_rank - 1;
}
else {
return my_rank + 1;
}
}
// 奇通信阶段,奇数为通信双方的较小进程
else {
if (my_rank % 2 == 0) {
return my_rank + 1;
}
else {
return my_rank - 1;
}
}
}
/*这个函数用来产生随机数,并分发至各个进程*/
void Get_Input(int A[], int local_n, int my_rank) {
int* a = NULL;
// 主进程动态开辟内存,产生随机数,分发至各个进程
if (my_rank == 0) {
ifstream data("data.txt");
a = new int[N];
for(int i=0;i<N;i++){
data >> a[i];
//cout<<a[i]<<endl;
}
data.close();
MPI_Scatter(a, local_n, MPI_INT, A, local_n, MPI_INT, 0, MPI_COMM_WORLD);
delete[] a;
}
// 其余进程接收随机数
else {
MPI_Scatter(a, local_n, MPI_INT, A, local_n, MPI_INT, 0, MPI_COMM_WORLD);
}
}
/*该函数用来合并两个进程的数据,并取较小的一半数据*/
void Merge_Low(int A[], int B[], int local_n) {
int* a = new int[local_n]; // 临时数组,倒腾较小的数据
int p_a = 0, p_b = 0, i = 0; //分别为A,B,a三个数组的指针
// 这里不同担心数组越界,因为三个数组的大小是相等的
while (i < local_n) {
if (A[p_a] < B[p_b]) {
a[i++] = A[p_a++];
}
else {
a[i++] = B[p_b++];
}
}
// 倒腾一下
for (i = 0; i < local_n; i++) {
A[i] = a[i];
}
delete[] a;
}
/*该函数用来合并两个进程的数据,并取较大的一半数据,与前面的Merge_Low函数类似*/
void Merge_High(int A[], int B[], int local_n) {
int p_a = local_n - 1, p_b = local_n - 1, i = local_n - 1;
int* a = new int[local_n];
// 注意取最大值需要从后往前面取
while (i >= 0) {
if (A[p_a] > B[p_b]) {
a[i--] = A[p_a--];
}
else {
a[i--] = B[p_b--];
}
}
for (i = 0; i < local_n; i++) {
A[i] = a[i];
}
delete[] a;
}
/*这个函数用来输出排序后的数组*/
void Print_Sorted_Vector(int A[], int local_n, int my_rank) {
int* a = NULL;
// 0号进程接收各个进程的A的分量,并输出至控制台
if (my_rank == 0) {
a = new int[N];
MPI_Gather(A, local_n, MPI_INT, a, local_n, MPI_INT, 0, MPI_COMM_WORLD);
ofstream fout("data.txt");
for (int i = 0; i < N; i++) {
if (fout) { // 如果创建成功
fout <<a[i]<< endl; // 使用与cout同样的方式进行写入
}
cout << setw(8)<<a[i];
if (i % local_n == local_n-1) {
cout << endl;
}
}
fout.close(); // 执行完操作后关闭文件句柄
cout << endl;
delete[] a;
}
// 其余进程将y分量发送至0号进程
else {
MPI_Gather(A, local_n, MPI_INT, a, local_n, MPI_INT, 0, MPI_COMM_WORLD);
}
}
int main() {
int local_n; // 各个进程中数组的大小
int* A, * B; // A为进程中保存的数据,B为进程通信中获得的数据
int comm_sz, my_rank;
int temp;
temp = load();
MPI_Init(NULL, NULL);
// 获得进程数和当前进程的编号
MPI_Comm_size(MPI_COMM_WORLD, &comm_sz);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
// 计算每个进程应当获得的数据量,动态开辟空间
local_n = N / comm_sz;
A = new int[local_n];
B = new int[local_n];
// 随机产生数据并分发至各个进程
Get_Input(A, local_n, my_rank);
// 先有序化本地数据
if(temp == 0){
sort(A, A + local_n);
}
else{
// 定理:如果p个进程运行奇偶排序算法,那么p个阶段后,输入列表有序
for (int i = 0; i < comm_sz; i++) {
// 获得本次交换数据的进程号
int partner = Get_Partner(my_rank, temp-1);
// 如果本次数据交换的进程号有效
if (partner != -1 && partner != comm_sz) {
// 与对方进程交换数据
MPI_Sendrecv(A, local_n, MPI_INT, partner, 0, B, local_n, MPI_INT, partner, 0, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
// 如果本进程号大于目标进程,就应该取值较大的部分
if (my_rank > partner) {
Merge_High(A, B, local_n);
}
// 否则应该取值较小的部分
else {
Merge_Low(A, B, local_n);
}
}
}
}
// 打印排序后的数组
Print_Sorted_Vector(A, local_n, my_rank);
MPI_Finalize();
return 0;
}
docker与python交互:
sort.py
import time
import random
import docker
import paramiko
import yaml
import numpy as np
import os
class Sort():
def __init__(self):
self.client = docker.APIClient(base_url='unix://var/run/docker.sock',version='auto',timeout=5) # connect the cluster
self.dataFilepath = "/home/share/data.txt"
def initialLocation(self,N=1000):
"""
:param N: 实现保存文件的初始化
"""
seed = 10
random.seed(seed)
a = random.sample(range(0,10000),N)
# 写出到本地
with open(self.dataFilepath, 'w') as fp:
for i in a:
fp.write("{:d}\n".format(i))
def getNodeinfo(self):
'''get node info '''
node1 = self.client.nodes()[0]
node2 = self.client.nodes()[1]
info1 = {}
info2 = {}
info1['Hostname'] = node1['Description']['Hostname']
info1['State'] = node1['Status']['State']
info1['Role'] = node1['Spec']['Role']
info1['IP'] = node1['Status']['Addr']
info2['Hostname'] = node2['Description']['Hostname']
info2['State'] = node2['Status']['State']
info2['Role'] = node2['Spec']['Role']
info2['IP'] = node2['Status']['Addr']
return [info1,info2]
def isActive(self):
"""
check worker is active
:return:
"""
nodes = self.client.nodes()
for node in nodes:
if node['Description']['Hostname']=='wy':
if node['Status']['State']=='ready':
return True
else:
return False
def create_service(self,image = 'dispel4py/docker.openmpi',command = None,name = None):
container_spec = docker.types.ContainerSpec(image=image,command=command)
task_tmpl = docker.types.TaskTemplate(container_spec)
service_id = self.client.create_service(task_tmpl, name=name)
return service_id
def getService(self):
services = self.client.services()
result = []
for service in services:
tmp = {}
tmp['ID'] = service['ID']
tmp['name'] = service['Spec']['Name']
tmp['Replicas'] = service['Spec']['Mode']['Replicated']['Replicas']
tmp['image'] = service['Spec']['TaskTemplate']['ContainerSpec']['Image'].split('@')[0]
result.append(tmp)
return result
def rmService(self,name):
self.client.remove_service(name)
def deployMpi(self,node_num=10):
with open('/home/docker-compose.yml') as fp:
yaml_obj = yaml.load(fp.read())
yaml_obj['services']['mpi_node']['deploy']['replicas'] = node_num
main_yaml = open('/home/docker-compose.yml', 'w')
yaml.dump(yaml_obj, main_yaml)
main_yaml.close()
os.system('docker stack deploy --compose-file /home/docker-compose.yml mpi')
#time.sleep(30)
def get_node_ls(self):
node = [] # ip of nodes who runs mpi programme
with open(file='/home/share/mpi_config_file') as fp:
for line in fp.readlines():
node.append(line.split()[0])
return node
def Run(self,currentIteration = 0):
for service in self.client.services():
if 'head' in service['Spec']['Name']:
port = service['Endpoint']['Ports'][0]['PublishedPort']
ssh = paramiko.SSHClient() # 创建一个ssh的客户端,用来连接服务器
know_host = paramiko.AutoAddPolicy() # 创建一个ssh的白名单
ssh.set_missing_host_key_policy(know_host)# 加载创建的白名单
# 获取运行结点的ip并保存到文件
while True:
try:
ssh.connect(hostname="localhost",port=port,username="root",password="tutorial")
if(currentIteration !=0):
print("异常处理完毕")
break
except:
print("异常处理:尝试连接主节点@"+str(port))
time.sleep(5)
chanelSSHOb = ssh.invoke_shell()
time.sleep(0.1)
chanelSSHOb.send('su tutorial\n')
time.sleep(0.1)
chanelSSHOb.send('cd ~\n')
time.sleep(0.1)
chanelSSHOb.send("dig tasks.mpi_node|grep ^tasks|awk '{print $5}' > mpi_config_file && sudo cp mpi_config_file ./works/\n")
time.sleep(0.1)
print(chanelSSHOb.recv(9999).decode("utf8"))
nodeIP = self.get_node_ls()
lastModifiedTime = os.stat(self.dataFilepath).st_mtime
try:
chanelSSHOb.send("ssh " + nodeIP[0] + '\n')
time.sleep(0.1)
except:
pass
chanelSSHOb.send("cd ~/works\n")
time.sleep(0.1)
chanelSSHOb.send("mpicxx -std=c++11 ./sort.cpp -o ./sort -lm\n")
time.sleep(1)
print(chanelSSHOb.recv(9999).decode("utf8"))
for i in range(currentIteration,len(nodeIP)+1):
with open("/home/share/temp.txt", 'w') as fp:
fp.write("{:d}".format(i))
chanelSSHOb.send("mpiexec --mca btl_tcp_if_include eth0 -np "+str(len(nodeIP))+ " -hostfile ./mpi_config_file ./sort\n") # execute mpi programme
for j in range(100):
modifiedTime = os.stat(self.dataFilepath).st_mtime
if modifiedTime!= lastModifiedTime:
lastModifiedTime = modifiedTime
break
if currentIteration==0 and (not self.isActive()):
print('\033[31m断开连接\033[0m')
return i
else:
if currentIteration==0:
time.sleep(5)
else:
time.sleep(1)
print("\033[32m保持连接\033[0m")
print(chanelSSHOb.recv(999999).decode("utf8"))
return i
if __name__ == "__main__":
sort = Sort()
sort.initialLocation()
sort.Run()
# nbody.rmService('mpi_mpi_head')
# nbody.rmService('mpi_mpi_node')
UI:
import time
import tkinter as tk
from tkinter import messagebox
import paramiko
from PIL import Image, ImageTk
import tkinter.font as tkFont
from tkinter import FLAT, GROOVE
import numpy as np
from tkinter import ttk
from tkinter import StringVar
from sort import Sort
class Window():
def __init__(self):
self.OE_Swap_sort = Sort()
self.font = 'song ti'
self.createMainFrame()
def createMainFrame(self):
root = tk.Tk()
root.geometry("800x600")
root.title("基于docker的奇偶交换排序") # 窗体标题
screenwidth = root.winfo_screenwidth()
screenheight = root.winfo_screenheight()
width, height = self.get_window_size(root)[:2]
size = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 3)
root.geometry(size) # 将窗体移动到屏幕中央
frame_main = tk.Frame(root)
frame_main.propagate(False)
frame_main.pack(expand=tk.YES, fill=tk.BOTH)
frame_maintop = tk.Frame(frame_main, bg="white", height=120)
frame_maintop.pack(fill=tk.X, padx=20)
imagetop = tk.Label(frame_maintop, width=240, height=160)
imgmaintop = Image.open(r'image/docker.png')
w, h = imgmaintop.size
width = 240
height = 160
img2 = imgmaintop.resize((width, height), Image.ANTIALIAS)
_2img = ImageTk.PhotoImage(img2)
imagetop.image = _2img
imagetop.config(image=_2img)
imagetop.pack(side=tk.LEFT, padx=10, pady=10)
tk.Label(frame_maintop, text="基于docker的奇偶交换排序", bg="white", fg='black', height=4,
font=tkFont.Font(family=self.font, size=18)).pack(side=tk.LEFT)
root_canvas = tk.Canvas(root, width=800, height=420)
img_root = self.get_image('./image/11.png',800, 420)
root_canvas.create_image(400, 200, image=img_root)
root_canvas.pack()
img_button = self.get_image('./image/12.png', 220, 80)
btn01 = tk.Button(root, image=img_button, compound=tk.CENTER, text="创建服务",font=(self.font,18), relief=FLAT,
command=lambda: self.create_service())
btn02 = tk.Button(root, image=img_button, compound=tk.CENTER, text="查看服务", font=(self.font, 18), relief=FLAT,
command=lambda: self.check_service())
btn03 = tk.Button(root, image=img_button, compound=tk.CENTER, text="删除服务", font=(self.font, 18), relief=FLAT,
command=lambda: self.delete_service())
btn04 = tk.Button(root, image=img_button, compound=tk.CENTER, text="查看docker集群", font=(self.font, 18),
relief=FLAT,
command=lambda: self.check_docker_swarm())
btn05 = tk.Button(root, image=img_button, compound=tk.CENTER, text="mpi集群部署", font=(self.font, 18), relief=FLAT,
command=lambda: self.mpi_deploy())
btn06 = tk.Button(root, image=img_button, compound=tk.CENTER, text="run mpi", font=(self.font, 18),
relief=FLAT,
command=lambda: self.mpi_OE_sort())
# 第四步 确定控件放置位置,并设置单击事件
btn01.place(x=100, y=200, width=220, height=80)
btn02.place(x=500, y=200, width=220, height=80)
btn03.place(x=100, y=330, width=220, height=80)
btn04.place(x=500, y=330, width=220, height=80)
btn05.place(x=100, y=460, width=220, height=80)
btn06.place(x=500, y=460, width=220, height=80)
root.mainloop()
def get_image(self, filename, width, height):
img = Image.open(filename).resize((width, height))
return ImageTk.PhotoImage(img)
def get_window_size(self, win, update=True):
""" 获得窗体的尺寸 """
if update:
win.update()
return win.winfo_width(), win.winfo_height(), win.winfo_x(), win.winfo_y()
# 第1个按钮绑定函数-创建服务
def create_service(self):
window1 = tk.Toplevel()
window1.title("创建服务")
window1.geometry("400x280") # 窗体尺寸
screenwidth1 = window1.winfo_screenwidth()
screenheight1 = window1.winfo_screenheight()
width1, height1 = self.get_window_size(window1)[:2]
size1 = '%dx%d+%d+%d' % (width1, height1, (screenwidth1 - width1) / 2, (screenheight1 - height1) / 3)
window1.geometry(size1) # 将窗体移动到屏幕中央
frame1 = tk.Frame(window1, bg="white")
frame1.pack(fill=tk.X)
tk.Label(frame1, text="image: ", bg="white", fg='black', height=3,
font=tkFont.Font(family=self.font, size=15)).pack(side=tk.LEFT, padx=20, pady=10)
image_entry = tk.Entry(frame1, width=27)
image_entry.insert(0, "dispel4py/docker.openmpi")
image_entry.pack(side=tk.LEFT)
frame2 = tk.Frame(window1, bg="white")
frame2.pack(fill=tk.X)
tk.Label(frame2, text="command: ", bg="white", fg='black', height=3,
font=tkFont.Font(family=self.font, size=15)).pack(side=tk.LEFT, padx=20, pady=10)
command_entry = tk.Entry(frame2, width=27)
command_entry.insert(0, "Default:None")
command_entry.pack(side=tk.LEFT)
frame3 = tk.Frame(window1, bg="white")
frame3.pack(fill=tk.X)
tk.Label(frame3, text="name: ", bg="white", fg='black', height=3,
font=tkFont.Font(family=self.font, size=15)).pack(side=tk.LEFT, padx=20, pady=10)
service_entry = tk.Entry(frame3, width=27)
service_entry.insert(0, "Default:None")
service_entry.pack(side=tk.LEFT)
def confirmation():
image = image_entry.get()
if command_entry.get() == "Default:None":
command = None
else:
command = command_entry.get()
if service_entry.get() == "Default:None":
service = None
else:
service = service_entry.get()
try:
ID = self.OE_Swap_sort.create_service(image, command, service)
info = "INFO:\nID:{}\nimage:{}\ncommand:{}\nname:{}".format(ID['ID'], image, command, service)
tk.messagebox.showinfo('创建成功', info, parent=window1)
except:
tk.messagebox.showerror('错误', '创建失败', parent=window1)
image_entry.delete(0, "end")
service_entry.delete(0, "end")
command_entry.delete(0, "end")
frame5 = tk.Frame(window1, bg="white")
frame5.pack(fill=tk.X)
tk.Button(frame5, text='确认', width=10, height=1, bg='white', relief=GROOVE, command=confirmation).pack(
side=tk.RIGHT, padx=10)
# 第2个按钮绑定函数-查看服务
def check_service(self):
window2 = tk.Toplevel()
window2.title("查看服务")
window2.geometry("1000x250") # 窗体尺寸
screenwidth1 = window2.winfo_screenwidth()
screenheight1 = window2.winfo_screenheight()
width1, height1 = self.get_window_size(window2)[:2]
size1 = '%dx%d+%d+%d' % (width1, height1, (screenwidth1 - width1) / 2, (screenheight1 - height1) / 3)
window2.geometry(size1) # 将窗体移动到屏幕中央
tmp = self.OE_Swap_sort.getService()
service_num = len(tmp)
tree = ttk.Treeview(window2) # #创建表格对象
tree["columns"] = ("ID", "Name", "Replicas", "Image") # #定义列
tree.column("ID", width=250, anchor='center')
tree.column("Name", width=150, anchor='center') # #设置列
tree.column("Replicas", width=80, anchor='center')
tree.column("Image", width=250, anchor='center')
tree.heading("ID", text="ID", anchor='center')
tree.heading("Name", text="Name", anchor='center') # #设置显示的表头名
tree.heading("Replicas", text="Replicas", anchor='center')
tree.heading("Image", text="Image", anchor='center')
values = []
for i in range(service_num):
temp = []
for key, value in tmp[i].items():
temp.append(value)
values.append(temp)
for i in range(service_num):
tree.insert("", i, text="service" + str(i + 1), values=values[i]) # #给第0行添加数据,索引值可重复
tree.pack()
# 第3个按钮绑定函数-删除服务
def delete_service(self):
window3 = tk.Toplevel()
window3.title("删除服务")
window3.geometry("900x300") # 窗体尺寸
screenwidth1 = window3.winfo_screenwidth()
screenheight1 = window3.winfo_screenheight()
width1, height1 = self.get_window_size(window3)[:2]
size1 = '%dx%d+%d+%d' % (width1, height1, (screenwidth1 - width1) / 2, (screenheight1 - height1) / 3)
window3.geometry(size1) # 将窗体移动到屏幕中央
frame1 = tk.Frame(window3, bg="white")
frame1.pack(fill=tk.X)
tk.Label(frame1, text="name/ID:", bg="white", fg='black', height=3, width=20,
font=tkFont.Font(family=self.font, size=10)).pack(side=tk.LEFT, padx=20)
name_entry = tk.Entry(frame1, width=27)
name_entry.pack(side=tk.LEFT)
def confirmation():
name_Id = name_entry.get()
try:
self.OE_Swap_sort.rmService(name_Id)
tk.messagebox.showinfo('提示', '成功删除name为{}的服务'.format(name_entry.get()), parent=window3)
except:
tk.messagebox.showerror('错误', '删除服务失败', parent=window3)
name_entry.delete(0, "end")
frame2 = tk.Frame(window3, bg="white")
frame2.pack(fill=tk.X)
tk.Button(frame2, text='确认', width=10, height=1, bg='white', relief=GROOVE, command=confirmation).pack(
anchor=tk.E, ipadx=30, ipady=0)
tmp = self.OE_Swap_sort.getService()
service_num = len(tmp)
tree = ttk.Treeview(window3) # #创建表格对象
tree["columns"] = ("ID", "Name", "Replicas", "Image") # #定义列
tree.column("ID", width=250, anchor='center')
tree.column("Name", width=150, anchor='center') # #设置列
tree.column("Replicas", width=80, anchor='center')
tree.column("Image", width=250, anchor='center')
tree.heading("ID", text="ID", anchor='center')
tree.heading("Name", text="Name", anchor='center') # #设置显示的表头名
tree.heading("Replicas", text="Replicas", anchor='center')
tree.heading("Image", text="Image", anchor='center')
values = []
for i in range(service_num):
temp = []
for key, value in tmp[i].items():
temp.append(value)
values.append(temp)
for i in range(service_num):
tree.insert("", i, text="service" + str(i + 1), values=values[i]) # #给第0行添加数据,索引值可重复
tree.pack()
# 第4个按钮绑定函数-查看docker集群
def check_docker_swarm(self):
window4 = tk.Toplevel()
window4.title("查看docker集群")
window4.geometry("600x200") # 窗体尺寸
screenwidth1 = window4.winfo_screenwidth()
screenheight1 = window4.winfo_screenheight()
width1, height1 = self.get_window_size(window4)[:2]
size1 = '%dx%d+%d+%d' % (width1, height1, (screenwidth1 - width1) / 2, (screenheight1 - height1) / 3)
window4.geometry(size1) # 将窗体移动到屏幕中央
tmp = self.OE_Swap_sort.getNodeinfo()
node_num = len(tmp)
tree = ttk.Treeview(window4) # #创建表格对象
tree["columns"] = ("Hostname", "State", "Role", "IP") # #定义列
tree.column("Hostname", width=80, anchor='center') # #设置列
tree.column("State", width=80, anchor='center')
tree.column("Role", width=80, anchor='center')
tree.column("IP", width=160, anchor='center')
tree.heading("Hostname", text="Hostname", anchor='center') # #设置显示的表头名
tree.heading("State", text="State", anchor='center')
tree.heading("Role", text="Role", anchor='center')
tree.heading("IP", text="IP", anchor='center')
values = []
for i in range(node_num):
temp = []
for key, value in tmp[i].items():
temp.append(value)
values.append(temp)
for i in range(node_num):
tree.insert("", i, text="host" + str(i + 1), values=values[i]) # #给第0行添加数据,索引值可重复
tree.pack()
# 第5个按钮绑定函数-mpi集群部署
def mpi_deploy(self):
window5 = tk.Toplevel()
window5.title("mpi集群部署")
window5.geometry("400x115") # 窗体尺寸
screenwidth1 = window5.winfo_screenwidth()
screenheight1 = window5.winfo_screenheight()
width1, height1 = self.get_window_size(window5)[:2]
size1 = '%dx%d+%d+%d' % (width1, height1, (screenwidth1 - width1) / 2, (screenheight1 - height1) / 3)
window5.geometry(size1) # 将窗体移动到屏幕中央
frame1 = tk.Frame(window5, bg="white")
frame1.pack(fill=tk.X)
tk.Label(frame1, text="node_num: ", bg="white", fg='black', height=3,
font=tkFont.Font(family=self.font, size=10)).pack(side=tk.LEFT, padx=20, pady=10)
num_entry = tk.Entry(frame1, width=27)
num_entry.pack(side=tk.LEFT)
def confirmation():
try:
num = int(num_entry.get())
self.OE_Swap_sort.deployMpi(num)
tk.messagebox.showinfo('提示', '成功部署{}个节点的mpi集群'.format(num), parent=window5)
except:
tk.messagebox.showerror('错误', '部署集群失败', parent=window5)
num_entry.delete(0, "end")
frame2 = tk.Frame(window5, bg="white")
frame2.pack(fill=tk.X)
tk.Button(frame2, text='确认', width=10, height=1, bg='white', relief=GROOVE, command=confirmation).pack(
side=tk.RIGHT, padx=10)
# 第6个按钮绑定函数-mpi n体模拟
def mpi_OE_sort(self):
self.OE_Swap_sort.initialLocation()
status = self.OE_Swap_sort.Run()
nodelist = self.OE_Swap_sort.get_node_ls()
if status != len(nodelist):
tk.messagebox.showerror('error', "异常处理中.....")
while status != len(nodelist):
self.OE_Swap_sort.deployMpi()
time.sleep(10)
for service in self.OE_Swap_sort.client.services():
if 'head' in service['Spec']['Name']:
port = service['Endpoint']['Ports'][0]['PublishedPort']
ssh = paramiko.SSHClient() # 创建一个ssh的客户端,用来连接服务器
know_host = paramiko.AutoAddPolicy() # 创建一个ssh的白名单
ssh.set_missing_host_key_policy(know_host) # 加载创建的白名单
while True:
try:
ssh.connect(hostname="localhost", port=port, username="root", password="tutorial")
break
except:
print("异常处理:尝试连接主节点@" + str(port))
time.sleep(5)
tk.messagebox.showinfo('info', "异常处理完毕!")
print("continue...")
status= self.OE_Swap_sort.Run(status)
time.sleep(5)
tk.messagebox.showinfo('提示', "执行完毕")
if __name__ == '__main__':
Window = Window()