Support per-VM migration type selectors
Allow a VM to specify its migration type as a default choice. The valid options are "default" (i.e. behave as now), "live" which forces a live migration only, and "shutdown" which forces a shutdown migration only. The new option is treated as a VM meta option and is set to default if not found.
This commit is contained in:
@@ -717,9 +717,10 @@ def format_list_template_system(template_data):
|
||||
template_serial_length = 7
|
||||
template_vnc_length = 4
|
||||
template_vnc_bind_length = 10
|
||||
template_node_limit_length = 9
|
||||
template_node_selector_length = 11
|
||||
template_node_autostart_length = 11
|
||||
template_node_limit_length = 6
|
||||
template_node_selector_length = 9
|
||||
template_node_autostart_length = 10
|
||||
template_migration_method_length = 10
|
||||
|
||||
for template in template_data:
|
||||
# template_name column
|
||||
@@ -762,17 +763,22 @@ def format_list_template_system(template_data):
|
||||
_template_node_autostart_length = len(str(template['node_autostart'])) + 1
|
||||
if _template_node_autostart_length > template_node_autostart_length:
|
||||
template_node_autostart_length = _template_node_autostart_length
|
||||
# template_migration_method column
|
||||
_template_migration_method_length = len(str(template['migration_method'])) + 1
|
||||
if _template_migration_method_length > template_migration_method_length:
|
||||
template_migration_method_length = _template_migration_method_length
|
||||
|
||||
# Format the string (header)
|
||||
template_list_output_header = '{bold}{template_name: <{template_name_length}} {template_id: <{template_id_length}} \
|
||||
{template_vcpu: <{template_vcpu_length}} \
|
||||
{template_vram: <{template_vram_length}} \
|
||||
Consoles: {template_serial: <{template_serial_length}} \
|
||||
Console: {template_serial: <{template_serial_length}} \
|
||||
{template_vnc: <{template_vnc_length}} \
|
||||
{template_vnc_bind: <{template_vnc_bind_length}} \
|
||||
Metadata: {template_node_limit: <{template_node_limit_length}} \
|
||||
Meta: {template_node_limit: <{template_node_limit_length}} \
|
||||
{template_node_selector: <{template_node_selector_length}} \
|
||||
{template_node_autostart: <{template_node_autostart_length}}{end_bold}'.format(
|
||||
{template_node_autostart: <{template_node_autostart_length}} \
|
||||
{template_migration_method: <{template_migration_method_length}}{end_bold}'.format(
|
||||
template_name_length=template_name_length,
|
||||
template_id_length=template_id_length,
|
||||
template_vcpu_length=template_vcpu_length,
|
||||
@@ -783,6 +789,7 @@ Metadata: {template_node_limit: <{template_node_limit_length}} \
|
||||
template_node_limit_length=template_node_limit_length,
|
||||
template_node_selector_length=template_node_selector_length,
|
||||
template_node_autostart_length=template_node_autostart_length,
|
||||
template_migration_method_length=template_migration_method_length,
|
||||
bold=ansiprint.bold(),
|
||||
end_bold=ansiprint.end(),
|
||||
template_state_colour='',
|
||||
@@ -796,7 +803,8 @@ Metadata: {template_node_limit: <{template_node_limit_length}} \
|
||||
template_vnc_bind='VNC bind',
|
||||
template_node_limit='Limit',
|
||||
template_node_selector='Selector',
|
||||
template_node_autostart='Autostart'
|
||||
template_node_autostart='Autostart',
|
||||
template_migration_method='Migration'
|
||||
)
|
||||
|
||||
# Keep track of nets we found to be valid to cut down on duplicate API hits
|
||||
@@ -808,12 +816,13 @@ Metadata: {template_node_limit: <{template_node_limit_length}} \
|
||||
'{bold}{template_name: <{template_name_length}} {template_id: <{template_id_length}} \
|
||||
{template_vcpu: <{template_vcpu_length}} \
|
||||
{template_vram: <{template_vram_length}} \
|
||||
{template_serial: <{template_serial_length}} \
|
||||
{template_serial: <{template_serial_length}} \
|
||||
{template_vnc: <{template_vnc_length}} \
|
||||
{template_vnc_bind: <{template_vnc_bind_length}} \
|
||||
{template_node_limit: <{template_node_limit_length}} \
|
||||
{template_node_limit: <{template_node_limit_length}} \
|
||||
{template_node_selector: <{template_node_selector_length}} \
|
||||
{template_node_autostart: <{template_node_autostart_length}}{end_bold}'.format(
|
||||
{template_node_autostart: <{template_node_autostart_length}} \
|
||||
{template_migration_method: <{template_migration_method_length}}{end_bold}'.format(
|
||||
template_name_length=template_name_length,
|
||||
template_id_length=template_id_length,
|
||||
template_vcpu_length=template_vcpu_length,
|
||||
@@ -824,6 +833,7 @@ Metadata: {template_node_limit: <{template_node_limit_length}} \
|
||||
template_node_limit_length=template_node_limit_length,
|
||||
template_node_selector_length=template_node_selector_length,
|
||||
template_node_autostart_length=template_node_autostart_length,
|
||||
template_migration_method_length=template_migration_method_length,
|
||||
bold='',
|
||||
end_bold='',
|
||||
template_name=str(template['name']),
|
||||
@@ -835,7 +845,8 @@ Metadata: {template_node_limit: <{template_node_limit_length}} \
|
||||
template_vnc_bind=str(template['vnc_bind']),
|
||||
template_node_limit=str(template['node_limit']),
|
||||
template_node_selector=str(template['node_selector']),
|
||||
template_node_autostart=str(template['node_autostart'])
|
||||
template_node_autostart=str(template['node_autostart']),
|
||||
template_migration_method=str(template['migration_method'])
|
||||
)
|
||||
)
|
||||
|
||||
|
@@ -80,19 +80,20 @@ def vm_list(config, limit, target_node, target_state):
|
||||
else:
|
||||
return False, response.json().get('message', '')
|
||||
|
||||
def vm_define(config, xml, node, node_limit, node_selector, node_autostart):
|
||||
def vm_define(config, xml, node, node_limit, node_selector, node_autostart, migration_method):
|
||||
"""
|
||||
Define a new VM on the cluster
|
||||
|
||||
API endpoint: POST /vm
|
||||
API arguments: xml={xml}, node={node}, limit={node_limit}, selector={node_selector}, autostart={node_autostart}
|
||||
API arguments: xml={xml}, node={node}, limit={node_limit}, selector={node_selector}, autostart={node_autostart}, migration_method={migration_method}
|
||||
API schema: {"message":"{data}"}
|
||||
"""
|
||||
params = {
|
||||
'node': node,
|
||||
'limit': node_limit,
|
||||
'selector': node_selector,
|
||||
'autostart': node_autostart
|
||||
'autostart': node_autostart,
|
||||
'migration_method': migration_method
|
||||
}
|
||||
data = {
|
||||
'xml': xml
|
||||
@@ -129,12 +130,12 @@ def vm_modify(config, vm, xml, restart):
|
||||
|
||||
return retstatus, response.json().get('message', '')
|
||||
|
||||
def vm_metadata(config, vm, node_limit, node_selector, node_autostart, provisioner_profile):
|
||||
def vm_metadata(config, vm, node_limit, node_selector, node_autostart, migration_method, provisioner_profile):
|
||||
"""
|
||||
Modify PVC metadata of a VM
|
||||
|
||||
API endpoint: GET /vm/{vm}/meta, POST /vm/{vm}/meta
|
||||
API arguments: limit={node_limit}, selector={node_selector}, autostart={node_autostart}, profile={provisioner_profile}
|
||||
API arguments: limit={node_limit}, selector={node_selector}, autostart={node_autostart}, migration_method={migration_method} profile={provisioner_profile}
|
||||
API schema: {"message":"{data}"}
|
||||
"""
|
||||
params = dict()
|
||||
@@ -149,6 +150,9 @@ def vm_metadata(config, vm, node_limit, node_selector, node_autostart, provision
|
||||
if node_autostart is not None:
|
||||
params['autostart'] = node_autostart
|
||||
|
||||
if migration_method is not None:
|
||||
params['migration_method'] = migration_method
|
||||
|
||||
if provisioner_profile is not None:
|
||||
params['profile'] = provisioner_profile
|
||||
|
||||
@@ -391,24 +395,30 @@ def format_info(config, domain_information, long_output):
|
||||
ainformation.append('')
|
||||
ainformation.append('{}Failure reason:{} {}'.format(ansiprint.purple(), ansiprint.end(), domain_information['failed_reason']))
|
||||
|
||||
if not domain_information['node_selector']:
|
||||
if not domain_information.get('node_selector'):
|
||||
formatted_node_selector = "False"
|
||||
else:
|
||||
formatted_node_selector = domain_information['node_selector']
|
||||
|
||||
if not domain_information['node_limit']:
|
||||
if not domain_information.get('node_limit'):
|
||||
formatted_node_limit = "False"
|
||||
else:
|
||||
formatted_node_limit = ', '.join(domain_information['node_limit'])
|
||||
|
||||
if not domain_information['node_autostart']:
|
||||
if not domain_information.get('node_autostart'):
|
||||
formatted_node_autostart = "False"
|
||||
else:
|
||||
formatted_node_autostart = domain_information['node_autostart']
|
||||
|
||||
if not domain_information.get('migration_method'):
|
||||
formatted_migration_method = "default"
|
||||
else:
|
||||
formatted_migration_method = domain_information['migration_method']
|
||||
|
||||
ainformation.append('{}Migration selector:{} {}'.format(ansiprint.purple(), ansiprint.end(), formatted_node_selector))
|
||||
ainformation.append('{}Node limit:{} {}'.format(ansiprint.purple(), ansiprint.end(), formatted_node_limit))
|
||||
ainformation.append('{}Autostart:{} {}'.format(ansiprint.purple(), ansiprint.end(), formatted_node_autostart))
|
||||
ainformation.append('{}Migration Method:{} {}'.format(ansiprint.purple(), ansiprint.end(), formatted_migration_method))
|
||||
|
||||
# Network list
|
||||
net_list = []
|
||||
|
@@ -593,11 +593,16 @@ def cli_vm():
|
||||
'-a/-A', '--autostart/--no-autostart', 'node_autostart', is_flag=True, default=False,
|
||||
help='Start VM automatically on next unflush/ready state of home node; unset by daemon once used.'
|
||||
)
|
||||
@click.option(
|
||||
'-m', '--method', 'migration_method', default='none', show_default=True,
|
||||
type=click.Choice(['none','live','shutdown']),
|
||||
help='The preferred migration method of the VM between nodes; saved with VM.'
|
||||
)
|
||||
@click.argument(
|
||||
'vmconfig', type=click.File()
|
||||
)
|
||||
@cluster_req
|
||||
def vm_define(vmconfig, target_node, node_limit, node_selector, node_autostart):
|
||||
def vm_define(vmconfig, target_node, node_limit, node_selector, node_autostart, migration_method):
|
||||
"""
|
||||
Define a new virtual machine from Libvirt XML configuration file VMCONFIG.
|
||||
"""
|
||||
@@ -613,7 +618,7 @@ def vm_define(vmconfig, target_node, node_limit, node_selector, node_autostart):
|
||||
except:
|
||||
cleanup(False, 'Error: XML is malformed or invalid')
|
||||
|
||||
retcode, retmsg = pvc_vm.vm_define(config, new_cfg, target_node, node_limit, node_selector, node_autostart)
|
||||
retcode, retmsg = pvc_vm.vm_define(config, new_cfg, target_node, node_limit, node_selector, node_autostart, migration_method)
|
||||
cleanup(retcode, retmsg)
|
||||
|
||||
###############################################################################
|
||||
@@ -633,6 +638,11 @@ def vm_define(vmconfig, target_node, node_limit, node_selector, node_autostart):
|
||||
'-a/-A', '--autostart/--no-autostart', 'node_autostart', is_flag=True, default=None,
|
||||
help='Start VM automatically on next unflush/ready state of home node; unset by daemon once used.'
|
||||
)
|
||||
@click.option(
|
||||
'-m', '--method', 'migration_method', default='none', show_default=True,
|
||||
type=click.Choice(['none','live','shutdown']),
|
||||
help='The preferred migration method of the VM between nodes; saved with VM.'
|
||||
)
|
||||
@click.option(
|
||||
'-p', '--profile', 'provisioner_profile', default=None, show_default=False,
|
||||
help='PVC provisioner profile name for VM.'
|
||||
@@ -641,15 +651,15 @@ def vm_define(vmconfig, target_node, node_limit, node_selector, node_autostart):
|
||||
'domain'
|
||||
)
|
||||
@cluster_req
|
||||
def vm_meta(domain, node_limit, node_selector, node_autostart, provisioner_profile):
|
||||
def vm_meta(domain, node_limit, node_selector, node_autostart, migration_method, provisioner_profile):
|
||||
"""
|
||||
Modify the PVC metadata of existing virtual machine DOMAIN. At least one option to update must be specified. DOMAIN may be a UUID or name.
|
||||
"""
|
||||
|
||||
if node_limit is None and node_selector is None and node_autostart is None and provisioner_profile is None:
|
||||
if node_limit is None and node_selector is None and node_autostart is None and migration_method is None and provisioner_profile is None:
|
||||
cleanup(False, 'At least one metadata option must be specified to update.')
|
||||
|
||||
retcode, retmsg = pvc_vm.vm_metadata(config, domain, node_limit, node_selector, node_autostart, provisioner_profile)
|
||||
retcode, retmsg = pvc_vm.vm_metadata(config, domain, node_limit, node_selector, node_autostart, migration_method, provisioner_profile)
|
||||
cleanup(retcode, retmsg)
|
||||
|
||||
###############################################################################
|
||||
@@ -2301,8 +2311,14 @@ def provisioner_template_system_list(limit):
|
||||
is_flag=True, default=False,
|
||||
help='Autostart VM with their parent Node on first/next boot.'
|
||||
)
|
||||
@click.option(
|
||||
'--migration-method', 'migration_method',
|
||||
type=click.Choice(['none','live','shutdown'], case_sensitive=False),
|
||||
default=None, # Use cluster default
|
||||
help='The preferred migration method of the VM between nodes'
|
||||
)
|
||||
@cluster_req
|
||||
def provisioner_template_system_add(name, vcpus, vram, serial, vnc, vnc_bind, node_limit, node_selector, node_autostart):
|
||||
def provisioner_template_system_add(name, vcpus, vram, serial, vnc, vnc_bind, node_limit, node_selector, node_autostart, migration_method):
|
||||
"""
|
||||
Add a new system template NAME to the PVC cluster provisioner.
|
||||
"""
|
||||
@@ -2320,6 +2336,8 @@ def provisioner_template_system_add(name, vcpus, vram, serial, vnc, vnc_bind, no
|
||||
params['node_selector'] = node_selector
|
||||
if node_autostart:
|
||||
params['node_autostart'] = node_autostart
|
||||
if migration_method:
|
||||
params['migration_method'] = migration_method
|
||||
|
||||
retcode, retdata = pvc_provisioner.template_add(config, params, template_type='system')
|
||||
cleanup(retcode, retdata)
|
||||
@@ -2369,8 +2387,14 @@ def provisioner_template_system_add(name, vcpus, vram, serial, vnc, vnc_bind, no
|
||||
is_flag=True, default=None,
|
||||
help='Autostart VM with their parent Node on first/next boot.'
|
||||
)
|
||||
@click.option(
|
||||
'--migration-method', 'migration_method',
|
||||
type=click.Choice(['none','live','shutdown'], case_sensitive=False),
|
||||
default=None, # Use cluster default
|
||||
help='The preferred migration method of the VM between nodes'
|
||||
)
|
||||
@cluster_req
|
||||
def provisioner_template_system_modify(name, vcpus, vram, serial, vnc, vnc_bind, node_limit, node_selector, node_autostart):
|
||||
def provisioner_template_system_modify(name, vcpus, vram, serial, vnc, vnc_bind, node_limit, node_selector, node_autostart, migration_method):
|
||||
"""
|
||||
Add a new system template NAME to the PVC cluster provisioner.
|
||||
"""
|
||||
@@ -2383,6 +2407,7 @@ def provisioner_template_system_modify(name, vcpus, vram, serial, vnc, vnc_bind,
|
||||
params['node_limit'] = node_limit
|
||||
params['node_selector'] = node_selector
|
||||
params['node_autostart'] = node_autostart
|
||||
params['migration_method'] = migration_method
|
||||
|
||||
retcode, retdata = pvc_provisioner.template_modify(config, params, name, template_type='system')
|
||||
cleanup(retcode, retdata)
|
||||
|
Reference in New Issue
Block a user