#!/usr/bin/python
#
-# Copyright (C) 2006, 2007 Google Inc.
+# Copyright (C) 2006, 2007, 2008, 2009, 2010 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
from ganeti.cli import *
from ganeti import opcodes
from ganeti import constants
+from ganeti import compat
from ganeti import utils
from ganeti import errors
+from ganeti import netutils
_SHUTDOWN_CLUSTER = "cluster"
for name in inames:
op = fn(name, opts)
jex.QueueJob(name, op)
- jex.WaitOrShow(not opts.submit_only)
- return 0
+ results = jex.WaitOrShow(not opts.submit_only)
+ rcode = compat.all(row[0] for row in results)
+ return int(not rcode)
return realfn
"snodes": "Secondary_Nodes", "admin_state": "Autostart",
"oper_state": "Running",
"oper_ram": "Memory", "disk_template": "Disk_template",
+ "oper_vcpus": "VCPUs",
"ip": "IP_address", "mac": "MAC_address",
"nic_mode": "NIC_Mode", "nic_link": "NIC_Link",
"bridge": "Bridge",
elif field == "oper_ram":
if val is None:
val = "(node down)"
+ elif field == "oper_vcpus":
+ if val is None:
+ val = "(node down)"
elif field == "sda_size" or field == "sdb_size":
if val is None:
val = "N/A"
val = ",".join(str(item) for item in val)
elif val is None:
val = "-"
+ if opts.roman_integers and isinstance(val, int):
+ val = compat.TryToRoman(val)
row[idx] = str(val)
data = GenerateTable(separator=opts.separator, headers=headers,
"hypervisor": None,
"hvparams": {},
"file_storage_dir": None,
+ "force_variant": False,
"file_driver": 'loop'}
def _PopulateWithDefaults(spec):
ToStderr("Can't parse the instance definition file: %s" % str(err))
return 1
+ if not isinstance(instance_data, dict):
+ ToStderr("The instance definition file is not in dict format.")
+ return 1
+
jex = JobExecutor(opts=opts)
# Iterate over the instances and do:
# * Populate the specs with default value
# * Validate the instance specs
- i_names = utils.NiceSort(instance_data.keys())
+ i_names = utils.NiceSort(instance_data.keys()) # pylint: disable-msg=E1103
for name in i_names:
specs = instance_data[name]
specs = _PopulateWithDefaults(specs)
disk_template=specs['template'],
mode=constants.INSTANCE_CREATE,
os_type=specs['os'],
- force_variant=opts.force_variant,
+ force_variant=specs["force_variant"],
pnode=specs['primary_node'],
snode=specs['secondary_node'],
nics=tmp_nics,
@return: the desired exit code
"""
+ if not opts.name_check:
+ if not AskUser("As you disabled the check of the DNS entry, please verify"
+ " that '%s' is a FQDN. Continue?" % args[1]):
+ return 1
+
op = opcodes.OpRenameInstance(instance_name=args[0],
new_name=args[1],
- ignore_ip=not opts.ip_check)
- SubmitOrSend(op, opts)
+ ip_check=opts.ip_check,
+ name_check=opts.name_check)
+ result = SubmitOrSend(op, opts)
+
+ ToStdout("Instance '%s' renamed to '%s'", args[0], result)
+
return 0
else:
usertext = ("Instance %s will be migrated. Note that migration" %
(instance_name,))
- usertext += (" is **experimental** in this version."
- " This might impact the instance if anything goes wrong."
- " Continue?")
+ usertext += (" might impact the instance if anything goes wrong"
+ " (e.g. due to bugs in the hypervisor). Continue?")
if not AskUser(usertext):
return 1
- op = opcodes.OpMigrateInstance(instance_name=instance_name, live=opts.live,
+ # this should be removed once --non-live is deprecated
+ if not opts.live and opts.migration_mode is not None:
+ raise errors.OpPrereqError("Only one of the --non-live and "
+ "--migration-mode options can be passed",
+ errors.ECODE_INVAL)
+ if not opts.live: # --non-live passed
+ mode = constants.HT_MIGRATION_NONLIVE
+ else:
+ mode = opts.migration_mode
+
+ op = opcodes.OpMigrateInstance(instance_name=instance_name, mode=mode,
cleanup=opts.cleanup)
SubmitOpCode(op, cl=cl, opts=opts)
return 0
os._exit(1) # pylint: disable-msg=W0212
-def _FormatLogicalID(dev_type, logical_id):
+def _FormatLogicalID(dev_type, logical_id, roman):
"""Formats the logical_id of a disk.
"""
if dev_type == constants.LD_DRBD8:
node_a, node_b, port, minor_a, minor_b, key = logical_id
data = [
- ("nodeA", "%s, minor=%s" % (node_a, minor_a)),
- ("nodeB", "%s, minor=%s" % (node_b, minor_b)),
- ("port", port),
+ ("nodeA", "%s, minor=%s" % (node_a, compat.TryToRoman(minor_a,
+ convert=roman))),
+ ("nodeB", "%s, minor=%s" % (node_b, compat.TryToRoman(minor_b,
+ convert=roman))),
+ ("port", compat.TryToRoman(port, convert=roman)),
("auth key", key),
]
elif dev_type == constants.LD_LV:
return data
-def _FormatBlockDevInfo(idx, top_level, dev, static):
+def _FormatBlockDevInfo(idx, top_level, dev, static, roman):
"""Show block device information.
This is only used by L{ShowInstanceConfig}, but it's too big to be
@type static: boolean
@param static: wheter the device information doesn't contain
runtime information but only static data
+ @type roman: boolean
+ @param roman: whether to try to use roman integers
@return: a list of either strings, tuples or lists
(which should be formatted at a higher indent level)
if major is None:
major_string = "N/A"
else:
- major_string = str(major)
+ major_string = str(compat.TryToRoman(major, convert=roman))
if minor is None:
minor_string = "N/A"
else:
- minor_string = str(minor)
+ minor_string = str(compat.TryToRoman(minor, convert=roman))
txt += ("%s (%s:%s)" % (path, major_string, minor_string))
if dtype in (constants.LD_DRBD8, ):
if syncp is not None:
sync_text = "*RECOVERING* %5.2f%%," % syncp
if estt:
- sync_text += " ETA %ds" % estt
+ sync_text += " ETA %ss" % compat.TryToRoman(estt, convert=roman)
else:
sync_text += " ETA unknown"
else:
if dev["iv_name"] is not None:
txt = dev["iv_name"]
else:
- txt = "disk %d" % idx
+ txt = "disk %s" % compat.TryToRoman(idx, convert=roman)
else:
- txt = "child %d" % idx
+ txt = "child %s" % compat.TryToRoman(idx, convert=roman)
if isinstance(dev["size"], int):
nice_size = utils.FormatUnit(dev["size"], "h")
else:
data.append(("access mode", dev["mode"]))
if dev["logical_id"] is not None:
try:
- l_id = _FormatLogicalID(dev["dev_type"], dev["logical_id"])
+ l_id = _FormatLogicalID(dev["dev_type"], dev["logical_id"], roman)
except ValueError:
l_id = [str(dev["logical_id"])]
if len(l_id) == 1:
if dev["children"]:
data.append("child devices:")
for c_idx, child in enumerate(dev["children"]):
- data.append(_FormatBlockDevInfo(c_idx, False, child, static))
+ data.append(_FormatBlockDevInfo(c_idx, False, child, static, roman))
d1.append(data)
return d1
_FormatList(buf, elem, indent_level+1)
+def _FormatParameterDict(buf, per_inst, actual):
+ """Formats a parameter dictionary.
+
+ @type buf: L{StringIO}
+ @param buf: the buffer into which to write
+ @type per_inst: dict
+ @param per_inst: the instance's own parameters
+ @type actual: dict
+ @param actual: the current parameter set (including defaults)
+
+ """
+ for key in sorted(actual):
+ val = per_inst.get(key, "default (%s)" % actual[key])
+ buf.write(" - %s: %s\n" % (key, val))
+
def ShowInstanceConfig(opts, args):
"""Compute instance run-time status.
instance = result[instance_name]
buf.write("Instance name: %s\n" % instance["name"])
buf.write("UUID: %s\n" % instance["uuid"])
- buf.write("Serial number: %s\n" % instance["serial_no"])
+ buf.write("Serial number: %s\n" %
+ compat.TryToRoman(instance["serial_no"],
+ convert=opts.roman_integers))
buf.write("Creation time: %s\n" % utils.FormatTime(instance["ctime"]))
buf.write("Modification time: %s\n" % utils.FormatTime(instance["mtime"]))
buf.write("State: configured to be %s" % instance["config_state"])
buf.write(" - primary: %s\n" % instance["pnode"])
buf.write(" - secondaries: %s\n" % utils.CommaJoin(instance["snodes"]))
buf.write(" Operating system: %s\n" % instance["os"])
+ _FormatParameterDict(buf, instance["os_instance"], instance["os_actual"])
if instance.has_key("network_port"):
- buf.write(" Allocated network port: %s\n" % instance["network_port"])
+ buf.write(" Allocated network port: %s\n" %
+ compat.TryToRoman(instance["network_port"],
+ convert=opts.roman_integers))
buf.write(" Hypervisor: %s\n" % instance["hypervisor"])
# custom VNC console information
if vnc_bind_address:
port = instance["network_port"]
display = int(port) - constants.VNC_BASE_PORT
- if display > 0 and vnc_bind_address == constants.BIND_ADDRESS_GLOBAL:
+ if display > 0 and vnc_bind_address == constants.IP4_ADDRESS_ANY:
vnc_console_port = "%s:%s (display %s)" % (instance["pnode"],
port,
display)
- elif display > 0 and utils.IsValidIP(vnc_bind_address):
+ elif display > 0 and netutils.IsValidIP4(vnc_bind_address):
vnc_console_port = ("%s:%s (node %s) (display %s)" %
(vnc_bind_address, port,
instance["pnode"], display))
vnc_bind_address)
buf.write(" - console connection: vnc to %s\n" % vnc_console_port)
- for key in instance["hv_actual"]:
- if key in instance["hv_instance"]:
- val = instance["hv_instance"][key]
- else:
- val = "default (%s)" % instance["hv_actual"][key]
- buf.write(" - %s: %s\n" % (key, val))
+ _FormatParameterDict(buf, instance["hv_instance"], instance["hv_actual"])
buf.write(" Hardware:\n")
- buf.write(" - VCPUs: %d\n" %
- instance["be_actual"][constants.BE_VCPUS])
- buf.write(" - memory: %dMiB\n" %
- instance["be_actual"][constants.BE_MEMORY])
+ buf.write(" - VCPUs: %s\n" %
+ compat.TryToRoman(instance["be_actual"][constants.BE_VCPUS],
+ convert=opts.roman_integers))
+ buf.write(" - memory: %sMiB\n" %
+ compat.TryToRoman(instance["be_actual"][constants.BE_MEMORY],
+ convert=opts.roman_integers))
buf.write(" - NICs:\n")
for idx, (ip, mac, mode, link) in enumerate(instance["nics"]):
buf.write(" - nic/%d: MAC: %s, IP: %s, mode: %s, link: %s\n" %
buf.write(" Disks:\n")
for idx, device in enumerate(instance["disks"]):
- _FormatList(buf, _FormatBlockDevInfo(idx, True, device, opts.static), 2)
+ _FormatList(buf, _FormatBlockDevInfo(idx, True, device, opts.static,
+ opts.roman_integers), 2)
ToStdout(buf.getvalue().rstrip('\n'))
return retcode
@return: the desired exit code
"""
- if not (opts.nics or opts.disks or
- opts.hvparams or opts.beparams):
+ if not (opts.nics or opts.disks or opts.disk_template or
+ opts.hvparams or opts.beparams or opts.os or opts.osparams):
ToStderr("Please give at least one of the parameters.")
return 1
errors.ECODE_INVAL)
disk_dict['size'] = utils.ParseUnit(disk_dict['size'])
+ if (opts.disk_template and
+ opts.disk_template in constants.DTS_NET_MIRROR and
+ not opts.node):
+ ToStderr("Changing the disk template to a mirrored one requires"
+ " specifying a secondary node")
+ return 1
+
op = opcodes.OpSetInstanceParams(instance_name=args[0],
nics=opts.nics,
disks=opts.disks,
+ disk_template=opts.disk_template,
+ remote_node=opts.node,
hvparams=opts.hvparams,
beparams=opts.beparams,
+ os_name=opts.os,
+ osparams=opts.osparams,
+ force_variant=opts.force_variant,
force=opts.force)
# even if here we process the result, we allow submit only
ToStdout("Modified instance %s", args[0])
for param, data in result:
ToStdout(" - %-5s -> %s", param, data)
- ToStdout("Please don't forget that these parameters take effect"
+ ToStdout("Please don't forget that most parameters take effect"
" only at the next start of the instance.")
return 0
NONICS_OPT,
NOSTART_OPT,
NWSYNC_OPT,
+ OSPARAMS_OPT,
OS_OPT,
FORCE_VARIANT_OPT,
+ NO_INSTALL_OPT,
OS_SIZE_OPT,
SUBMIT_OPT,
]
" using the remote mirror (only for instances of type drbd)"),
'migrate': (
MigrateInstance, ARGS_ONE_INSTANCE,
- [FORCE_OPT, NONLIVE_OPT, CLEANUP_OPT],
+ [FORCE_OPT, NONLIVE_OPT, MIGRATION_MODE_OPT, CLEANUP_OPT],
"[-f] <instance>", "Migrate instance to its secondary node"
" (only for instances of type drbd)"),
'move': (
" (only for instances of type file and lv)"),
'info': (
ShowInstanceConfig, ARGS_MANY_INSTANCES,
- [STATIC_OPT, ALL_OPT],
+ [STATIC_OPT, ALL_OPT, ROMAN_OPT],
"[-s] {--all | <instance>...}",
"Show information on the specified instance(s)"),
'list': (
ListInstances, ARGS_MANY_INSTANCES,
- [NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT, SYNC_OPT],
+ [NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT, SYNC_OPT, ROMAN_OPT],
"[<instance>...]",
"Lists the instances and their status. The available fields are"
" (see the man page for details): status, oper_state, oper_ram,"
- " name, os, pnode, snodes, admin_state, admin_ram, disk_template,"
- " ip, mac, nic_mode, nic_link, sda_size, sdb_size, vcpus, serial_no,"
+ " oper_vcpus, name, os, pnode, snodes, admin_state, admin_ram,"
+ " disk_template, ip, mac, nic_mode, nic_link, sda_size, sdb_size,"
+ " vcpus, serial_no,"
" nic.count, nic.mac/N, nic.ip/N, nic.mode/N, nic.link/N,"
" nic.macs, nic.ips, nic.modes, nic.links,"
" disk.count, disk.size/N, disk.sizes,"
'rename': (
RenameInstance,
[ArgInstance(min=1, max=1), ArgHost(min=1, max=1)],
- [NOIPCHECK_OPT, SUBMIT_OPT],
+ [NOIPCHECK_OPT, NONAMECHECK_OPT, SUBMIT_OPT],
"<instance> <new_name>", "Rename the instance"),
'replace-disks': (
ReplaceDisks, ARGS_ONE_INSTANCE,
"Replaces all disks for the instance"),
'modify': (
SetInstanceParams, ARGS_ONE_INSTANCE,
- [BACKEND_OPT, DISK_OPT, FORCE_OPT, HVOPTS_OPT, NET_OPT, SUBMIT_OPT],
+ [BACKEND_OPT, DISK_OPT, FORCE_OPT, HVOPTS_OPT, NET_OPT, SUBMIT_OPT,
+ DISK_TEMPLATE_OPT, SINGLE_NODE_OPT, OS_OPT, FORCE_VARIANT_OPT,
+ OSPARAMS_OPT],
"<instance>", "Alters the parameters of an instance"),
'shutdown': (
GenericManyOps("shutdown", _ShutdownInstance), [ArgInstance()],