Allow specifying arbitrary script_args on CLI

Allow the specifying of arbitrary provisioner script install() args on
the provisioner create CLI, either overriding or adding additional
per-VM arguments to those found in the profile. Reference example is
setting a "vm_fqdn" on a per-run basis.

Closes #100
This commit is contained in:
Joshua Boniface 2020-07-08 13:18:12 -04:00
parent 8fc5299d38
commit a1ba9d2eeb
4 changed files with 33 additions and 10 deletions

View File

@ -195,8 +195,9 @@ def Authenticator(function):
# Job functions # Job functions
# #
@celery.task(bind=True) @celery.task(bind=True)
def create_vm(self, vm_name, profile_name, define_vm=True, start_vm=True): def create_vm(self, vm_name, profile_name, define_vm=True, start_vm=True, script_run_args=[]):
return api_provisioner.create_vm(self, vm_name, profile_name, define_vm=define_vm, start_vm=start_vm) print(script_run_args)
return api_provisioner.create_vm(self, vm_name, profile_name, define_vm=define_vm, start_vm=start_vm, script_run_args=script_run_args)
########################################################## ##########################################################
@ -5974,7 +5975,8 @@ class API_Provisioner_Create_Root(Resource):
{ 'name': 'name', 'required': True, 'helpmsg': "A VM name must be specified." }, { 'name': 'name', 'required': True, 'helpmsg': "A VM name must be specified." },
{ 'name': 'profile', 'required': True, 'helpmsg': "A profile name must be specified." }, { 'name': 'profile', 'required': True, 'helpmsg': "A profile name must be specified." },
{ 'name': 'define_vm' }, { 'name': 'define_vm' },
{ 'name': 'start_vm' } { 'name': 'start_vm' },
{ 'name': 'arg', 'action': 'append' }
]) ])
@Authenticator @Authenticator
def post(self, reqargs): def post(self, reqargs):
@ -6005,6 +6007,10 @@ class API_Provisioner_Create_Root(Resource):
type: boolean type: boolean
required: false required: false
description: Whether to start the VM after provisioning description: Whether to start the VM after provisioning
- in: query
name: arg
type: string
description: Script install() function keywork argument in "arg=data" format; may be specified multiple times to add multiple arguments
responses: responses:
200: 200:
description: OK description: OK
@ -6039,7 +6045,8 @@ class API_Provisioner_Create_Root(Resource):
reqargs.get('name', None), reqargs.get('name', None),
reqargs.get('profile', None), reqargs.get('profile', None),
define_vm=define_vm, define_vm=define_vm,
start_vm=start_vm start_vm=start_vm,
script_run_args=reqargs.get('arg', []),
) )
return { "task_id": task.id }, 202, { 'Location': Api.url_for(api, API_Provisioner_Status_Element, task_id=task.id) } return { "task_id": task.id }, 202, { 'Location': Api.url_for(api, API_Provisioner_Status_Element, task_id=task.id) }
api.add_resource(API_Provisioner_Create_Root, '/provisioner/create') api.add_resource(API_Provisioner_Create_Root, '/provisioner/create')

View File

@ -1026,7 +1026,7 @@ def delete_profile(name):
# #
# Main VM provisioning function - executed by the Celery worker # Main VM provisioning function - executed by the Celery worker
# #
def create_vm(self, vm_name, vm_profile, define_vm=True, start_vm=True): def create_vm(self, vm_name, vm_profile, define_vm=True, start_vm=True, script_run_args=[]):
# Runtime imports # Runtime imports
import time import time
import importlib import importlib
@ -1542,6 +1542,13 @@ def create_vm(self, vm_name, vm_profile, define_vm=True, start_vm=True):
argument_name, argument_data = argument.split('=') argument_name, argument_data = argument.split('=')
script_arguments[argument_name] = argument_data script_arguments[argument_name] = argument_data
# Parse the runtime arguments
for argument in script_run_args:
argument_name, argument_data = argument.split('=')
script_arguments[argument_name] = argument_data
print("Script arguments: {}".format(script_arguments))
# Run the script # Run the script
try: try:
installer_script.install( installer_script.install(

View File

@ -557,19 +557,20 @@ def profile_remove(config, name):
return retvalue, response.json()['message'] return retvalue, response.json()['message']
def vm_create(config, name, profile, wait_flag, define_flag, start_flag): def vm_create(config, name, profile, wait_flag, define_flag, start_flag, script_args):
""" """
Create a new VM named {name} with profile {profile} Create a new VM named {name} with profile {profile}
API endpoint: POST /api/v1/provisioner/create API endpoint: POST /api/v1/provisioner/create
API_arguments: name={name}, profile={profile} API_arguments: name={name}, profile={profile}, arg={script_args}
API schema: {message} API schema: {message}
""" """
params = { params = {
'name': name, 'name': name,
'profile': profile, 'profile': profile,
'start_vm': start_flag, 'start_vm': start_flag,
'define_vm': define_flag 'define_vm': define_flag,
'arg': script_args
} }
response = call_api(config, 'post', '/provisioner/create', params=params) response = call_api(config, 'post', '/provisioner/create', params=params)

View File

@ -3316,6 +3316,11 @@ def provisioner_profile_remove(name, confirm_flag):
@click.argument( @click.argument(
'profile' 'profile'
) )
@click.option(
'-a', '--script-arg', 'script_args',
default=[], multiple=True,
help='Additional argument to the script install() function in key=value format.'
)
@click.option( @click.option(
'-d/-D', '--define/--no-define', 'define_flag', '-d/-D', '--define/--no-define', 'define_flag',
is_flag=True, default=True, show_default=True, is_flag=True, default=True, show_default=True,
@ -3332,7 +3337,7 @@ def provisioner_profile_remove(name, confirm_flag):
help='Wait for provisioning to complete, showing progress' help='Wait for provisioning to complete, showing progress'
) )
@cluster_req @cluster_req
def provisioner_create(name, profile, wait_flag, define_flag, start_flag): def provisioner_create(name, profile, wait_flag, define_flag, start_flag, script_args):
""" """
Create a new VM NAME with profile PROFILE. Create a new VM NAME with profile PROFILE.
@ -3345,11 +3350,14 @@ def provisioner_create(name, profile, wait_flag, define_flag, start_flag):
created VM on the PVC cluster. This can be useful for the administrator to create a "template" created VM on the PVC cluster. This can be useful for the administrator to create a "template"
set of VM disks via the normal provisioner, but without ever starting the resulting VM. The set of VM disks via the normal provisioner, but without ever starting the resulting VM. The
resulting disk(s) can then be used as source volumes in other disk templates. resulting disk(s) can then be used as source volumes in other disk templates.
The "--script-arg" option can be specified as many times as required to pass additional,
VM-specific arguments to the provisioner install() function, beyond those set by the profile.
""" """
if not define_flag: if not define_flag:
start_flag = False start_flag = False
retcode, retdata = pvc_provisioner.vm_create(config, name, profile, wait_flag, define_flag, start_flag) retcode, retdata = pvc_provisioner.vm_create(config, name, profile, wait_flag, define_flag, start_flag, script_args)
if retcode and wait_flag: if retcode and wait_flag:
task_id = retdata task_id = retdata