parent
eb23488486
commit
f91e210f1a
121
pvc.py
121
pvc.py
|
@ -354,20 +354,27 @@ def verifyNode(zk_conn, node):
|
||||||
click.echo('ERROR: No node named "{}" is present in the cluster.'.format(node))
|
click.echo('ERROR: No node named "{}" is present in the cluster.'.format(node))
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Find a migration target
|
||||||
|
#
|
||||||
def findTargetHypervisor(zk_conn, search_field, dom_uuid):
|
def findTargetHypervisor(zk_conn, search_field, dom_uuid):
|
||||||
if search_field == 'mem':
|
if search_field == 'mem':
|
||||||
return findTargetHypervisorMem(zk_conn, dom_uuid)
|
return findTargetHypervisorMem(zk_conn, dom_uuid)
|
||||||
|
if search_field == 'load':
|
||||||
|
return findTargetHypervisorLoad(zk_conn, dom_uuid)
|
||||||
|
if search_field == 'vcpus':
|
||||||
|
return findTargetHypervisorVCPUs(zk_conn, dom_uuid)
|
||||||
|
if search_field == 'vms':
|
||||||
|
return findTargetHypervisorVMs(zk_conn, dom_uuid)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def findTargetHypervisorMem(zk_conn, dom_uuid):
|
# Get the list of valid target hypervisors
|
||||||
# Find a target node
|
def getHypervisors(zk_conn, dom_uuid):
|
||||||
most_allocfree = 0
|
valid_hypervisor_list = {}
|
||||||
target_hypervisor = None
|
full_hypervisor_list = zkhandler.listchildren(zk_conn, '/nodes')
|
||||||
|
|
||||||
hypervisor_list = zkhandler.listchildren(zk_conn, '/nodes')
|
|
||||||
current_hypervisor = zkhandler.readdata(zk_conn, '/domains/{}/hypervisor'.format(dom_uuid))
|
current_hypervisor = zkhandler.readdata(zk_conn, '/domains/{}/hypervisor'.format(dom_uuid))
|
||||||
|
|
||||||
for hypervisor in hypervisor_list:
|
for hypervisor in full_hypervisor_list:
|
||||||
daemon_state = zkhandler.readdata(zk_conn, '/nodes/{}/daemonstate'.format(hypervisor))
|
daemon_state = zkhandler.readdata(zk_conn, '/nodes/{}/daemonstate'.format(hypervisor))
|
||||||
domain_state = zkhandler.readdata(zk_conn, '/nodes/{}/domainstate'.format(hypervisor))
|
domain_state = zkhandler.readdata(zk_conn, '/nodes/{}/domainstate'.format(hypervisor))
|
||||||
|
|
||||||
|
@ -376,7 +383,18 @@ def findTargetHypervisorMem(zk_conn, dom_uuid):
|
||||||
|
|
||||||
if daemon_state != 'run' or domain_state != 'ready':
|
if daemon_state != 'run' or domain_state != 'ready':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
valid_hypervisor_list.append(hypervisor)
|
||||||
|
|
||||||
|
return full_hypervisor_list
|
||||||
|
|
||||||
|
# via free memory (relative to allocated memory)
|
||||||
|
def findTargetHypervisorMem(zk_conn, dom_uuid):
|
||||||
|
most_allocfree = 0
|
||||||
|
target_hypervisor = None
|
||||||
|
|
||||||
|
hypervisor_list = getHypervisors(zk_conn, dom_uuid)
|
||||||
|
for hypervisor in hypervisor_list:
|
||||||
memalloc = int(zkhandler.readdata(zk_conn, '/nodes/{}/memalloc'.format(hypervisor)))
|
memalloc = int(zkhandler.readdata(zk_conn, '/nodes/{}/memalloc'.format(hypervisor)))
|
||||||
memused = int(zkhandler.readdata(zk_conn, '/nodes/{}/memused'.format(hypervisor)))
|
memused = int(zkhandler.readdata(zk_conn, '/nodes/{}/memused'.format(hypervisor)))
|
||||||
memfree = int(zkhandler.readdata(zk_conn, '/nodes/{}/memfree'.format(hypervisor)))
|
memfree = int(zkhandler.readdata(zk_conn, '/nodes/{}/memfree'.format(hypervisor)))
|
||||||
|
@ -389,6 +407,51 @@ def findTargetHypervisorMem(zk_conn, dom_uuid):
|
||||||
|
|
||||||
return target_hypervisor
|
return target_hypervisor
|
||||||
|
|
||||||
|
# via load average
|
||||||
|
def findTargetHypervisorLoad(zk_conn, dom_uuid):
|
||||||
|
least_load = 9999
|
||||||
|
target_hypervisor = None
|
||||||
|
|
||||||
|
hypervisor_list = getHypervisors(zk_conn, dom_uuid)
|
||||||
|
for hypervisor in hypervisor_list:
|
||||||
|
load = int(zkhandler.readdata(zk_conn, '/nodes/{}/load'.format(hypervisor)))
|
||||||
|
|
||||||
|
if load < least_load:
|
||||||
|
least_load = load
|
||||||
|
target_hypevisor = hypervisor
|
||||||
|
|
||||||
|
return target_hypervisor
|
||||||
|
|
||||||
|
# via total vCPUs
|
||||||
|
def findTargetHypervisorVCPUs(zk_conn, dom_uuid):
|
||||||
|
least_vcpus = 9999
|
||||||
|
target_hypervisor = None
|
||||||
|
|
||||||
|
hypervisor_list = getHypervisors(zk_conn, dom_uuid)
|
||||||
|
for hypervisor in hypervisor_list:
|
||||||
|
vcpus = int(zkhandler.readdata(zk_conn, '/nodes/{}/vcpualloc'.format(hypervisor)))
|
||||||
|
|
||||||
|
if vcpus < least_vcpus:
|
||||||
|
least_vcpus = vcpus
|
||||||
|
target_hypervisor = hypervisor
|
||||||
|
|
||||||
|
return target_hypervisor
|
||||||
|
|
||||||
|
# via total VMs
|
||||||
|
def findTargetHypervisorVMs(zk_conn, dom_uuid):
|
||||||
|
least_vms = 9999
|
||||||
|
target_hypervisor = None
|
||||||
|
|
||||||
|
hypervisor_list = getHypervisors(zk_conn, dom_uuid)
|
||||||
|
for hypervisor in hypervisor_list:
|
||||||
|
vms = int(zkhandler.readdata(zk_conn, '/nodes/{}/domainscount'.format(hypervisor)))
|
||||||
|
|
||||||
|
if vms < least_vms:
|
||||||
|
least_vms = vms
|
||||||
|
target_hypervisor = hypervisor
|
||||||
|
|
||||||
|
return target_hypervisor
|
||||||
|
|
||||||
|
|
||||||
########################
|
########################
|
||||||
########################
|
########################
|
||||||
|
@ -680,13 +743,18 @@ def vm():
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@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(
|
@click.option(
|
||||||
'-t', '--hypervisor', 'target_hypervisor', default=myhostname, show_default=True,
|
'-t', '--hypervisor', 'target_hypervisor',
|
||||||
help='The home hypervisor for this domain.'
|
help='The home hypervisor for this domain; autoselects if unspecified.'
|
||||||
|
)
|
||||||
|
@click.option(
|
||||||
|
'-s', '--selector', 'selector', default='mem',
|
||||||
|
type=click.Choice(['mem','load','vcpus','vms']),
|
||||||
|
help='Method to determine the optimal target hypervisor automatically.'
|
||||||
)
|
)
|
||||||
@click.argument(
|
@click.argument(
|
||||||
'config', type=click.File()
|
'config', type=click.File()
|
||||||
)
|
)
|
||||||
def define_vm(config, target_hypervisor):
|
def define_vm(config, target_hypervisor, selector):
|
||||||
"""
|
"""
|
||||||
Define a new virtual machine from Libvirt XML configuration file CONFIG.
|
Define a new virtual machine from Libvirt XML configuration file CONFIG.
|
||||||
"""
|
"""
|
||||||
|
@ -704,6 +772,9 @@ def define_vm(config, target_hypervisor):
|
||||||
# Open a Zookeeper connection
|
# Open a Zookeeper connection
|
||||||
zk_conn = startZKConnection(zk_host)
|
zk_conn = startZKConnection(zk_host)
|
||||||
|
|
||||||
|
if target_hypervisor == None:
|
||||||
|
target_hypervisor = findTargetHypervisor(zk_conn, selector, dom_uuid)
|
||||||
|
|
||||||
# Verify node is valid
|
# Verify node is valid
|
||||||
verifyNode(zk_conn, target_hypervisor)
|
verifyNode(zk_conn, target_hypervisor)
|
||||||
|
|
||||||
|
@ -956,7 +1027,12 @@ def stop_vm(domain):
|
||||||
'-t', '--hypervisor', 'target_hypervisor', default=None,
|
'-t', '--hypervisor', 'target_hypervisor', default=None,
|
||||||
help='The target hypervisor to migrate to. Autodetect based on most free RAM if unspecified.'
|
help='The target hypervisor to migrate to. Autodetect based on most free RAM if unspecified.'
|
||||||
)
|
)
|
||||||
def move_vm(domain, target_hypervisor):
|
@click.option(
|
||||||
|
'-s', '--selector', 'selector', default='mem',
|
||||||
|
type=click.Choice(['mem','load','vcpus','vms']),
|
||||||
|
help='Method to determine the optimal target hypervisor automatically.'
|
||||||
|
)
|
||||||
|
def move_vm(domain, target_hypervisor, selector):
|
||||||
"""
|
"""
|
||||||
Permanently move virtual machine DOMAIN, via live migration if running and possible, to another hypervisor node. DOMAIN may be a UUID or name.
|
Permanently move virtual machine DOMAIN, via live migration if running and possible, to another hypervisor node. DOMAIN may be a UUID or name.
|
||||||
"""
|
"""
|
||||||
|
@ -980,7 +1056,7 @@ def move_vm(domain, target_hypervisor):
|
||||||
current_hypervisor = zk_conn.get('/domains/{}/hypervisor'.format(dom_uuid))[0].decode('ascii')
|
current_hypervisor = zk_conn.get('/domains/{}/hypervisor'.format(dom_uuid))[0].decode('ascii')
|
||||||
|
|
||||||
if target_hypervisor == None:
|
if target_hypervisor == None:
|
||||||
target_hypervisor = findTargetHypervisor(zk_conn, 'mem', dom_uuid)
|
target_hypervisor = findTargetHypervisor(zk_conn, selector, dom_uuid)
|
||||||
else:
|
else:
|
||||||
if target_hypervisor == current_hypervisor:
|
if target_hypervisor == current_hypervisor:
|
||||||
click.echo('ERROR: The VM "{}" is already running on hypervisor "{}".'.format(dom_uuid, current_hypervisor))
|
click.echo('ERROR: The VM "{}" is already running on hypervisor "{}".'.format(dom_uuid, current_hypervisor))
|
||||||
|
@ -1019,11 +1095,16 @@ def move_vm(domain, target_hypervisor):
|
||||||
'-t', '--hypervisor', 'target_hypervisor', default=None,
|
'-t', '--hypervisor', 'target_hypervisor', default=None,
|
||||||
help='The target hypervisor to migrate to. Autodetect based on most free RAM if unspecified.'
|
help='The target hypervisor to migrate to. Autodetect based on most free RAM if unspecified.'
|
||||||
)
|
)
|
||||||
|
@click.option(
|
||||||
|
'-s', '--selector', 'selector', default='mem',
|
||||||
|
type=click.Choice(['mem','load','vcpus','vms']),
|
||||||
|
help='Method to determine the optimal target hypervisor automatically.'
|
||||||
|
)
|
||||||
@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(domain, target_hypervisor, force_migrate):
|
def migrate_vm(domain, target_hypervisor, selector, force_migrate):
|
||||||
"""
|
"""
|
||||||
Temporarily migrate running virtual machine DOMAIN, via live migration if possible, to another hypervisor node. DOMAIN may be a UUID or name. If DOMAIN is not running, it will be started on the target node.
|
Temporarily migrate running virtual machine DOMAIN, via live migration if possible, to another hypervisor node. DOMAIN may be a UUID or name. If DOMAIN is not running, it will be started on the target node.
|
||||||
"""
|
"""
|
||||||
|
@ -1062,19 +1143,7 @@ def migrate_vm(domain, target_hypervisor, force_migrate):
|
||||||
return
|
return
|
||||||
|
|
||||||
if target_hypervisor == None:
|
if target_hypervisor == None:
|
||||||
# Determine the best hypervisor to migrate the VM to based on active memory usage
|
target_hypervisor = findTargetHypervisor(zk_conn, selector, dom_uuid)
|
||||||
hypervisor_list = zk_conn.get_children('/nodes')
|
|
||||||
most_memfree = 0
|
|
||||||
for hypervisor in hypervisor_list:
|
|
||||||
daemon_state = zk_conn.get('/nodes/{}/daemonstate'.format(hypervisor))[0].decode('ascii')
|
|
||||||
domain_state = zk_conn.get('/nodes/{}/domainstate'.format(hypervisor))[0].decode('ascii')
|
|
||||||
if daemon_state != 'run' or domain_state != 'ready' or hypervisor == current_hypervisor:
|
|
||||||
continue
|
|
||||||
|
|
||||||
memfree = int(zk_conn.get('/nodes/{}/memfree'.format(hypervisor))[0].decode('ascii'))
|
|
||||||
if memfree > most_memfree:
|
|
||||||
most_memfree = memfree
|
|
||||||
target_hypervisor = hypervisor
|
|
||||||
else:
|
else:
|
||||||
if target_hypervisor == current_hypervisor:
|
if target_hypervisor == current_hypervisor:
|
||||||
click.echo('ERROR: The VM "{}" is already running on hypervisor "{}".'.format(dom_uuid, current_hypervisor))
|
click.echo('ERROR: The VM "{}" is already running on hypervisor "{}".'.format(dom_uuid, current_hypervisor))
|
||||||
|
|
Loading…
Reference in New Issue