Finish up output printing and several other tweaks
This commit is contained in:
parent
aff0af5630
commit
75477c7297
|
@ -214,7 +214,6 @@ class NodeInstance():
|
||||||
|
|
||||||
# Set our information in zookeeper
|
# Set our information in zookeeper
|
||||||
self.name = conn.getHostname()
|
self.name = conn.getHostname()
|
||||||
self.cpucount = conn.getCPUMap()[0]
|
|
||||||
self.memused = int(psutil.virtual_memory().used / 1024 / 1024)
|
self.memused = int(psutil.virtual_memory().used / 1024 / 1024)
|
||||||
self.memfree = int(psutil.virtual_memory().free / 1024 / 1024)
|
self.memfree = int(psutil.virtual_memory().free / 1024 / 1024)
|
||||||
self.cpuload = os.getloadavg()[0]
|
self.cpuload = os.getloadavg()[0]
|
||||||
|
@ -222,7 +221,6 @@ class NodeInstance():
|
||||||
keepalive_time = int(time.time())
|
keepalive_time = int(time.time())
|
||||||
try:
|
try:
|
||||||
transaction = self.zk.transaction()
|
transaction = self.zk.transaction()
|
||||||
transaction.set_data('/nodes/{}/cpucount'.format(self.name), str(self.cpucount).encode('ascii'))
|
|
||||||
transaction.set_data('/nodes/{}/memused'.format(self.name), str(self.memused).encode('ascii'))
|
transaction.set_data('/nodes/{}/memused'.format(self.name), str(self.memused).encode('ascii'))
|
||||||
transaction.set_data('/nodes/{}/memfree'.format(self.name), str(self.memfree).encode('ascii'))
|
transaction.set_data('/nodes/{}/memfree'.format(self.name), str(self.memfree).encode('ascii'))
|
||||||
transaction.set_data('/nodes/{}/cpuload'.format(self.name), str(self.cpuload).encode('ascii'))
|
transaction.set_data('/nodes/{}/cpuload'.format(self.name), str(self.cpuload).encode('ascii'))
|
||||||
|
@ -238,7 +236,7 @@ class NodeInstance():
|
||||||
|
|
||||||
# Display node information to the terminal
|
# Display node information to the terminal
|
||||||
ansiiprint.echo('{}{} keepalive{}'.format(ansiiprint.purple(), self.name, ansiiprint.end()), '', 't')
|
ansiiprint.echo('{}{} keepalive{}'.format(ansiiprint.purple(), self.name, ansiiprint.end()), '', 't')
|
||||||
ansiiprint.echo('{0}Active domains:{1} {2} {0}CPUs:{1} {3} {0}Free memory [MiB]:{1} {4} {0}Used memory [MiB]:{1} {5} {0}Load:{1} {6}'.format(ansiiprint.bold(), ansiiprint.end(), self.domains_count, self.cpucount, self.memfree, self.memused, self.cpuload), '', 'c')
|
ansiiprint.echo('{0}Active domains:{1} {2} {0}Free memory [MiB]:{1} {3} {0}Used memory [MiB]:{1} {4} {0}Load:{1} {5}'.format(ansiiprint.bold(), ansiiprint.end(), self.domains_count, self.memfree, self.memused, self.cpuload), '', 'c')
|
||||||
|
|
||||||
# Update our local node lists
|
# Update our local node lists
|
||||||
for node_name in self.t_node:
|
for node_name in self.t_node:
|
||||||
|
|
32
pvc.py
32
pvc.py
|
@ -127,18 +127,21 @@ def ready_host(node_name):
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@click.command(name='info', short_help='Show details of a node object')
|
@click.command(name='info', short_help='Show details of a node object')
|
||||||
@click.option(
|
@click.option(
|
||||||
'-n', '--name', 'dom_name',
|
'-n', '--name', 'node_name',
|
||||||
help='Search for this name.'
|
help='Search for this name.'
|
||||||
)
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
'-l', '--long', 'long_output', is_flag=True, default=False,
|
'-l', '--long', 'long_output', is_flag=True, default=False,
|
||||||
help='Display more detailed information.'
|
help='Display more detailed information.'
|
||||||
)
|
)
|
||||||
def node_info(dom_name, dom_uuid, long_output):
|
def node_info(node_name, long_output):
|
||||||
"""
|
"""
|
||||||
Search the cluster for a node's information.
|
Search the cluster for a node's information.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# Open a Zookeeper connection
|
||||||
|
zk = pvcf.startZKConnection(zk_host)
|
||||||
|
|
||||||
# Verify node is valid
|
# Verify node is valid
|
||||||
try:
|
try:
|
||||||
zk.get('/nodes/{}'.format(node_name))
|
zk.get('/nodes/{}'.format(node_name))
|
||||||
|
@ -146,7 +149,24 @@ def node_info(dom_name, dom_uuid, long_output):
|
||||||
click.echo('ERROR: No node named {} is present in the cluster.'.format(node_name))
|
click.echo('ERROR: No node named {} is present in the cluster.'.format(node_name))
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
pass
|
# Get information about node in a pretty format
|
||||||
|
information = pvcf.getInformationFromNode(zk, node_name, long_output)
|
||||||
|
|
||||||
|
if information == None:
|
||||||
|
click.echo('ERROR: Could not find a domain matching that name or UUID.')
|
||||||
|
return
|
||||||
|
|
||||||
|
click.echo(information)
|
||||||
|
|
||||||
|
if long_output == True:
|
||||||
|
click.echo('')
|
||||||
|
click.echo('{}Virtual machines on node:{}'.format(ansiiprint.bold(), ansiiprint.end()))
|
||||||
|
click.echo('')
|
||||||
|
# List all VMs on this node
|
||||||
|
_vm_list(node_name)
|
||||||
|
|
||||||
|
# Close the Zookeeper connection
|
||||||
|
pvcf.stopZKConnection(zk)
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
@ -178,7 +198,7 @@ def node_list():
|
||||||
for node_name in node_list:
|
for node_name in node_list:
|
||||||
node_daemon_state[node_name] = zk.get('/nodes/{}/daemonstate'.format(node_name))[0].decode('ascii')
|
node_daemon_state[node_name] = zk.get('/nodes/{}/daemonstate'.format(node_name))[0].decode('ascii')
|
||||||
node_domain_state[node_name] = zk.get('/nodes/{}/domainstate'.format(node_name))[0].decode('ascii')
|
node_domain_state[node_name] = zk.get('/nodes/{}/domainstate'.format(node_name))[0].decode('ascii')
|
||||||
node_cpu_count[node_name] = zk.get('/nodes/{}/cpucount'.format(node_name))[0].decode('ascii')
|
node_cpu_count[node_name] = zk.get('/nodes/{}/staticdata'.format(node_name))[0].decode('ascii').split()[0]
|
||||||
node_mem_used[node_name] = zk.get('/nodes/{}/memused'.format(node_name))[0].decode('ascii')
|
node_mem_used[node_name] = zk.get('/nodes/{}/memused'.format(node_name))[0].decode('ascii')
|
||||||
node_mem_free[node_name] = zk.get('/nodes/{}/memfree'.format(node_name))[0].decode('ascii')
|
node_mem_free[node_name] = zk.get('/nodes/{}/memfree'.format(node_name))[0].decode('ascii')
|
||||||
node_mem_total[node_name] = int(node_mem_used[node_name]) + int(node_mem_free[node_name])
|
node_mem_total[node_name] = int(node_mem_used[node_name]) + int(node_mem_free[node_name])
|
||||||
|
@ -836,6 +856,10 @@ def vm_info(dom_name, dom_uuid, long_output):
|
||||||
help='Limit list to this hypervisor.'
|
help='Limit list to this hypervisor.'
|
||||||
)
|
)
|
||||||
def vm_list(hypervisor):
|
def vm_list(hypervisor):
|
||||||
|
vm_list(hypervisor)
|
||||||
|
|
||||||
|
# Wrapped function to allow calling from `node info`
|
||||||
|
def _vm_list(hypervisor):
|
||||||
"""
|
"""
|
||||||
List all virtual machines in the cluster.
|
List all virtual machines in the cluster.
|
||||||
"""
|
"""
|
||||||
|
|
31
pvcd.py
31
pvcd.py
|
@ -112,7 +112,6 @@ def zk_listener(state):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
zk.add_listener(zk_listener)
|
zk.add_listener(zk_listener)
|
||||||
zk.set('/nodes/{}/daemonstate'.format(myhostname), 'init'.encode('ascii'))
|
|
||||||
|
|
||||||
def cleanup():
|
def cleanup():
|
||||||
try:
|
try:
|
||||||
|
@ -125,12 +124,28 @@ def cleanup():
|
||||||
|
|
||||||
atexit.register(cleanup)
|
atexit.register(cleanup)
|
||||||
|
|
||||||
|
# Gather useful data about our host for staticdata
|
||||||
|
# Static data format: 'cpu_count', 'arch', 'os', 'kernel'
|
||||||
|
staticdata = []
|
||||||
|
staticdata.append(str(psutil.cpu_count()))
|
||||||
|
staticdata.append(subprocess.run(['uname', '-r'], stdout=subprocess.PIPE).stdout.decode('ascii').strip())
|
||||||
|
staticdata.append(subprocess.run(['uname', '-o'], stdout=subprocess.PIPE).stdout.decode('ascii').strip())
|
||||||
|
staticdata.append(subprocess.run(['uname', '-m'], stdout=subprocess.PIPE).stdout.decode('ascii').strip())
|
||||||
|
# Print static data on start
|
||||||
|
|
||||||
print('{0}Node hostname:{1} {2}'.format(ansiiprint.bold(), ansiiprint.end(), myhostname))
|
print('{0}Node hostname:{1} {2}'.format(ansiiprint.bold(), ansiiprint.end(), myhostname))
|
||||||
print('{0}IPMI hostname:{1} {2}'.format(ansiiprint.bold(), ansiiprint.end(), config['ipmi_hostname']))
|
print('{0}IPMI hostname:{1} {2}'.format(ansiiprint.bold(), ansiiprint.end(), config['ipmi_hostname']))
|
||||||
|
print('{0}Machine details:{1}'.format(ansiiprint.bold(), ansiiprint.end()))
|
||||||
|
print(' {0}CPUs:{1} {2}'.format(ansiiprint.bold(), ansiiprint.end(), staticdata[0]))
|
||||||
|
print(' {0}Arch:{1} {2}'.format(ansiiprint.bold(), ansiiprint.end(), staticdata[1]))
|
||||||
|
print(' {0}OS:{1} {2}'.format(ansiiprint.bold(), ansiiprint.end(), staticdata[2]))
|
||||||
|
print(' {0}Kernel:{1} {2}'.format(ansiiprint.bold(), ansiiprint.end(), staticdata[3]))
|
||||||
|
|
||||||
# Check if our node exists in Zookeeper, and create it if not
|
# Check if our node exists in Zookeeper, and create it if not
|
||||||
if zk.exists('/nodes/{}'.format(myhostname)):
|
if zk.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
|
||||||
|
zk.set('/nodes/{}/staticdata'.format(myhostname), ' '.join(staticdata).encode('ascii'))
|
||||||
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())
|
||||||
|
@ -138,8 +153,7 @@ else:
|
||||||
# Basic state information
|
# Basic state information
|
||||||
zk.create('/nodes/{}/daemonstate'.format(myhostname), 'stop'.encode('ascii'))
|
zk.create('/nodes/{}/daemonstate'.format(myhostname), 'stop'.encode('ascii'))
|
||||||
zk.create('/nodes/{}/domainstate'.format(myhostname), 'ready'.encode('ascii'))
|
zk.create('/nodes/{}/domainstate'.format(myhostname), 'ready'.encode('ascii'))
|
||||||
zk.create('/nodes/{}/cpucount'.format(myhostname), '0'.encode('ascii'))
|
zk.create('/nodes/{}/staticdata'.format(myhostname), ' '.join(staticdata).encode('ascii'))
|
||||||
zk.create('/nodes/{}/staticdata'.format(myhostname), ''.encode('ascii'))
|
|
||||||
zk.create('/nodes/{}/memfree'.format(myhostname), '0'.encode('ascii'))
|
zk.create('/nodes/{}/memfree'.format(myhostname), '0'.encode('ascii'))
|
||||||
zk.create('/nodes/{}/memused'.format(myhostname), '0'.encode('ascii'))
|
zk.create('/nodes/{}/memused'.format(myhostname), '0'.encode('ascii'))
|
||||||
zk.create('/nodes/{}/cpuload'.format(myhostname), '0.0'.encode('ascii'))
|
zk.create('/nodes/{}/cpuload'.format(myhostname), '0.0'.encode('ascii'))
|
||||||
|
@ -151,16 +165,7 @@ else:
|
||||||
zk.create('/nodes/{}/ipmiusername'.format(myhostname), config['ipmi_username'].encode('ascii'))
|
zk.create('/nodes/{}/ipmiusername'.format(myhostname), config['ipmi_username'].encode('ascii'))
|
||||||
zk.create('/nodes/{}/ipmipassword'.format(myhostname), config['ipmi_password'].encode('ascii'))
|
zk.create('/nodes/{}/ipmipassword'.format(myhostname), config['ipmi_password'].encode('ascii'))
|
||||||
|
|
||||||
|
zk.set('/nodes/{}/daemonstate'.format(myhostname), 'init'.encode('ascii'))
|
||||||
# Gather useful data about our host for staticdata
|
|
||||||
# Static data format: 'cpu_count', 'arch', 'kernel', 'os'
|
|
||||||
staticdata = []
|
|
||||||
staticdata.append(str(psutil.cpu_count()))
|
|
||||||
staticdata.append(subprocess.run(['uname', '-r'], stdout=subprocess.PIPE).stdout.decode('ascii').strip())
|
|
||||||
staticdata.append(subprocess.run(['uname', '-m'], stdout=subprocess.PIPE).stdout.decode('ascii').strip())
|
|
||||||
staticdata.append(subprocess.run(['uname', '-o'], stdout=subprocess.PIPE).stdout.decode('ascii').strip())
|
|
||||||
|
|
||||||
zk.set('/nodes/{}/staticdata'.format(myhostname), ' '.join(staticdata).encode('ascii'))
|
|
||||||
|
|
||||||
t_node = dict()
|
t_node = dict()
|
||||||
s_domain = dict()
|
s_domain = dict()
|
||||||
|
|
62
pvcf.py
62
pvcf.py
|
@ -146,7 +146,67 @@ def getDomainXML(zk, dom_uuid):
|
||||||
parsed_xml = lxml.objectify.fromstring(xml)
|
parsed_xml = lxml.objectify.fromstring(xml)
|
||||||
return parsed_xml
|
return parsed_xml
|
||||||
|
|
||||||
# Root function
|
# Root functions
|
||||||
|
def getInformationFromNode(zk, node_name, long_output):
|
||||||
|
node_daemon_state = zk.get('/nodes/{}/daemonstate'.format(node_name))[0].decode('ascii')
|
||||||
|
node_domain_state = zk.get('/nodes/{}/domainstate'.format(node_name))[0].decode('ascii')
|
||||||
|
node_cpu_count = zk.get('/nodes/{}/staticdata'.format(node_name))[0].decode('ascii').split()[0]
|
||||||
|
node_arch = zk.get('/nodes/{}/staticdata'.format(node_name))[0].decode('ascii').split()[1]
|
||||||
|
node_os = zk.get('/nodes/{}/staticdata'.format(node_name))[0].decode('ascii').split()[2]
|
||||||
|
node_kernel = zk.get('/nodes/{}/staticdata'.format(node_name))[0].decode('ascii').split()[3]
|
||||||
|
node_mem_used = zk.get('/nodes/{}/memused'.format(node_name))[0].decode('ascii')
|
||||||
|
node_mem_free = zk.get('/nodes/{}/memfree'.format(node_name))[0].decode('ascii')
|
||||||
|
node_mem_total = int(node_mem_used) + int(node_mem_free)
|
||||||
|
node_domains_count = zk.get('/nodes/{}/domainscount'.format(node_name))[0].decode('ascii')
|
||||||
|
node_running_domains = zk.get('/nodes/{}/runningdomains'.format(node_name))[0].decode('ascii').split()
|
||||||
|
node_mem_allocated = 0
|
||||||
|
for domain in node_running_domains:
|
||||||
|
parsed_xml = pvcf.getDomainXML(zk, domain)
|
||||||
|
duuid, dname, dmemory, dvcpu, dvcputopo = pvcf.getDomainMainDetails(parsed_xml)
|
||||||
|
node_mem_allocated += int(dmemory)
|
||||||
|
|
||||||
|
if node_daemon_state == 'run':
|
||||||
|
daemon_state_colour = ansiiprint.green()
|
||||||
|
elif node_daemon_state == 'stop':
|
||||||
|
daemon_state_colour = ansiiprint.red()
|
||||||
|
elif node_daemon_state == 'init':
|
||||||
|
daemon_state_colour = ansiiprint.yellow()
|
||||||
|
elif node_daemon_state == 'dead':
|
||||||
|
daemon_state_colour = ansiiprint.red() + ansiiprint.bold()
|
||||||
|
else:
|
||||||
|
daemon_state_colour = ansiiprint.blue()
|
||||||
|
|
||||||
|
if node_domain_state == 'ready':
|
||||||
|
domain_state_colour = ansiiprint.green()
|
||||||
|
else:
|
||||||
|
domain_state_colour = ansiiprint.blue()
|
||||||
|
|
||||||
|
# Format a nice output; do this line-by-line then concat the elements at the end
|
||||||
|
ainformation = []
|
||||||
|
ainformation.append('{}Hypervisor Node information:{}'.format(ansiiprint.bold(), ansiiprint.end()))
|
||||||
|
ainformation.append('')
|
||||||
|
# Basic information
|
||||||
|
ainformation.append('{}Name:{} {}'.format(ansiiprint.purple(), ansiiprint.end(), node_name))
|
||||||
|
ainformation.append('{}Daemon State:{} {}{}{}'.format(ansiiprint.purple(), ansiiprint.end(), daemon_state_colour, node_daemon_state, ansiiprint.end()))
|
||||||
|
ainformation.append('{}Domain State:{} {}{}{}'.format(ansiiprint.purple(), ansiiprint.end(), domain_state_colour, node_domain_state, ansiiprint.end()))
|
||||||
|
ainformation.append('{}Active Domain Count:{} {}'.format(ansiiprint.purple(), ansiiprint.end(), node_domains_count))
|
||||||
|
if long_output == True:
|
||||||
|
ainformation.append('')
|
||||||
|
ainformation.append('{}Architecture:{} {}'.format(ansiiprint.purple(), ansiiprint.end(), node_arch))
|
||||||
|
ainformation.append('{}Operating System:{} {}'.format(ansiiprint.purple(), ansiiprint.end(), node_os))
|
||||||
|
ainformation.append('{}Kernel Version:{} {}'.format(ansiiprint.purple(), ansiiprint.end(), node_kernel))
|
||||||
|
ainformation.append('')
|
||||||
|
ainformation.append('{}CPUs:{} {}'.format(ansiiprint.purple(), ansiiprint.end(), node_cpu_count))
|
||||||
|
ainformation.append('{}Total RAM (MiB):{} {}'.format(ansiiprint.purple(), ansiiprint.end(), node_mem_total))
|
||||||
|
ainformation.append('{}Used RAM (MiB):{} {}'.format(ansiiprint.purple(), ansiiprint.end(), node_mem_used))
|
||||||
|
ainformation.append('{}Free RAM (MiB):{} {}'.format(ansiiprint.purple(), ansiiprint.end(), node_mem_free))
|
||||||
|
ainformation.append('{}Allocated RAM (MiB):{} {}'.format(ansiiprint.purple(), ansiiprint.end(), node_mem_allocated))
|
||||||
|
|
||||||
|
# Join it all together
|
||||||
|
information = '\n'.join(ainformation)
|
||||||
|
return information
|
||||||
|
|
||||||
|
|
||||||
def getInformationFromXML(zk, uuid, long_output):
|
def getInformationFromXML(zk, uuid, long_output):
|
||||||
# Obtain the contents of the XML from Zookeeper
|
# Obtain the contents of the XML from Zookeeper
|
||||||
try:
|
try:
|
||||||
|
|
Loading…
Reference in New Issue