Provide pretty status bars to indicate upload progress for tasks that perform large file uploads to the API ('provisioner ova upload' and 'storage volume upload') so the administrator can gauge progress and estimated time to completion.
1507 lines
57 KiB
Python
1507 lines
57 KiB
Python
#!/usr/bin/env python3
|
|
|
|
# provisioner.py - PVC CLI client function library, Provisioner functions
|
|
# Part of the Parallel Virtual Cluster (PVC) system
|
|
#
|
|
# Copyright (C) 2018-2020 Joshua M. Boniface <joshua@boniface.me>
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
#
|
|
###############################################################################
|
|
|
|
import time
|
|
import re
|
|
import subprocess
|
|
import ast
|
|
|
|
from requests_toolbelt.multipart.encoder import MultipartEncoder, MultipartEncoderMonitor
|
|
|
|
import cli_lib.ansiprint as ansiprint
|
|
from cli_lib.common import UploadProgressBar, call_api
|
|
|
|
#
|
|
# Primary functions
|
|
#
|
|
def template_info(config, template, template_type):
|
|
"""
|
|
Get information about template
|
|
|
|
API endpoint: GET /api/v1/provisioner/template/{template_type}/{template}
|
|
API arguments:
|
|
API schema: {json_template_object}
|
|
"""
|
|
response = call_api(config, 'get', '/provisioner/template/{template_type}/{template}'.format(template_type=template_type, template=template))
|
|
|
|
if response.status_code == 200:
|
|
return True, response.json()
|
|
else:
|
|
return False, response.json()['message']
|
|
|
|
def template_list(config, limit, template_type=None):
|
|
"""
|
|
Get list information about templates (limited by {limit})
|
|
|
|
API endpoint: GET /api/v1/provisioner/template/{template_type}
|
|
API arguments: limit={limit}
|
|
API schema: [{json_template_object},{json_template_object},etc.]
|
|
"""
|
|
params = dict()
|
|
if limit:
|
|
params['limit'] = limit
|
|
|
|
if template_type is not None:
|
|
response = call_api(config, 'get', '/provisioner/template/{template_type}'.format(template_type=template_type), params=params)
|
|
else:
|
|
response = call_api(config, 'get', '/provisioner/template', params=params)
|
|
|
|
if response.status_code == 200:
|
|
return True, response.json()
|
|
else:
|
|
return False, response.json()['message']
|
|
|
|
def template_add(config, params, template_type=None):
|
|
"""
|
|
Add a new template of {template_type} with {params}
|
|
|
|
API endpoint: POST /api/v1/provisioner/template/{template_type}
|
|
API_arguments: args
|
|
API schema: {message}
|
|
"""
|
|
response = call_api(config, 'post', '/provisioner/template/{template_type}'.format(template_type=template_type), params=params)
|
|
|
|
if response.status_code == 200:
|
|
retvalue = True
|
|
else:
|
|
retvalue = False
|
|
|
|
return retvalue, response.json()['message']
|
|
|
|
def template_modify(config, params, name, template_type):
|
|
"""
|
|
Modify an existing template of {template_type} with {params}
|
|
|
|
API endpoint: PUT /api/v1/provisioner/template/{template_type}/{name}
|
|
API_arguments: args
|
|
API schema: {message}
|
|
"""
|
|
response = call_api(config, 'put', '/provisioner/template/{template_type}/{name}'.format(template_type=template_type, name=name), params=params)
|
|
|
|
if response.status_code == 200:
|
|
retvalue = True
|
|
else:
|
|
retvalue = False
|
|
|
|
return retvalue, response.json()['message']
|
|
|
|
def template_remove(config, name, template_type):
|
|
"""
|
|
Remove template {name} of {template_type}
|
|
|
|
API endpoint: DELETE /api/v1/provisioner/template/{template_type}/{name}
|
|
API_arguments:
|
|
API schema: {message}
|
|
"""
|
|
response = call_api(config, 'delete', '/provisioner/template/{template_type}/{name}'.format(template_type=template_type, name=name))
|
|
|
|
if response.status_code == 200:
|
|
retvalue = True
|
|
else:
|
|
retvalue = False
|
|
|
|
return retvalue, response.json()['message']
|
|
|
|
def template_element_add(config, name, element_id, params, element_type=None, template_type=None):
|
|
"""
|
|
Add a new template element of {element_type} with {params} to template {name} of {template_type}
|
|
|
|
API endpoint: POST /api/v1/provisioner/template/{template_type}/{name}/{element_type}/{element_id}
|
|
API_arguments: args
|
|
API schema: {message}
|
|
"""
|
|
response = call_api(config, 'post', '/provisioner/template/{template_type}/{name}/{element_type}/{element_id}'.format(template_type=template_type, name=name, element_type=element_type, element_id=element_id), params=params)
|
|
|
|
if response.status_code == 200:
|
|
retvalue = True
|
|
else:
|
|
retvalue = False
|
|
|
|
return retvalue, response.json()['message']
|
|
|
|
def template_element_remove(config, name, element_id, element_type=None, template_type=None):
|
|
"""
|
|
Remove template element {element_id} of {element_type} from template {name} of {template_type}
|
|
|
|
API endpoint: DELETE /api/v1/provisioner/template/{template_type}/{name}/{element_type}/{element_id}
|
|
API_arguments:
|
|
API schema: {message}
|
|
"""
|
|
response = call_api(config, 'delete', '/provisioner/template/{template_type}/{name}/{element_type}/{element_id}'.format(template_type=template_type, name=name, element_type=element_type, element_id=element_id))
|
|
|
|
if response.status_code == 200:
|
|
retvalue = True
|
|
else:
|
|
retvalue = False
|
|
|
|
return retvalue, response.json()['message']
|
|
|
|
def userdata_info(config, userdata):
|
|
"""
|
|
Get information about userdata
|
|
|
|
API endpoint: GET /api/v1/provisioner/userdata/{userdata}
|
|
API arguments:
|
|
API schema: {json_data_object}
|
|
"""
|
|
response = call_api(config, 'get', '/provisioner/userdata/{userdata}'.format(userdata=userdata))
|
|
|
|
if response.status_code == 200:
|
|
return True, response.json()[0]
|
|
else:
|
|
return False, response.json()['message']
|
|
|
|
def userdata_list(config, limit):
|
|
"""
|
|
Get list information about userdatas (limited by {limit})
|
|
|
|
API endpoint: GET /api/v1/provisioner/userdata
|
|
API arguments: limit={limit}
|
|
API schema: [{json_data_object},{json_data_object},etc.]
|
|
"""
|
|
params = dict()
|
|
if limit:
|
|
params['limit'] = limit
|
|
|
|
response = call_api(config, 'get', '/provisioner/userdata', params=params)
|
|
|
|
if response.status_code == 200:
|
|
return True, response.json()
|
|
else:
|
|
return False, response.json()['message']
|
|
|
|
def userdata_add(config, params):
|
|
"""
|
|
Add a new userdata with {params}
|
|
|
|
API endpoint: POST /api/v1/provisioner/userdata
|
|
API_arguments: args
|
|
API schema: {message}
|
|
"""
|
|
name = params.get('name')
|
|
userdata_data = params.get('data')
|
|
|
|
params = {
|
|
'name': name
|
|
}
|
|
data = {
|
|
'data': userdata_data
|
|
}
|
|
response = call_api(config, 'post', '/provisioner/userdata', params=params, data=data)
|
|
|
|
if response.status_code == 200:
|
|
retvalue = True
|
|
else:
|
|
retvalue = False
|
|
|
|
return retvalue, response.json()['message']
|
|
|
|
def userdata_modify(config, name, params):
|
|
"""
|
|
Modify userdata {name} with {params}
|
|
|
|
API endpoint: PUT /api/v1/provisioner/userdata/{name}
|
|
API_arguments: args
|
|
API schema: {message}
|
|
"""
|
|
userdata_data = params.get('data')
|
|
|
|
params = {
|
|
'name': name
|
|
}
|
|
data = {
|
|
'data': userdata_data
|
|
}
|
|
response = call_api(config, 'put', '/provisioner/userdata/{name}'.format(name=name), params=params, data=data)
|
|
|
|
if response.status_code == 200:
|
|
retvalue = True
|
|
else:
|
|
retvalue = False
|
|
|
|
return retvalue, response.json()['message']
|
|
|
|
def userdata_remove(config, name):
|
|
"""
|
|
Remove userdata {name}
|
|
|
|
API endpoint: DELETE /api/v1/provisioner/userdata/{name}
|
|
API_arguments:
|
|
API schema: {message}
|
|
"""
|
|
response = call_api(config, 'delete', '/provisioner/userdata/{name}'.format(name=name))
|
|
|
|
if response.status_code == 200:
|
|
retvalue = True
|
|
else:
|
|
retvalue = False
|
|
|
|
return retvalue, response.json()['message']
|
|
|
|
def script_info(config, script):
|
|
"""
|
|
Get information about script
|
|
|
|
API endpoint: GET /api/v1/provisioner/script/{script}
|
|
API arguments:
|
|
API schema: {json_data_object}
|
|
"""
|
|
response = call_api(config, 'get', '/provisioner/script/{script}'.format(script=script))
|
|
|
|
if response.status_code == 200:
|
|
return True, response.json()[0]
|
|
else:
|
|
return False, response.json()['message']
|
|
|
|
def script_list(config, limit):
|
|
"""
|
|
Get list information about scripts (limited by {limit})
|
|
|
|
API endpoint: GET /api/v1/provisioner/script
|
|
API arguments: limit={limit}
|
|
API schema: [{json_data_object},{json_data_object},etc.]
|
|
"""
|
|
params = dict()
|
|
if limit:
|
|
params['limit'] = limit
|
|
|
|
response = call_api(config, 'get', '/provisioner/script', params=params)
|
|
|
|
if response.status_code == 200:
|
|
return True, response.json()
|
|
else:
|
|
return False, response.json()['message']
|
|
|
|
def script_add(config, params):
|
|
"""
|
|
Add a new script with {params}
|
|
|
|
API endpoint: POST /api/v1/provisioner/script
|
|
API_arguments: args
|
|
API schema: {message}
|
|
"""
|
|
name = params.get('name')
|
|
script_data = params.get('data')
|
|
|
|
params = {
|
|
'name': name
|
|
}
|
|
data = {
|
|
'data': script_data
|
|
}
|
|
response = call_api(config, 'post', '/provisioner/script', params=params, data=data)
|
|
|
|
if response.status_code == 200:
|
|
retvalue = True
|
|
else:
|
|
retvalue = False
|
|
|
|
return retvalue, response.json()['message']
|
|
|
|
def script_modify(config, name, params):
|
|
"""
|
|
Modify script {name} with {params}
|
|
|
|
API endpoint: PUT /api/v1/provisioner/script/{name}
|
|
API_arguments: args
|
|
API schema: {message}
|
|
"""
|
|
script_data = params.get('data')
|
|
|
|
params = {
|
|
'name': name
|
|
}
|
|
data = {
|
|
'data': script_data
|
|
}
|
|
response = call_api(config, 'put', '/provisioner/script/{name}'.format(name=name), params=params, data=data)
|
|
|
|
if response.status_code == 200:
|
|
retvalue = True
|
|
else:
|
|
retvalue = False
|
|
|
|
return retvalue, response.json()['message']
|
|
|
|
def script_remove(config, name):
|
|
"""
|
|
Remove script {name}
|
|
|
|
API endpoint: DELETE /api/v1/provisioner/script/{name}
|
|
API_arguments:
|
|
API schema: {message}
|
|
"""
|
|
response = call_api(config, 'delete', '/provisioner/script/{name}'.format(name=name))
|
|
|
|
if response.status_code == 200:
|
|
retvalue = True
|
|
else:
|
|
retvalue = False
|
|
|
|
return retvalue, response.json()['message']
|
|
|
|
def ova_info(config, name):
|
|
"""
|
|
Get information about OVA image {name}
|
|
|
|
API endpoint: GET /api/v1/provisioner/ova/{name}
|
|
API arguments:
|
|
API schema: {json_data_object}
|
|
"""
|
|
response = call_api(config, 'get', '/provisioner/ova/{name}'.format(name=name))
|
|
|
|
if response.status_code == 200:
|
|
return True, response.json()[0]
|
|
else:
|
|
return False, response.json()['message']
|
|
|
|
def ova_list(config, limit):
|
|
"""
|
|
Get list information about OVA images (limited by {limit})
|
|
|
|
API endpoint: GET /api/v1/provisioner/ova
|
|
API arguments: limit={limit}
|
|
API schema: [{json_data_object},{json_data_object},etc.]
|
|
"""
|
|
params = dict()
|
|
if limit:
|
|
params['limit'] = limit
|
|
|
|
response = call_api(config, 'get', '/provisioner/ova', params=params)
|
|
|
|
if response.status_code == 200:
|
|
return True, response.json()
|
|
else:
|
|
return False, response.json()['message']
|
|
|
|
def ova_upload(config, name, ova_file, params):
|
|
"""
|
|
Upload an OVA image to the cluster
|
|
|
|
API endpoint: POST /api/v1/provisioner/ova/{name}
|
|
API arguments: pool={pool}, ova_size={ova_size}
|
|
API schema: {"message":"{data}"}
|
|
"""
|
|
import click
|
|
|
|
bar = UploadProgressBar(ova_file, end_message="Parsing file on remote side...", end_nl=False)
|
|
upload_data = MultipartEncoder(
|
|
fields={ 'file': ('filename', open(ova_file, 'rb'), 'text/plain')}
|
|
)
|
|
upload_monitor = MultipartEncoderMonitor(upload_data, bar.update)
|
|
|
|
headers = {
|
|
"Content-Type": upload_monitor.content_type
|
|
}
|
|
|
|
response = call_api(config, 'post', '/provisioner/ova/{}'.format(name), headers=headers, params=params, data=upload_monitor)
|
|
|
|
click.echo("done.")
|
|
click.echo()
|
|
|
|
if response.status_code == 200:
|
|
retstatus = True
|
|
else:
|
|
retstatus = False
|
|
|
|
return retstatus, response.json()['message']
|
|
|
|
def ova_remove(config, name):
|
|
"""
|
|
Remove OVA image {name}
|
|
|
|
API endpoint: DELETE /api/v1/provisioner/ova/{name}
|
|
API_arguments:
|
|
API schema: {message}
|
|
"""
|
|
response = call_api(config, 'delete', '/provisioner/ova/{name}'.format(name=name))
|
|
|
|
if response.status_code == 200:
|
|
retvalue = True
|
|
else:
|
|
retvalue = False
|
|
|
|
return retvalue, response.json()['message']
|
|
|
|
def profile_info(config, profile):
|
|
"""
|
|
Get information about profile
|
|
|
|
API endpoint: GET /api/v1/provisioner/profile/{profile}
|
|
API arguments:
|
|
API schema: {json_data_object}
|
|
"""
|
|
response = call_api(config, 'get', '/provisioner/profile/{profile}'.format(profile=profile))
|
|
|
|
if response.status_code == 200:
|
|
return True, response.json()[0]
|
|
else:
|
|
return False, response.json()['message']
|
|
|
|
def profile_list(config, limit):
|
|
"""
|
|
Get list information about profiles (limited by {limit})
|
|
|
|
API endpoint: GET /api/v1/provisioner/profile/{profile_type}
|
|
API arguments: limit={limit}
|
|
API schema: [{json_data_object},{json_data_object},etc.]
|
|
"""
|
|
params = dict()
|
|
if limit:
|
|
params['limit'] = limit
|
|
|
|
response = call_api(config, 'get', '/provisioner/profile', params=params)
|
|
|
|
if response.status_code == 200:
|
|
return True, response.json()
|
|
else:
|
|
return False, response.json()['message']
|
|
|
|
def profile_add(config, params):
|
|
"""
|
|
Add a new profile with {params}
|
|
|
|
API endpoint: POST /api/v1/provisioner/profile
|
|
API_arguments: args
|
|
API schema: {message}
|
|
"""
|
|
response = call_api(config, 'post', '/provisioner/profile', params=params)
|
|
|
|
if response.status_code == 200:
|
|
retvalue = True
|
|
else:
|
|
retvalue = False
|
|
|
|
return retvalue, response.json()['message']
|
|
|
|
def profile_modify(config, name, params):
|
|
"""
|
|
Modify profile {name} with {params}
|
|
|
|
API endpoint: PUT /api/v1/provisioner/profile/{name}
|
|
API_arguments: args
|
|
API schema: {message}
|
|
"""
|
|
response = call_api(config, 'put', '/provisioner/profile/{name}'.format(name=name), params=params)
|
|
|
|
if response.status_code == 200:
|
|
retvalue = True
|
|
else:
|
|
retvalue = False
|
|
|
|
return retvalue, response.json()['message']
|
|
|
|
def profile_remove(config, name):
|
|
"""
|
|
Remove profile {name}
|
|
|
|
API endpoint: DELETE /api/v1/provisioner/profile/{name}
|
|
API_arguments:
|
|
API schema: {message}
|
|
"""
|
|
response = call_api(config, 'delete', '/provisioner/profile/{name}'.format(name=name))
|
|
|
|
if response.status_code == 200:
|
|
retvalue = True
|
|
else:
|
|
retvalue = False
|
|
|
|
return retvalue, response.json()['message']
|
|
|
|
def vm_create(config, name, profile, wait_flag, define_flag, start_flag):
|
|
"""
|
|
Create a new VM named {name} with profile {profile}
|
|
|
|
API endpoint: POST /api/v1/provisioner/create
|
|
API_arguments: name={name}, profile={profile}
|
|
API schema: {message}
|
|
"""
|
|
params = {
|
|
'name': name,
|
|
'profile': profile,
|
|
'start_vm': start_flag,
|
|
'define_vm': define_flag
|
|
}
|
|
response = call_api(config, 'post', '/provisioner/create', params=params)
|
|
|
|
if response.status_code == 202:
|
|
retvalue = True
|
|
if not wait_flag:
|
|
retdata = 'Task ID: {}'.format(response.json()['task_id'])
|
|
else:
|
|
# Just return the task_id raw, instead of formatting it
|
|
retdata = response.json()['task_id']
|
|
else:
|
|
retvalue = False
|
|
retdata = response.json()['message']
|
|
|
|
return retvalue, retdata
|
|
|
|
def task_status(config, task_id=None, is_watching=False):
|
|
"""
|
|
Get information about provisioner job {task_id} or all tasks if None
|
|
|
|
API endpoint: GET /api/v1/provisioner/status
|
|
API arguments:
|
|
API schema: {json_data_object}
|
|
"""
|
|
if task_id is not None:
|
|
response = call_api(config, 'get', '/provisioner/status/{task_id}'.format(task_id=task_id))
|
|
else:
|
|
response = call_api(config, 'get', '/provisioner/status')
|
|
|
|
if task_id is not None:
|
|
if response.status_code == 200:
|
|
retvalue = True
|
|
respjson = response.json()
|
|
|
|
if is_watching:
|
|
# Just return the raw JSON to the watching process instead of formatting it
|
|
return respjson
|
|
|
|
job_state = respjson['state']
|
|
if job_state == 'RUNNING':
|
|
retdata = 'Job state: RUNNING\nStage: {}/{}\nStatus: {}'.format(
|
|
respjson['current'],
|
|
respjson['total'],
|
|
respjson['status']
|
|
)
|
|
elif job_state == 'FAILED':
|
|
retdata = 'Job state: FAILED\nStatus: {}'.format(
|
|
respjson['status']
|
|
)
|
|
elif job_state == 'COMPLETED':
|
|
retdata = 'Job state: COMPLETED\nStatus: {}'.format(
|
|
respjson['status']
|
|
)
|
|
else:
|
|
retdata = 'Job state: {}\nStatus: {}'.format(
|
|
respjson['state'],
|
|
respjson['status']
|
|
)
|
|
else:
|
|
retvalue = False
|
|
retdata = response.json()['message']
|
|
else:
|
|
retvalue = True
|
|
task_data_raw = response.json()
|
|
# Format the Celery data into a more useful data structure
|
|
task_data = list()
|
|
for task_type in ['active', 'reserved', 'scheduled']:
|
|
type_data = task_data_raw[task_type]
|
|
if not type_data:
|
|
type_data = dict()
|
|
for task_host in type_data:
|
|
for task_job in task_data_raw[task_type][task_host]:
|
|
task = dict()
|
|
if task_type == 'reserved':
|
|
task['type'] = 'pending'
|
|
else:
|
|
task['type'] = task_type
|
|
task['worker'] = task_host
|
|
task['id'] = task_job.get('id')
|
|
task_args = ast.literal_eval(task_job.get('args'))
|
|
task['vm_name'] = task_args[0]
|
|
task['vm_profile'] = task_args[1]
|
|
task_kwargs = ast.literal_eval(task_job.get('kwargs'))
|
|
task['vm_define'] = str(bool(task_kwargs['define_vm']))
|
|
task['vm_start'] = str(bool(task_kwargs['start_vm']))
|
|
task_data.append(task)
|
|
retdata = task_data
|
|
|
|
return retvalue, retdata
|
|
|
|
#
|
|
# Format functions
|
|
#
|
|
def format_list_template(template_data, template_type=None):
|
|
"""
|
|
Format the returned template template
|
|
|
|
template_type can be used to only display part of the full list, allowing function
|
|
reuse with more limited output options.
|
|
"""
|
|
template_types = [ 'system', 'network', 'storage' ]
|
|
normalized_template_data = dict()
|
|
ainformation = list()
|
|
|
|
if template_type in template_types:
|
|
template_types = [ template_type ]
|
|
template_data_type = '{}_templates'.format(template_type)
|
|
normalized_template_data[template_data_type] = template_data
|
|
else:
|
|
normalized_template_data = template_data
|
|
|
|
if 'system' in template_types:
|
|
ainformation.append('System templates:')
|
|
ainformation.append('')
|
|
ainformation.append(format_list_template_system(normalized_template_data['system_templates']))
|
|
if len(template_types) > 1:
|
|
ainformation.append('')
|
|
|
|
if 'network' in template_types:
|
|
ainformation.append('Network templates:')
|
|
ainformation.append('')
|
|
ainformation.append(format_list_template_network(normalized_template_data['network_templates']))
|
|
if len(template_types) > 1:
|
|
ainformation.append('')
|
|
|
|
if 'storage' in template_types:
|
|
ainformation.append('Storage templates:')
|
|
ainformation.append('')
|
|
ainformation.append(format_list_template_storage(normalized_template_data['storage_templates']))
|
|
|
|
return '\n'.join(ainformation)
|
|
|
|
def format_list_template_system(template_data):
|
|
if isinstance(template_data, dict):
|
|
template_data = [ template_data ]
|
|
|
|
template_list_output = []
|
|
|
|
# Determine optimal column widths
|
|
template_name_length = 5
|
|
template_id_length = 3
|
|
template_vcpu_length = 6
|
|
template_vram_length = 10
|
|
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
|
|
|
|
for template in template_data:
|
|
# template_name column
|
|
_template_name_length = len(str(template['name'])) + 1
|
|
if _template_name_length > template_name_length:
|
|
template_name_length = _template_name_length
|
|
# template_id column
|
|
_template_id_length = len(str(template['id'])) + 1
|
|
if _template_id_length > template_id_length:
|
|
template_id_length = _template_id_length
|
|
# template_vcpu column
|
|
_template_vcpu_length = len(str(template['vcpu_count'])) + 1
|
|
if _template_vcpu_length > template_vcpu_length:
|
|
template_vcpu_length = _template_vcpu_length
|
|
# template_vram column
|
|
_template_vram_length = len(str(template['vram_mb'])) + 1
|
|
if _template_vram_length > template_vram_length:
|
|
template_vram_length = _template_vram_length
|
|
# template_serial column
|
|
_template_serial_length = len(str(template['serial'])) + 1
|
|
if _template_serial_length > template_serial_length:
|
|
template_serial_length = _template_serial_length
|
|
# template_vnc column
|
|
_template_vnc_length = len(str(template['vnc'])) + 1
|
|
if _template_vnc_length > template_vnc_length:
|
|
template_vnc_length = _template_vnc_length
|
|
# template_vnc_bind column
|
|
_template_vnc_bind_length = len(str(template['vnc_bind'])) + 1
|
|
if _template_vnc_bind_length > template_vnc_bind_length:
|
|
template_vnc_bind_length = _template_vnc_bind_length
|
|
# template_node_limit column
|
|
_template_node_limit_length = len(str(template['node_limit'])) + 1
|
|
if _template_node_limit_length > template_node_limit_length:
|
|
template_node_limit_length = _template_node_limit_length
|
|
# template_node_selector column
|
|
_template_node_selector_length = len(str(template['node_selector'])) + 1
|
|
if _template_node_selector_length > template_node_selector_length:
|
|
template_node_selector_length = _template_node_selector_length
|
|
# template_node_autostart column
|
|
_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
|
|
|
|
# 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}} \
|
|
{template_vnc: <{template_vnc_length}} \
|
|
{template_vnc_bind: <{template_vnc_bind_length}} \
|
|
Metadata: {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_name_length=template_name_length,
|
|
template_id_length=template_id_length,
|
|
template_vcpu_length=template_vcpu_length,
|
|
template_vram_length=template_vram_length,
|
|
template_serial_length=template_serial_length,
|
|
template_vnc_length=template_vnc_length,
|
|
template_vnc_bind_length=template_vnc_bind_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,
|
|
bold=ansiprint.bold(),
|
|
end_bold=ansiprint.end(),
|
|
template_state_colour='',
|
|
end_colour='',
|
|
template_name='Name',
|
|
template_id='ID',
|
|
template_vcpu='vCPUs',
|
|
template_vram='vRAM [MB]',
|
|
template_serial='Serial',
|
|
template_vnc='VNC',
|
|
template_vnc_bind='VNC bind',
|
|
template_node_limit='Limit',
|
|
template_node_selector='Selector',
|
|
template_node_autostart='Autostart'
|
|
)
|
|
|
|
# Keep track of nets we found to be valid to cut down on duplicate API hits
|
|
valid_net_list = []
|
|
# Format the string (elements)
|
|
|
|
for template in sorted(template_data, key=lambda i: i.get('name', None)):
|
|
template_list_output.append(
|
|
'{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_vnc: <{template_vnc_length}} \
|
|
{template_vnc_bind: <{template_vnc_bind_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_name_length=template_name_length,
|
|
template_id_length=template_id_length,
|
|
template_vcpu_length=template_vcpu_length,
|
|
template_vram_length=template_vram_length,
|
|
template_serial_length=template_serial_length,
|
|
template_vnc_length=template_vnc_length,
|
|
template_vnc_bind_length=template_vnc_bind_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,
|
|
bold='',
|
|
end_bold='',
|
|
template_name=str(template['name']),
|
|
template_id=str(template['id']),
|
|
template_vcpu=str(template['vcpu_count']),
|
|
template_vram=str(template['vram_mb']),
|
|
template_serial=str(template['serial']),
|
|
template_vnc=str(template['vnc']),
|
|
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'])
|
|
)
|
|
)
|
|
|
|
return '\n'.join([template_list_output_header] + template_list_output)
|
|
|
|
return True, ''
|
|
|
|
def format_list_template_network(template_template):
|
|
if isinstance(template_template, dict):
|
|
template_template = [ template_template ]
|
|
|
|
template_list_output = []
|
|
|
|
# Determine optimal column widths
|
|
template_name_length = 5
|
|
template_id_length = 3
|
|
template_mac_template_length = 13
|
|
template_networks_length = 10
|
|
|
|
for template in template_template:
|
|
# Join the networks elements into a single list of VNIs
|
|
network_list = list()
|
|
for network in template['networks']:
|
|
network_list.append(str(network['vni']))
|
|
template['networks_csv'] = ','.join(network_list)
|
|
|
|
for template in template_template:
|
|
# template_name column
|
|
_template_name_length = len(str(template['name'])) + 1
|
|
if _template_name_length > template_name_length:
|
|
template_name_length = _template_name_length
|
|
# template_id column
|
|
_template_id_length = len(str(template['id'])) + 1
|
|
if _template_id_length > template_id_length:
|
|
template_id_length = _template_id_length
|
|
# template_mac_template column
|
|
_template_mac_template_length = len(str(template['mac_template'])) + 1
|
|
if _template_mac_template_length > template_mac_template_length:
|
|
template_mac_template_length = _template_mac_template_length
|
|
# template_networks column
|
|
_template_networks_length = len(str(template['networks_csv'])) + 1
|
|
if _template_networks_length > template_networks_length:
|
|
template_networks_length = _template_networks_length
|
|
|
|
# Format the string (header)
|
|
template_list_output_header = '{bold}{template_name: <{template_name_length}} {template_id: <{template_id_length}} \
|
|
{template_mac_template: <{template_mac_template_length}} \
|
|
{template_networks: <{template_networks_length}}{end_bold}'.format(
|
|
template_name_length=template_name_length,
|
|
template_id_length=template_id_length,
|
|
template_mac_template_length=template_mac_template_length,
|
|
template_networks_length=template_networks_length,
|
|
bold=ansiprint.bold(),
|
|
end_bold=ansiprint.end(),
|
|
template_name='Name',
|
|
template_id='ID',
|
|
template_mac_template='MAC template',
|
|
template_networks='Network VNIs'
|
|
)
|
|
|
|
# Format the string (elements)
|
|
for template in sorted(template_template, key=lambda i: i.get('name', None)):
|
|
template_list_output.append(
|
|
'{bold}{template_name: <{template_name_length}} {template_id: <{template_id_length}} \
|
|
{template_mac_template: <{template_mac_template_length}} \
|
|
{template_networks: <{template_networks_length}}{end_bold}'.format(
|
|
template_name_length=template_name_length,
|
|
template_id_length=template_id_length,
|
|
template_mac_template_length=template_mac_template_length,
|
|
template_networks_length=template_networks_length,
|
|
bold='',
|
|
end_bold='',
|
|
template_name=str(template['name']),
|
|
template_id=str(template['id']),
|
|
template_mac_template=str(template['mac_template']),
|
|
template_networks=str(template['networks_csv'])
|
|
)
|
|
)
|
|
|
|
return '\n'.join([template_list_output_header] + template_list_output)
|
|
|
|
def format_list_template_storage(template_template):
|
|
if isinstance(template_template, dict):
|
|
template_template = [ template_template ]
|
|
|
|
template_list_output = []
|
|
|
|
# Determine optimal column widths
|
|
template_name_length = 5
|
|
template_id_length = 3
|
|
template_disk_id_length = 8
|
|
template_disk_pool_length = 8
|
|
template_disk_source_length = 14
|
|
template_disk_size_length = 10
|
|
template_disk_filesystem_length = 11
|
|
template_disk_fsargs_length = 10
|
|
template_disk_mountpoint_length = 10
|
|
|
|
for template in template_template:
|
|
# template_name column
|
|
_template_name_length = len(str(template['name'])) + 1
|
|
if _template_name_length > template_name_length:
|
|
template_name_length = _template_name_length
|
|
# template_id column
|
|
_template_id_length = len(str(template['id'])) + 1
|
|
if _template_id_length > template_id_length:
|
|
template_id_length = _template_id_length
|
|
|
|
for disk in template['disks']:
|
|
# template_disk_id column
|
|
_template_disk_id_length = len(str(disk['disk_id'])) + 1
|
|
if _template_disk_id_length > template_disk_id_length:
|
|
template_disk_id_length = _template_disk_id_length
|
|
# template_disk_pool column
|
|
_template_disk_pool_length = len(str(disk['pool'])) + 1
|
|
if _template_disk_pool_length > template_disk_pool_length:
|
|
template_disk_pool_length = _template_disk_pool_length
|
|
# template_disk_source column
|
|
_template_disk_source_length = len(str(disk['source_volume'])) + 1
|
|
if _template_disk_source_length > template_disk_source_length:
|
|
template_disk_source_length = _template_disk_source_length
|
|
# template_disk_size column
|
|
_template_disk_size_length = len(str(disk['disk_size_gb'])) + 1
|
|
if _template_disk_size_length > template_disk_size_length:
|
|
template_disk_size_length = _template_disk_size_length
|
|
# template_disk_filesystem column
|
|
_template_disk_filesystem_length = len(str(disk['filesystem'])) + 1
|
|
if _template_disk_filesystem_length > template_disk_filesystem_length:
|
|
template_disk_filesystem_length = _template_disk_filesystem_length
|
|
# template_disk_fsargs column
|
|
_template_disk_fsargs_length = len(str(disk['filesystem_args'])) + 1
|
|
if _template_disk_fsargs_length > template_disk_fsargs_length:
|
|
template_disk_fsargs_length = _template_disk_fsargs_length
|
|
# template_disk_mountpoint column
|
|
_template_disk_mountpoint_length = len(str(disk['mountpoint'])) + 1
|
|
if _template_disk_mountpoint_length > template_disk_mountpoint_length:
|
|
template_disk_mountpoint_length = _template_disk_mountpoint_length
|
|
|
|
# Format the string (header)
|
|
template_list_output_header = '{bold}{template_name: <{template_name_length}} {template_id: <{template_id_length}} \
|
|
{template_disk_id: <{template_disk_id_length}} \
|
|
{template_disk_pool: <{template_disk_pool_length}} \
|
|
{template_disk_source: <{template_disk_source_length}} \
|
|
{template_disk_size: <{template_disk_size_length}} \
|
|
{template_disk_filesystem: <{template_disk_filesystem_length}} \
|
|
{template_disk_fsargs: <{template_disk_fsargs_length}} \
|
|
{template_disk_mountpoint: <{template_disk_mountpoint_length}}{end_bold}'.format(
|
|
template_name_length=template_name_length,
|
|
template_id_length=template_id_length,
|
|
template_disk_id_length=template_disk_id_length,
|
|
template_disk_pool_length=template_disk_pool_length,
|
|
template_disk_source_length=template_disk_source_length,
|
|
template_disk_size_length=template_disk_size_length,
|
|
template_disk_filesystem_length=template_disk_filesystem_length,
|
|
template_disk_fsargs_length=template_disk_fsargs_length,
|
|
template_disk_mountpoint_length=template_disk_mountpoint_length,
|
|
bold=ansiprint.bold(),
|
|
end_bold=ansiprint.end(),
|
|
template_name='Name',
|
|
template_id='ID',
|
|
template_disk_id='Disk ID',
|
|
template_disk_pool='Pool',
|
|
template_disk_source='Source Volume',
|
|
template_disk_size='Size [GB]',
|
|
template_disk_filesystem='Filesystem',
|
|
template_disk_fsargs='Arguments',
|
|
template_disk_mountpoint='Mountpoint'
|
|
)
|
|
|
|
# Format the string (elements)
|
|
for template in sorted(template_template, key=lambda i: i.get('name', None)):
|
|
template_list_output.append(
|
|
'{bold}{template_name: <{template_name_length}} {template_id: <{template_id_length}}{end_bold}'.format(
|
|
template_name_length=template_name_length,
|
|
template_id_length=template_id_length,
|
|
bold='',
|
|
end_bold='',
|
|
template_name=str(template['name']),
|
|
template_id=str(template['id'])
|
|
)
|
|
)
|
|
for disk in sorted(template['disks'], key=lambda i: i.get('disk_id', None)):
|
|
template_list_output.append(
|
|
'{bold}{template_name: <{template_name_length}} {template_id: <{template_id_length}} \
|
|
{template_disk_id: <{template_disk_id_length}} \
|
|
{template_disk_pool: <{template_disk_pool_length}} \
|
|
{template_disk_source: <{template_disk_source_length}} \
|
|
{template_disk_size: <{template_disk_size_length}} \
|
|
{template_disk_filesystem: <{template_disk_filesystem_length}} \
|
|
{template_disk_fsargs: <{template_disk_fsargs_length}} \
|
|
{template_disk_mountpoint: <{template_disk_mountpoint_length}}{end_bold}'.format(
|
|
template_name_length=template_name_length,
|
|
template_id_length=template_id_length,
|
|
template_disk_id_length=template_disk_id_length,
|
|
template_disk_pool_length=template_disk_pool_length,
|
|
template_disk_source_length=template_disk_source_length,
|
|
template_disk_size_length=template_disk_size_length,
|
|
template_disk_filesystem_length=template_disk_filesystem_length,
|
|
template_disk_fsargs_length=template_disk_fsargs_length,
|
|
template_disk_mountpoint_length=template_disk_mountpoint_length,
|
|
bold='',
|
|
end_bold='',
|
|
template_name='',
|
|
template_id='',
|
|
template_disk_id=str(disk['disk_id']),
|
|
template_disk_pool=str(disk['pool']),
|
|
template_disk_source=str(disk['source_volume']),
|
|
template_disk_size=str(disk['disk_size_gb']),
|
|
template_disk_filesystem=str(disk['filesystem']),
|
|
template_disk_fsargs=str(disk['filesystem_args']),
|
|
template_disk_mountpoint=str(disk['mountpoint'])
|
|
)
|
|
)
|
|
|
|
return '\n'.join([template_list_output_header] + template_list_output)
|
|
|
|
def format_list_userdata(userdata_data, lines=None):
|
|
if isinstance(userdata_data, dict):
|
|
userdata_data = [ userdata_data ]
|
|
|
|
userdata_list_output = []
|
|
|
|
# Determine optimal column widths
|
|
userdata_name_length = 5
|
|
userdata_id_length = 3
|
|
userdata_useruserdata_length = 8
|
|
|
|
for userdata in userdata_data:
|
|
# userdata_name column
|
|
_userdata_name_length = len(str(userdata['name'])) + 1
|
|
if _userdata_name_length > userdata_name_length:
|
|
userdata_name_length = _userdata_name_length
|
|
# userdata_id column
|
|
_userdata_id_length = len(str(userdata['id'])) + 1
|
|
if _userdata_id_length > userdata_id_length:
|
|
userdata_id_length = _userdata_id_length
|
|
|
|
# Format the string (header)
|
|
userdata_list_output_header = '{bold}{userdata_name: <{userdata_name_length}} {userdata_id: <{userdata_id_length}} \
|
|
{userdata_data}{end_bold}'.format(
|
|
userdata_name_length=userdata_name_length,
|
|
userdata_id_length=userdata_id_length,
|
|
bold=ansiprint.bold(),
|
|
end_bold=ansiprint.end(),
|
|
userdata_name='Name',
|
|
userdata_id='ID',
|
|
userdata_data='Document'
|
|
)
|
|
|
|
# Format the string (elements)
|
|
for data in sorted(userdata_data, key=lambda i: i.get('name', None)):
|
|
line_count = 0
|
|
for line in data['userdata'].split('\n'):
|
|
if line_count < 1:
|
|
userdata_name = data['name']
|
|
userdata_id = data['id']
|
|
else:
|
|
userdata_name = ''
|
|
userdata_id = ''
|
|
line_count += 1
|
|
|
|
if lines and line_count > lines:
|
|
userdata_list_output.append(
|
|
'{bold}{userdata_name: <{userdata_name_length}} {userdata_id: <{userdata_id_length}} \
|
|
{userdata_data}{end_bold}'.format(
|
|
userdata_name_length=userdata_name_length,
|
|
userdata_id_length=userdata_id_length,
|
|
bold='',
|
|
end_bold='',
|
|
userdata_name=userdata_name,
|
|
userdata_id=userdata_id,
|
|
userdata_data='[...]'
|
|
)
|
|
)
|
|
break
|
|
|
|
userdata_list_output.append(
|
|
'{bold}{userdata_name: <{userdata_name_length}} {userdata_id: <{userdata_id_length}} \
|
|
{userdata_data}{end_bold}'.format(
|
|
userdata_name_length=userdata_name_length,
|
|
userdata_id_length=userdata_id_length,
|
|
bold='',
|
|
end_bold='',
|
|
userdata_name=userdata_name,
|
|
userdata_id=userdata_id,
|
|
userdata_data=str(line)
|
|
)
|
|
)
|
|
|
|
return '\n'.join([userdata_list_output_header] + userdata_list_output)
|
|
|
|
def format_list_script(script_data, lines=None):
|
|
if isinstance(script_data, dict):
|
|
script_data = [ script_data ]
|
|
|
|
script_list_output = []
|
|
|
|
# Determine optimal column widths
|
|
script_name_length = 5
|
|
script_id_length = 3
|
|
script_script_length = 8
|
|
|
|
for script in script_data:
|
|
# script_name column
|
|
_script_name_length = len(str(script['name'])) + 1
|
|
if _script_name_length > script_name_length:
|
|
script_name_length = _script_name_length
|
|
# script_id column
|
|
_script_id_length = len(str(script['id'])) + 1
|
|
if _script_id_length > script_id_length:
|
|
script_id_length = _script_id_length
|
|
|
|
# Format the string (header)
|
|
script_list_output_header = '{bold}{script_name: <{script_name_length}} {script_id: <{script_id_length}} \
|
|
{script_data}{end_bold}'.format(
|
|
script_name_length=script_name_length,
|
|
script_id_length=script_id_length,
|
|
bold=ansiprint.bold(),
|
|
end_bold=ansiprint.end(),
|
|
script_name='Name',
|
|
script_id='ID',
|
|
script_data='Script'
|
|
)
|
|
|
|
# Format the string (elements)
|
|
for script in sorted(script_data, key=lambda i: i.get('name', None)):
|
|
line_count = 0
|
|
for line in script['script'].split('\n'):
|
|
if line_count < 1:
|
|
script_name = script['name']
|
|
script_id = script['id']
|
|
else:
|
|
script_name = ''
|
|
script_id = ''
|
|
line_count += 1
|
|
|
|
if lines and line_count > lines:
|
|
script_list_output.append(
|
|
'{bold}{script_name: <{script_name_length}} {script_id: <{script_id_length}} \
|
|
{script_data}{end_bold}'.format(
|
|
script_name_length=script_name_length,
|
|
script_id_length=script_id_length,
|
|
bold='',
|
|
end_bold='',
|
|
script_name=script_name,
|
|
script_id=script_id,
|
|
script_data='[...]'
|
|
)
|
|
)
|
|
break
|
|
|
|
script_list_output.append(
|
|
'{bold}{script_name: <{script_name_length}} {script_id: <{script_id_length}} \
|
|
{script_data}{end_bold}'.format(
|
|
script_name_length=script_name_length,
|
|
script_id_length=script_id_length,
|
|
bold='',
|
|
end_bold='',
|
|
script_name=script_name,
|
|
script_id=script_id,
|
|
script_data=str(line)
|
|
)
|
|
)
|
|
|
|
return '\n'.join([script_list_output_header] + script_list_output)
|
|
|
|
def format_list_ova(ova_data):
|
|
if isinstance(ova_data, dict):
|
|
ova_data = [ ova_data ]
|
|
|
|
ova_list_output = []
|
|
|
|
# Determine optimal column widths
|
|
ova_name_length = 5
|
|
ova_id_length = 3
|
|
ova_disk_id_length = 8
|
|
ova_disk_size_length = 10
|
|
ova_disk_pool_length = 5
|
|
ova_disk_volume_format_length = 7
|
|
ova_disk_volume_name_length = 13
|
|
|
|
for ova in ova_data:
|
|
# ova_name column
|
|
_ova_name_length = len(str(ova['name'])) + 1
|
|
if _ova_name_length > ova_name_length:
|
|
ova_name_length = _ova_name_length
|
|
# ova_id column
|
|
_ova_id_length = len(str(ova['id'])) + 1
|
|
if _ova_id_length > ova_id_length:
|
|
ova_id_length = _ova_id_length
|
|
|
|
for disk in ova['volumes']:
|
|
# ova_disk_id column
|
|
_ova_disk_id_length = len(str(disk['disk_id'])) + 1
|
|
if _ova_disk_id_length > ova_disk_id_length:
|
|
ova_disk_id_length = _ova_disk_id_length
|
|
# ova_disk_size column
|
|
_ova_disk_size_length = len(str(disk['disk_size_gb'])) + 1
|
|
if _ova_disk_size_length > ova_disk_size_length:
|
|
ova_disk_size_length = _ova_disk_size_length
|
|
# ova_disk_pool column
|
|
_ova_disk_pool_length = len(str(disk['pool'])) + 1
|
|
if _ova_disk_pool_length > ova_disk_pool_length:
|
|
ova_disk_pool_length = _ova_disk_pool_length
|
|
# ova_disk_volume_format column
|
|
_ova_disk_volume_format_length = len(str(disk['volume_format'])) + 1
|
|
if _ova_disk_volume_format_length > ova_disk_volume_format_length:
|
|
ova_disk_volume_format_length = _ova_disk_volume_format_length
|
|
# ova_disk_volume_name column
|
|
_ova_disk_volume_name_length = len(str(disk['volume_name'])) + 1
|
|
if _ova_disk_volume_name_length > ova_disk_volume_name_length:
|
|
ova_disk_volume_name_length = _ova_disk_volume_name_length
|
|
|
|
# Format the string (header)
|
|
ova_list_output_header = '{bold}{ova_name: <{ova_name_length}} {ova_id: <{ova_id_length}} \
|
|
{ova_disk_id: <{ova_disk_id_length}} \
|
|
{ova_disk_size: <{ova_disk_size_length}} \
|
|
{ova_disk_pool: <{ova_disk_pool_length}} \
|
|
{ova_disk_volume_format: <{ova_disk_volume_format_length}} \
|
|
{ova_disk_volume_name: <{ova_disk_volume_name_length}}{end_bold}'.format(
|
|
ova_name_length=ova_name_length,
|
|
ova_id_length=ova_id_length,
|
|
ova_disk_id_length=ova_disk_id_length,
|
|
ova_disk_pool_length=ova_disk_pool_length,
|
|
ova_disk_size_length=ova_disk_size_length,
|
|
ova_disk_volume_format_length=ova_disk_volume_format_length,
|
|
ova_disk_volume_name_length=ova_disk_volume_name_length,
|
|
bold=ansiprint.bold(),
|
|
end_bold=ansiprint.end(),
|
|
ova_name='Name',
|
|
ova_id='ID',
|
|
ova_disk_id='Disk ID',
|
|
ova_disk_size='Size [GB]',
|
|
ova_disk_pool='Pool',
|
|
ova_disk_volume_format='Format',
|
|
ova_disk_volume_name='Source Volume',
|
|
)
|
|
|
|
# Format the string (elements)
|
|
for ova in sorted(ova_data, key=lambda i: i.get('name', None)):
|
|
ova_list_output.append(
|
|
'{bold}{ova_name: <{ova_name_length}} {ova_id: <{ova_id_length}}{end_bold}'.format(
|
|
ova_name_length=ova_name_length,
|
|
ova_id_length=ova_id_length,
|
|
bold='',
|
|
end_bold='',
|
|
ova_name=str(ova['name']),
|
|
ova_id=str(ova['id'])
|
|
)
|
|
)
|
|
for disk in sorted(ova['volumes'], key=lambda i: i.get('disk_id', None)):
|
|
ova_list_output.append(
|
|
'{bold}{ova_name: <{ova_name_length}} {ova_id: <{ova_id_length}} \
|
|
{ova_disk_id: <{ova_disk_id_length}} \
|
|
{ova_disk_size: <{ova_disk_size_length}} \
|
|
{ova_disk_pool: <{ova_disk_pool_length}} \
|
|
{ova_disk_volume_format: <{ova_disk_volume_format_length}} \
|
|
{ova_disk_volume_name: <{ova_disk_volume_name_length}}{end_bold}'.format(
|
|
ova_name_length=ova_name_length,
|
|
ova_id_length=ova_id_length,
|
|
ova_disk_id_length=ova_disk_id_length,
|
|
ova_disk_size_length=ova_disk_size_length,
|
|
ova_disk_pool_length=ova_disk_pool_length,
|
|
ova_disk_volume_format_length=ova_disk_volume_format_length,
|
|
ova_disk_volume_name_length=ova_disk_volume_name_length,
|
|
bold='',
|
|
end_bold='',
|
|
ova_name='',
|
|
ova_id='',
|
|
ova_disk_id=str(disk['disk_id']),
|
|
ova_disk_size=str(disk['disk_size_gb']),
|
|
ova_disk_pool=str(disk['pool']),
|
|
ova_disk_volume_format=str(disk['volume_format']),
|
|
ova_disk_volume_name=str(disk['volume_name']),
|
|
)
|
|
)
|
|
|
|
return '\n'.join([ova_list_output_header] + ova_list_output)
|
|
|
|
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'] = 'OVA {}'.format(profile['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
|
|
profile_storage_template_length = 8
|
|
profile_userdata_length = 9
|
|
profile_script_length = 7
|
|
|
|
for profile in profile_data:
|
|
# profile_name column
|
|
_profile_name_length = len(str(profile['name'])) + 1
|
|
if _profile_name_length > profile_name_length:
|
|
profile_name_length = _profile_name_length
|
|
# profile_id column
|
|
_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:
|
|
profile_system_template_length = _profile_system_template_length
|
|
# profile_network_template column
|
|
_profile_network_template_length = len(str(profile['network_template'])) + 1
|
|
if _profile_network_template_length > profile_network_template_length:
|
|
profile_network_template_length = _profile_network_template_length
|
|
# profile_storage_template column
|
|
_profile_storage_template_length = len(str(profile['storage_template'])) + 1
|
|
if _profile_storage_template_length > profile_storage_template_length:
|
|
profile_storage_template_length = _profile_storage_template_length
|
|
# profile_userdata column
|
|
_profile_userdata_length = len(str(profile['userdata'])) + 1
|
|
if _profile_userdata_length > profile_userdata_length:
|
|
profile_userdata_length = _profile_userdata_length
|
|
# profile_script column
|
|
_profile_script_length = len(str(profile['script'])) + 1
|
|
if _profile_script_length > profile_script_length:
|
|
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_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}} \
|
|
Data: {profile_userdata: <{profile_userdata_length}} \
|
|
{profile_script: <{profile_script_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,
|
|
profile_userdata_length=profile_userdata_length,
|
|
profile_script_length=profile_script_length,
|
|
bold=ansiprint.bold(),
|
|
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',
|
|
profile_userdata='Userdata',
|
|
profile_script='Script',
|
|
profile_arguments='Script Arguments'
|
|
)
|
|
|
|
# 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}} {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}} \
|
|
{profile_userdata: <{profile_userdata_length}} \
|
|
{profile_script: <{profile_script_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,
|
|
profile_userdata_length=profile_userdata_length,
|
|
profile_script_length=profile_script_length,
|
|
bold='',
|
|
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'],
|
|
profile_userdata=profile['userdata'],
|
|
profile_script=profile['script'],
|
|
profile_arguments=', '.join(profile['arguments'])
|
|
)
|
|
)
|
|
|
|
return '\n'.join([profile_list_output_header] + profile_list_output)
|
|
|
|
def format_list_task(task_data):
|
|
task_list_output = []
|
|
|
|
# Determine optimal column widths
|
|
task_id_length = 7
|
|
task_type_length = 7
|
|
task_vm_name_length = 5
|
|
task_vm_profile_length = 8
|
|
task_vm_define_length = 8
|
|
task_vm_start_length = 7
|
|
task_worker_length = 8
|
|
|
|
for task in task_data:
|
|
# task_id column
|
|
_task_id_length = len(str(task['id'])) + 1
|
|
if _task_id_length > task_id_length:
|
|
task_id_length = _task_id_length
|
|
# task_type column
|
|
_task_type_length = len(str(task['type'])) + 1
|
|
if _task_type_length > task_type_length:
|
|
task_type_length = _task_type_length
|
|
# task_vm_name column
|
|
_task_vm_name_length = len(str(task['vm_name'])) + 1
|
|
if _task_vm_name_length > task_vm_name_length:
|
|
task_vm_name_length = _task_vm_name_length
|
|
# task_vm_profile column
|
|
_task_vm_profile_length = len(str(task['vm_profile'])) + 1
|
|
if _task_vm_profile_length > task_vm_profile_length:
|
|
task_vm_profile_length = _task_vm_profile_length
|
|
# task_vm_define column
|
|
_task_vm_define_length = len(str(task['vm_define'])) + 1
|
|
if _task_vm_define_length > task_vm_define_length:
|
|
task_vm_define_length = _task_vm_define_length
|
|
# task_vm_start column
|
|
_task_vm_start_length = len(str(task['vm_start'])) + 1
|
|
if _task_vm_start_length > task_vm_start_length:
|
|
task_vm_start_length = _task_vm_start_length
|
|
# task_worker column
|
|
_task_worker_length = len(str(task['worker'])) + 1
|
|
if _task_worker_length > task_worker_length:
|
|
task_worker_length = _task_worker_length
|
|
|
|
# Format the string (header)
|
|
task_list_output_header = '{bold}{task_id: <{task_id_length}} {task_type: <{task_type_length}} \
|
|
{task_worker: <{task_worker_length}} \
|
|
VM: {task_vm_name: <{task_vm_name_length}} \
|
|
{task_vm_profile: <{task_vm_profile_length}} \
|
|
{task_vm_define: <{task_vm_define_length}} \
|
|
{task_vm_start: <{task_vm_start_length}}{end_bold}'.format(
|
|
task_id_length=task_id_length,
|
|
task_type_length=task_type_length,
|
|
task_worker_length=task_worker_length,
|
|
task_vm_name_length=task_vm_name_length,
|
|
task_vm_profile_length=task_vm_profile_length,
|
|
task_vm_define_length=task_vm_define_length,
|
|
task_vm_start_length=task_vm_start_length,
|
|
bold=ansiprint.bold(),
|
|
end_bold=ansiprint.end(),
|
|
task_id='Job ID',
|
|
task_type='Status',
|
|
task_worker='Worker',
|
|
task_vm_name='Name',
|
|
task_vm_profile='Profile',
|
|
task_vm_define='Define?',
|
|
task_vm_start='Start?'
|
|
)
|
|
|
|
# Format the string (elements)
|
|
for task in sorted(task_data, key=lambda i: i.get('type', None)):
|
|
task_list_output.append(
|
|
'{bold}{task_id: <{task_id_length}} {task_type: <{task_type_length}} \
|
|
{task_worker: <{task_worker_length}} \
|
|
{task_vm_name: <{task_vm_name_length}} \
|
|
{task_vm_profile: <{task_vm_profile_length}} \
|
|
{task_vm_define: <{task_vm_define_length}} \
|
|
{task_vm_start: <{task_vm_start_length}}{end_bold}'.format(
|
|
task_id_length=task_id_length,
|
|
task_type_length=task_type_length,
|
|
task_worker_length=task_worker_length,
|
|
task_vm_name_length=task_vm_name_length,
|
|
task_vm_profile_length=task_vm_profile_length,
|
|
task_vm_define_length=task_vm_define_length,
|
|
task_vm_start_length=task_vm_start_length,
|
|
bold='',
|
|
end_bold='',
|
|
task_id=task['id'],
|
|
task_type=task['type'],
|
|
task_worker=task['worker'],
|
|
task_vm_name=task['vm_name'],
|
|
task_vm_profile=task['vm_profile'],
|
|
task_vm_define=task['vm_define'],
|
|
task_vm_start=task['vm_start']
|
|
)
|
|
)
|
|
|
|
return '\n'.join([task_list_output_header] + task_list_output)
|