day11-RPC

作业要求:
可以对指定机器异步的执行多个命令
例子:
>>:run "df -h" --hosts 192.168.3.55 10.4.3.4
task id: 45334
>>: check_task 45334
>>:
注意,每执行一条命令,即立刻生成一个任务ID,不需等待结果返回,通过命令check_task TASK_ID来得到任务结果

server
 1 import pika
 2 import paramiko,os,
 3 
 4 class Server(object):
 5     def __init__(self,rabbitmq,queue_name):
 6         self.queue_name = queue_name
 7         self.connection = pika.BlockingConnection(pika.ConnectionParameters(
 8             host=rabbitmq))
 9         self.channel = self.connection.channel()
10         self.channel.queue_declare(queue=self.queue_name)
11 
12     def handle(self,cmd,host):
13 
14         #print(cmd,host)
15         message = self.paramiko_ex(cmd,host)
16         if not message:
17             message = "Wrong Command"
18         return message
19 
20     def paramiko_ex(self,command,host):
21         transport =paramiko.Transport((host,22))
22         transport.connect(username="root",password="cdw123") #用户密码简单写死,可以扩展类别根据IP 判断用户,密码。
23         ssh=paramiko.SSHClient()
24         ssh._transport = transport
25         stdin,stdout,stderr = ssh.exec_command(command)
26         #print(stdout.read().decode())
27         ack_msg=stdout.read().decode()
28         #print(ack_msg)
29         transport.close()
30         return ack_msg
31 
32     def on_request(self,ch, method, props, body):
33         #print(body,type(body))
34         body=body.decode()
35         body=body.split("_")
36         cmd,host=body[0],body[1]
37         #print(cmd,host)
38         response = self.handle(cmd,host)
39         ch.basic_publish(exchange='',
40                          routing_key=props.reply_to,  # 回信息队列名
41                          properties=pika.BasicProperties(correlation_id=
42                                                          props.correlation_id),
43                          body=str(response))
44         ch.basic_ack(delivery_tag=method.delivery_tag)
45 
46     def start(self):
47         self.channel.basic_consume(self.on_request,
48                                    queue=self.queue_name)
49 
50         print(" [x] Awaiting RPC requests")
51         self.channel.start_consuming()
52 
53 
54 if __name__ == "__main__":
55     rabbitmq = "localhost"      #rabbitmq服务器地址
56     queue_name = "rpc_5"
57     server = Server(rabbitmq,queue_name)
58     server.start()

client

  1 import pika,random,uuid,threading
  2 
  3 
  4 class Client(object):
  5     def __init__(self):
  6         self.connection = pika.BlockingConnection(pika.ConnectionParameters(
  7             host="localhost"))
  8         self.channel = self.connection.channel()
  9 
 10     def on_response(self, ch, method, props, body):
 11         '''获取命令执行结果的回调函数'''
 12         # print("验证码核对",self.callback_id,props.correlation_id)
 13         if self.callback_id == props.correlation_id:  # 验证码核对
 14             self.response = body
 15         ch.basic_ack(delivery_tag=method.delivery_tag)
 16 
 17     def get_response(self,callback_queue,callback_id):
 18         '''取队列里的值,获取callback_queued的执行结果'''
 19         self.callback_id = callback_id
 20         self.response = None
 21         self.channel.basic_consume(self.on_response,  # 只要收到消息就执行on_response
 22                                    queue=callback_queue)
 23         while self.response is None:
 24             self.connection.process_data_events()  # 非阻塞版的start_consuming
 25         return self.response
 26 
 27     def call(self,host,command):
 28         '''队列里发送数据'''
 29 
 30         result = self.channel.queue_declare(exclusive=False) #exclusive=False 必须这样写
 31         self.callback_queue = result.method.queue
 32         self.corr_id = str(uuid.uuid4())
 33         # print(self.corr_id)
 34         self.channel.basic_publish(exchange='',
 35                                    routing_key="rpc_5",
 36                                    properties=pika.BasicProperties(
 37                                        reply_to=self.callback_queue,  # 发送返回信息的队列name
 38                                        correlation_id=self.corr_id,  # 发送uuid 相当于验证码
 39                                    ),
 40                                    body=command+"_"+host) #组合命令,跟主机IP发给server
 41 
 42         return self.callback_queue,self.corr_id
 43 
 44 
 45 
 46 
 47 class Handler(object):
 48     def __init__(self):
 49         self.information = {}   # 后台进程信息
 50     def check_all(self,*args):
 51         '''查看所有task_id信息'''
 52 
 53         for key in self.information:
 54             print("TASK_ID【%s】\tHOST【%s】\tCOMMAND【%s】"%(key,self.information[key][0],
 55                                                                     self.information[key][1]))
 56 
 57     def check_task(self,user_cmd):
 58         '''查看task_id执行结果'''
 59 
 60         try:
 61             task_id = user_cmd.split()[1]
 62             task_id = int(task_id)
 63             callback_queue=self.information[task_id][2]
 64             callback_id=self.information[task_id][3]
 65             client = Client()
 66             response = client.get_response(callback_queue, callback_id)
 67             print(response.decode())
 68             del self.information[task_id]
 69 
 70         except KeyError  as e :
 71             print("\33[31;0mWrong id[%s]\33[0m"%e)
 72         except IndexError as e:
 73             print("\33[31;0mWrong id[%s]\33[0m"%e)
 74 
 75     def run(self,user_cmd):
 76         '''执行命令'''
 77         try:
 78             #time.sleep(2)
 79             #print("--->>",user_cmd)
 80             #print(user_cmd)
 81             command = user_cmd.split("\"")[1]
 82             #print(user_cmd.split()[4:])
 83             hosts = user_cmd.split()[4:]
 84             for host in hosts:
 85                 #print(command,host)
 86                 # cmd_dict={"cmd":command,
 87                 #           "host":hosts}
 88                 task_id = random.randint(10000, 99999)
 89                 client = Client()
 90                 response = client.call(host, command)
 91                 # print(response)
 92                 self.information[task_id] = [host, command, response[0],response[1]]
 93         except IndexError as e:
 94             print("\33[31;0mError:%s\33[0m"%e)
 95 
 96     def reflect(self,str,user_cmd):
 97         '''反射'''
 98         if hasattr(self, str):
 99             getattr(self, str)(user_cmd)
100 
101 
102     def start(self):
103         while True:
104             user_cmd = input("->>").strip()
105             if not user_cmd:continue
106             str = user_cmd.split()[0]
107             t1 = threading.Thread(target=self.reflect,args=(str,user_cmd))  #多线程
108             t1.start()
109 
110 if __name__ == '__main__':
111     obj = Handler()
112     obj.start()

 

posted @ 2018-04-20 13:10  东郭仔  阅读(101)  评论(0)    收藏  举报