diff --git a/api-daemon/pvcapid/provisioner.py b/api-daemon/pvcapid/provisioner.py index 79daaa2d..5d026125 100755 --- a/api-daemon/pvcapid/provisioner.py +++ b/api-daemon/pvcapid/provisioner.py @@ -661,6 +661,10 @@ def delete_script(name): close_database(conn, cur) return retmsg, retcode +# +# OVA functions +# + # # Profile functions # @@ -691,12 +695,16 @@ def list_profile(limit, is_fuzzy=True): profile_data = dict() profile_data['id'] = profile['id'] profile_data['name'] = profile['name'] + profile_data['type'] = profile['profile_type'] # Parse the name of each subelement - for etype in 'system_template', 'network_template', 'storage_template', 'userdata', 'script': + for etype in 'system_template', 'network_template', 'storage_template', 'userdata', 'script', 'ova': query = 'SELECT name from {} WHERE id = %s'.format(etype) args = (profile[etype],) cur.execute(query, args) - name = cur.fetchone()['name'] + try: + name = cur.fetchone()['name'] + except: + name = "N/A" profile_data[etype] = name # Split the arguments back into a list profile_data['arguments'] = profile['arguments'].split('|') @@ -708,12 +716,17 @@ def list_profile(limit, is_fuzzy=True): else: return {'message': 'No profiles found'}, 404 -def create_profile(name, system_template, network_template, storage_template, userdata, script, arguments=None): +def create_profile(name, profile_type, system_template, network_template, storage_template, userdata=None, script=None, ova=None, arguments=None): if list_profile(name, is_fuzzy=False)[-1] != 404: retmsg = { 'message': 'The profile "{}" already exists'.format(name) } retcode = 400 return retmsg, retcode + if profile_type not in ['script', 'clone', 'ova']: + retmsg = { 'message': 'A valid profile type (script, clone, ova) must be specified' } + retcode = 400 + return retmsg, retcode + system_templates, code = list_template_system(None) system_template_id = None for template in system_templates: @@ -749,20 +762,18 @@ def create_profile(name, system_template, network_template, storage_template, us for template in userdatas: if template['name'] == userdata: userdata_id = template['id'] - if not userdata_id: - retmsg = { 'message': 'The userdata template "{}" for profile "{}" does not exist'.format(userdata, name) } - retcode = 400 - return retmsg, retcode scripts, code = list_script(None) script_id = None for scr in scripts: if scr['name'] == script: script_id = scr['id'] - if not script_id: - retmsg = { 'message': 'The script "{}" for profile "{}" does not exist'.format(script, name) } - retcode = 400 - return retmsg, retcode + + ovas, code = list_ova(None) + ova_id = None + for ov in ovas: + if ov['name'] == ova: + ova_id = ov['id'] if arguments is not None and isinstance(arguments, list): arguments_formatted = '|'.join(arguments) @@ -771,8 +782,8 @@ def create_profile(name, system_template, network_template, storage_template, us conn, cur = open_database(config) try: - query = "INSERT INTO profile (name, system_template, network_template, storage_template, userdata, script, arguments) VALUES (%s, %s, %s, %s, %s, %s, %s);" - args = (name, system_template_id, network_template_id, storage_template_id, userdata_id, script_id, arguments_formatted) + query = "INSERT INTO profile (name, type, system_template, network_template, storage_template, userdata, script, ova, arguments) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s);" + args = (name, profile_type, system_template_id, network_template_id, storage_template_id, userdata_id, script_id, ova_id, arguments_formatted) cur.execute(query, args) retmsg = { "message": 'Created VM profile "{}"'.format(name) } retcode = 200 @@ -782,7 +793,7 @@ def create_profile(name, system_template, network_template, storage_template, us close_database(conn, cur) return retmsg, retcode -def modify_profile(name, system_template, network_template, storage_template, userdata, script, arguments=None): +def modify_profile(name, profile_type, system_template, network_template, storage_template, userdata, script, ova, arguments=None): if list_profile(name, is_fuzzy=False)[-1] != 200: retmsg = { 'message': 'The profile "{}" does not exist'.format(name) } retcode = 400 @@ -790,6 +801,13 @@ def modify_profile(name, system_template, network_template, storage_template, us fields = [] + if profile_type is not None: + if profile_type not in ['script', 'clone', 'ova']: + retmsg = { 'message': 'A valid profile type (script, clone, ova) must be specified' } + retcode = 400 + return retmsg, retcode + fields.append({'field': 'type', 'data': profile_type}) + if system_template is not None: system_templates, code = list_template_system(None) system_template_id = None @@ -850,6 +868,18 @@ def modify_profile(name, system_template, network_template, storage_template, us return retmsg, retcode fields.append({'field': 'script', 'data': script_id}) + if ova is not None: + ovas, code = list_ova(None) + ova_id = None + for ov in ovas: + if ov['name'] == ova: + ova_id = ov['id'] + if not ova_id: + retmsg = { 'message': 'The OVA "{}" for profile "{}" does not exist'.format(ova, name) } + retcode = 400 + return retmsg, retcode + fields.append({'field': 'ova', 'data': ova_id}) + if arguments is not None: if isinstance(arguments, list): arguments_formatted = '|'.join(arguments) @@ -857,7 +887,6 @@ def modify_profile(name, system_template, network_template, storage_template, us arguments_formatted = '' fields.append({'field': 'arguments', 'data': arguments_formatted}) - conn, cur = open_database(config) try: for field in fields: diff --git a/client-cli/cli_lib/provisioner.py b/client-cli/cli_lib/provisioner.py index b5f6ecbd..fe9eda15 100644 --- a/client-cli/cli_lib/provisioner.py +++ b/client-cli/cli_lib/provisioner.py @@ -1073,11 +1073,22 @@ def format_list_profile(profile_data): if isinstance(profile_data, dict): profile_data = [ profile_data ] + # Format the profile "source" from the type and, if applicable, OVA profile name + for profile in profile_data: + profile_type = profile['type'] + if 'ova' in profile_type: + # Set the source to the name of the OVA: + profile['source'] = profile_data['ova'] + else: + # Set the source to be the type + profile['source'] = profile_type + profile_list_output = [] # Determine optimal column widths profile_name_length = 5 profile_id_length = 3 + profile_source_length = 7 profile_system_template_length = 7 profile_network_template_length = 8 @@ -1094,6 +1105,10 @@ def format_list_profile(profile_data): _profile_id_length = len(str(profile['id'])) + 1 if _profile_id_length > profile_id_length: profile_id_length = _profile_id_length + # profile_source column + _profile_source_length = len(str(profile['source'])) + 1 + if _profile_source_length > profile_source_length: + profile_source_length = _profile_source_length # profile_system_template column _profile_system_template_length = len(str(profile['system_template'])) + 1 if _profile_system_template_length > profile_system_template_length: @@ -1116,7 +1131,7 @@ def format_list_profile(profile_data): profile_script_length = _profile_script_length # Format the string (header) - profile_list_output_header = '{bold}{profile_name: <{profile_name_length}} {profile_id: <{profile_id_length}} \ + profile_list_output_header = '{bold}{profile_name: <{profile_name_length}} {profile_id: <{profile_id_length}} {profile_source: <{profile_source_length}} \ Templates: {profile_system_template: <{profile_system_template_length}} \ {profile_network_template: <{profile_network_template_length}} \ {profile_storage_template: <{profile_storage_template_length}} \ @@ -1125,6 +1140,7 @@ Data: {profile_userdata: <{profile_userdata_length}} \ {profile_arguments}{end_bold}'.format( profile_name_length=profile_name_length, profile_id_length=profile_id_length, + profile_source_length=profile_source_length, profile_system_template_length=profile_system_template_length, profile_network_template_length=profile_network_template_length, profile_storage_template_length=profile_storage_template_length, @@ -1134,6 +1150,7 @@ Data: {profile_userdata: <{profile_userdata_length}} \ end_bold=ansiprint.end(), profile_name='Name', profile_id='ID', + profile_source='Source', profile_system_template='System', profile_network_template='Network', profile_storage_template='Storage', @@ -1145,7 +1162,7 @@ Data: {profile_userdata: <{profile_userdata_length}} \ # Format the string (elements) for profile in sorted(profile_data, key=lambda i: i.get('name', None)): profile_list_output.append( - '{bold}{profile_name: <{profile_name_length}} {profile_id: <{profile_id_length}} \ + '{bold}{profile_name: <{profile_name_length}} {profile_id: <{profile_id_length}} {profile_source: <{profile_source_length}} \ {profile_system_template: <{profile_system_template_length}} \ {profile_network_template: <{profile_network_template_length}} \ {profile_storage_template: <{profile_storage_template_length}} \ @@ -1154,6 +1171,7 @@ Data: {profile_userdata: <{profile_userdata_length}} \ {profile_arguments}{end_bold}'.format( profile_name_length=profile_name_length, profile_id_length=profile_id_length, + profile_source_length=profile_source_length, profile_system_template_length=profile_system_template_length, profile_network_template_length=profile_network_template_length, profile_storage_template_length=profile_storage_template_length, @@ -1163,6 +1181,7 @@ Data: {profile_userdata: <{profile_userdata_length}} \ end_bold='', profile_name=profile['name'], profile_id=profile['id'], + profile_source=profile['source'], profile_system_template=profile['system_template'], profile_network_template=profile['network_template'], profile_storage_template=profile['storage_template'],