From a3d003d7ec92f3ae23a667954a790c71efdbfdbe Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 20 Sep 2010 11:46:18 +0200 Subject: Move the code that extracts the console output into the virt drivers. Move the code that formats it up into the API layer. Add support for Xen console. --- nova/compute/manager.py | 18 +----------------- nova/endpoint/cloud.py | 15 ++++++++++----- nova/virt/fake.py | 2 ++ nova/virt/libvirt_conn.py | 40 ++++++++++++++++++++++++++++++++++++++++ nova/virt/xenapi.py | 3 +++ 5 files changed, 56 insertions(+), 22 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index ae7099812..9f5674be2 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -144,26 +144,10 @@ class ComputeManager(manager.Manager): @exception.wrap_exception def get_console_output(self, context, instance_id): """Send the console output for an instance.""" - # TODO(vish): Move this into the driver layer - logging.debug("instance %s: getting console output", instance_id) instance_ref = self.db.instance_get(context, instance_id) - if FLAGS.connection_type == 'libvirt': - fname = os.path.abspath(os.path.join(FLAGS.instances_path, - instance_ref['str_id'], - 'console.log')) - with open(fname, 'r') as f: - output = f.read() - else: - output = 'FAKE CONSOLE OUTPUT' - - # TODO(termie): this stuff belongs in the API layer, no need to - # munge the data we send to ourselves - output = {"InstanceId": instance_id, - "Timestamp": "2", - "output": base64.b64encode(output)} - return output + return self.driver.get_console_output(instance_ref) @defer.inlineCallbacks @exception.wrap_exception diff --git a/nova/endpoint/cloud.py b/nova/endpoint/cloud.py index 622b4e2a4..a55c00a0d 100644 --- a/nova/endpoint/cloud.py +++ b/nova/endpoint/cloud.py @@ -233,11 +233,16 @@ class CloudController(object): def get_console_output(self, context, instance_id, **kwargs): # instance_id is passed in as a list of instances instance_ref = db.instance_get_by_str(context, instance_id[0]) - return rpc.call('%s.%s' % (FLAGS.compute_topic, - instance_ref['host']), - {"method": "get_console_output", - "args": {"context": None, - "instance_id": instance_ref['id']}}) + d = rpc.call('%s.%s' % (FLAGS.compute_topic, + instance_ref['host']), + { "method" : "get_console_output", + "args" : { "context": None, + "instance_id": instance_ref['id']}}) + + d.addCallback(lambda output: { "InstanceId": instance_id, + "Timestamp": "2", + "output": base64.b64encode(output)}) + return d @rbac.allow('projectmanager', 'sysadmin') def describe_volumes(self, context, **kwargs): diff --git a/nova/virt/fake.py b/nova/virt/fake.py index 4ae6afcc4..dc6112f20 100644 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -223,6 +223,8 @@ class FakeConnection(object): """ return [0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L] + def get_console_output(self, instance): + return 'FAKE CONSOLE OUTPUT' class FakeInstance(object): def __init__(self): diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index 09f178c2a..addd9c997 100644 --- a/nova/virt/libvirt_conn.py +++ b/nova/virt/libvirt_conn.py @@ -248,6 +248,46 @@ class LibvirtConnection(object): timer.start(interval=0.5, now=True) yield local_d + def _flush_xen_console(self, virsh_output): + logging.info('virsh said: %r' % (virsh_output,)) + virsh_output = virsh_output[0].strip() + + if virsh_output.startswith('/dev/'): + logging.info('cool, it\'s a device') + d = process.simple_execute("sudo dd if=%s iflag=nonblock" % virsh_output, check_exit_code=False) + d.addCallback(lambda r:r[0]) + return d + else: + return '' + + def _append_to_file(self, data, fpath): + logging.info('data: %r, fpath: %r' % (data, fpath)) + fp = open(fpath, 'a+') + fp.write(data) + return fpath + + def _dump_file(self, fpath): + fp = open(fpath, 'r+') + contents = fp.read() + logging.info('Contents: %r' % (contents,)) + return contents + + @exception.wrap_exception + def get_console_output(self, instance): + console_log = os.path.join(FLAGS.instances_path, instance['name'], 'console.log') + logging.info('console_log: %s' % console_log) + logging.info('FLAGS.libvirt_type: %s' % FLAGS.libvirt_type) + if FLAGS.libvirt_type == 'xen': + # Xen is spethial + d = process.simple_execute("virsh ttyconsole %s" % instance['name']) + d.addCallback(self._flush_xen_console) + d.addCallback(self._append_to_file, console_log) + else: + d = defer.succeed(console_log) + d.addCallback(self._dump_file) + return d + + @defer.inlineCallbacks def _create_image(self, inst, libvirt_xml): # syntactic nicety diff --git a/nova/virt/xenapi.py b/nova/virt/xenapi.py index 1c6de4403..5fdd2b9fc 100644 --- a/nova/virt/xenapi.py +++ b/nova/virt/xenapi.py @@ -299,6 +299,9 @@ class XenAPIConnection(object): 'num_cpu': rec['VCPUs_max'], 'cpu_time': 0} + def get_console_output(self, instance): + return 'FAKE CONSOLE OUTPUT' + @utils.deferredToThread def _lookup(self, i): return self._lookup_blocking(i) -- cgit