parent
9de14c46fb
commit
f46c2e7f6a
|
@ -1804,6 +1804,45 @@ class API_VM_Console(Resource):
|
||||||
api.add_resource(API_VM_Console, '/vm/<vm>/console')
|
api.add_resource(API_VM_Console, '/vm/<vm>/console')
|
||||||
|
|
||||||
|
|
||||||
|
# /vm/<vm>/rename
|
||||||
|
class API_VM_Rename(Resource):
|
||||||
|
@RequestParser([
|
||||||
|
{'name': 'new_name'}
|
||||||
|
])
|
||||||
|
@Authenticator
|
||||||
|
def post(self, vm, reqargs):
|
||||||
|
"""
|
||||||
|
Rename VM {vm}, and all connected disk volumes which include this name, to {new_name}
|
||||||
|
---
|
||||||
|
tags:
|
||||||
|
- vm
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: new_name
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
description: The new name of the VM
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
id: Message
|
||||||
|
400:
|
||||||
|
description: Bad request
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
id: Message
|
||||||
|
"""
|
||||||
|
return api_helper.vm_rename(
|
||||||
|
vm,
|
||||||
|
reqargs.get('new_name', None)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
api.add_resource(API_VM_Rename, '/vm/<vm>/rename')
|
||||||
|
|
||||||
|
|
||||||
##########################################################
|
##########################################################
|
||||||
# Client API - Network
|
# Client API - Network
|
||||||
##########################################################
|
##########################################################
|
||||||
|
|
|
@ -601,6 +601,37 @@ def vm_modify(name, restart, xml):
|
||||||
return output, retcode
|
return output, retcode
|
||||||
|
|
||||||
|
|
||||||
|
def vm_rename(name, new_name):
|
||||||
|
"""
|
||||||
|
Rename a VM in the PVC cluster.
|
||||||
|
"""
|
||||||
|
if new_name is None:
|
||||||
|
output = {
|
||||||
|
'message': 'A new VM name must be specified'
|
||||||
|
}
|
||||||
|
return 400, output
|
||||||
|
|
||||||
|
zk_conn = pvc_common.startZKConnection(config['coordinators'])
|
||||||
|
if pvc_vm.searchClusterByName(zk_conn, new_name) is not None:
|
||||||
|
output = {
|
||||||
|
'message': 'A VM named \'{}\' is already present in the cluster'.format(new_name)
|
||||||
|
}
|
||||||
|
return 400, output
|
||||||
|
|
||||||
|
retflag, retdata = pvc_vm.rename_vm(zk_conn, name, new_name)
|
||||||
|
pvc_common.stopZKConnection(zk_conn)
|
||||||
|
|
||||||
|
if retflag:
|
||||||
|
retcode = 200
|
||||||
|
else:
|
||||||
|
retcode = 400
|
||||||
|
|
||||||
|
output = {
|
||||||
|
'message': retdata.replace('\"', '\'')
|
||||||
|
}
|
||||||
|
return output, retcode
|
||||||
|
|
||||||
|
|
||||||
def vm_undefine(name):
|
def vm_undefine(name):
|
||||||
"""
|
"""
|
||||||
Undefine a VM from the PVC cluster.
|
Undefine a VM from the PVC cluster.
|
||||||
|
|
|
@ -130,6 +130,27 @@ def vm_modify(config, vm, xml, restart):
|
||||||
return retstatus, response.json().get('message', '')
|
return retstatus, response.json().get('message', '')
|
||||||
|
|
||||||
|
|
||||||
|
def vm_rename(config, vm, new_name):
|
||||||
|
"""
|
||||||
|
Rename VM to new name
|
||||||
|
|
||||||
|
API endpoint: POST /vm/{vm}/rename
|
||||||
|
API arguments: new_name={new_name}
|
||||||
|
API schema: {"message":"{data}"}
|
||||||
|
"""
|
||||||
|
params = {
|
||||||
|
'new_name': new_name
|
||||||
|
}
|
||||||
|
response = call_api(config, 'post', '/vm/{vm}/rename'.format(vm=vm), params=params)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
retstatus = True
|
||||||
|
else:
|
||||||
|
retstatus = False
|
||||||
|
|
||||||
|
return retstatus, response.json().get('message', '')
|
||||||
|
|
||||||
|
|
||||||
def vm_metadata(config, vm, node_limit, node_selector, node_autostart, migration_method, provisioner_profile):
|
def vm_metadata(config, vm, node_limit, node_selector, node_autostart, migration_method, provisioner_profile):
|
||||||
"""
|
"""
|
||||||
Modify PVC metadata of a VM
|
Modify PVC metadata of a VM
|
||||||
|
|
|
@ -790,6 +790,36 @@ def vm_modify(domain, cfgfile, editor, restart, confirm_flag):
|
||||||
cleanup(retcode, retmsg)
|
cleanup(retcode, retmsg)
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# pvc vm rename
|
||||||
|
###############################################################################
|
||||||
|
@click.command(name='rename', short_help='Rename a virtual machine.')
|
||||||
|
@click.argument(
|
||||||
|
'domain'
|
||||||
|
)
|
||||||
|
@click.argument(
|
||||||
|
'new_name'
|
||||||
|
)
|
||||||
|
@click.option(
|
||||||
|
'-y', '--yes', 'confirm_flag',
|
||||||
|
is_flag=True, default=False,
|
||||||
|
help='Confirm the rename'
|
||||||
|
)
|
||||||
|
@cluster_req
|
||||||
|
def vm_rename(domain, new_name, confirm_flag):
|
||||||
|
"""
|
||||||
|
Rename virtual machine DOMAIN, and all its connected disk volumes, to NEW_NAME. DOMAIN may be a UUID or name.
|
||||||
|
"""
|
||||||
|
if not confirm_flag and not config['unsafe']:
|
||||||
|
try:
|
||||||
|
click.confirm('Rename VM {} to {}'.format(domain, new_name), prompt_suffix='? ', abort=True)
|
||||||
|
except Exception:
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
retcode, retmsg = pvc_vm.vm_rename(config, domain, new_name)
|
||||||
|
cleanup(retcode, retmsg)
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# pvc vm undefine
|
# pvc vm undefine
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
@ -4395,6 +4425,7 @@ vm_volume.add_command(vm_volume_remove)
|
||||||
cli_vm.add_command(vm_define)
|
cli_vm.add_command(vm_define)
|
||||||
cli_vm.add_command(vm_meta)
|
cli_vm.add_command(vm_meta)
|
||||||
cli_vm.add_command(vm_modify)
|
cli_vm.add_command(vm_modify)
|
||||||
|
cli_vm.add_command(vm_rename)
|
||||||
cli_vm.add_command(vm_undefine)
|
cli_vm.add_command(vm_undefine)
|
||||||
cli_vm.add_command(vm_remove)
|
cli_vm.add_command(vm_remove)
|
||||||
cli_vm.add_command(vm_dump)
|
cli_vm.add_command(vm_dump)
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
import time
|
import time
|
||||||
import re
|
import re
|
||||||
import lxml.objectify
|
import lxml.objectify
|
||||||
|
import lxml.etree
|
||||||
|
|
||||||
import daemon_lib.zkhandler as zkhandler
|
import daemon_lib.zkhandler as zkhandler
|
||||||
import daemon_lib.common as common
|
import daemon_lib.common as common
|
||||||
|
@ -299,6 +300,55 @@ def dump_vm(zk_conn, domain):
|
||||||
return True, vm_xml
|
return True, vm_xml
|
||||||
|
|
||||||
|
|
||||||
|
def rename_vm(zk_conn, domain, new_domain):
|
||||||
|
dom_uuid = getDomainUUID(zk_conn, domain)
|
||||||
|
if not dom_uuid:
|
||||||
|
return False, 'ERROR: Could not find VM "{}" in the cluster!'.format(domain)
|
||||||
|
|
||||||
|
# Verify that the VM is in a stopped state; renaming is not supported otherwise
|
||||||
|
state = zkhandler.readdata(zk_conn, '/domains/{}/state'.format(dom_uuid))
|
||||||
|
if state != 'stop':
|
||||||
|
return False, 'ERROR: VM "{}" is not in stopped state; VMs cannot be renamed while running.'.format(domain)
|
||||||
|
|
||||||
|
# Parse and valiate the XML
|
||||||
|
vm_config = common.getDomainXML(zk_conn, dom_uuid)
|
||||||
|
|
||||||
|
# Obtain the RBD disk list using the common functions
|
||||||
|
ddisks = common.getDomainDisks(vm_config, {})
|
||||||
|
pool_list = []
|
||||||
|
rbd_list = []
|
||||||
|
for disk in ddisks:
|
||||||
|
if disk['type'] == 'rbd':
|
||||||
|
pool_list.append(disk['name'].split('/')[0])
|
||||||
|
rbd_list.append(disk['name'].split('/')[1])
|
||||||
|
|
||||||
|
# Rename each volume in turn
|
||||||
|
for idx, rbd in enumerate(rbd_list):
|
||||||
|
rbd_new = re.sub(r"{}".format(domain), new_domain, rbd)
|
||||||
|
# Skip renaming if nothing changed
|
||||||
|
if rbd_new == rbd:
|
||||||
|
continue
|
||||||
|
ceph.rename_volume(zk_conn, pool_list[idx], rbd, rbd_new)
|
||||||
|
|
||||||
|
# Replace the name in the config
|
||||||
|
vm_config_new = lxml.etree.tostring(vm_config, encoding='ascii', method='xml').decode().replace(domain, new_domain)
|
||||||
|
|
||||||
|
# Get VM information
|
||||||
|
_b, dom_info = get_info(zk_conn, dom_uuid)
|
||||||
|
|
||||||
|
# Undefine the old VM
|
||||||
|
undefine_vm(zk_conn, dom_uuid)
|
||||||
|
|
||||||
|
# Define the new VM
|
||||||
|
define_vm(zk_conn, vm_config_new, dom_info['node'], dom_info['node_limit'], dom_info['node_selector'], dom_info['node_autostart'], migration_method=dom_info['migration_method'], profile=dom_info['profile'], initial_state='stop')
|
||||||
|
|
||||||
|
# If the VM is migrated, store that
|
||||||
|
if dom_info['migrated'] != 'no':
|
||||||
|
zkhandler.writedata(zk_conn, {'/domains/{}/lastnode'.format(dom_uuid): dom_info['last_node']})
|
||||||
|
|
||||||
|
return True, 'Successfully renamed VM "{}" to "{}".'.format(domain, new_domain)
|
||||||
|
|
||||||
|
|
||||||
def undefine_vm(zk_conn, domain):
|
def undefine_vm(zk_conn, domain):
|
||||||
# Validate that VM exists in cluster
|
# Validate that VM exists in cluster
|
||||||
dom_uuid = getDomainUUID(zk_conn, domain)
|
dom_uuid = getDomainUUID(zk_conn, domain)
|
||||||
|
|
|
@ -6035,6 +6035,38 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/v1/vm/{vm}/rename": {
|
||||||
|
"post": {
|
||||||
|
"description": "",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "The new name of the VM",
|
||||||
|
"in": "query",
|
||||||
|
"name": "new_name",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/Message"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/Message"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"summary": "Rename VM {vm}, and all connected disk volumes which include this name, to {new_name}",
|
||||||
|
"tags": [
|
||||||
|
"vm"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/v1/vm/{vm}/state": {
|
"/api/v1/vm/{vm}/state": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "",
|
"description": "",
|
||||||
|
|
Loading…
Reference in New Issue