Support per-VM migration type selectors
Allow a VM to specify its migration type as a default choice. The valid options are "default" (i.e. behave as now), "live" which forces a live migration only, and "shutdown" which forces a shutdown migration only. The new option is treated as a VM meta option and is set to default if not found.
This commit is contained in:
@ -834,6 +834,9 @@ class API_VM_Root(Resource):
|
||||
node_autostart:
|
||||
type: boolean
|
||||
description: Whether to autostart the VM when its node returns to ready domain state
|
||||
migration_method:
|
||||
type: string
|
||||
description: The preferred migration method (live, shutdown, none)
|
||||
description:
|
||||
type: string
|
||||
description: The description of the VM
|
||||
@ -1036,6 +1039,7 @@ class API_VM_Root(Resource):
|
||||
{ 'name': 'node' },
|
||||
{ 'name': 'selector', 'choices': ('mem', 'vcpus', 'load', 'vms'), 'helptext': "A valid selector must be specified" },
|
||||
{ 'name': 'autostart' },
|
||||
{ 'name': 'migration_method', 'choices': ('live', 'shutdown', 'none'), 'helptext': "A valid migration_method must be specified" },
|
||||
{ 'name': 'xml', 'required': True, 'helptext': "A Libvirt XML document must be specified" },
|
||||
])
|
||||
@Authenticator
|
||||
@ -1077,6 +1081,16 @@ class API_VM_Root(Resource):
|
||||
type: boolean
|
||||
required: false
|
||||
description: Whether to autostart the VM when its node returns to ready domain state
|
||||
- in: query
|
||||
name: migration_method
|
||||
type: string
|
||||
required: false
|
||||
description: The preferred migration method (live, shutdown, none)
|
||||
default: none
|
||||
enum:
|
||||
- live
|
||||
- shutdown
|
||||
- none
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
@ -1094,7 +1108,8 @@ class API_VM_Root(Resource):
|
||||
reqargs.get('node', None),
|
||||
reqargs.get('limit', None),
|
||||
reqargs.get('selector', 'mem'),
|
||||
bool(strtobool(reqargs.get('autostart', 'false')))
|
||||
bool(strtobool(reqargs.get('autostart', 'false'))),
|
||||
reqargs.get('migration_method', 'none')
|
||||
)
|
||||
api.add_resource(API_VM_Root, '/vm')
|
||||
|
||||
@ -1125,6 +1140,7 @@ class API_VM_Element(Resource):
|
||||
{ 'name': 'node' },
|
||||
{ 'name': 'selector', 'choices': ('mem', 'vcpus', 'load', 'vms'), 'helptext': "A valid selector must be specified" },
|
||||
{ 'name': 'autostart' },
|
||||
{ 'name': 'migration_method', 'choices': ('live', 'shutdown', 'none'), 'helptext': "A valid migration_method must be specified" },
|
||||
{ 'name': 'xml', 'required': True, 'helptext': "A Libvirt XML document must be specified" },
|
||||
])
|
||||
@Authenticator
|
||||
@ -1168,6 +1184,16 @@ class API_VM_Element(Resource):
|
||||
type: boolean
|
||||
required: false
|
||||
description: Whether to autostart the VM when its node returns to ready domain state
|
||||
- in: query
|
||||
name: migration_method
|
||||
type: string
|
||||
required: false
|
||||
description: The preferred migration method (live, shutdown, none)
|
||||
default: none
|
||||
enum:
|
||||
- live
|
||||
- shutdown
|
||||
- none
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
@ -1185,7 +1211,8 @@ class API_VM_Element(Resource):
|
||||
reqargs.get('node', None),
|
||||
reqargs.get('limit', None),
|
||||
reqargs.get('selector', 'mem'),
|
||||
bool(strtobool(reqargs.get('autostart', 'false')))
|
||||
bool(strtobool(reqargs.get('autostart', 'false'))),
|
||||
reqargs.get('migration_method', 'none')
|
||||
)
|
||||
|
||||
@RequestParser([
|
||||
@ -1296,6 +1323,9 @@ class API_VM_Metadata(Resource):
|
||||
node_autostart:
|
||||
type: string
|
||||
description: Whether to autostart the VM when its node returns to ready domain state
|
||||
migration_method:
|
||||
type: string
|
||||
description: The preferred migration method (live, shutdown, none)
|
||||
404:
|
||||
description: Not found
|
||||
schema:
|
||||
@ -1309,6 +1339,7 @@ class API_VM_Metadata(Resource):
|
||||
{ 'name': 'selector', 'choices': ('mem', 'vcpus', 'load', 'vms'), 'helptext': "A valid selector must be specified" },
|
||||
{ 'name': 'autostart' },
|
||||
{ 'name': 'profile' },
|
||||
{ 'name': 'migration_method', 'choices': ('live', 'shutdown', 'none'), 'helptext': "A valid migration_method must be specified" },
|
||||
])
|
||||
@Authenticator
|
||||
def post(self, vm, reqargs):
|
||||
@ -1343,6 +1374,16 @@ class API_VM_Metadata(Resource):
|
||||
type: string
|
||||
required: false
|
||||
description: The PVC provisioner profile for the VM
|
||||
- in: query
|
||||
name: migration_method
|
||||
type: string
|
||||
required: false
|
||||
description: The preferred migration method (live, shutdown, none)
|
||||
default: none
|
||||
enum:
|
||||
- live
|
||||
- shutdown
|
||||
- none
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
@ -1360,7 +1401,8 @@ class API_VM_Metadata(Resource):
|
||||
reqargs.get('limit', None),
|
||||
reqargs.get('selector', None),
|
||||
reqargs.get('autostart', None),
|
||||
reqargs.get('profile', None)
|
||||
reqargs.get('profile', None),
|
||||
reqargs.get('migration_method', None)
|
||||
)
|
||||
api.add_resource(API_VM_Metadata, '/vm/<vm>/meta')
|
||||
|
||||
@ -4057,6 +4099,9 @@ class API_Provisioner_Template_System_Root(Resource):
|
||||
node_autostart:
|
||||
type: boolean
|
||||
description: Whether to start VM with node ready state (one-time)
|
||||
migration_method:
|
||||
type: string
|
||||
description: The preferred migration method (live, shutdown, none)
|
||||
parameters:
|
||||
- in: query
|
||||
name: limit
|
||||
@ -4084,7 +4129,8 @@ class API_Provisioner_Template_System_Root(Resource):
|
||||
{ 'name': 'vnc_bind' },
|
||||
{ 'name': 'node_limit' },
|
||||
{ 'name': 'node_selector' },
|
||||
{ 'name': 'node_autostart' }
|
||||
{ 'name': 'node_autostart' },
|
||||
{ 'name': 'migration_method' }
|
||||
])
|
||||
@Authenticator
|
||||
def post(self, reqargs):
|
||||
@ -4139,6 +4185,11 @@ class API_Provisioner_Template_System_Root(Resource):
|
||||
type: boolean
|
||||
required: false
|
||||
description: Whether to start VM with node ready state (one-time)
|
||||
- in: query
|
||||
name: migration_method
|
||||
type: string
|
||||
required: false
|
||||
description: The preferred migration method (live, shutdown, none)
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
@ -4185,7 +4236,8 @@ class API_Provisioner_Template_System_Root(Resource):
|
||||
vnc_bind,
|
||||
reqargs.get('node_limit', None),
|
||||
reqargs.get('node_selector', None),
|
||||
node_autostart
|
||||
node_autostart,
|
||||
reqargs.get('migration_method', None),
|
||||
)
|
||||
api.add_resource(API_Provisioner_Template_System_Root, '/provisioner/template/system')
|
||||
|
||||
@ -4222,7 +4274,8 @@ class API_Provisioner_Template_System_Element(Resource):
|
||||
{ 'name': 'vnc_bind' },
|
||||
{ 'name': 'node_limit' },
|
||||
{ 'name': 'node_selector' },
|
||||
{ 'name': 'node_autostart' }
|
||||
{ 'name': 'node_autostart' },
|
||||
{ 'name': 'migration_method' }
|
||||
])
|
||||
@Authenticator
|
||||
def post(self, template, reqargs):
|
||||
@ -4272,6 +4325,11 @@ class API_Provisioner_Template_System_Element(Resource):
|
||||
type: boolean
|
||||
required: false
|
||||
description: Whether to start VM with node ready state (one-time)
|
||||
- in: query
|
||||
name: migration_method
|
||||
type: string
|
||||
required: false
|
||||
description: The preferred migration method (live, shutdown, none)
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
@ -4318,7 +4376,8 @@ class API_Provisioner_Template_System_Element(Resource):
|
||||
vnc_bind,
|
||||
reqargs.get('node_limit', None),
|
||||
reqargs.get('node_selector', None),
|
||||
node_autostart
|
||||
node_autostart,
|
||||
reqargs.get('migration_method', None),
|
||||
)
|
||||
|
||||
@RequestParser([
|
||||
@ -4329,7 +4388,8 @@ class API_Provisioner_Template_System_Element(Resource):
|
||||
{ 'name': 'vnc_bind' },
|
||||
{ 'name': 'node_limit' },
|
||||
{ 'name': 'node_selector' },
|
||||
{ 'name': 'node_autostart' }
|
||||
{ 'name': 'node_autostart' },
|
||||
{ 'name': 'migration_method' }
|
||||
])
|
||||
@Authenticator
|
||||
def put(self, template, reqargs):
|
||||
@ -4371,6 +4431,10 @@ class API_Provisioner_Template_System_Element(Resource):
|
||||
name: node_autostart
|
||||
type: boolean
|
||||
description: Whether to start VM with node ready state (one-time)
|
||||
- in: query
|
||||
name: migration_method
|
||||
type: string
|
||||
description: The preferred migration method (live, shutdown, none)
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
@ -4392,7 +4456,8 @@ class API_Provisioner_Template_System_Element(Resource):
|
||||
reqargs.get('vnc_bind'),
|
||||
reqargs.get('node_limit', None),
|
||||
reqargs.get('node_selector', None),
|
||||
reqargs.get('node_autostart', None)
|
||||
reqargs.get('node_autostart', None),
|
||||
reqargs.get('migration_method', None)
|
||||
)
|
||||
|
||||
@Authenticator
|
||||
|
@ -431,7 +431,7 @@ def vm_list(node=None, state=None, limit=None, is_fuzzy=True):
|
||||
|
||||
return retdata, retcode
|
||||
|
||||
def vm_define(xml, node, limit, selector, autostart):
|
||||
def vm_define(xml, node, limit, selector, autostart, migration_method):
|
||||
"""
|
||||
Define a VM from Libvirt XML in the PVC cluster.
|
||||
"""
|
||||
@ -443,7 +443,7 @@ def vm_define(xml, node, limit, selector, autostart):
|
||||
return { 'message': 'XML is malformed or incorrect: {}'.format(e) }, 400
|
||||
|
||||
zk_conn = pvc_common.startZKConnection(config['coordinators'])
|
||||
retflag, retdata = pvc_vm.define_vm(zk_conn, new_cfg, node, limit, selector, autostart, profile=None)
|
||||
retflag, retdata = pvc_vm.define_vm(zk_conn, new_cfg, node, limit, selector, autostart, migration_method, profile=None)
|
||||
pvc_common.stopZKConnection(zk_conn)
|
||||
|
||||
if retflag:
|
||||
@ -475,7 +475,8 @@ def get_vm_meta(vm):
|
||||
'name': vm,
|
||||
'node_limit': retdata['node_limit'],
|
||||
'node_selector': retdata['node_selector'],
|
||||
'node_autostart': retdata['node_autostart']
|
||||
'node_autostart': retdata['node_autostart'],
|
||||
'migration_method': retdata['migration_method']
|
||||
}
|
||||
else:
|
||||
retcode = 404
|
||||
@ -490,7 +491,7 @@ def get_vm_meta(vm):
|
||||
|
||||
return retdata, retcode
|
||||
|
||||
def update_vm_meta(vm, limit, selector, autostart, provisioner_profile):
|
||||
def update_vm_meta(vm, limit, selector, autostart, provisioner_profile, migration_method):
|
||||
"""
|
||||
Update metadata of a VM.
|
||||
"""
|
||||
@ -500,7 +501,7 @@ def update_vm_meta(vm, limit, selector, autostart, provisioner_profile):
|
||||
autostart = bool(strtobool(autostart))
|
||||
except:
|
||||
autostart = False
|
||||
retflag, retdata = pvc_vm.modify_vm_metadata(zk_conn, vm, limit, selector, autostart, provisioner_profile)
|
||||
retflag, retdata = pvc_vm.modify_vm_metadata(zk_conn, vm, limit, selector, autostart, provisioner_profile, migration_method)
|
||||
pvc_common.stopZKConnection(zk_conn)
|
||||
|
||||
if retflag:
|
||||
|
@ -35,9 +35,10 @@ class DBSystemTemplate(db.Model):
|
||||
node_limit = db.Column(db.Text)
|
||||
node_selector = db.Column(db.Text)
|
||||
node_autostart = db.Column(db.Boolean, nullable=False)
|
||||
migration_method = db.Column(db.Text)
|
||||
ova = db.Column(db.Integer, db.ForeignKey("ova.id"), nullable=True)
|
||||
|
||||
def __init__(self, name, vcpu_count, vram_mb, serial, vnc, vnc_bind, node_limit, node_selector, node_autostart, ova=None):
|
||||
def __init__(self, name, vcpu_count, vram_mb, serial, vnc, vnc_bind, node_limit, node_selector, node_autostart, migration_method, ova=None):
|
||||
self.name = name
|
||||
self.vcpu_count = vcpu_count
|
||||
self.vram_mb = vram_mb
|
||||
@ -47,6 +48,7 @@ class DBSystemTemplate(db.Model):
|
||||
self.node_limit = node_limit
|
||||
self.node_selector = node_selector
|
||||
self.node_autostart = node_autostart
|
||||
self.migration_method = migration_method
|
||||
self.ova = ova
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -214,14 +214,14 @@ def template_list(limit):
|
||||
#
|
||||
# Template Create functions
|
||||
#
|
||||
def create_template_system(name, vcpu_count, vram_mb, serial=False, vnc=False, vnc_bind=None, node_limit=None, node_selector=None, node_autostart=False, ova=None):
|
||||
def create_template_system(name, vcpu_count, vram_mb, serial=False, vnc=False, vnc_bind=None, node_limit=None, node_selector=None, node_autostart=False, migration_method=None, ova=None):
|
||||
if list_template_system(name, is_fuzzy=False)[-1] != 404:
|
||||
retmsg = { 'message': 'The system template "{}" already exists.'.format(name) }
|
||||
retcode = 400
|
||||
return retmsg, retcode
|
||||
|
||||
query = "INSERT INTO system_template (name, vcpu_count, vram_mb, serial, vnc, vnc_bind, node_limit, node_selector, node_autostart, ova) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s);"
|
||||
args = (name, vcpu_count, vram_mb, serial, vnc, vnc_bind, node_limit, node_selector, node_autostart, ova)
|
||||
query = "INSERT INTO system_template (name, vcpu_count, vram_mb, serial, vnc, vnc_bind, node_limit, node_selector, node_autostart, migration_method, ova) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s);"
|
||||
args = (name, vcpu_count, vram_mb, serial, vnc, vnc_bind, node_limit, node_selector, node_autostart, migration_method, ova)
|
||||
|
||||
conn, cur = open_database(config)
|
||||
try:
|
||||
@ -359,7 +359,7 @@ def create_template_storage_element(name, disk_id, pool, source_volume=None, dis
|
||||
#
|
||||
# Template Modify functions
|
||||
#
|
||||
def modify_template_system(name, vcpu_count=None, vram_mb=None, serial=None, vnc=None, vnc_bind=None, node_limit=None, node_selector=None, node_autostart=None):
|
||||
def modify_template_system(name, vcpu_count=None, vram_mb=None, serial=None, vnc=None, vnc_bind=None, node_limit=None, node_selector=None, node_autostart=None, migration_method=None):
|
||||
if list_profile(name, is_fuzzy=False)[-1] != 200:
|
||||
retmsg = { 'message': 'The system template "{}" does not exist.'.format(name) }
|
||||
retcode = 400
|
||||
@ -420,6 +420,9 @@ def modify_template_system(name, vcpu_count=None, vram_mb=None, serial=None, vnc
|
||||
retcode = 400
|
||||
fields.append({'field': 'node_autostart', 'data': node_autostart})
|
||||
|
||||
if migration_method is not None:
|
||||
fields.append({'field': 'migration_method', 'data': migration_method})
|
||||
|
||||
conn, cur = open_database(config)
|
||||
try:
|
||||
for field in fields:
|
||||
@ -1403,7 +1406,8 @@ def create_vm(self, vm_name, vm_profile, define_vm=True, start_vm=True, script_r
|
||||
node_limit = node_limit.split(',')
|
||||
node_selector = vm_data['system_details']['node_selector']
|
||||
node_autostart = vm_data['system_details']['node_autostart']
|
||||
retcode, retmsg = pvc_vm.define_vm(zk_conn, vm_schema.strip(), target_node, node_limit, node_selector, node_autostart, vm_profile, initial_state='provision')
|
||||
migration_method = vm_data['system_details']['migration_method']
|
||||
retcode, retmsg = pvc_vm.define_vm(zk_conn, vm_schema.strip(), target_node, node_limit, node_selector, node_autostart, migration_method, vm_profile, initial_state='provision')
|
||||
print(retmsg)
|
||||
else:
|
||||
print("Skipping VM definition")
|
||||
|
Reference in New Issue
Block a user