diff --git a/app/network/forms.py b/app/network/forms.py index cd89d472358acfe2a79be8066a611f3aba646a5d..ab58a88308a8142737f730fb8f9b162b326430cb 100644 --- a/app/network/forms.py +++ b/app/network/forms.py @@ -231,6 +231,7 @@ class CreateVMForm(CSEntryForm): cores = SelectField("Cores", default=2, coerce=int) memory = SelectField("Memory (GB)", default=2, coerce=int) disk = SelectField("Disk (GB)", default=15, coerce=int) + skip_post_install_job = BooleanField("Skip post install job", default=False) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/app/network/views.py b/app/network/views.py index 2a539d86557fb193e06b221813175faf7b4286fa..756d35ccbbf3ee03d00681efdfbe76bd975687a2 100644 --- a/app/network/views.py +++ b/app/network/views.py @@ -192,7 +192,7 @@ def view_host(name): try: host.ansible_vars.update(csentry_vars) # If we don't flag the field as modified, it's not saved to the database - # Might be because we update an existing directory + # Might be because we update an existing dict sa.orm.attributes.flag_modified(host, "ansible_vars") except AttributeError: host.ansible_vars = csentry_vars @@ -202,6 +202,7 @@ def view_host(name): interface, csentry_vars["csentry_vm_memory"], csentry_vars["csentry_vm_cores"], + skip_post_install_job=form.skip_post_install_job.data, ) db.session.commit() current_app.logger.info(f"Creation of {name} requested: task {task.id}") diff --git a/app/settings.py b/app/settings.py index f7fd21102a06988fcf5bee46ca8e84391493a6a6..47043995bb85eae0f6928c0000ff02b1679ef37d 100644 --- a/app/settings.py +++ b/app/settings.py @@ -94,6 +94,14 @@ AWX_CORE_SERVICES_UPDATE = "ics-ans-core @ DHCP test" AWX_CREATE_VM = "deploy-vm-in-proxmox" AWX_CREATE_VIOC = "ics-ans-deploy-vioc" AWX_ZTP_CONFIGURATION = "ics-ans-ztp" +AWX_POST_INSTALL = { + "VIOC": {"esss.lu.se": "", "tn.esss.lu.se": "", "cslab.esss.lu.se": ""}, + "VM": { + "esss.lu.se": "", + "tn.esss.lu.se": "", + "cslab.esss.lu.se": "customize-LabVM", + }, +} AWX_JOB_ENABLED = False AWX_VM_CREATION_ENABLED = False diff --git a/app/tasks.py b/app/tasks.py index 3ba23b15136c505c92da0c5dd2d7e0c5a5d9a4aa..d260ac3152768e442d8f4662f8f9bcbc2c7dbebf 100644 --- a/app/tasks.py +++ b/app/tasks.py @@ -81,8 +81,9 @@ class TaskWorker(Worker): super().prepare_job_execution(job) -def trigger_vm_creation(name, interface, memory, cores): +def trigger_vm_creation(name, interface, memory, cores, skip_post_install_job): """Trigger a job to create a virtual machine or virtual IOC""" + domain = interface.network.domain.name extra_vars = [ f"vmname={name}", f"memory={memory}", @@ -95,13 +96,15 @@ def trigger_vm_creation(name, interface, memory, cores): if interface.is_ioc: task_name = "trigger_vioc_creation" job_template = current_app.config["AWX_CREATE_VIOC"] + post_job_template = current_app.config["AWX_POST_INSTALL"]["VIOC"].get(domain) else: task_name = "trigger_vm_creation" job_template = current_app.config["AWX_CREATE_VM"] + post_job_template = current_app.config["AWX_POST_INSTALL"]["VM"].get(domain) extra_vars.extend( [ f"ip_address={interface.ip}", - f"domain={interface.network.domain.name}", + f"domain={domain}", f"netmask={interface.network.netmask}", f"gateway={interface.network.gateway}", ] @@ -116,6 +119,19 @@ def trigger_vm_creation(name, interface, memory, cores): extra_vars=extra_vars, timeout=500, ) + + if post_job_template and not skip_post_install_job: + current_user.launch_task( + "trigger_post_install_job", + func="launch_job_template", + job_template=post_job_template, + limit=f"{name}.{domain}", + depends_on=task.id, + timeout=500, + ) + current_app.logger.info( + f"Trigger post install job: run {post_job_template} on {name}.{domain}" + ) return task diff --git a/app/templates/_helpers.html b/app/templates/_helpers.html index 4c1f01af4ec88e31269682a56121bb5b7a4f9a1d..29c208444355d2644b858c8a8fc551640896d619 100644 --- a/app/templates/_helpers.html +++ b/app/templates/_helpers.html @@ -100,7 +100,7 @@ {% if field.type == 'BooleanField' %} <div class="col-sm-{{ input_size }} offset-sm-{{ label_size }}"> <div class="form-check"> - {{ field(class_="form-check-input") }} + {{ field(class_="form-check-input", **kwargs) }} {{ field.label(class_="form-check-label") }} </div> </div> diff --git a/app/templates/network/view_host.html b/app/templates/network/view_host.html index 544ab6e9c9f9a5c0cac6cfadc561713f475d1711..38c9b450f7149cae3ba11f4e30b2c10992769f31 100644 --- a/app/templates/network/view_host.html +++ b/app/templates/network/view_host.html @@ -19,7 +19,7 @@ {% block hosts_main %} <div class="row"> - <div class="col-sm-9"> + <div class="col-sm-8"> <dl class="row"> <dt class="col-sm-3">Hostname</dt> <dd class="col-sm-9"> @@ -70,17 +70,20 @@ {% else %} {% set vm_type = 'VM' %} {% endif %} - <div class="col-sm-3"> + <div class="col-sm-4"> <form id="createVMForm" method="POST"> {{ form.hidden_tag() }} - {{ render_field(form.cores, label_size='6', input_size='6') }} - {{ render_field(form.memory, label_size='6', input_size='6') }} - {{ render_field(form.disk, label_size='6', input_size='6') }} + {{ render_field(form.cores, label_size='5', input_size='7') }} + {{ render_field(form.memory, label_size='5', input_size='7') }} + {{ render_field(form.disk, label_size='5', input_size='7') }} + {% if current_user.is_admin %} + {{ render_field(form.skip_post_install_job, label_size='5', input_size='7') }} + {% endif %} {{ submit_button_with_confirmation('Create ' + vm_type, 'Do you really want to create the ' + vm_type + ' ' + host.name + '?') }} </form> </div> {% elif host.device_type.name == 'Network' and host.model and current_user.is_admin %} - <div class="col-sm-3"> + <div class="col-sm-4"> <form id="generateZTPForm" method="POST"> {{ form.hidden_tag() }} {{ submit_button_with_confirmation('Generate ZTP configuration', 'Do you really want to generate the ZTP configuration for ' + host.name + '?') }} diff --git a/docs/_static/create_vioc.png b/docs/_static/create_vioc.png index 8febd8a537f74bb0d371a39c07a9c42c604231cc..c7878ba683e67765734f2ff4fa6e9de6c2891631 100644 Binary files a/docs/_static/create_vioc.png and b/docs/_static/create_vioc.png differ diff --git a/docs/_static/create_vm.png b/docs/_static/create_vm.png index df0b4f85b6df2fc8a4bc1d7abb0567a17124eb0f..16033163b3bcb4054e3327e1cda5a1a78cb2e8e4 100644 Binary files a/docs/_static/create_vm.png and b/docs/_static/create_vm.png differ diff --git a/docs/_static/create_vm_confirmation.png b/docs/_static/create_vm_confirmation.png index 1ec33d60b6b5bd333b04b24560d703b6fb645607..49482bfc7ffb3cdf1c8c5518af2e075039403de5 100644 Binary files a/docs/_static/create_vm_confirmation.png and b/docs/_static/create_vm_confirmation.png differ diff --git a/docs/network.rst b/docs/network.rst index 050d6bb54d9c102d1a6308af3df1bf415e72d54c..78cbb2c7b5cb7049abd92c6f76892114d631d082 100644 --- a/docs/network.rst +++ b/docs/network.rst @@ -137,6 +137,13 @@ In both case, a confirmation dialog will be displayed when you submit the form. .. image:: _static/create_vm_confirmation.png +To create a VM or VIOC, a job template is triggered on AWX (**AWX_CREATE_VM** or **AWX_CREATE_VIOC**). +If a post install job template is defined, a task is enqueued to run after the successful completion of the first one. +The post install job name can be defined per domain in the **AWX_POST_INSTALL** dictionary. + +Admin users can disable the post install job run by selecting the *Skip post install job* checkbox. +This checkbox is only visible to admin users. + Ansible inventory -----------------