[虚拟化/云][全栈demo] 为qemu增加一个PCI的watchdog外设(八)
目的:
1. 通过网页读取watchdog的信息
2. 通过网页设置watchdog
准备工作:
1. 选择一个web框架,选用 cherrypy
$ sudo apt-get install python-cherrypy3
2. 熟悉 RESTFUL , 参考 RESR_API(Mark McLoughlin) redhat REST API 指导
步骤:
我们选择了一个cherrypy作为web框架。 cherrypy的部署简单。
这只是个demo,没有实现MVC,大家自己练习。
此外也没有实现模板,距离一个正式的网站还差的很远。
界面实现如下:
代码如下:
代码中,喂狗代码采用了一个线程。需要改进。
发现不是很好,因为每个wsgi的请求都是一个线程。
最好是采用cherrypy提供的background, 或者将该逻辑独立为一个单例模式。
watchdog.py
1 import cherrypy 2 import json 3 import time 4 import threading 5 6 7 index_html = """ 8 <html> 9 <head> 10 <style type="text/css"> 11 .watchdog-state { 12 display: inline-block; 13 height: 16px; 14 width: 16px; 15 border-radius: 8px; 16 margin-left: 10px; 17 margin-right: 10px; 18 } 19 .up { 20 background: linear-gradient(to bottom, #BFD255 0%%, #8EB92A 50%%, 21 #72AA00 51%%, #9ECB2D 100%%) repeat scroll 0 0 transparent; 22 } 23 24 .down { 25 background: linear-gradient(to bottom, #AFAFAF 0%%, #AFAFAF 50%%, 26 #AFAFAF 51%%, #AFAFAF 100%%) repeat scroll 0 0 transparent; 27 } 28 </style> 29 </head> 30 31 <body> 32 <script type="text/javascript"> 33 function requestJSON(url, suc, done, err) { 34 var xmlhttp; 35 xmlhttp = new XMLHttpRequest(); 36 xmlhttp.open("POST", url, true); 37 xmlhttp.setRequestHeader("Content-type", "application/json"); 38 xmlhttp.setRequestHeader("dataType", "application/json"); 39 xmlhttp.onreadystatechange=function(){ 40 if (xmlhttp.readyState==4 && xmlhttp.status==200) { 41 var responseContext = xmlhttp.responseText; 42 var jsonobj=eval('('+responseContext+')'); 43 suc(jsonobj); 44 } else{ 45 // alert("readyState: " + xmlhttp.readyState + "status" + xmlhttp.status); 46 } 47 } 48 xmlhttp.send(); 49 } 50 51 function operationWatchdog() 52 { 53 // alert("operationWatchdog"); 54 var url = "watchdog/deactivate"; 55 var action = document.getElementById("watchdog-action"); 56 if (action.innerHTML == "Activate"){ 57 url = "watchdog/activate"; 58 } 59 requestJSON(url, function(data){ 60 // alert(data.value); 61 }); 62 if (action.innerHTML == "Activate"){ 63 action.innerHTML = "Deactivate"; 64 } else { 65 action.innerHTML = "Activate"; 66 } 67 var status = document.getElementById("watch-status"); 68 if (status.className.match("up$")){ 69 status.className = "watchdog-state down"; 70 } else{ 71 status.className = "watchdog-state up"; 72 } 73 } 74 function FeedWatchod() 75 { 76 // alert("FeedWatchod"); 77 var url = "watchdog/feedstop"; 78 var feed = document.getElementById("feed-watchdog"); 79 if (feed.innerHTML == "Start"){ 80 url = "watchdog/feedstart"; 81 } 82 requestJSON(url, function(data){ 83 //alert(data.value); 84 }); 85 if (feed.innerHTML == "Start"){ 86 feed.innerHTML = "Stop"; 87 } else { 88 feed.innerHTML = "Start"; 89 } 90 } 91 </script> 92 <div> 93 Status of watchdog: <span id="watch-status" class="watchdog-state %s"> </span> 94 <button id="watchdog-action" type="button" onclick="operationWatchdog()">%s</button> 95 </div> 96 <div> 97 Feed watchdog: 98 <button id="feed-watchdog" type="button" onclick="FeedWatchod()">Start</button> 99 </div> 100 </body> 101 </html> """ 102 103 def jsonObj(data): 104 cherrypy.response.headers['Content-Type'] = 'application/json;charset=utf-8' 105 return json.dumps(data, indent=2, separators=(',', ':')) 106 107 watchdog_hadle = open("/dev/cwd_demo", "w+") 108 def watchdogStatus(): 109 vals = watchdog_hadle.readlines(); 110 return vals[0] == ['B\x01\n'] 111 112 def watchdogAction(action): 113 watchdog_hadle.write(action) 114 watchdog_hadle.flush() 115 116 class WelcomePage(object): 117 def __init__(self): 118 self.watchdog = Watchdog() 119 120 def index(self): 121 watchdog_state = "down" 122 watchdog_action = "Activate" 123 if watchdogStatus(): 124 watchdog_state = "up" 125 watchdog_action = "Deactivate" 126 a = index_html % (watchdog_state, watchdog_action) 127 print a 128 return a 129 index.exposed = True 130 131 132 def default(*args, **kwargs): 133 data = {"hello": "world"} 134 return jsonObj(data) 135 default.exposed = True 136 137 138 139 class Watchdog(object): 140 exposed = True 141 feed_running = False 142 feed_thread = None 143 144 def __init__(self): 145 pass 146 147 @classmethod 148 def worker(cls): 149 while cls.feed_running: 150 print "worker" 151 watchdogAction('t') 152 time.sleep(1) 153 return 154 155 @cherrypy.expose 156 def index(self, *args, **kwargs): 157 data = {"value": False} 158 data = {"value": watchdogStatus()} 159 return jsonObj(data) 160 161 @cherrypy.tools.accept(media='application/json') 162 @cherrypy.expose 163 def activate(self, *args, **kwargs): 164 watchdogAction('a') 165 print "activate" 166 raise cherrypy.InternalRedirect("/watchdog") 167 168 @cherrypy.tools.accept(media='application/json') 169 @cherrypy.expose 170 def deactivate(self, *args, **kwargs): 171 watchdogAction('d') 172 print "deactivate" 173 raise cherrypy.InternalRedirect("/watchdog") 174 175 @cherrypy.tools.accept(media='application/json') 176 @cherrypy.expose 177 def feedstart(self, *args, **kwargs): 178 watchdogAction('t') 179 print "feed start" 180 if self.__class__.feed_thread == None: 181 self.__class__.feed_thread = threading.Thread( 182 target=self.__class__.worker) 183 if self.__class__.feed_running == False: 184 self.__class__.feed_running = True 185 self.__class__.feed_thread.start() 186 raise cherrypy.InternalRedirect("/watchdog") 187 188 @cherrypy.expose 189 def feedstop(self, *args, **kwargs): 190 print "feed stop" 191 if self.__class__.feed_thread.isAlive(): 192 self.__class__.feed_running = False 193 self.__class__.feed_thread.join(1.5) 194 self.__class__.feed_thread = None 195 raise cherrypy.InternalRedirect("/watchdog") 196 197 if __name__ == '__main__': 198 # CherryPy always starts with app.root when trying to map request URIs 199 # to objects, so we need to mount a request handler root. A request 200 # to '/' will be mapped to HelloWorld().index(). 201 cherrypy.quickstart(WelcomePage()) 202 else: 203 # This branch is for the test suite; you can ignore it. 204 cherrypy.tree.mount(WelcomePage())