Major usability tweaks to client; use arguments instead of options for the main argument of each command and remove mutual exclusivity options

This commit is contained in:
Joshua Boniface 2018-06-16 22:22:07 -04:00
parent 23f5434159
commit 4881a93758
1 changed files with 164 additions and 333 deletions

497
pvc.py
View File

@ -345,47 +345,6 @@ def searchClusterByName(zk, name):
return uuid return uuid
#
# Allow mutually exclusive options in Click
#
class MutuallyExclusiveOption(click.Option):
def __init__(self, *args, **kwargs):
meargs = kwargs.pop('mutually_exclusive', [])
_me_arg = []
_me_func = []
for arg in meargs:
_me_arg.append(arg['argument'])
_me_func.append(arg['function'])
self.me_arg = set(_me_arg)
self.me_func = set(_me_func)
help = kwargs.get('help', '')
if self.me_func:
ex_str = ', '.join(self.me_arg)
kwargs['help'] = help + (
' Mutually exclusive with `' + ex_str + '`.'
)
super(MutuallyExclusiveOption, self).__init__(*args, **kwargs)
def handle_parse_result(self, ctx, opts, args):
if self.me_func.intersection(opts) and self.name in opts:
raise click.UsageError(
"Illegal usage: `{}` is mutually exclusive with "
"arguments `{}`.".format(
self.opts[-1],
', '.join(self.me_arg)
)
)
return super(MutuallyExclusiveOption, self).handle_parse_result(
ctx,
opts,
args
)
######################## ########################
######################## ########################
## ## ## ##
@ -414,17 +373,12 @@ def node():
# pvc node flush # pvc node flush
############################################################################### ###############################################################################
@click.command(name='flush', short_help='Take a node out of service') @click.command(name='flush', short_help='Take a node out of service')
@click.option( @click.argument(
'-n', '--name', 'node_name', default=myhostname, show_default=True, 'node', default=myhostname
help='The PVC node to operate on.'
) )
def flush_host(node_name): def flush_host(node):
""" """
Take a node out of active service and migrate away all VMs. Take NODE out of active service and migrate away all VMs. If unspecified, defaults to this host.
Notes:
* The '--name' option defaults to the current host if not set, which is likely not what you want when running this command from a remote host!
""" """
# Open a Zookeeper connection # Open a Zookeeper connection
@ -432,16 +386,16 @@ def flush_host(node_name):
# Verify node is valid # Verify node is valid
try: try:
zk.get('/nodes/{}'.format(node_name)) zk.get('/nodes/{}'.format(node))
except: except:
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))
exit(1) exit(1)
click.echo('Flushing hypervisor {} of running VMs.'.format(node_name)) click.echo('Flushing hypervisor {} of running VMs.'.format(node))
# Add the new domain to Zookeeper # Add the new domain to Zookeeper
transaction = zk.transaction() transaction = zk.transaction()
transaction.set_data('/nodes/{}/domainstate'.format(node_name), 'flush'.encode('ascii')) transaction.set_data('/nodes/{}/domainstate'.format(node), 'flush'.encode('ascii'))
results = transaction.commit() results = transaction.commit()
# Close the Zookeeper connection # Close the Zookeeper connection
@ -452,17 +406,12 @@ def flush_host(node_name):
# pvc node ready # pvc node ready
############################################################################### ###############################################################################
@click.command(name='ready', short_help='Restore node to service') @click.command(name='ready', short_help='Restore node to service')
@click.option( @click.argument(
'-n', '--name', 'node_name', default=myhostname, show_default=True, 'node', default=myhostname
help='The PVC node to operate on.'
) )
def ready_host(node_name): def ready_host(node):
""" """
Restore a host to active service and migrate back all VMs. Restore NODE to active service and migrate back all VMs. If unspecified, defaults to this host.
Notes:
* The '--name' option defaults to the current host if not set, which is likely not what you want when running this command from a remote host!
""" """
# Open a Zookeeper connection # Open a Zookeeper connection
@ -470,16 +419,16 @@ def ready_host(node_name):
# Verify node is valid # Verify node is valid
try: try:
zk.get('/nodes/{}'.format(node_name)) zk.get('/nodes/{}'.format(node))
except: except:
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))
exit(1) exit(1)
click.echo('Restoring hypervisor {} to active service.'.format(node_name)) click.echo('Restoring hypervisor {} to active service.'.format(node))
# Add the new domain to Zookeeper # Add the new domain to Zookeeper
transaction = zk.transaction() transaction = zk.transaction()
transaction.set_data('/nodes/{}/domainstate'.format(node_name), 'unflush'.encode('ascii')) transaction.set_data('/nodes/{}/domainstate'.format(node), 'unflush'.encode('ascii'))
results = transaction.commit() results = transaction.commit()
# Close the Zookeeper connection # Close the Zookeeper connection
@ -490,17 +439,16 @@ def ready_host(node_name):
# pvc node info # pvc node info
############################################################################### ###############################################################################
@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.argument(
'-n', '--name', 'node_name', 'node', default=myhostname
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(node_name, long_output): def node_info(node, long_output):
""" """
Search the cluster for a node's information. Show information about node NODE. If unspecified, defaults to this host.
""" """
# Open a Zookeeper connection # Open a Zookeeper connection
@ -508,16 +456,16 @@ def node_info(node_name, long_output):
# Verify node is valid # Verify node is valid
try: try:
zk.get('/nodes/{}'.format(node_name)) zk.get('/nodes/{}'.format(node))
except: except:
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))
exit(1) exit(1)
# Get information about node in a pretty format # Get information about node in a pretty format
information = getInformationFromNode(zk, node_name, long_output) information = getInformationFromNode(zk, node, long_output)
if information == None: if information == None:
click.echo('ERROR: Could not find a domain matching that name or UUID.') click.echo('ERROR: Could not find a node matching that name.')
return return
click.echo(information) click.echo(information)
@ -527,7 +475,7 @@ def node_info(node_name, long_output):
click.echo('{}Virtual machines on node:{}'.format(ansiiprint.bold(), ansiiprint.end())) click.echo('{}Virtual machines on node:{}'.format(ansiiprint.bold(), ansiiprint.end()))
click.echo('') click.echo('')
# List all VMs on this node # List all VMs on this node
_vm_list(node_name) get_vm_list(node)
# Close the Zookeeper connection # Close the Zookeeper connection
stopZKConnection(zk) stopZKConnection(zk)
@ -669,27 +617,21 @@ def vm():
# pvc vm define # pvc vm define
############################################################################### ###############################################################################
@click.command(name='define', short_help='Define a new virtual machine from a Libvirt XML file.') @click.command(name='define', short_help='Define a new virtual machine from a Libvirt XML file.')
@click.option(
'-x', '--xml', 'xml_config_file',
help='The XML config file to define the domain from.'
)
@click.option( @click.option(
'-t', '--hypervisor', 'target_hypervisor', default=myhostname, show_default=True, '-t', '--hypervisor', 'target_hypervisor', default=myhostname, show_default=True,
help='The home hypervisor for this domain.' help='The home hypervisor for this domain.'
) )
def define_vm(xml_config_file, target_hypervisor): @click.argument(
'config', type=click.File()
)
def define_vm(config, target_hypervisor):
""" """
Define a new virtual machine from a Libvirt XML configuration file. Define a new virtual machine from Libvirt XML configuration file CONFIG.
Notes:
* The '--hypervisor' option defaults to the current host if not set, which is likely not what you want when running this command from a remote host!
""" """
# Open the XML file # Open the XML file
with open(xml_config_file, 'r') as f_domxmlfile: data = config.read()
data = f_domxmlfile.read() config.close()
f_domxmlfile.close()
# Parse the XML data # Parse the XML data
parsed_xml = lxml.objectify.fromstring(data) parsed_xml = lxml.objectify.fromstring(data)
@ -717,42 +659,33 @@ def define_vm(xml_config_file, target_hypervisor):
# pvc vm undefine # pvc vm undefine
############################################################################### ###############################################################################
@click.command(name='undefine', short_help='Undefine and stop a virtual machine.') @click.command(name='undefine', short_help='Undefine and stop a virtual machine.')
@click.option( @click.argument(
'-n', '--name', 'dom_name', 'domain'
cls=MutuallyExclusiveOption,
mutually_exclusive=[{ 'function': 'dom_uuid', 'argument': '--uuid' }],
help='Search for this human-readable name.'
) )
@click.option( def undefine_vm(domain):
'-u', '--uuid', 'dom_uuid',
cls=MutuallyExclusiveOption,
mutually_exclusive=[{ 'function': 'dom_name', 'argument': '--name' }],
help='Search for this UUID.'
)
def undefine_vm(dom_name, dom_uuid):
""" """
Stop a virtual machine and remove it from the cluster database. Stop virtual machine DOMAIN and remove it from the cluster database. DOMAIN may be a UUID or name.
""" """
# Ensure at least one search method is set # Ensure at least one search method is set
if dom_name == None and dom_uuid == None: if domain == None:
click.echo("ERROR: You must specify either a `--name` or `--uuid` value.") click.echo("ERROR: You must specify either a name or UUID value.")
return return
# Open a Zookeeper connection # Open a Zookeeper connection
zk = startZKConnection(zk_host) zk = startZKConnection(zk_host)
# If the --name value was passed, get the UUID # Validate and obtain alternate passed value
if dom_name != None: if validateUUID(domain):
dom_name = searchClusterByUUID(zk, domain)
dom_uuid = searchClusterByName(zk, dom_name) dom_uuid = searchClusterByName(zk, dom_name)
else:
dom_uuid = searchClusterByName(zk, domain)
dom_name = searchClusterByUUID(zk, dom_uuid)
# Verify we got a result or abort if dom_uuid == None:
if not validateUUID(dom_uuid): click.echo('ERROR: Could not find VM "{}" in the cluster!'.format(domain))
if dom_name != None: stopZKConnection(zk)
message_name = dom_name
else:
message_name = dom_uuid
click.echo('ERROR: Could not find VM "{}" in the cluster!'.format(message_name))
return return
current_vm_state = zk.get('/domains/{}/state'.format(dom_uuid))[0].decode('ascii') current_vm_state = zk.get('/domains/{}/state'.format(dom_uuid))[0].decode('ascii')
@ -768,6 +701,7 @@ def undefine_vm(dom_name, dom_uuid):
time.sleep(1) time.sleep(1)
# Gracefully terminate the class instances # Gracefully terminate the class instances
click.echo('Deleting VM "{}" from nodes.'.format(dom_uuid))
zk.set('/domains/{}/state'.format(dom_uuid), 'delete'.encode('ascii')) zk.set('/domains/{}/state'.format(dom_uuid), 'delete'.encode('ascii'))
time.sleep(5) time.sleep(5)
# Delete the configurations # Delete the configurations
@ -788,42 +722,28 @@ def undefine_vm(dom_name, dom_uuid):
# pvc vm start # pvc vm start
############################################################################### ###############################################################################
@click.command(name='start', short_help='Start up a defined virtual machine.') @click.command(name='start', short_help='Start up a defined virtual machine.')
@click.option( @click.argument(
'-n', '--name', 'dom_name', 'domain'
cls=MutuallyExclusiveOption,
mutually_exclusive=[{ 'function': 'dom_uuid', 'argument': '--uuid' }],
help='Search for this human-readable name.'
) )
@click.option( def start_vm(domain):
'-u', '--uuid', 'dom_uuid',
cls=MutuallyExclusiveOption,
mutually_exclusive=[{ 'function': 'dom_name', 'argument': '--name' }],
help='Search for this UUID.'
)
def start_vm(dom_name, dom_uuid):
""" """
Start up a virtual machine on its configured hypervisor. Start virtual machine DOMAIN on its configured hypervisor. DOMAIN may be a UUID or name.
""" """
# Ensure at least one search method is set
if dom_name == None and dom_uuid == None:
click.echo("ERROR: You must specify either a `--name` or `--uuid` value.")
return
# Open a Zookeeper connection # Open a Zookeeper connection
zk = startZKConnection(zk_host) zk = startZKConnection(zk_host)
# If the --name value was passed, get the UUID # Validate and obtain alternate passed value
if dom_name != None: if validateUUID(domain):
dom_name = searchClusterByUUID(zk, domain)
dom_uuid = searchClusterByName(zk, dom_name) dom_uuid = searchClusterByName(zk, dom_name)
else:
dom_uuid = searchClusterByName(zk, domain)
dom_name = searchClusterByUUID(zk, dom_uuid)
# Verify we got a result or abort if dom_uuid == None:
if not validateUUID(dom_uuid): click.echo('ERROR: Could not find VM "{}" in the cluster!'.format(domain))
if dom_name != None: stopZKConnection(zk)
message_name = dom_name
else:
message_name = dom_uuid
click.echo('ERROR: Could not find VM "{}" in the cluster!'.format(message_name))
return return
# Set the VM to start # Set the VM to start
@ -838,42 +758,28 @@ def start_vm(dom_name, dom_uuid):
# pvc vm restart # pvc vm restart
############################################################################### ###############################################################################
@click.command(name='restart', short_help='Restart virtual machine.') @click.command(name='restart', short_help='Restart virtual machine.')
@click.option( @click.argument(
'-n', '--name', 'dom_name', 'domain'
cls=MutuallyExclusiveOption,
mutually_exclusive=[{ 'function': 'dom_uuid', 'argument': '--uuid' }],
help='Search for this human-readable name.'
)
@click.option(
'-u', '--uuid', 'dom_uuid',
cls=MutuallyExclusiveOption,
mutually_exclusive=[{ 'function': 'dom_name', 'argument': '--name' }],
help='Search for this UUID.'
) )
def restart_vm(dom_name, dom_uuid): def restart_vm(dom_name, dom_uuid):
""" """
Restart a virtual machine on its configured hypervisor. Restart a virtual machine on its configured hypervisor.
""" """
# Ensure at least one search method is set
if dom_name == None and dom_uuid == None:
click.echo("ERROR: You must specify either a `--name` or `--uuid` value.")
return
# Open a Zookeeper connection # Open a Zookeeper connection
zk = startZKConnection(zk_host) zk = startZKConnection(zk_host)
# If the --name value was passed, get the UUID # Validate and obtain alternate passed value
if dom_name != None: if validateUUID(domain):
dom_name = searchClusterByUUID(zk, domain)
dom_uuid = searchClusterByName(zk, dom_name) dom_uuid = searchClusterByName(zk, dom_name)
else:
dom_uuid = searchClusterByName(zk, domain)
dom_name = searchClusterByUUID(zk, dom_uuid)
# Verify we got a result or abort if dom_uuid == None:
if not validateUUID(dom_uuid): click.echo('ERROR: Could not find VM "{}" in the cluster!'.format(domain))
if dom_name != None: stopZKConnection(zk)
message_name = dom_name
else:
message_name = dom_uuid
click.echo('ERROR: Could not find VM "{}" in the cluster!'.format(message_name))
return return
# Get state and verify we're OK to proceed # Get state and verify we're OK to proceed
@ -894,42 +800,28 @@ def restart_vm(dom_name, dom_uuid):
# pvc vm shutdown # pvc vm shutdown
############################################################################### ###############################################################################
@click.command(name='shutdown', short_help='Gracefully shut down a running virtual machine.') @click.command(name='shutdown', short_help='Gracefully shut down a running virtual machine.')
@click.option( @click.argument(
'-n', '--name', 'dom_name', 'domain'
cls=MutuallyExclusiveOption,
mutually_exclusive=[{ 'function': 'dom_uuid', 'argument': '--uuid' }],
help='Search for this human-readable name.'
) )
@click.option( def shutdown_vm(domain):
'-u', '--uuid', 'dom_uuid',
cls=MutuallyExclusiveOption,
mutually_exclusive=[{ 'function': 'dom_name', 'argument': '--name' }],
help='Search for this UUID.'
)
def shutdown_vm(dom_name, dom_uuid):
""" """
Gracefully shut down a running virtual machine. Gracefully shut down virtual machine DOMAIN. DOMAIN may be a UUID or name.
""" """
# Ensure at least one search method is set
if dom_name == None and dom_uuid == None:
click.echo("ERROR: You must specify either a `--name` or `--uuid` value.")
return
# Open a Zookeeper connection # Open a Zookeeper connection
zk = startZKConnection(zk_host) zk = startZKConnection(zk_host)
# If the --name value was passed, get the UUID # Validate and obtain alternate passed value
if dom_name != None: if validateUUID(domain):
dom_name = searchClusterByUUID(zk, domain)
dom_uuid = searchClusterByName(zk, dom_name) dom_uuid = searchClusterByName(zk, dom_name)
else:
dom_uuid = searchClusterByName(zk, domain)
dom_name = searchClusterByUUID(zk, dom_uuid)
# Verify we got a result or abort if dom_uuid == None:
if not validateUUID(dom_uuid): click.echo('ERROR: Could not find VM "{}" in the cluster!'.format(domain))
if dom_name != None: stopZKConnection(zk)
message_name = dom_name
else:
message_name = dom_uuid
click.echo('ERROR: Could not find VM "{}" in the cluster!'.format(message_name))
return return
# Get state and verify we're OK to proceed # Get state and verify we're OK to proceed
@ -950,42 +842,28 @@ def shutdown_vm(dom_name, dom_uuid):
# pvc vm stop # pvc vm stop
############################################################################### ###############################################################################
@click.command(name='stop', short_help='Forcibly halt a running virtual machine.') @click.command(name='stop', short_help='Forcibly halt a running virtual machine.')
@click.option( @click.argument(
'-n', '--name', 'dom_name', 'domain'
cls=MutuallyExclusiveOption,
mutually_exclusive=[{ 'function': 'dom_uuid', 'argument': '--uuid' }],
help='Search for this human-readable name.'
) )
@click.option( def stop_vm(domain):
'-u', '--uuid', 'dom_uuid',
cls=MutuallyExclusiveOption,
mutually_exclusive=[{ 'function': 'dom_name', 'argument': '--name' }],
help='Search for this UUID.'
)
def stop_vm(dom_name, dom_uuid):
""" """
Forcibly halt (destroy) a running virtual machine. Forcibly halt (destroy) running virtual machine DOMAIN. DOMAIN may be a UUID or name.
""" """
# Ensure at least one search method is set
if dom_name == None and dom_uuid == None:
click.echo("ERROR: You must specify either a `--name` or `--uuid` value.")
return
# Open a Zookeeper connection # Open a Zookeeper connection
zk = startZKConnection(zk_host) zk = startZKConnection(zk_host)
# If the --name value was passed, get the UUID # Validate and obtain alternate passed value
if dom_name != None: if validateUUID(domain):
dom_name = searchClusterByUUID(zk, domain)
dom_uuid = searchClusterByName(zk, dom_name) dom_uuid = searchClusterByName(zk, dom_name)
else:
dom_uuid = searchClusterByName(zk, domain)
dom_name = searchClusterByUUID(zk, dom_uuid)
# Verify we got a result or abort if dom_uuid == None:
if not validateUUID(dom_uuid): click.echo('ERROR: Could not find VM "{}" in the cluster!'.format(domain))
if dom_name != None: stopZKConnection(zk)
message_name = dom_name
else:
message_name = dom_uuid
click.echo('ERROR: Could not find VM "{}" in the cluster!'.format(message_name))
return return
# Get state and verify we're OK to proceed # Get state and verify we're OK to proceed
@ -1006,46 +884,32 @@ def stop_vm(dom_name, dom_uuid):
# pvc vm move # pvc vm move
############################################################################### ###############################################################################
@click.command(name='move', short_help='Permanently move a virtual machine to another node.') @click.command(name='move', short_help='Permanently move a virtual machine to another node.')
@click.option( @click.argument(
'-n', '--name', 'dom_name', 'domain'
cls=MutuallyExclusiveOption,
mutually_exclusive=[{ 'function': 'dom_uuid', 'argument': '--uuid' }],
help='Search for this human-readable name.'
) )
@click.option( @click.option(
'-u', '--uuid', 'dom_uuid', '-t', '--hypervisor', 'target_hypervisor', default=None,
cls=MutuallyExclusiveOption, help='The target hypervisor to migrate to. Autodetect based on most free RAM if unspecified.'
mutually_exclusive=[{ 'function': 'dom_name', 'argument': '--name' }],
help='Search for this UUID.'
) )
@click.option( def move_vm(domain, target_hypervisor):
'-t', '--target', 'target_hypervisor', default=None,
help='The target hypervisor to migrate to.'
)
def move_vm(dom_name, dom_uuid, target_hypervisor):
""" """
Permanently move a virtual machine, via live migration if running and possible, to another hypervisor node. Permanently move virtual machine DOMAIN, via live migration if running and possible, to another hypervisor node. DOMAIN may be a UUID or name.
""" """
# Ensure at least one search method is set
if dom_name == None and dom_uuid == None:
click.echo("ERROR: You must specify either a `--name` or `--uuid` value.")
return
# Open a Zookeeper connection # Open a Zookeeper connection
zk = startZKConnection(zk_host) zk = startZKConnection(zk_host)
# If the --name value was passed, get the UUID # Validate and obtain alternate passed value
if dom_name != None: if validateUUID(domain):
dom_name = searchClusterByUUID(zk, domain)
dom_uuid = searchClusterByName(zk, dom_name) dom_uuid = searchClusterByName(zk, dom_name)
else:
dom_uuid = searchClusterByName(zk, domain)
dom_name = searchClusterByUUID(zk, dom_uuid)
# Verify we got a result or abort if dom_uuid == None:
if not validateUUID(dom_uuid): click.echo('ERROR: Could not find VM "{}" in the cluster!'.format(domain))
if dom_name != None: stopZKConnection(zk)
message_name = dom_name
else:
message_name = dom_uuid
click.echo('ERROR: Could not find VM "{}" in the cluster!'.format(message_name))
return return
# Get state and verify we're OK to proceed # Get state and verify we're OK to proceed
@ -1061,8 +925,9 @@ def move_vm(dom_name, dom_uuid, target_hypervisor):
hypervisor_list = zk.get_children('/nodes') hypervisor_list = zk.get_children('/nodes')
most_memfree = 0 most_memfree = 0
for hypervisor in hypervisor_list: for hypervisor in hypervisor_list:
state = zk.get('/nodes/{}/state'.format(hypervisor))[0].decode('ascii') daemon_state = zk.get('/nodes/{}/daemonstate'.format(hypervisor))[0].decode('ascii')
if state != 'start' or hypervisor == current_hypervisor: domain_state = zk.get('/nodes/{}/domainstate'.format(hypervisor))[0].decode('ascii')
if daemon_state != 'run' or domain_state != 'ready' or hypervisor == current_hypervisor:
continue continue
memfree = int(zk.get('/nodes/{}/memfree'.format(hypervisor))[0].decode('ascii')) memfree = int(zk.get('/nodes/{}/memfree'.format(hypervisor))[0].decode('ascii'))
@ -1097,50 +962,36 @@ def move_vm(dom_name, dom_uuid, target_hypervisor):
# pvc vm migrate # pvc vm migrate
############################################################################### ###############################################################################
@click.command(name='migrate', short_help='Migrate a virtual machine to another node.') @click.command(name='migrate', short_help='Migrate a virtual machine to another node.')
@click.option( @click.argument(
'-n', '--name', 'dom_name', 'domain'
cls=MutuallyExclusiveOption,
mutually_exclusive=[{ 'function': 'dom_uuid', 'argument': '--uuid' }],
help='Search for this human-readable name.'
) )
@click.option( @click.option(
'-u', '--uuid', 'dom_uuid', '-t', '--hypervisor', 'target_hypervisor', default=None,
cls=MutuallyExclusiveOption, help='The target hypervisor to migrate to. Autodetect based on most free RAM if unspecified.'
mutually_exclusive=[{ 'function': 'dom_name', 'argument': '--name' }],
help='Search for this UUID.'
)
@click.option(
'-t', '--target', 'target_hypervisor', default=None,
help='The target hypervisor to migrate to.'
) )
@click.option( @click.option(
'-f', '--force', 'force_migrate', is_flag=True, default=False, '-f', '--force', 'force_migrate', is_flag=True, default=False,
help='Force migrate an already migrated VM.' help='Force migrate an already migrated VM.'
) )
def migrate_vm(dom_name, dom_uuid, target_hypervisor, force_migrate): def migrate_vm(domain, target_hypervisor, force_migrate):
""" """
Migrate a running virtual machine, via live migration if possible, to another hypervisor node. Migrate running virtual machine DOMAIN, via live migration if possible, to another hypervisor node. DOMAIN may be a UUID or name.
""" """
# Ensure at least one search method is set
if dom_name == None and dom_uuid == None:
click.echo("ERROR: You must specify either a `--name` or `--uuid` value.")
return
# Open a Zookeeper connection # Open a Zookeeper connection
zk = startZKConnection(zk_host) zk = startZKConnection(zk_host)
# If the --name value was passed, get the UUID # Validate and obtain alternate passed value
if dom_name != None: if validateUUID(domain):
dom_name = searchClusterByUUID(zk, domain)
dom_uuid = searchClusterByName(zk, dom_name) dom_uuid = searchClusterByName(zk, dom_name)
else:
dom_uuid = searchClusterByName(zk, domain)
dom_name = searchClusterByUUID(zk, dom_uuid)
# Verify we got a result or abort if dom_uuid == None:
if not validateUUID(dom_uuid): click.echo('ERROR: Could not find VM "{}" in the cluster!'.format(domain))
if dom_name != None: stopZKConnection(zk)
message_name = dom_name
else:
message_name = dom_uuid
click.echo('ERROR: Could not find VM "{}" in the cluster!'.format(message_name))
return return
# Get state and verify we're OK to proceed # Get state and verify we're OK to proceed
@ -1193,42 +1044,28 @@ def migrate_vm(dom_name, dom_uuid, target_hypervisor, force_migrate):
# pvc vm unmigrate # pvc vm unmigrate
############################################################################### ###############################################################################
@click.command(name='unmigrate', short_help='Restore a migrated virtual machine to its original node.') @click.command(name='unmigrate', short_help='Restore a migrated virtual machine to its original node.')
@click.option( @click.argument(
'-n', '--name', 'dom_name', 'domain'
cls=MutuallyExclusiveOption,
mutually_exclusive=[{ 'function': 'dom_uuid', 'argument': '--uuid' }],
help='Search for this human-readable name.'
) )
@click.option( def unmigrate_vm(domain):
'-u', '--uuid', 'dom_uuid',
cls=MutuallyExclusiveOption,
mutually_exclusive=[{ 'function': 'dom_name', 'argument': '--name' }],
help='Search for this UUID.'
)
def unmigrate_vm(dom_name, dom_uuid):
""" """
Restore a previously migrated virtual machine, via live migration if possible, to its original hypervisor node. Restore previously migrated virtual machine DOMAIN, via live migration if possible, to its original hypervisor node. DOMAIN may be a UUID or name.
""" """
# Ensure at least one search method is set
if dom_name == None and dom_uuid == None:
click.echo("ERROR: You must specify either a `--name` or `--uuid` value.")
return
# Open a Zookeeper connection # Open a Zookeeper connection
zk = startZKConnection(zk_host) zk = startZKConnection(zk_host)
# If the --name value was passed, get the UUID # Validate and obtain alternate passed value
if dom_name != None: if validateUUID(domain):
dom_name = searchClusterByUUID(zk, domain)
dom_uuid = searchClusterByName(zk, dom_name) dom_uuid = searchClusterByName(zk, dom_name)
else:
dom_uuid = searchClusterByName(zk, domain)
dom_name = searchClusterByUUID(zk, dom_uuid)
# Verify we got a result or abort if dom_uuid == None:
if not validateUUID(dom_uuid): click.echo('ERROR: Could not find VM "{}" in the cluster!'.format(domain))
if dom_name != None: stopZKConnection(zk)
message_name = dom_name
else:
message_name = dom_uuid
click.echo('ERROR: Could not find VM "{}" in the cluster!'.format(message_name))
return return
# Get state and verify we're OK to proceed # Get state and verify we're OK to proceed
@ -1258,45 +1095,39 @@ def unmigrate_vm(dom_name, dom_uuid):
# pvc vm info # pvc vm info
############################################################################### ###############################################################################
@click.command(name='info', short_help='Show details of a VM object') @click.command(name='info', short_help='Show details of a VM object')
@click.option( @click.argument(
'-n', '--name', 'dom_name', 'domain'
cls=MutuallyExclusiveOption,
mutually_exclusive=[{ 'function': 'dom_uuid', 'argument': '--uuid' }],
help='Search for this human-readable name.'
)
@click.option(
'-u', '--uuid', 'dom_uuid',
cls=MutuallyExclusiveOption,
mutually_exclusive=[{ 'function': 'dom_name', 'argument': '--name' }],
help='Search for this UUID.'
) )
@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 vm_info(dom_name, dom_uuid, long_output): def vm_info(domain, long_output):
""" """
Search the cluster for a virtual machine's information. Show information about virtual machine DOMAIN. DOMAIN may be a UUID or name.
""" """
# Ensure at least one search method is set # Open a Zookeeper connection
if dom_name == None and dom_uuid == None:
click.echo("ERROR: You must specify either a `--name` or `--uuid` value.")
return
zk = startZKConnection(zk_host) zk = startZKConnection(zk_host)
if dom_name != None:
# Validate and obtain alternate passed value
if validateUUID(domain):
dom_name = searchClusterByUUID(zk, domain)
dom_uuid = searchClusterByName(zk, dom_name) dom_uuid = searchClusterByName(zk, dom_name)
if dom_uuid != None: else:
dom_uuid = searchClusterByName(zk, domain)
dom_name = searchClusterByUUID(zk, dom_uuid) dom_name = searchClusterByUUID(zk, dom_uuid)
information = getInformationFromXML(zk, dom_uuid, long_output) if dom_uuid == None:
click.echo('ERROR: Could not find VM "{}" in the cluster!'.format(domain))
if information == None: stopZKConnection(zk)
click.echo('ERROR: Could not find a domain matching that name or UUID.')
return return
# Gather information from XML config and print it
information = getInformationFromXML(zk, dom_uuid, long_output)
click.echo(information) click.echo(information)
# Close the Zookeeper connection
stopZKConnection(zk) stopZKConnection(zk)
@ -1309,10 +1140,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) get_vm_list(hypervisor)
# Wrapped function to allow calling from `node info` # Wrapped function to allow calling from `node info`
def _vm_list(hypervisor): def get_vm_list(hypervisor):
""" """
List all virtual machines in the cluster. List all virtual machines in the cluster.
""" """