云计算--基于docker+swarm集群的奇偶交换排序

云计算–基于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()

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值