diff --git a/NodeInstance.py b/NodeInstance.py index 31f15d30..f820a407 100644 --- a/NodeInstance.py +++ b/NodeInstance.py @@ -12,7 +12,20 @@ class NodeInstance(threading.Thread): self.state = 'stop' self.stop_thread = threading.Event() self.node_list = node_list - self.domainlist = [] + self.domain_list = [] + + # Zookeeper handlers for changed states + @zk.DataWatch(self.zkey + '/state') + def watch_hypervisor_state(data, stat, event=""): + self.state = data.decode('ascii') + + @zk.DataWatch(self.zkey + '/memfree') + def watch_hypervisor_memfree(data, stat, event=""): + self.memfree = data.decode('ascii') + + @zk.DataWatch(self.zkey + '/runningdomains') + def watch_hypervisor_runningdomains(data, stat, event=""): + self.domain_list = data.decode('ascii').split() # Get value functions def getfreemem(self): @@ -27,6 +40,9 @@ class NodeInstance(threading.Thread): def getstate(self): return self.state + def getdomainlist(self): + return self.domain_list + # Update value functions def updatenodelist(self, node_list): self.node_list = node_list @@ -37,7 +53,7 @@ class NodeInstance(threading.Thread): # Flush all VMs on the host def flush(self): - for domain in self.domainlist: + for domain in self.domain_list: # Determine the best target hypervisor least_mem = (2^64)/8 least_load = 999.0 @@ -80,12 +96,13 @@ class NodeInstance(threading.Thread): try: self.zk.set(self.zkey + '/memfree', str(self.memfree).encode('ascii')) self.zk.set(self.zkey + '/cpuload', str(self.cpuload).encode('ascii')) + self.zk.set(self.zkey + '/runningdomains', ' '.join(self.domain_list).encode('ascii')) except: if self.stop_thread.is_set(): return - print("%s - Free memory: %s | Load: %s" % ( time.strftime("%d/%m/%Y %H:%M:%S"), self.memfree, self.cpuload )) - print("Active domains: %s" % self.domainlist) + print(">>> %s - Free memory: %s | Load: %s" % ( time.strftime("%d/%m/%Y %H:%M:%S"), self.memfree, self.cpuload )) + print("Active domains: %s" % self.domain_list) active_node_list = [] flushed_node_list = [] inactive_node_list = [] diff --git a/VMInstance.py b/VMInstance.py index e7c1c783..3f1cc5da 100644 --- a/VMInstance.py +++ b/VMInstance.py @@ -17,14 +17,14 @@ class VMInstance: # Watch for changes to the hypervisor field in Zookeeper @zk.DataWatch(self.zkey + '/hypervisor') - def watch_hypervisor(data, stat): + def watch_hypervisor(data, stat, event=""): if self.hypervisor != data.decode('ascii'): self.hypervisor = data.decode('ascii') self.manage_vm_state() # Watch for changes to the state field in Zookeeper @zk.DataWatch(self.zkey + '/state') - def watch_state(data, stat): + def watch_state(data, stat, event=""): if self.state != data.decode('ascii'): self.state = data.decode('ascii') self.manage_vm_state() @@ -36,20 +36,23 @@ class VMInstance: if dom == None: print('Failed to create a domain from an XML definition.') exit(1) - self.thishypervisor.domainlist.append(self.domuuid) + if not self.domuuid in self.thishypervisor.domain_list: + self.thishypervisor.domain_list.append(self.domuuid) return dom # Stop the VM forcibly def stop_vm(self): print("Forcibly stopping VM %s" % self.domuuid) self.dom.destroy() - self.thishypervisor.domainlist.remove(self.domuuid) + if self.domuuid in self.thishypervisor.domain_list: + self.thishypervisor.domain_list.remove(self.domuuid) # Shutdown the VM gracefully def shutdown_vm(self): print("Stopping VM %s" % self.domuuid) self.dom.shutdown() - self.thishypervisor.domainlist.remove(self.domuuid) + if self.domuuid in self.thishypervisor.domain_list: + self.thishypervisor.domain_list.remove(self.domuuid) # Migrate the VM to a target host def migrate_vm(self): @@ -64,7 +67,7 @@ class VMInstance: print('Could not migrate to the new domain') exit(1) - self.thishypervisor.domainlist.remove(self.domuuid) + self.thishypervisor.domain_list.remove(self.domuuid) print('Migrated successfully') dest_conn.close() @@ -75,7 +78,8 @@ class VMInstance: continue else: self.zk.set(self.zkey + '/status', b'start') - self.thishypervisor.domainlist.append(self.domuuid) + if not self.domuuid in self.thishypervisor.domain_list: + self.thishypervisor.domain_list.append(self.domuuid) break # @@ -93,32 +97,33 @@ class VMInstance: try: self.dom = conn.lookupByUUID(uuid.UUID(self.domuuid).bytes) if self.dom != None: - running = self.dom.state() + running, reason = self.dom.state() else: - running = False + running = libvirt.VIR_DOMAIN_NOSTATE except: - running = False + running = libvirt.VIR_DOMAIN_NOSTATE - if running != False and self.state == "stop" and self.hypervisor == self.thishypervisor.name: + if running == libvirt.VIR_DOMAIN_RUNNING and self.state == "stop" and self.hypervisor == self.thishypervisor.name: self.stop_vm() - if running != False and self.state == "shutdown" and self.hypervisor == self.thishypervisor.name: + if running == libvirt.VIR_DOMAIN_RUNNING and self.state == "shutdown" and self.hypervisor == self.thishypervisor.name: self.shutdown_vm() - elif running == False and self.state == "migrate" and self.hypervisr == self.thishypervisor.name: + elif running != libvirt.VIR_DOMAIN_RUNNING and self.state == "migrate" and self.hypervisr == self.thishypervisor.name: self.receive_migrate() - elif running != False and self.state == "migrate" and self.hypervisr != self.thishypervisor.name: + elif running == libvirt.VIR_DOMAIN_RUNNING and self.state == "migrate" and self.hypervisr != self.thishypervisor.name: self.migrate_vm() - elif running == False and self.state == "start" and self.hypervisor == self.thishypervisor.name: + elif running != libvirt.VIR_DOMAIN_RUNNING and self.state == "start" and self.hypervisor == self.thishypervisor.name: # Grab the domain information from Zookeeper domxml, domxmlstat = self.zk.get(self.zkey + '/xml') domxml = str(domxml.decode('ascii')) self.dom = self.start_vm(conn, domxml) - elif running != False and self.state == "start" and self.hypervisor == self.thishypervisor.name: - self.thishypervisor.domainlist.append(self.domuuid) + elif running == libvirt.VIR_DOMAIN_RUNNING and self.state == "start" and self.hypervisor == self.thishypervisor.name: + if not self.domuuid in self.thishypervisor.domain_list: + self.thishypervisor.domain_list.append(self.domuuid) # The VM should now be running so return the domain and active connection conn.close diff --git a/pvcd.py b/pvcd.py index ff20dcff..6566cc15 100755 --- a/pvcd.py +++ b/pvcd.py @@ -44,11 +44,13 @@ mynodestring = '/nodes/%s' % myhostname def cleanup(): t_node[myhostname].stop() + time.sleep(0.2) try: zk.set('/nodes/' + myhostname + '/state', 'stop'.encode('ascii')) + zk.stop() + zk.close() except: pass - zk.stop() atexit.register(cleanup) @@ -61,6 +63,7 @@ else: zk.create('%s/cpucount' % mynodestring, '0'.encode('ascii')) zk.create('%s/memfree' % mynodestring, '0'.encode('ascii')) zk.create('%s/cpuload' % mynodestring, '0.0'.encode('ascii')) + zk.create('%s/runningdomains' % mynodestring, ''.encode('ascii')) t_node = dict() s_domain = dict()