Add OVA script support
1. Ensure that system_template and script are not nullable in the DB. 2. Ensure that the CLI and API enforce the above and clean up CLI arguments for profile add. 3. Ensure that, before uploading OVAs, a 'default_ova' provisioning script is present. 4. Use the 'default_ova' script for new OVA uploads. 5. Ensure that OVA details are properly added to the vm_data dict in the provisioner vmbuilder.
This commit is contained in:
parent
bffab7a5a1
commit
7a3870fc44
|
@ -0,0 +1,38 @@
|
|||
"""PVC version 0.9.55
|
||||
|
||||
Revision ID: 88fa0d88a9f8
|
||||
Revises: 5c2109dbbeae
|
||||
Create Date: 2022-10-06 10:33:38.784497
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '88fa0d88a9f8'
|
||||
down_revision = '5c2109dbbeae'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.alter_column('profile', 'script',
|
||||
existing_type=sa.INTEGER(),
|
||||
nullable=False)
|
||||
op.alter_column('profile', 'system_template',
|
||||
existing_type=sa.INTEGER(),
|
||||
nullable=False)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.alter_column('profile', 'system_template',
|
||||
existing_type=sa.INTEGER(),
|
||||
nullable=True)
|
||||
op.alter_column('profile', 'script',
|
||||
existing_type=sa.INTEGER(),
|
||||
nullable=True)
|
||||
# ### end Alembic commands ###
|
|
@ -7352,11 +7352,19 @@ class API_Provisioner_Profile_Root(Resource):
|
|||
"required": True,
|
||||
"helptext": "A profile type must be specified.",
|
||||
},
|
||||
{"name": "system_template"},
|
||||
{
|
||||
"name": "system_template",
|
||||
"required": True,
|
||||
"helptext": "A system_template must be specified.",
|
||||
},
|
||||
{"name": "network_template"},
|
||||
{"name": "storage_template"},
|
||||
{"name": "userdata"},
|
||||
{"name": "script"},
|
||||
{
|
||||
"name": "script",
|
||||
"required": True,
|
||||
"helptext": "A script must be specified.",
|
||||
},
|
||||
{"name": "ova"},
|
||||
{"name": "arg", "action": "append"},
|
||||
]
|
||||
|
@ -7385,12 +7393,12 @@ class API_Provisioner_Profile_Root(Resource):
|
|||
- in: query
|
||||
name: script
|
||||
type: string
|
||||
required: false
|
||||
required: true
|
||||
description: Script name
|
||||
- in: query
|
||||
name: system_template
|
||||
type: string
|
||||
required: false
|
||||
required: true
|
||||
description: System template name
|
||||
- in: query
|
||||
name: network_template
|
||||
|
@ -7473,11 +7481,19 @@ class API_Provisioner_Profile_Element(Resource):
|
|||
"required": True,
|
||||
"helptext": "A profile type must be specified.",
|
||||
},
|
||||
{"name": "system_template"},
|
||||
{
|
||||
"name": "system_template",
|
||||
"required": True,
|
||||
"helptext": "A system_template must be specified.",
|
||||
},
|
||||
{"name": "network_template"},
|
||||
{"name": "storage_template"},
|
||||
{"name": "userdata"},
|
||||
{"name": "script"},
|
||||
{
|
||||
"name": "script",
|
||||
"required": True,
|
||||
"helptext": "A script must be specified.",
|
||||
},
|
||||
{"name": "ova"},
|
||||
{"name": "arg", "action": "append"},
|
||||
]
|
||||
|
@ -7511,17 +7527,17 @@ class API_Provisioner_Profile_Element(Resource):
|
|||
- in: query
|
||||
name: network_template
|
||||
type: string
|
||||
required: true
|
||||
required: false
|
||||
description: Network template name
|
||||
- in: query
|
||||
name: storage_template
|
||||
type: string
|
||||
required: true
|
||||
required: false
|
||||
description: Storage template name
|
||||
- in: query
|
||||
name: userdata
|
||||
type: string
|
||||
required: true
|
||||
required: false
|
||||
description: Userdata template name
|
||||
- in: query
|
||||
name: ova
|
||||
|
|
|
@ -230,11 +230,13 @@ class DBProfile(db.Model):
|
|||
id = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.Text, nullable=False, unique=True)
|
||||
profile_type = db.Column(db.Text, nullable=False)
|
||||
system_template = db.Column(db.Integer, db.ForeignKey("system_template.id"))
|
||||
system_template = db.Column(
|
||||
db.Integer, db.ForeignKey("system_template.id"), nullable=False
|
||||
)
|
||||
network_template = db.Column(db.Integer, db.ForeignKey("network_template.id"))
|
||||
storage_template = db.Column(db.Integer, db.ForeignKey("storage_template.id"))
|
||||
userdata = db.Column(db.Integer, db.ForeignKey("userdata.id"))
|
||||
script = db.Column(db.Integer, db.ForeignKey("script.id"))
|
||||
script = db.Column(db.Integer, db.ForeignKey("script.id"), nullable=False)
|
||||
ova = db.Column(db.Integer, db.ForeignKey("ova.id"))
|
||||
arguments = db.Column(db.Text)
|
||||
|
||||
|
|
|
@ -168,6 +168,15 @@ def delete_ova(zkhandler, name):
|
|||
|
||||
@ZKConnection(config)
|
||||
def upload_ova(zkhandler, pool, name, ova_size):
|
||||
# Check that we have a default_ova provisioning script
|
||||
_, retcode = provisioner.list_script("default_ova", is_fuzzy=False)
|
||||
if retcode != "200":
|
||||
output = {
|
||||
"message": "Did not find a 'default_ova' provisioning script. Please add one with that name, either the example from '/usr/share/pvc/provisioner/examples/script/2-ova.py' or a custom one, before uploading OVAs."
|
||||
}
|
||||
retcode = 400
|
||||
return output, retcode
|
||||
|
||||
ova_archive = None
|
||||
|
||||
# Cleanup function
|
||||
|
@ -402,7 +411,7 @@ def upload_ova(zkhandler, pool, name, ova_size):
|
|||
None,
|
||||
None,
|
||||
userdata=None,
|
||||
script=None,
|
||||
script="default_ova",
|
||||
ova=name,
|
||||
arguments=None,
|
||||
)
|
||||
|
|
|
@ -277,6 +277,8 @@ def create_vm(
|
|||
vm_data["script"] = db_row.get("script")
|
||||
else:
|
||||
vm_data["script"] = None
|
||||
|
||||
if profile_data.get("profile_type") == "ova":
|
||||
query = "SELECT * FROM ova WHERE id = %s"
|
||||
args = (profile_data["ova"],)
|
||||
db_cur.execute(query, args)
|
||||
|
@ -285,6 +287,7 @@ def create_vm(
|
|||
query = "SELECT * FROM ova_volume WHERE ova = %s"
|
||||
args = (profile_data["ova"],)
|
||||
db_cur.execute(query, args)
|
||||
# Replace the existing volumes list with our OVA volume list
|
||||
vm_data["volumes"] = db_cur.fetchall()
|
||||
|
||||
retcode, stdout, stderr = pvc_common.run_os_command("uname -m")
|
||||
|
|
|
@ -5265,7 +5265,8 @@ def provisioner_profile_list(limit):
|
|||
"-s",
|
||||
"--system-template",
|
||||
"system_template",
|
||||
help="The system template for the profile.",
|
||||
required=True,
|
||||
help="The system template for the profile (required).",
|
||||
)
|
||||
@click.option(
|
||||
"-n",
|
||||
|
@ -5280,10 +5281,24 @@ def provisioner_profile_list(limit):
|
|||
help="The storage template for the profile.",
|
||||
)
|
||||
@click.option(
|
||||
"-u", "--userdata", "userdata", help="The userdata document for the profile."
|
||||
"-u",
|
||||
"--userdata",
|
||||
"userdata",
|
||||
help="The userdata document for the profile.",
|
||||
)
|
||||
@click.option(
|
||||
"-x",
|
||||
"--script",
|
||||
"script",
|
||||
required=True,
|
||||
help="The script for the profile (required).",
|
||||
)
|
||||
@click.option(
|
||||
"-o",
|
||||
"--ova",
|
||||
"ova",
|
||||
help="The OVA image for the profile; set automatically with 'provisioner ova upload'.",
|
||||
)
|
||||
@click.option("-x", "--script", "script", help="The script for the profile.")
|
||||
@click.option("-o", "--ova", "ova", help="The OVA image for the profile.")
|
||||
@click.option(
|
||||
"-a",
|
||||
"--script-arg",
|
||||
|
|
|
@ -3025,14 +3025,14 @@
|
|||
"description": "Script name",
|
||||
"in": "query",
|
||||
"name": "script",
|
||||
"required": false,
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "System template name",
|
||||
"in": "query",
|
||||
"name": "system_template",
|
||||
"required": false,
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
|
@ -3165,21 +3165,21 @@
|
|||
"description": "Network template name",
|
||||
"in": "query",
|
||||
"name": "network_template",
|
||||
"required": true,
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "Storage template name",
|
||||
"in": "query",
|
||||
"name": "storage_template",
|
||||
"required": true,
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "Userdata template name",
|
||||
"in": "query",
|
||||
"name": "userdata",
|
||||
"required": true,
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue