From a48bf2d71e75b70f5ee879c97e6fdafaf35b7573 Mon Sep 17 00:00:00 2001 From: "Joshua M. Boniface" Date: Tue, 1 Jun 2021 11:05:15 -0400 Subject: [PATCH] More gracefully handle none selectors Allow selection of "none" as the node selector, and handle this by always using the cluster default instead of writing it in. --- api-daemon/pvcapid/flaskapi.py | 11 ++++++----- api-daemon/pvcapid/helper.py | 4 +--- api-daemon/pvcapid/provisioner.py | 6 ++++++ client-cli/pvc.py | 18 +++++++++--------- daemon-common/common.py | 6 +++++- node-daemon/pvcnoded/common.py | 5 ++--- 6 files changed, 29 insertions(+), 21 deletions(-) diff --git a/api-daemon/pvcapid/flaskapi.py b/api-daemon/pvcapid/flaskapi.py index 0112d32f..2ce9c16b 100755 --- a/api-daemon/pvcapid/flaskapi.py +++ b/api-daemon/pvcapid/flaskapi.py @@ -1102,7 +1102,7 @@ class API_VM_Root(Resource): @RequestParser([ {'name': 'limit'}, {'name': 'node'}, - {'name': 'selector', 'choices': ('mem', 'vcpus', 'load', 'vms'), 'helptext': "A valid selector must be specified"}, + {'name': 'selector', 'choices': ('mem', 'vcpus', 'load', 'vms', 'none'), 'helptext': "A valid selector must be specified"}, {'name': 'autostart'}, {'name': 'migration_method', 'choices': ('live', 'shutdown', 'none'), 'helptext': "A valid migration_method must be specified"}, {'name': 'xml', 'required': True, 'helptext': "A Libvirt XML document must be specified"}, @@ -1172,7 +1172,7 @@ class API_VM_Root(Resource): reqargs.get('xml'), reqargs.get('node', None), reqargs.get('limit', None), - reqargs.get('selector', 'mem'), + reqargs.get('selector', 'none'), bool(strtobool(reqargs.get('autostart', 'false'))), reqargs.get('migration_method', 'none') ) @@ -1206,7 +1206,7 @@ class API_VM_Element(Resource): @RequestParser([ {'name': 'limit'}, {'name': 'node'}, - {'name': 'selector', 'choices': ('mem', 'vcpus', 'load', 'vms'), 'helptext': "A valid selector must be specified"}, + {'name': 'selector', 'choices': ('mem', 'vcpus', 'load', 'vms', 'none'), 'helptext': "A valid selector must be specified"}, {'name': 'autostart'}, {'name': 'migration_method', 'choices': ('live', 'shutdown', 'none'), 'helptext': "A valid migration_method must be specified"}, {'name': 'xml', 'required': True, 'helptext': "A Libvirt XML document must be specified"}, @@ -1247,6 +1247,7 @@ class API_VM_Element(Resource): - vcpus - load - vms + - none (cluster default) - in: query name: autostart type: boolean @@ -1278,7 +1279,7 @@ class API_VM_Element(Resource): reqargs.get('xml'), reqargs.get('node', None), reqargs.get('limit', None), - reqargs.get('selector', 'mem'), + reqargs.get('selector', 'none'), bool(strtobool(reqargs.get('autostart', 'false'))), reqargs.get('migration_method', 'none') ) @@ -1407,7 +1408,7 @@ class API_VM_Metadata(Resource): @RequestParser([ {'name': 'limit'}, - {'name': 'selector', 'choices': ('mem', 'vcpus', 'load', 'vms'), 'helptext': "A valid selector must be specified"}, + {'name': 'selector', 'choices': ('mem', 'vcpus', 'load', 'vms', 'none'), 'helptext': "A valid selector must be specified"}, {'name': 'autostart'}, {'name': 'profile'}, {'name': 'migration_method', 'choices': ('live', 'shutdown', 'none'), 'helptext': "A valid migration_method must be specified"}, diff --git a/api-daemon/pvcapid/helper.py b/api-daemon/pvcapid/helper.py index 94fb3d41..b561dbf6 100755 --- a/api-daemon/pvcapid/helper.py +++ b/api-daemon/pvcapid/helper.py @@ -53,9 +53,6 @@ def initialize_cluster(zkhandler, overwrite=False): # Delete the existing keys; ignore any errors status = zkhandler.delete([ '/config' - '/config/primary_node', - '/config/upstream_ip', - '/config/maintenance', '/nodes', '/domains', '/networks', @@ -81,6 +78,7 @@ def initialize_cluster(zkhandler, overwrite=False): ('/config/primary_node', 'none'), ('/config/upstream_ip', 'none'), ('/config/maintenance', 'False'), + ('/config/migration_target_selector', 'none'), ('/nodes', ''), ('/domains', ''), ('/networks', ''), diff --git a/api-daemon/pvcapid/provisioner.py b/api-daemon/pvcapid/provisioner.py index 6c058112..524f174e 100755 --- a/api-daemon/pvcapid/provisioner.py +++ b/api-daemon/pvcapid/provisioner.py @@ -219,6 +219,9 @@ def create_template_system(name, vcpu_count, vram_mb, serial=False, vnc=False, v retcode = 400 return retmsg, retcode + if node_selector == 'none': + node_selector = None + query = "INSERT INTO system_template (name, vcpu_count, vram_mb, serial, vnc, vnc_bind, node_limit, node_selector, node_autostart, migration_method, ova) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s);" args = (name, vcpu_count, vram_mb, serial, vnc, vnc_bind, node_limit, node_selector, node_autostart, migration_method, ova) @@ -414,6 +417,9 @@ def modify_template_system(name, vcpu_count=None, vram_mb=None, serial=None, vnc fields.append({'field': 'node_limit', 'data': node_limit}) if node_selector is not None: + if node_selector == 'none': + node_selector = 'None' + fields.append({'field': 'node_selector', 'data': node_selector}) if node_autostart is not None: diff --git a/client-cli/pvc.py b/client-cli/pvc.py index fc79b27d..8a09ed63 100755 --- a/client-cli/pvc.py +++ b/client-cli/pvc.py @@ -618,8 +618,8 @@ def cli_vm(): ) @click.option( '-s', '--selector', 'node_selector', default='mem', show_default=True, - type=click.Choice(['mem', 'load', 'vcpus', 'vms']), - help='Method to determine optimal target node during autoselect; saved with VM.' + type=click.Choice(['mem', 'load', 'vcpus', 'vms', 'none']), + help='Method to determine optimal target node during autoselect; "none" will use the default for the cluster.' ) @click.option( '-a/-A', '--autostart/--no-autostart', 'node_autostart', is_flag=True, default=False, @@ -664,8 +664,8 @@ def vm_define(vmconfig, target_node, node_limit, node_selector, node_autostart, ) @click.option( '-s', '--selector', 'node_selector', default=None, show_default=False, - type=click.Choice(['mem', 'load', 'vcpus', 'vms']), - help='Method to determine optimal target node during autoselect.' + type=click.Choice(['mem', 'load', 'vcpus', 'vms', 'none']), + help='Method to determine optimal target node during autoselect; "none" will use the default for the cluster.' ) @click.option( '-a/-A', '--autostart/--no-autostart', 'node_autostart', is_flag=True, default=None, @@ -2895,9 +2895,9 @@ def provisioner_template_system_list(limit): ) @click.option( '--node-selector', 'node_selector', - type=click.Choice(['mem', 'vcpus', 'vms', 'load'], case_sensitive=False), - default=None, # Use cluster default - help='Use this selector to determine the optimal node during migrations.' + type=click.Choice(['mem', 'vcpus', 'vms', 'load', 'none'], case_sensitive=False), + default='none', + help='Method to determine optimal target node during autoselect; "none" will use the default for the cluster.' ) @click.option( '--node-autostart', 'node_autostart', @@ -2973,8 +2973,8 @@ def provisioner_template_system_add(name, vcpus, vram, serial, vnc, vnc_bind, no ) @click.option( '--node-selector', 'node_selector', - type=click.Choice(['mem', 'vcpus', 'vms', 'load'], case_sensitive=False), - help='Use this selector to determine the optimal node during migrations.' + type=click.Choice(['mem', 'vcpus', 'vms', 'load', 'none'], case_sensitive=False), + help='Method to determine optimal target node during autoselect; "none" will use the default for the cluster.' ) @click.option( '--node-autostart', 'node_autostart', diff --git a/daemon-common/common.py b/daemon-common/common.py index 7414e502..44d8207d 100644 --- a/daemon-common/common.py +++ b/daemon-common/common.py @@ -430,7 +430,11 @@ def findTargetNode(zkhandler, dom_uuid): try: search_field = zkhandler.read('/domains/{}/node_selector'.format(dom_uuid)) except Exception: - search_field = 'mem' + search_field = None + + # If our search field is invalid, use the default + if search_field is None or search_field == 'None': + search_field = zkhandler.read('/config/migration_target_selector') # Execute the search if search_field == 'mem': diff --git a/node-daemon/pvcnoded/common.py b/node-daemon/pvcnoded/common.py index 51fd2e6f..17a08d0f 100644 --- a/node-daemon/pvcnoded/common.py +++ b/node-daemon/pvcnoded/common.py @@ -160,10 +160,9 @@ def findTargetNode(zk_conn, config, logger, dom_uuid): except Exception: search_field = None - # If our search field is invalid, use and set the default (for next time) + # If our search field is invalid, use the default if search_field is None or search_field == 'None': - search_field = config['migration_target_selector'] - zkhandler.writedata(zk_conn, {'/domains/{}/node_selector'.format(dom_uuid): config['migration_target_selector']}) + search_field = zkhandler.readdata(zk_conn, '/config/migration_target_selector') if config['debug']: logger.out('Migrating VM {} with selector {}'.format(dom_uuid, search_field), state='d', prefix='node-flush')