[#5] Use better dict-based format for write updates

This commit is contained in:
Joshua Boniface 2018-06-26 23:24:33 -04:00
parent 276b618137
commit 4320fcdf0e
4 changed files with 52 additions and 52 deletions

View File

@ -146,7 +146,7 @@ zk_conn.add_listener(zk_listener)
def cleanup(signum, frame): def cleanup(signum, frame):
ansiiprint.echo('Terminating daemon', '', 'e') ansiiprint.echo('Terminating daemon', '', 'e')
# Set stop state in Zookeeper # Set stop state in Zookeeper
zkhandler.writedata(zk_conn, '/nodes/{}/daemonstate'.format(myhostname), [ 'stop' ]) zkhandler.writedata(zk_conn, { '/nodes/{}/daemonstate'.format(myhostname): 'stop' })
# Close the Zookeeper connection # Close the Zookeeper connection
zk_conn.close() zk_conn.close()
# Stop keepalive thread # Stop keepalive thread
@ -180,7 +180,7 @@ print(' {0}Kernel:{1} {2}'.format(ansiiprint.bold(), ansiiprint.end(), staticda
if zk_conn.exists('/nodes/{}'.format(myhostname)): if zk_conn.exists('/nodes/{}'.format(myhostname)):
print("Node is " + ansiiprint.green() + "present" + ansiiprint.end() + " in Zookeeper") print("Node is " + ansiiprint.green() + "present" + ansiiprint.end() + " in Zookeeper")
# Update static data just in case it's changed # Update static data just in case it's changed
zkhandler.writedata(zk_conn, '/nodes/{}/staticdata'.format(myhostname), [ ' '.join(staticdata) ]) zkhandler.writedata(zk_conn, { '/nodes/{}/staticdata'.format(myhostname): ' '.join(staticdata) })
else: else:
print("Node is " + ansiiprint.red() + "absent" + ansiiprint.end() + " in Zookeeper; adding new node") print("Node is " + ansiiprint.red() + "absent" + ansiiprint.end() + " in Zookeeper; adding new node")
keepalive_time = int(time.time()) keepalive_time = int(time.time())
@ -202,7 +202,7 @@ else:
transaction.create('/nodes/{}/ipmipassword'.format(myhostname), config['ipmi_password'].encode('ascii')) transaction.create('/nodes/{}/ipmipassword'.format(myhostname), config['ipmi_password'].encode('ascii'))
transaction.commit() transaction.commit()
zkhandler.writedata(zk_conn, '/nodes/{}/daemonstate'.format(myhostname), [ 'init' ]) zkhandler.writedata(zk_conn, { '/nodes/{}/daemonstate'.format(myhostname): 'init' })
t_node = dict() t_node = dict()
s_domain = dict() s_domain = dict()

View File

@ -151,36 +151,34 @@ class NodeInstance():
if target_hypervisor == None: if target_hypervisor == None:
ansiiprint.echo('Failed to find migration target for VM "{}"; shutting down'.format(dom_uuid), '', 'e') ansiiprint.echo('Failed to find migration target for VM "{}"; shutting down'.format(dom_uuid), '', 'e')
transaction = self.zk_conn.transaction() zkhandler.writedata(self.zk_conn, { '/domains/{}/state'.format(dom_uuid): 'shutdown' })
transaction.set_data('/domains/{}/state'.format(dom_uuid), 'shutdown'.encode('ascii'))
transaction.commit()
else: else:
ansiiprint.echo('Migrating VM "{}" to hypervisor "{}"'.format(dom_uuid, target_hypervisor), '', 'i') ansiiprint.echo('Migrating VM "{}" to hypervisor "{}"'.format(dom_uuid, target_hypervisor), '', 'i')
transaction = self.zk_conn.transaction() zkhandler.writedata(self.zk_conn, {
transaction.set_data('/domains/{}/state'.format(dom_uuid), 'migrate'.encode('ascii')) '/domains/{}/state'.format(dom_uuid): 'migrate',
transaction.set_data('/domains/{}/hypervisor'.format(dom_uuid), target_hypervisor.encode('ascii')) '/domains/{}/hypervisor'.format(dom_uuid): target_hypervisor,
transaction.set_data('/domains/{}/lasthypervisor'.format(dom_uuid), current_hypervisor.encode('ascii')) '/domains/{}/lasthypervisor'.format(dom_uuid): current_hypervisor
transaction.commit() })
zkhandler.writedata(self.zk_conn, '/nodes/{}/runningdomains'.format(self.name), [ '' ]) zkhandler.writedata(self.zk_conn, { '/nodes/{}/runningdomains'.format(self.name): '' })
zkhandler.writedata(self.zk_conn, '/nodes/{}/domainstate'.format(self.name), [ 'flushed' ]) zkhandler.writedata(self.zk_conn, { '/nodes/{}/domainstate'.format(self.name): 'flushed' })
self.inflush = False self.inflush = False
def unflush(self): def unflush(self):
self.inflush = True self.inflush = True
ansiiprint.echo('Restoring node {} to active service.'.format(self.name), '', 'i') ansiiprint.echo('Restoring node {} to active service.'.format(self.name), '', 'i')
zkhandler.writedata(self.zk_conn, '/nodes/{}/domainstate'.format(self.name), [ 'ready' ]) zkhandler.writedata(self.zk_conn, { '/nodes/{}/domainstate'.format(self.name): 'ready' })
for dom_uuid in self.s_domain: for dom_uuid in self.s_domain:
last_hypervisor = zkhandler.readdata(self.zk_conn, '/domains/{}/lasthypervisor'.format(dom_uuid)) last_hypervisor = zkhandler.readdata(self.zk_conn, '/domains/{}/lasthypervisor'.format(dom_uuid))
if last_hypervisor != self.name: if last_hypervisor != self.name:
continue continue
ansiiprint.echo('Setting unmigration for VM "{}"'.format(dom_uuid), '', 'i') ansiiprint.echo('Setting unmigration for VM "{}"'.format(dom_uuid), '', 'i')
transaction = self.zk_conn.transaction() zkhandler.writedata(self.zk_conn, {
transaction.set_data('/domains/{}/state'.format(dom_uuid), 'migrate'.encode('ascii')) '/domains/{}/state'.format(dom_uuid): 'migrate',
transaction.set_data('/domains/{}/hypervisor'.format(dom_uuid), self.name.encode('ascii')) '/domains/{}/hypervisor'.format(dom_uuid): self.name,
transaction.set_data('/domains/{}/lasthypervisor'.format(dom_uuid), ''.encode('ascii')) '/domains/{}/lasthypervisor'.format(dom_uuid): ''
transaction.commit() })
self.inflush = False self.inflush = False
@ -196,7 +194,7 @@ class NodeInstance():
past_state = zkhandler.readdata(self.zk_conn, '/nodes/{}/daemonstate'.format(self.name)) past_state = zkhandler.readdata(self.zk_conn, '/nodes/{}/daemonstate'.format(self.name))
if past_state != 'run': if past_state != 'run':
self.daemon_state = 'run' self.daemon_state = 'run'
zkhandler.writedata(self.zk_conn, '/nodes/{}/daemonstate'.format(self.name), [ 'run' ]) zkhandler.writedata(self.zk_conn, { '/nodes/{}/daemonstate'.format(self.name): 'run' })
else: else:
self.daemon_state = 'run' self.daemon_state = 'run'
@ -210,7 +208,7 @@ class NodeInstance():
raise raise
except Exception as e: except Exception as e:
# Toggle a state "change" # Toggle a state "change"
zkhandler.writedata(self.zk_conn, '/domains/{}/state'.format(domain), [ instance.getstate() ]) zkhandler.writedata(self.zk_conn, { '/domains/{}/state'.format(domain): instance.getstate() })
# Set our information in zookeeper # Set our information in zookeeper
self.name = lv_conn.getHostname() self.name = lv_conn.getHostname()
@ -220,14 +218,14 @@ class NodeInstance():
self.domains_count = len(lv_conn.listDomainsID()) self.domains_count = len(lv_conn.listDomainsID())
keepalive_time = int(time.time()) keepalive_time = int(time.time())
try: try:
transaction = self.zk_conn.transaction() zkhandler.writedata(self.zk_conn, {
transaction.set_data('/nodes/{}/memused'.format(self.name), str(self.memused).encode('ascii')) '/nodes/{}/memused'.format(self.name): str(self.memused),
transaction.set_data('/nodes/{}/memfree'.format(self.name), str(self.memfree).encode('ascii')) '/nodes/{}/memfree'.format(self.name): str(self.memfree),
transaction.set_data('/nodes/{}/cpuload'.format(self.name), str(self.cpuload).encode('ascii')) '/nodes/{}/cpuload'.format(self.name): str(self.cpuload),
transaction.set_data('/nodes/{}/runningdomains'.format(self.name), ' '.join(self.domain_list).encode('ascii')) '/nodes/{}/runningdomains'.format(self.name): ' '.join(self.domain_list),
transaction.set_data('/nodes/{}/domainscount'.format(self.name), str(self.domains_count).encode('ascii')) '/nodes/{}/domainscount'.format(self.name): str(self.domains_count),
transaction.set_data('/nodes/{}/keepalive'.format(self.name), str(keepalive_time).encode('ascii')) '/nodes/{}/keepalive'.format(self.name): str(keepalive_time)
transaction.commit() })
except: except:
return return
@ -256,7 +254,7 @@ class NodeInstance():
if node_keepalive < node_deadtime and node_daemon_state == 'run': if node_keepalive < node_deadtime and node_daemon_state == 'run':
# CHECK VERSIONING HERE # CHECK VERSIONING HERE
ansiiprint.echo('Node {} seems dead - starting monitor for fencing'.format(node_name), '', 'w') ansiiprint.echo('Node {} seems dead - starting monitor for fencing'.format(node_name), '', 'w')
zkhandler.writedata(self.zk_conn, '/nodes/{}/daemonstate'.format(node_name), [ 'dead' ]) zkhandler.writedata(self.zk_conn, { '/nodes/{}/daemonstate'.format(node_name): 'dead' })
fence_thread = threading.Thread(target=fenceNode, args=(node_name, self.zk_conn), kwargs={}) fence_thread = threading.Thread(target=fenceNode, args=(node_name, self.zk_conn), kwargs={})
fence_thread.start() fence_thread.start()
@ -344,14 +342,14 @@ def fenceNode(node_name, zk_conn):
target_hypervisor = hypervisor target_hypervisor = hypervisor
ansiiprint.echo('Moving VM "{}" to hypervisor "{}"'.format(dom_uuid, target_hypervisor), '', 'i') ansiiprint.echo('Moving VM "{}" to hypervisor "{}"'.format(dom_uuid, target_hypervisor), '', 'i')
transaction = zk_conn.transaction() zkhandler.writedata(self.zk_conn, {
transaction.set_data('/domains/{}/state'.format(dom_uuid), 'start'.encode('ascii')) '/domains/{}/state'.format(dom_uuid): 'start',
transaction.set_data('/domains/{}/hypervisor'.format(dom_uuid), target_hypervisor.encode('ascii')) '/domains/{}/hypervisor'.format(dom_uuid): target_hypervisor,
transaction.set_data('/domains/{}/lasthypervisor'.format(dom_uuid), current_hypervisor.encode('ascii')) '/domains/{}/lasthypervisor'.format(dom_uuid): current_hypervisor
transaction.commit() })
# Set node in flushed state for easy remigrating when it comes back # Set node in flushed state for easy remigrating when it comes back
zkhandler.writedata(self.zk_conn, '/nodes/{}/domainstate'.format(node_name), [ 'flushed' ]) zkhandler.writedata(self.zk_conn, { '/nodes/{}/domainstate'.format(node_name): 'flushed' })
# #
# Perform an IPMI fence # Perform an IPMI fence

View File

@ -72,7 +72,7 @@ class VMInstance:
# Add the domain to the domain_list array # Add the domain to the domain_list array
self.thishypervisor.domain_list.append(self.domuuid) self.thishypervisor.domain_list.append(self.domuuid)
# Push the change up to Zookeeper # Push the change up to Zookeeper
zkhandler.writedata(self.zk_conn, '/nodes/{}/runningdomains'.format(self.thishypervisor.name), [ ' '.join(self.thishypervisor.domain_list) ]) zkhandler.writedata(self.zk_conn, { '/nodes/{}/runningdomains'.format(self.thishypervisor.name): ' '.join(self.thishypervisor.domain_list) })
except Exception as e: except Exception as e:
ansiiprint.echo('Error adding domain to list: {}'.format(e), '', 'c') ansiiprint.echo('Error adding domain to list: {}'.format(e), '', 'c')
@ -82,7 +82,7 @@ class VMInstance:
# Remove the domain from the domain_list array # Remove the domain from the domain_list array
self.thishypervisor.domain_list.remove(self.domuuid) self.thishypervisor.domain_list.remove(self.domuuid)
# Push the change up to Zookeeper # Push the change up to Zookeeper
zkhandler.writedata(self.zk_conn, '/nodes/{}/runningdomains'.format(self.thishypervisor.name), [ ' '.join(self.thishypervisor.domain_list) ]) zkhandler.writedata(self.zk_conn, { '/nodes/{}/runningdomains'.format(self.thishypervisor.name): ' '.join(self.thishypervisor.domain_list) })
except Exception as e: except Exception as e:
ansiiprint.echo('Error removing domain from list: {}'.format(e), '', 'c') ansiiprint.echo('Error removing domain from list: {}'.format(e), '', 'c')
@ -108,7 +108,7 @@ class VMInstance:
self.dom = dom self.dom = dom
except libvirt.libvirtError as e: except libvirt.libvirtError as e:
ansiiprint.echo('Failed to create VM', '{}:'.format(self.domuuid), 'e') ansiiprint.echo('Failed to create VM', '{}:'.format(self.domuuid), 'e')
zkhandler.writedata(self.zk_conn, '/domains/{}/state'.format(self.domuuid), [ 'failed' ]) zkhandler.writedata(self.zk_conn, { '/domains/{}/state'.format(self.domuuid): 'failed' })
self.dom = None self.dom = None
lv_conn.close() lv_conn.close()
@ -135,7 +135,7 @@ class VMInstance:
except libvirt.libvirtError as e: except libvirt.libvirtError as e:
ansiiprint.echo('Failed to restart VM', '{}:'.format(self.domuuid), 'e') ansiiprint.echo('Failed to restart VM', '{}:'.format(self.domuuid), 'e')
zkhandler.writedata(self.zk_conn, '/domains/{}/state'.format(self.domuuid), [ 'start' ]) zkhandler.writedata(self.zk_conn, { '/domains/{}/state'.format(self.domuuid): 'start' })
lv_conn.close() lv_conn.close()
self.inrestart = False self.inrestart = False
@ -163,7 +163,7 @@ class VMInstance:
self.removeDomainFromList() self.removeDomainFromList()
if self.inrestart == False: if self.inrestart == False:
zkhandler.writedata(self.zk_conn, '/domains/{}/state'.format(self.domuuid), [ 'stop' ]) zkhandler.writedata(self.zk_conn, { '/domains/{}/state'.format(self.domuuid): 'stop' })
ansiiprint.echo('Successfully stopped VM', '{}:'.format(self.domuuid), 'o') ansiiprint.echo('Successfully stopped VM', '{}:'.format(self.domuuid), 'o')
self.dom = None self.dom = None
@ -191,7 +191,7 @@ class VMInstance:
self.removeDomainFromList() self.removeDomainFromList()
if self.inrestart == False: if self.inrestart == False:
zkhandler.writedata(self.zk_conn, '/domains/{}/state'.format(self.domuuid), [ 'stop' ]) zkhandler.writedata(self.zk_conn, { '/domains/{}/state'.format(self.domuuid): 'stop' })
ansiiprint.echo('Successfully shutdown VM', '{}:'.format(self.domuuid), 'o') ansiiprint.echo('Successfully shutdown VM', '{}:'.format(self.domuuid), 'o')
self.dom = None self.dom = None
@ -237,7 +237,7 @@ class VMInstance:
self.removeDomainFromList() self.removeDomainFromList()
time.sleep(1) time.sleep(1)
zkhandler.writedata(self.zk_conn, '/domains/{}/state'.format(self.domuuid), [ 'start' ]) zkhandler.writedata(self.zk_conn, { '/domains/{}/state'.format(self.domuuid): 'start' })
self.inmigrate = False self.inmigrate = False
# Receive the migration from another host (wait until VM is running) # Receive the migration from another host (wait until VM is running)
@ -322,7 +322,7 @@ class VMInstance:
self.addDomainToList() self.addDomainToList()
# VM is already running and should be but stuck in migrate state # VM is already running and should be but stuck in migrate state
elif self.state == "migrate": elif self.state == "migrate":
zkhandler.writedata(self.zk_conn, '/domains/{}/state'.format(self.domuuid), [ 'start' ]) zkhandler.writedata(self.zk_conn, { '/domains/{}/state'.format(self.domuuid): 'start' })
self.addDomainToList() self.addDomainToList()
# VM should be restarted # VM should be restarted
elif self.state == "restart": elif self.state == "restart":
@ -342,7 +342,7 @@ class VMInstance:
self.receive_migrate() self.receive_migrate()
# VM should be restarted (i.e. started since it isn't running) # VM should be restarted (i.e. started since it isn't running)
if self.state == "restart": if self.state == "restart":
zkhandler.writedata(self.zk_conn, '/domains/{}/state'.format(self.domuuid), [ 'start' ]) zkhandler.writedata(self.zk_conn, { '/domains/{}/state'.format(self.domuuid): 'start' })
# VM should be shut down; ensure it's gone from this node's domain_list # VM should be shut down; ensure it's gone from this node's domain_list
elif self.state == "shutdown": elif self.state == "shutdown":
self.removeDomainFromList() self.removeDomainFromList()

View File

@ -35,22 +35,24 @@ def readdata(zk_conn, key):
return data return data
# Data write function # Data write function
def writedata(zk_conn, key, data): def writedata(zk_conn, kv):
# Get the current version # Get the current version; we base this off the first key (ordering in multi-key calls is irrelevant)
orig_data_raw = zk_conn.get(key) first_key = list(kv.keys())[0]
orig_data_raw = zk_conn.get(first_key)
meta = orig_data_raw[1] meta = orig_data_raw[1]
if meta == None: if meta == None:
ansiiprint.echo('Zookeeper key "{}" does not exist'.format(key), '', 'e') ansiiprint.echo('Zookeeper key "{}" does not exist'.format(first_key), '', 'e')
return 1 return 1
version = meta.version version = meta.version
new_version = version + 1 new_version = version + 1
zk_transaction = zk_conn.transaction() zk_transaction = zk_conn.transaction()
zk_transaction.set_data(key, data.encode('ascii')) for key, data in kv:
zk_transaction.set_data(key, data.encode('ascii'))
try: try:
zk_transaction.check(key, new_version) zk_transaction.check(first_key, new_version)
except TypeError: except TypeError:
ansiiprint.echo('Zookeeper key "{}" does not match expected version'.format(key), '', 'e') ansiiprint.echo('Zookeeper key "{}" does not match expected version'.format(first_key), '', 'e')
return 1 return 1
zk_transaction.commit() zk_transaction.commit()
return 0 return 0