|
|
|
@ -331,11 +331,7 @@ def cluster_list():
|
|
|
|
|
if os.path.isfile(cfgfile):
|
|
|
|
|
description, address, port, scheme, api_key = read_from_yaml(cfgfile)
|
|
|
|
|
else:
|
|
|
|
|
description = 'N/A'
|
|
|
|
|
address = 'N/A'
|
|
|
|
|
port = 'N/A'
|
|
|
|
|
scheme = 'N/A'
|
|
|
|
|
api_key = 'N/A'
|
|
|
|
|
continue
|
|
|
|
|
else:
|
|
|
|
|
address = cluster_details.get('host', 'N/A')
|
|
|
|
|
description = cluster_details.get('description', 'N/A')
|
|
|
|
@ -735,12 +731,6 @@ def vm_modify(domain, cfgfile, editor, restart, confirm_flag):
|
|
|
|
|
if not retcode and not vm_information.get('name', None):
|
|
|
|
|
cleanup(False, 'ERROR: Could not find VM "{}"!'.format(domain))
|
|
|
|
|
|
|
|
|
|
if restart and not confirm_flag and not config['unsafe']:
|
|
|
|
|
try:
|
|
|
|
|
click.confirm('Restart VM {} after applying change'.format(domain), prompt_suffix='? ', abort=True)
|
|
|
|
|
except Exception:
|
|
|
|
|
exit(0)
|
|
|
|
|
|
|
|
|
|
dom_name = vm_information.get('name')
|
|
|
|
|
|
|
|
|
|
if editor is True:
|
|
|
|
@ -756,38 +746,28 @@ def vm_modify(domain, cfgfile, editor, restart, confirm_flag):
|
|
|
|
|
else:
|
|
|
|
|
new_vm_cfgfile = new_vm_cfgfile.strip()
|
|
|
|
|
|
|
|
|
|
# Show a diff and confirm
|
|
|
|
|
click.echo('Pending modifications:')
|
|
|
|
|
click.echo('')
|
|
|
|
|
diff = list(difflib.unified_diff(current_vm_cfgfile.split('\n'), new_vm_cfgfile.split('\n'), fromfile='current', tofile='modified', fromfiledate='', tofiledate='', n=3, lineterm=''))
|
|
|
|
|
for line in diff:
|
|
|
|
|
if re.match(r'^\+', line) is not None:
|
|
|
|
|
click.echo(colorama.Fore.GREEN + line + colorama.Fore.RESET)
|
|
|
|
|
elif re.match(r'^\-', line) is not None:
|
|
|
|
|
click.echo(colorama.Fore.RED + line + colorama.Fore.RESET)
|
|
|
|
|
elif re.match(r'^\^', line) is not None:
|
|
|
|
|
click.echo(colorama.Fore.BLUE + line + colorama.Fore.RESET)
|
|
|
|
|
else:
|
|
|
|
|
click.echo(line)
|
|
|
|
|
click.echo('')
|
|
|
|
|
|
|
|
|
|
click.confirm('Write modifications to cluster?', abort=True)
|
|
|
|
|
|
|
|
|
|
if restart:
|
|
|
|
|
click.echo('Writing modified configuration of VM "{}" and restarting.'.format(dom_name))
|
|
|
|
|
else:
|
|
|
|
|
click.echo('Writing modified configuration of VM "{}".'.format(dom_name))
|
|
|
|
|
|
|
|
|
|
# We're operating in replace mode
|
|
|
|
|
else:
|
|
|
|
|
# Open the XML file
|
|
|
|
|
new_vm_cfgfile = cfgfile.read()
|
|
|
|
|
cfgfile.close()
|
|
|
|
|
|
|
|
|
|
if restart:
|
|
|
|
|
click.echo('Replacing configuration of VM "{}" with file "{}" and restarting.'.format(dom_name, cfgfile.name))
|
|
|
|
|
click.echo('Replacing configuration of VM "{}" with file "{}".'.format(dom_name, cfgfile.name))
|
|
|
|
|
|
|
|
|
|
# Show a diff and confirm
|
|
|
|
|
click.echo('Pending modifications:')
|
|
|
|
|
click.echo('')
|
|
|
|
|
diff = list(difflib.unified_diff(current_vm_cfgfile.split('\n'), new_vm_cfgfile.split('\n'), fromfile='current', tofile='modified', fromfiledate='', tofiledate='', n=3, lineterm=''))
|
|
|
|
|
for line in diff:
|
|
|
|
|
if re.match(r'^\+', line) is not None:
|
|
|
|
|
click.echo(colorama.Fore.GREEN + line + colorama.Fore.RESET)
|
|
|
|
|
elif re.match(r'^\-', line) is not None:
|
|
|
|
|
click.echo(colorama.Fore.RED + line + colorama.Fore.RESET)
|
|
|
|
|
elif re.match(r'^\^', line) is not None:
|
|
|
|
|
click.echo(colorama.Fore.BLUE + line + colorama.Fore.RESET)
|
|
|
|
|
else:
|
|
|
|
|
click.echo('Replacing configuration of VM "{}" with file "{}".'.format(dom_name, cfgfile.name))
|
|
|
|
|
click.echo(line)
|
|
|
|
|
click.echo('')
|
|
|
|
|
|
|
|
|
|
# Verify our XML is sensible
|
|
|
|
|
try:
|
|
|
|
@ -796,6 +776,14 @@ def vm_modify(domain, cfgfile, editor, restart, confirm_flag):
|
|
|
|
|
except Exception as e:
|
|
|
|
|
cleanup(False, 'Error: XML is malformed or invalid: {}'.format(e))
|
|
|
|
|
|
|
|
|
|
click.confirm('Write modifications to cluster?', abort=True)
|
|
|
|
|
|
|
|
|
|
if restart and not confirm_flag and not config['unsafe']:
|
|
|
|
|
try:
|
|
|
|
|
click.confirm('Restart VM {}'.format(domain), prompt_suffix='? ', abort=True)
|
|
|
|
|
except Exception:
|
|
|
|
|
restart = False
|
|
|
|
|
|
|
|
|
|
retcode, retmsg = pvc_vm.vm_modify(config, domain, new_cfg, restart)
|
|
|
|
|
if retcode and not restart:
|
|
|
|
|
retmsg = retmsg + " Changes will be applied on next VM start/restart."
|
|
|
|
@ -1151,23 +1139,23 @@ def vm_vcpu_set(domain, vcpus, topology, restart, confirm_flag):
|
|
|
|
|
|
|
|
|
|
By default, the topology of the vCPus is 1 socket, VCPUS cores per socket, 1 thread per core.
|
|
|
|
|
"""
|
|
|
|
|
if restart and not confirm_flag and not config['unsafe']:
|
|
|
|
|
try:
|
|
|
|
|
click.confirm('Restart VM {} after applying change'.format(domain), prompt_suffix='? ', abort=True)
|
|
|
|
|
except Exception:
|
|
|
|
|
exit(0)
|
|
|
|
|
|
|
|
|
|
if topology is not None:
|
|
|
|
|
try:
|
|
|
|
|
sockets, cores, threads = topology.split(',')
|
|
|
|
|
if sockets * cores * threads != vcpus:
|
|
|
|
|
raise
|
|
|
|
|
except Exception:
|
|
|
|
|
cleanup(False, "The topology specified is not valid.")
|
|
|
|
|
cleanup(False, "The specified topology is not valid.")
|
|
|
|
|
topology = (sockets, cores, threads)
|
|
|
|
|
else:
|
|
|
|
|
topology = (1, vcpus, 1)
|
|
|
|
|
|
|
|
|
|
if restart and not confirm_flag and not config['unsafe']:
|
|
|
|
|
try:
|
|
|
|
|
click.confirm('Restart VM {}'.format(domain), prompt_suffix='? ', abort=True)
|
|
|
|
|
except Exception:
|
|
|
|
|
restart = False
|
|
|
|
|
|
|
|
|
|
retcode, retmsg = pvc_vm.vm_vcpus_set(config, domain, vcpus, topology, restart)
|
|
|
|
|
if retcode and not restart:
|
|
|
|
|
retmsg = retmsg + " Changes will be applied on next VM start/restart."
|
|
|
|
@ -1234,9 +1222,9 @@ def vm_memory_set(domain, memory, restart, confirm_flag):
|
|
|
|
|
"""
|
|
|
|
|
if restart and not confirm_flag and not config['unsafe']:
|
|
|
|
|
try:
|
|
|
|
|
click.confirm('Restart VM {} after applying change'.format(domain), prompt_suffix='? ', abort=True)
|
|
|
|
|
click.confirm('Restart VM {}'.format(domain), prompt_suffix='? ', abort=True)
|
|
|
|
|
except Exception:
|
|
|
|
|
exit(0)
|
|
|
|
|
restart = False
|
|
|
|
|
|
|
|
|
|
retcode, retmsg = pvc_vm.vm_memory_set(config, domain, memory, restart)
|
|
|
|
|
if retcode and not restart:
|
|
|
|
@ -1319,9 +1307,9 @@ def vm_network_add(domain, vni, macaddr, model, restart, confirm_flag):
|
|
|
|
|
"""
|
|
|
|
|
if restart and not confirm_flag and not config['unsafe']:
|
|
|
|
|
try:
|
|
|
|
|
click.confirm('Restart VM {} after applying change'.format(domain), prompt_suffix='? ', abort=True)
|
|
|
|
|
click.confirm('Restart VM {}'.format(domain), prompt_suffix='? ', abort=True)
|
|
|
|
|
except Exception:
|
|
|
|
|
exit(0)
|
|
|
|
|
restart = False
|
|
|
|
|
|
|
|
|
|
retcode, retmsg = pvc_vm.vm_networks_add(config, domain, vni, macaddr, model, restart)
|
|
|
|
|
if retcode and not restart:
|
|
|
|
@ -1355,9 +1343,9 @@ def vm_network_remove(domain, vni, restart, confirm_flag):
|
|
|
|
|
"""
|
|
|
|
|
if restart and not confirm_flag and not config['unsafe']:
|
|
|
|
|
try:
|
|
|
|
|
click.confirm('Restart VM {} after applying change'.format(domain), prompt_suffix='? ', abort=True)
|
|
|
|
|
click.confirm('Restart VM {}'.format(domain), prompt_suffix='? ', abort=True)
|
|
|
|
|
except Exception:
|
|
|
|
|
exit(0)
|
|
|
|
|
restart = False
|
|
|
|
|
|
|
|
|
|
retcode, retmsg = pvc_vm.vm_networks_remove(config, domain, vni, restart)
|
|
|
|
|
if retcode and not restart:
|
|
|
|
@ -1448,9 +1436,9 @@ def vm_volume_add(domain, volume, disk_id, bus, disk_type, restart, confirm_flag
|
|
|
|
|
"""
|
|
|
|
|
if restart and not confirm_flag and not config['unsafe']:
|
|
|
|
|
try:
|
|
|
|
|
click.confirm('Restart VM {} after applying change'.format(domain), prompt_suffix='? ', abort=True)
|
|
|
|
|
click.confirm('Restart VM {}'.format(domain), prompt_suffix='? ', abort=True)
|
|
|
|
|
except Exception:
|
|
|
|
|
exit(0)
|
|
|
|
|
restart = False
|
|
|
|
|
|
|
|
|
|
retcode, retmsg = pvc_vm.vm_volumes_add(config, domain, volume, disk_id, bus, disk_type, restart)
|
|
|
|
|
if retcode and not restart:
|
|
|
|
@ -1484,9 +1472,9 @@ def vm_volume_remove(domain, vni, restart, confirm_flag):
|
|
|
|
|
"""
|
|
|
|
|
if restart and not confirm_flag and not config['unsafe']:
|
|
|
|
|
try:
|
|
|
|
|
click.confirm('Restart VM {} after applying change'.format(domain), prompt_suffix='? ', abort=True)
|
|
|
|
|
click.confirm('Restart VM {}'.format(domain), prompt_suffix='? ', abort=True)
|
|
|
|
|
except Exception:
|
|
|
|
|
exit(0)
|
|
|
|
|
restart = False
|
|
|
|
|
|
|
|
|
|
retcode, retmsg = pvc_vm.vm_volumes_remove(config, domain, vni, restart)
|
|
|
|
|
if retcode and not restart:
|
|
|
|
@ -1775,6 +1763,7 @@ def net_modify(vni, description, domain, name_servers, ip6_network, ip6_gateway,
|
|
|
|
|
Modify details of virtual network VNI. All fields optional; only specified fields will be updated.
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
|
|
pvc network modify 1001 --gateway 10.1.1.1 --dhcp
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
@ -2389,14 +2378,16 @@ def ceph_pool():
|
|
|
|
|
default='copies=3,mincopies=2', show_default=True, required=False,
|
|
|
|
|
help="""
|
|
|
|
|
The replication configuration, specifying both a "copies" and "mincopies" value, separated by a
|
|
|
|
|
comma, e.g. "copies=3,mincopies=2". The "copies" value specifies the total number of replicas and should not exceed the total number of nodes; the "mincopies" value specifies the minimum number of available copies to allow writes. For additional details please see the Cluster Architecture documentation.
|
|
|
|
|
comma, e.g. "copies=3,mincopies=2". The "copies" value specifies the total number of replicas
|
|
|
|
|
and should not exceed the total number of nodes; the "mincopies" value specifies the minimum
|
|
|
|
|
number of available copies to allow writes. For additional details please see the Cluster
|
|
|
|
|
Architecture documentation.
|
|
|
|
|
"""
|
|
|
|
|
)
|
|
|
|
|
@cluster_req
|
|
|
|
|
def ceph_pool_add(name, pgs, replcfg):
|
|
|
|
|
"""
|
|
|
|
|
Add a new Ceph RBD pool with name NAME and PGS placement groups.
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
retcode, retmsg = pvc_ceph.ceph_pool_add(config, name, pgs, replcfg)
|
|
|
|
@ -4198,9 +4189,13 @@ def status_cluster(oformat):
|
|
|
|
|
Show basic information and health for the active PVC cluster.
|
|
|
|
|
|
|
|
|
|
Output formats:
|
|
|
|
|
|
|
|
|
|
plain: Full text, full colour output for human-readability.
|
|
|
|
|
|
|
|
|
|
short: Health-only, full colour output for human-readability.
|
|
|
|
|
|
|
|
|
|
json: Compact JSON representation for machine parsing.
|
|
|
|
|
|
|
|
|
|
json-pretty: Pretty-printed JSON representation for machine parsing or human-readability.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|