Commit 5d28cb6f authored by Michael Hanselmann's avatar Michael Hanselmann
Browse files

Export console information as query field



This makes it possible to get the console information via a LUXI query.
Signed-off-by: default avatarMichael Hanselmann <hansmi@google.com>
Reviewed-by: default avatarIustin Pop <iustin@google.com>
parent a7c5085d
......@@ -3868,6 +3868,7 @@ class _InstanceQuery(_QueryBase):
"""Computes the list of instances and their attributes.
"""
cluster = lu.cfg.GetClusterInfo()
all_info = lu.cfg.GetAllInstancesInfo()
instance_names = self._GetNames(lu, all_info.keys(), locking.LEVEL_INSTANCE)
......@@ -3881,7 +3882,7 @@ class _InstanceQuery(_QueryBase):
wrongnode_inst = set()
# Gather data as requested
if query.IQ_LIVE in self.requested_data:
if self.requested_data & set([query.IQ_LIVE, query.IQ_CONSOLE]):
live_data = {}
node_data = lu.rpc.call_all_instances_info(nodes, hv_list)
for name in nodes:
......@@ -3911,9 +3912,21 @@ class _InstanceQuery(_QueryBase):
else:
disk_usage = None
if query.IQ_CONSOLE in self.requested_data:
consinfo = {}
for inst in instance_list:
if inst.name in live_data:
# Instance is running
consinfo[inst.name] = _GetInstanceConsole(cluster, inst)
else:
consinfo[inst.name] = None
assert set(consinfo.keys()) == set(instance_names)
else:
consinfo = None
return query.InstanceQueryData(instance_list, lu.cfg.GetClusterInfo(),
disk_usage, offline_nodes, bad_nodes,
live_data, wrongnode_inst)
live_data, wrongnode_inst, consinfo)
class LUQuery(NoHooksLU):
......@@ -7804,18 +7817,28 @@ class LUInstanceConsole(NoHooksLU):
logging.debug("Connecting to console of %s on %s", instance.name, node)
hyper = hypervisor.GetHypervisor(instance.hypervisor)
cluster = self.cfg.GetClusterInfo()
# beparams and hvparams are passed separately, to avoid editing the
# instance and then saving the defaults in the instance itself.
hvparams = cluster.FillHV(instance)
beparams = cluster.FillBE(instance)
console = hyper.GetInstanceConsole(instance, hvparams, beparams)
return _GetInstanceConsole(self.cfg.GetClusterInfo(), instance)
def _GetInstanceConsole(cluster, instance):
"""Returns console information for an instance.
@type cluster: L{objects.Cluster}
@type instance: L{objects.Instance}
@rtype: dict
"""
hyper = hypervisor.GetHypervisor(instance.hypervisor)
# beparams and hvparams are passed separately, to avoid editing the
# instance and then saving the defaults in the instance itself.
hvparams = cluster.FillHV(instance)
beparams = cluster.FillBE(instance)
console = hyper.GetInstanceConsole(instance, hvparams, beparams)
assert console.instance == instance.name
assert console.Validate()
assert console.instance == instance.name
assert console.Validate()
return console.ToDict()
return console.ToDict()
class LUInstanceReplaceDisks(LogicalUnit):
......
......@@ -79,7 +79,8 @@ from ganeti.constants import (QFT_UNKNOWN, QFT_TEXT, QFT_BOOL, QFT_NUMBER,
(IQ_CONFIG,
IQ_LIVE,
IQ_DISKUSAGE) = range(100, 103)
IQ_DISKUSAGE,
IQ_CONSOLE) = range(100, 104)
(LQ_MODE,
LQ_OWNER,
......@@ -664,7 +665,7 @@ class InstanceQueryData:
"""
def __init__(self, instances, cluster, disk_usage, offline_nodes, bad_nodes,
live_data, wrongnode_inst):
live_data, wrongnode_inst, console):
"""Initializes this class.
@param instances: List of instance objects
......@@ -679,6 +680,8 @@ class InstanceQueryData:
@param live_data: Per-instance live data
@type wrongnode_inst: set
@param wrongnode_inst: Set of instances running on wrong node(s)
@type console: dict; instance name as key
@param console: Per-instance console information
"""
assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \
......@@ -693,6 +696,7 @@ class InstanceQueryData:
self.bad_nodes = bad_nodes
self.live_data = live_data
self.wrongnode_inst = wrongnode_inst
self.console = console
# Used for individual rows
self.inst_hvparams = None
......@@ -991,6 +995,22 @@ def _GetInstDiskUsage(ctx, inst):
return usage
def _GetInstanceConsole(ctx, inst):
"""Get console information for instance.
@type ctx: L{InstanceQueryData}
@type inst: L{objects.Instance}
@param inst: Instance object
"""
consinfo = ctx.console[inst.name]
if consinfo is None:
return _FS_UNAVAIL
return consinfo
def _GetInstanceDiskFields():
"""Get instance fields involving disks.
......@@ -1108,6 +1128,8 @@ def _BuildInstanceFields():
_GetItemAttr("admin_up")),
(_MakeField("tags", "Tags", QFT_OTHER), IQ_CONFIG,
lambda ctx, inst: list(inst.GetTags())),
(_MakeField("console", "Console", QFT_OTHER), IQ_CONSOLE,
_GetInstanceConsole),
]
# Add simple fields
......
......@@ -539,7 +539,8 @@ class TestInstanceQuery(unittest.TestCase):
nics=[objects.NIC(ip="192.0.2.99", nicparams={})]),
]
iqd = query.InstanceQueryData(instances, cluster, None, [], [], {}, set())
iqd = query.InstanceQueryData(instances, cluster, None, [], [], {},
set(), {})
self.assertEqual(q.Query(iqd),
[[(constants.RS_NORMAL, "inst1"),
(constants.RS_NORMAL, 128),
......@@ -567,7 +568,8 @@ class TestInstanceQuery(unittest.TestCase):
q = self._Create(selected)
self.assertEqual(q.RequestedData(),
set([query.IQ_CONFIG, query.IQ_LIVE, query.IQ_DISKUSAGE]))
set([query.IQ_CONFIG, query.IQ_LIVE, query.IQ_DISKUSAGE,
query.IQ_CONSOLE]))
cluster = objects.Cluster(cluster_name="testcluster",
hvparams=constants.HVC_DEFAULTS,
......@@ -671,6 +673,8 @@ class TestInstanceQuery(unittest.TestCase):
assert not utils.FindDuplicates(inst.name for inst in instances)
instbyname = dict((inst.name, inst) for inst in instances)
disk_usage = dict((inst.name,
cmdlib._ComputeDiskSize(inst.disk_template,
[{"size": disk.size}
......@@ -696,9 +700,16 @@ class TestInstanceQuery(unittest.TestCase):
}
wrongnode_inst = set("inst2")
consinfo = dict((inst.name, None) for inst in instances)
consinfo["inst7"] = \
objects.InstanceConsole(instance="inst7", kind=constants.CONS_SSH,
host=instbyname["inst7"].primary_node,
user=constants.GANETI_RUNAS,
command=["hostname"]).ToDict()
iqd = query.InstanceQueryData(instances, cluster, disk_usage,
offline_nodes, bad_nodes, live_data,
wrongnode_inst)
wrongnode_inst, consinfo)
result = q.Query(iqd)
self.assertEqual(len(result), len(instances))
self.assert_(compat.all(len(row) == len(selected)
......@@ -792,12 +803,23 @@ class TestInstanceQuery(unittest.TestCase):
exp = (constants.RS_NORMAL, getattr(inst, field))
self.assertEqual(row[fieldidx[field]], exp)
self._CheckInstanceConsole(inst, row[fieldidx["console"]])
# Ensure all possible status' have been tested
self.assertEqual(tested_status,
set(["ERROR_nodeoffline", "ERROR_nodedown",
"running", "ERROR_up", "ERROR_down",
"ADMIN_down"]))
def _CheckInstanceConsole(self, instance, (status, consdata)):
if instance.name == "inst7":
self.assertEqual(status, constants.RS_NORMAL)
console = objects.InstanceConsole.FromDict(consdata)
self.assertTrue(console.Validate())
self.assertEqual(console.host, instance.primary_node)
else:
self.assertEqual(status, constants.RS_UNAVAIL)
class TestGroupQuery(unittest.TestCase):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment