summaryrefslogtreecommitdiffstats
path: root/nova/virt
diff options
context:
space:
mode:
Diffstat (limited to 'nova/virt')
-rw-r--r--nova/virt/fake.py3
-rw-r--r--nova/virt/libvirt.xml.template13
-rw-r--r--nova/virt/libvirt_conn.py45
-rw-r--r--nova/virt/xenapi/vmops.py5
-rw-r--r--nova/virt/xenapi_conn.py4
5 files changed, 70 insertions, 0 deletions
diff --git a/nova/virt/fake.py b/nova/virt/fake.py
index 849261f07..9186d885e 100644
--- a/nova/virt/fake.py
+++ b/nova/virt/fake.py
@@ -289,6 +289,9 @@ class FakeConnection(object):
def get_console_output(self, instance):
return 'FAKE CONSOLE OUTPUT'
+ def get_ajax_console(self, instance):
+ return 'http://fakeajaxconsole.com/?token=FAKETOKEN'
+
def get_console_pool_info(self, console_type):
return {'address': '127.0.0.1',
'username': 'fakeuser',
diff --git a/nova/virt/libvirt.xml.template b/nova/virt/libvirt.xml.template
index 3fb2243da..2eb7d9488 100644
--- a/nova/virt/libvirt.xml.template
+++ b/nova/virt/libvirt.xml.template
@@ -71,9 +71,22 @@
#end if
</filterref>
</interface>
+
+ <!-- The order is significant here. File must be defined first -->
<serial type="file">
<source path='${basepath}/console.log'/>
<target port='1'/>
</serial>
+
+ <console type='pty' tty='/dev/pts/2'>
+ <source path='/dev/pts/2'/>
+ <target port='0'/>
+ </console>
+
+ <serial type='pty'>
+ <source path='/dev/pts/2'/>
+ <target port='0'/>
+ </serial>
+
</devices>
</domain>
diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py
index 1bd4d250e..655c55fa1 100644
--- a/nova/virt/libvirt_conn.py
+++ b/nova/virt/libvirt_conn.py
@@ -38,6 +38,11 @@ Supports KVM, QEMU, UML, and XEN.
import os
import shutil
+import random
+import subprocess
+import uuid
+from xml.dom import minidom
+
from eventlet import greenthread
from eventlet import event
@@ -86,6 +91,9 @@ flags.DEFINE_string('libvirt_uri',
flags.DEFINE_bool('allow_project_net_traffic',
True,
'Whether to allow in project network traffic')
+flags.DEFINE_string('ajaxterm_portrange',
+ '10000-12000',
+ 'Range of ports that ajaxterm should randomly try to bind')
flags.DEFINE_string('firewall_driver',
'nova.virt.libvirt_conn.IptablesFirewallDriver',
'Firewall driver (defaults to iptables)')
@@ -433,6 +441,43 @@ class LibvirtConnection(object):
return self._dump_file(fpath)
+ @exception.wrap_exception
+ def get_ajax_console(self, instance):
+ def get_open_port():
+ start_port, end_port = FLAGS.ajaxterm_portrange.split("-")
+ for i in xrange(0, 100): # don't loop forever
+ port = random.randint(int(start_port), int(end_port))
+ # netcat will exit with 0 only if the port is in use,
+ # so a nonzero return value implies it is unused
+ cmd = 'netcat 0.0.0.0 %s -w 1 </dev/null || echo free' % (port)
+ stdout, stderr = utils.execute(cmd)
+ if stdout.strip() == 'free':
+ return port
+ raise Exception(_('Unable to find an open port'))
+
+ def get_pty_for_instance(instance_name):
+ virt_dom = self._conn.lookupByName(instance_name)
+ xml = virt_dom.XMLDesc(0)
+ dom = minidom.parseString(xml)
+
+ for serial in dom.getElementsByTagName('serial'):
+ if serial.getAttribute('type') == 'pty':
+ source = serial.getElementsByTagName('source')[0]
+ return source.getAttribute('path')
+
+ port = get_open_port()
+ token = str(uuid.uuid4())
+ host = instance['host']
+
+ ajaxterm_cmd = 'sudo socat - %s' \
+ % get_pty_for_instance(instance['name'])
+
+ cmd = '%s/tools/ajaxterm/ajaxterm.py --command "%s" -t %s -p %s' \
+ % (utils.novadir(), ajaxterm_cmd, token, port)
+
+ subprocess.Popen(cmd, shell=True)
+ return {'token': token, 'host': host, 'port': port}
+
def _create_image(self, inst, libvirt_xml, prefix='', disk_images=None):
# syntactic nicety
basepath = lambda fname = '', prefix = prefix: os.path.join(
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index e20930fe8..7e3585991 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -284,6 +284,11 @@ class VMOps(object):
# TODO: implement this to fix pylint!
return 'FAKE CONSOLE OUTPUT of instance'
+ def get_ajax_console(self, instance):
+ """Return link to instance's ajax console"""
+ # TODO: implement this!
+ return 'http://fakeajaxconsole/fake_url'
+
def list_from_xenstore(self, vm, path):
"""Runs the xenstore-ls command to get a listing of all records
from 'path' downward. Returns a dict with the sub-paths as keys,
diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py
index 11473ddf8..45d0738a5 100644
--- a/nova/virt/xenapi_conn.py
+++ b/nova/virt/xenapi_conn.py
@@ -181,6 +181,10 @@ class XenAPIConnection(object):
"""Return snapshot of console"""
return self._vmops.get_console_output(instance)
+ def get_ajax_console(self, instance):
+ """Return link to instance's ajax console"""
+ return self._vmops.get_ajax_console(instance)
+
def attach_volume(self, instance_name, device_path, mountpoint):
"""Attach volume storage to VM instance"""
return self._volumeops.attach_volume(instance_name,