summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nova/api/ec2/cloud.py15
-rw-r--r--nova/compute/manager.py18
-rw-r--r--nova/fakerabbit.py1
-rw-r--r--nova/tests/cloud_unittest.py1
-rw-r--r--nova/virt/fake.py2
-rw-r--r--nova/virt/libvirt.xen.xml.template30
-rw-r--r--nova/virt/libvirt_conn.py48
-rw-r--r--nova/virt/xenapi.py3
8 files changed, 94 insertions, 24 deletions
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index 278055be1..a7693cadd 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -452,11 +452,16 @@ class CloudController(object):
ec2_id = instance_id[0]
internal_id = ec2_id_to_internal_id(ec2_id)
instance_ref = db.instance_get_by_internal_id(context, internal_id)
- return rpc.call('%s.%s' % (FLAGS.compute_topic,
- instance_ref['host']),
- {"method": "get_console_output",
- "args": {"context": None,
- "instance_id": instance_ref['id']}})
+ output = rpc.call('%s.%s' % (FLAGS.compute_topic,
+ instance_ref['host']),
+ { "method" : "get_console_output",
+ "args" : { "context": None,
+ "instance_id": instance_ref['id']}})
+
+ now = datetime.datetime.utcnow()
+ return { "InstanceId" : ec2_id,
+ "Timestamp" : now,
+ "output" : base64.b64encode(output) }
def describe_volumes(self, context, **kwargs):
if context.user.is_admin():
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index f36e14aa2..c602d013d 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -149,26 +149,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['internal_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/fakerabbit.py b/nova/fakerabbit.py
index 835973810..df5e61e6e 100644
--- a/nova/fakerabbit.py
+++ b/nova/fakerabbit.py
@@ -116,6 +116,7 @@ class Backend(object):
message = Message(backend=self, body=message_data,
content_type=content_type,
content_encoding=content_encoding)
+ message.result = True
logging.debug('Getting from %s: %s', queue, message)
return message
diff --git a/nova/tests/cloud_unittest.py b/nova/tests/cloud_unittest.py
index a880237f2..ff466135d 100644
--- a/nova/tests/cloud_unittest.py
+++ b/nova/tests/cloud_unittest.py
@@ -75,7 +75,6 @@ class CloudTestCase(test.TrialTestCase):
proxy=self.network)
self.network_consumer.attach_to_eventlet()
-
self.manager = manager.AuthManager()
self.user = self.manager.create_user('admin', 'admin', 'admin', True)
self.project = self.manager.create_project('proj', 'admin', 'proj')
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.xen.xml.template b/nova/virt/libvirt.xen.xml.template
new file mode 100644
index 000000000..9677902c6
--- /dev/null
+++ b/nova/virt/libvirt.xen.xml.template
@@ -0,0 +1,30 @@
+<domain type='%(type)s'>
+ <name>%(name)s</name>
+ <os>
+ <type>linux</type>
+ <kernel>%(basepath)s/kernel</kernel>
+ <initrd>%(basepath)s/ramdisk</initrd>
+ <root>/dev/xvda1</root>
+ <cmdline>ro</cmdline>
+ </os>
+ <features>
+ <acpi/>
+ </features>
+ <memory>%(memory_kb)s</memory>
+ <vcpu>%(vcpus)s</vcpu>
+ <devices>
+ <disk type='file'>
+ <source file='%(basepath)s/disk'/>
+ <target dev='sda' />
+ </disk>
+ <interface type='bridge'>
+ <source bridge='%(bridge_name)s'/>
+ <mac address='%(mac_address)s'/>
+ </interface>
+ <console type="file">
+ <source path='%(basepath)s/console.log'/>
+ <target port='1'/>
+ </console>
+ </devices>
+</domain>
+
diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py
index 94a36a530..ce97ef1eb 100644
--- a/nova/virt/libvirt_conn.py
+++ b/nova/virt/libvirt_conn.py
@@ -50,6 +50,9 @@ FLAGS = flags.FLAGS
flags.DEFINE_string('libvirt_xml_template',
utils.abspath('virt/libvirt.qemu.xml.template'),
'Libvirt XML Template for QEmu/KVM')
+flags.DEFINE_string('libvirt_xen_xml_template',
+ utils.abspath('virt/libvirt.xen.xml.template'),
+ 'Libvirt XML Template for Xen')
flags.DEFINE_string('libvirt_uml_xml_template',
utils.abspath('virt/libvirt.uml.xml.template'),
'Libvirt XML Template for user-mode-linux')
@@ -58,7 +61,7 @@ flags.DEFINE_string('injected_network_template',
'Template file for injected network')
flags.DEFINE_string('libvirt_type',
'kvm',
- 'Libvirt domain type (valid options are: kvm, qemu, uml)')
+ 'Libvirt domain type (valid options are: kvm, qemu, uml, xen)')
flags.DEFINE_string('libvirt_uri',
'',
'Override the default libvirt URI (which is dependent'
@@ -110,6 +113,9 @@ class LibvirtConnection(object):
if FLAGS.libvirt_type == 'uml':
uri = FLAGS.libvirt_uri or 'uml:///system'
template_file = FLAGS.libvirt_uml_xml_template
+ elif FLAGS.libvirt_type == 'xen':
+ uri = FLAGS.libvirt_uri or 'xen:///'
+ template_file = FLAGS.libvirt_xen_xml_template
else:
uri = FLAGS.libvirt_uri or 'qemu:///system'
template_file = FLAGS.libvirt_xml_template
@@ -249,6 +255,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['internal_id'], '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 118e0b687..04e830b64 100644
--- a/nova/virt/xenapi.py
+++ b/nova/virt/xenapi.py
@@ -294,6 +294,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)