merge trunk
This commit is contained in:
@@ -14,3 +14,8 @@ CA/newcerts/*.pem
|
||||
CA/private/cakey.pem
|
||||
nova/vcsversion.py
|
||||
*.DS_Store
|
||||
.project
|
||||
.pydevproject
|
||||
clean.sqlite
|
||||
run_tests.log
|
||||
tests.sqlite
|
||||
|
1
Authors
1
Authors
@@ -12,6 +12,7 @@ Chiradeep Vittal <chiradeep@cloud.com>
|
||||
Chmouel Boudjnah <chmouel@chmouel.com>
|
||||
Chris Behrens <cbehrens@codestud.com>
|
||||
Christian Berendt <berendt@b1-systems.de>
|
||||
Chuck Short <zulcss@ubuntu.com>
|
||||
Cory Wright <corywright@gmail.com>
|
||||
Dan Prince <dan.prince@rackspace.com>
|
||||
David Pravec <David.Pravec@danix.org>
|
||||
|
@@ -115,7 +115,7 @@ class AjaxConsoleProxy(object):
|
||||
{'args': data['args'], 'last_activity': time.time()}
|
||||
|
||||
conn = rpc.Connection.instance(new=True)
|
||||
consumer = rpc.TopicConsumer(
|
||||
consumer = rpc.TopicAdapterConsumer(
|
||||
connection=conn,
|
||||
topic=FLAGS.ajax_console_proxy_topic)
|
||||
consumer.register_callback(Callback())
|
||||
|
@@ -48,6 +48,7 @@ flags.DECLARE('auth_driver', 'nova.auth.manager')
|
||||
flags.DECLARE('network_size', 'nova.network.manager')
|
||||
flags.DECLARE('num_networks', 'nova.network.manager')
|
||||
flags.DECLARE('update_dhcp_on_disassociate', 'nova.network.manager')
|
||||
flags.DEFINE_string('dnsmasq_interface', 'br0', 'Default Dnsmasq interface')
|
||||
|
||||
LOG = logging.getLogger('nova.dhcpbridge')
|
||||
|
||||
@@ -103,7 +104,8 @@ def main():
|
||||
utils.default_flagfile(flagfile)
|
||||
argv = FLAGS(sys.argv)
|
||||
logging.setup()
|
||||
interface = os.environ.get('DNSMASQ_INTERFACE', 'br0')
|
||||
# check ENV first so we don't break any older deploys
|
||||
interface = os.environ.get('DNSMASQ_INTERFACE', FLAGS.dnsmasq_interface)
|
||||
if int(os.environ.get('TESTING', '0')):
|
||||
from nova.tests import fake_flags
|
||||
action = argv[1]
|
||||
|
@@ -1098,8 +1098,8 @@ def main():
|
||||
script_name = argv.pop(0)
|
||||
if len(argv) < 1:
|
||||
print script_name + " category action [<args>]"
|
||||
print "Available categories:"
|
||||
for k, _ in CATEGORIES:
|
||||
print _("Available categories:")
|
||||
for k, _v in CATEGORIES:
|
||||
print "\t%s" % k
|
||||
sys.exit(2)
|
||||
category = argv.pop(0)
|
||||
@@ -1110,7 +1110,7 @@ def main():
|
||||
actions = methods_of(command_object)
|
||||
if len(argv) < 1:
|
||||
print script_name + " category action [<args>]"
|
||||
print "Available actions for %s category:" % category
|
||||
print _("Available actions for %s category:") % category
|
||||
for k, _v in actions:
|
||||
print "\t%s" % k
|
||||
sys.exit(2)
|
||||
@@ -1122,9 +1122,12 @@ def main():
|
||||
fn(*argv)
|
||||
sys.exit(0)
|
||||
except TypeError:
|
||||
print "Possible wrong number of arguments supplied"
|
||||
print _("Possible wrong number of arguments supplied")
|
||||
print "%s %s: %s" % (category, action, fn.__doc__)
|
||||
raise
|
||||
except Exception:
|
||||
print _("Command failed, please check log for more info")
|
||||
raise
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
101
bin/nova-vncproxy
Executable file
101
bin/nova-vncproxy
Executable file
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env python
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright (c) 2010 Openstack, LLC.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""VNC Console Proxy Server."""
|
||||
|
||||
import eventlet
|
||||
import gettext
|
||||
import os
|
||||
import sys
|
||||
|
||||
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
||||
os.pardir,
|
||||
os.pardir))
|
||||
if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
|
||||
sys.path.insert(0, possible_topdir)
|
||||
|
||||
gettext.install('nova', unicode=1)
|
||||
|
||||
from nova import flags
|
||||
from nova import log as logging
|
||||
from nova import service
|
||||
from nova import utils
|
||||
from nova import wsgi
|
||||
from nova import version
|
||||
from nova.vnc import auth
|
||||
from nova.vnc import proxy
|
||||
|
||||
|
||||
LOG = logging.getLogger('nova.vnc-proxy')
|
||||
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
flags.DEFINE_string('vncproxy_wwwroot', '/var/lib/nova/noVNC/',
|
||||
'Full path to noVNC directory')
|
||||
flags.DEFINE_boolean('vnc_debug', False,
|
||||
'Enable debugging features, like token bypassing')
|
||||
flags.DEFINE_integer('vncproxy_port', 6080,
|
||||
'Port that the VNC proxy should bind to')
|
||||
flags.DEFINE_string('vncproxy_host', '0.0.0.0',
|
||||
'Address that the VNC proxy should bind to')
|
||||
flags.DEFINE_integer('vnc_token_ttl', 300,
|
||||
'How many seconds before deleting tokens')
|
||||
flags.DEFINE_string('vncproxy_manager', 'nova.vnc.auth.VNCProxyAuthManager',
|
||||
'Manager for vncproxy auth')
|
||||
|
||||
flags.DEFINE_flag(flags.HelpFlag())
|
||||
flags.DEFINE_flag(flags.HelpshortFlag())
|
||||
flags.DEFINE_flag(flags.HelpXMLFlag())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
utils.default_flagfile()
|
||||
FLAGS(sys.argv)
|
||||
logging.setup()
|
||||
|
||||
LOG.audit(_("Starting nova-vnc-proxy node (version %s)"),
|
||||
version.version_string_with_vcs())
|
||||
|
||||
if not (os.path.exists(FLAGS.vncproxy_wwwroot) and
|
||||
os.path.exists(FLAGS.vncproxy_wwwroot + '/vnc_auto.html')):
|
||||
LOG.info(_("Missing vncproxy_wwwroot (version %s)"),
|
||||
FLAGS.vncproxy_wwwroot)
|
||||
LOG.info(_("You need a slightly modified version of noVNC "
|
||||
"to work with the nova-vnc-proxy"))
|
||||
LOG.info(_("Check out the most recent nova noVNC code: %s"),
|
||||
"git://github.com/sleepsonthefloor/noVNC.git")
|
||||
LOG.info(_("And drop it in %s"), FLAGS.vncproxy_wwwroot)
|
||||
exit(1)
|
||||
|
||||
app = proxy.WebsocketVNCProxy(FLAGS.vncproxy_wwwroot)
|
||||
|
||||
LOG.audit(_("Allowing access to the following files: %s"),
|
||||
app.get_whitelist())
|
||||
|
||||
with_logging = auth.LoggingMiddleware(app)
|
||||
|
||||
if FLAGS.vnc_debug:
|
||||
with_auth = proxy.DebugMiddleware(with_logging)
|
||||
else:
|
||||
with_auth = auth.VNCNovaAuthMiddleware(with_logging)
|
||||
|
||||
service.serve()
|
||||
|
||||
server = wsgi.Server()
|
||||
server.start(with_auth, FLAGS.vncproxy_port, host=FLAGS.vncproxy_host)
|
||||
server.wait()
|
@@ -324,14 +324,11 @@ class NovaAdminClient(object):
|
||||
|
||||
def get_user(self, name):
|
||||
"""Grab a single user by name."""
|
||||
try:
|
||||
return self.apiconn.get_object('DescribeUser',
|
||||
{'Name': name},
|
||||
UserInfo)
|
||||
except boto.exception.BotoServerError, e:
|
||||
if e.status == 400 and e.error_code == 'NotFound':
|
||||
return None
|
||||
raise
|
||||
user = self.apiconn.get_object('DescribeUser',
|
||||
{'Name': name},
|
||||
UserInfo)
|
||||
if user.username != None:
|
||||
return user
|
||||
|
||||
def has_user(self, username):
|
||||
"""Determine if user exists."""
|
||||
|
@@ -286,6 +286,16 @@ class ComputeTestCase(test.TestCase):
|
||||
|
||||
console = self.compute.get_ajax_console(self.context,
|
||||
instance_id)
|
||||
self.assert_(set(['token', 'host', 'port']).issubset(console.keys()))
|
||||
self.compute.terminate_instance(self.context, instance_id)
|
||||
|
||||
def test_vnc_console(self):
|
||||
"""Make sure we can a vnc console for an instance."""
|
||||
instance_id = self._create_instance()
|
||||
self.compute.run_instance(self.context, instance_id)
|
||||
|
||||
console = self.compute.get_vnc_console(self.context,
|
||||
instance_id)
|
||||
self.assert_(console)
|
||||
self.compute.terminate_instance(self.context, instance_id)
|
||||
|
||||
|
@@ -225,6 +225,49 @@ class LibvirtConnTestCase(test.TestCase):
|
||||
self._check_xml_and_uri(instance_data, expect_kernel=True,
|
||||
expect_ramdisk=True, rescue=True)
|
||||
|
||||
def test_lxc_container_and_uri(self):
|
||||
instance_data = dict(self.test_instance)
|
||||
self._check_xml_and_container(instance_data)
|
||||
|
||||
def _check_xml_and_container(self, instance):
|
||||
user_context = context.RequestContext(project=self.project,
|
||||
user=self.user)
|
||||
instance_ref = db.instance_create(user_context, instance)
|
||||
host = self.network.get_network_host(user_context.elevated())
|
||||
network_ref = db.project_get_network(context.get_admin_context(),
|
||||
self.project.id)
|
||||
|
||||
fixed_ip = {'address': self.test_ip,
|
||||
'network_id': network_ref['id']}
|
||||
|
||||
ctxt = context.get_admin_context()
|
||||
fixed_ip_ref = db.fixed_ip_create(ctxt, fixed_ip)
|
||||
db.fixed_ip_update(ctxt, self.test_ip,
|
||||
{'allocated': True,
|
||||
'instance_id': instance_ref['id']})
|
||||
|
||||
self.flags(libvirt_type='lxc')
|
||||
conn = libvirt_conn.LibvirtConnection(True)
|
||||
|
||||
uri = conn.get_uri()
|
||||
self.assertEquals(uri, 'lxc:///')
|
||||
|
||||
xml = conn.to_xml(instance_ref)
|
||||
tree = xml_to_tree(xml)
|
||||
|
||||
check = [
|
||||
(lambda t: t.find('.').get('type'), 'lxc'),
|
||||
(lambda t: t.find('./os/type').text, 'exe'),
|
||||
(lambda t: t.find('./devices/filesystem/target').get('dir'), '/')]
|
||||
|
||||
for i, (check, expected_result) in enumerate(check):
|
||||
self.assertEqual(check(tree),
|
||||
expected_result,
|
||||
'%s failed common check %d' % (xml, i))
|
||||
|
||||
target = tree.find('./devices/filesystem/source').get('dir')
|
||||
self.assertTrue(len(target) > 0)
|
||||
|
||||
def _check_xml_and_uri(self, instance, expect_ramdisk, expect_kernel,
|
||||
rescue=False):
|
||||
user_context = context.RequestContext(project=self.project,
|
||||
|
@@ -14,9 +14,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""
|
||||
Test suite for XenAPI
|
||||
"""
|
||||
"""Test suite for XenAPI."""
|
||||
|
||||
import functools
|
||||
import os
|
||||
@@ -65,9 +63,7 @@ def stub_vm_utils_with_vdi_attached_here(function, should_return=True):
|
||||
|
||||
|
||||
class XenAPIVolumeTestCase(test.TestCase):
|
||||
"""
|
||||
Unit tests for Volume operations
|
||||
"""
|
||||
"""Unit tests for Volume operations."""
|
||||
def setUp(self):
|
||||
super(XenAPIVolumeTestCase, self).setUp()
|
||||
self.stubs = stubout.StubOutForTesting()
|
||||
@@ -101,7 +97,7 @@ class XenAPIVolumeTestCase(test.TestCase):
|
||||
return db.volume_create(self.context, vol)
|
||||
|
||||
def test_create_iscsi_storage(self):
|
||||
""" This shows how to test helper classes' methods """
|
||||
"""This shows how to test helper classes' methods."""
|
||||
stubs.stubout_session(self.stubs, stubs.FakeSessionForVolumeTests)
|
||||
session = xenapi_conn.XenAPISession('test_url', 'root', 'test_pass')
|
||||
helper = volume_utils.VolumeHelper
|
||||
@@ -116,7 +112,7 @@ class XenAPIVolumeTestCase(test.TestCase):
|
||||
db.volume_destroy(context.get_admin_context(), vol['id'])
|
||||
|
||||
def test_parse_volume_info_raise_exception(self):
|
||||
""" This shows how to test helper classes' methods """
|
||||
"""This shows how to test helper classes' methods."""
|
||||
stubs.stubout_session(self.stubs, stubs.FakeSessionForVolumeTests)
|
||||
session = xenapi_conn.XenAPISession('test_url', 'root', 'test_pass')
|
||||
helper = volume_utils.VolumeHelper
|
||||
@@ -130,7 +126,7 @@ class XenAPIVolumeTestCase(test.TestCase):
|
||||
db.volume_destroy(context.get_admin_context(), vol['id'])
|
||||
|
||||
def test_attach_volume(self):
|
||||
""" This shows how to test Ops classes' methods """
|
||||
"""This shows how to test Ops classes' methods."""
|
||||
stubs.stubout_session(self.stubs, stubs.FakeSessionForVolumeTests)
|
||||
conn = xenapi_conn.get_connection(False)
|
||||
volume = self._create_volume()
|
||||
@@ -149,7 +145,7 @@ class XenAPIVolumeTestCase(test.TestCase):
|
||||
check()
|
||||
|
||||
def test_attach_volume_raise_exception(self):
|
||||
""" This shows how to test when exceptions are raised """
|
||||
"""This shows how to test when exceptions are raised."""
|
||||
stubs.stubout_session(self.stubs,
|
||||
stubs.FakeSessionForVolumeFailedTests)
|
||||
conn = xenapi_conn.get_connection(False)
|
||||
@@ -172,9 +168,7 @@ def reset_network(*args):
|
||||
|
||||
|
||||
class XenAPIVMTestCase(test.TestCase):
|
||||
"""
|
||||
Unit tests for VM operations
|
||||
"""
|
||||
"""Unit tests for VM operations."""
|
||||
def setUp(self):
|
||||
super(XenAPIVMTestCase, self).setUp()
|
||||
self.manager = manager.AuthManager()
|
||||
@@ -188,6 +182,7 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
instance_name_template='%d')
|
||||
xenapi_fake.reset()
|
||||
xenapi_fake.create_local_srs()
|
||||
xenapi_fake.create_local_pifs()
|
||||
db_fakes.stub_out_db_instance_api(self.stubs)
|
||||
xenapi_fake.create_network('fake', FLAGS.flat_network_bridge)
|
||||
stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests)
|
||||
@@ -247,12 +242,12 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
|
||||
check()
|
||||
|
||||
def create_vm_record(self, conn, os_type):
|
||||
def create_vm_record(self, conn, os_type, instance_id=1):
|
||||
instances = conn.list_instances()
|
||||
self.assertEquals(instances, ['1'])
|
||||
self.assertEquals(instances, [str(instance_id)])
|
||||
|
||||
# Get Nova record for VM
|
||||
vm_info = conn.get_info(1)
|
||||
vm_info = conn.get_info(instance_id)
|
||||
# Get XenAPI record for VM
|
||||
vms = [rec for ref, rec
|
||||
in xenapi_fake.get_all_records('VM').iteritems()
|
||||
@@ -286,19 +281,19 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
key = 'vm-data/networking/aabbccddeeff'
|
||||
xenstore_value = xenstore_data[key]
|
||||
tcpip_data = ast.literal_eval(xenstore_value)
|
||||
self.assertEquals(tcpip_data, {
|
||||
'label': 'test_network',
|
||||
'broadcast': '10.0.0.255',
|
||||
'ips': [{'ip': '10.0.0.3',
|
||||
'netmask':'255.255.255.0',
|
||||
'enabled':'1'}],
|
||||
'ip6s': [{'ip': 'fe80::a8bb:ccff:fedd:eeff',
|
||||
'netmask': '120',
|
||||
'enabled': '1',
|
||||
'gateway': 'fe80::a00:1'}],
|
||||
'mac': 'aa:bb:cc:dd:ee:ff',
|
||||
'dns': ['10.0.0.2'],
|
||||
'gateway': '10.0.0.1'})
|
||||
self.assertEquals(tcpip_data,
|
||||
{'label': 'fake_flat_network',
|
||||
'broadcast': '10.0.0.255',
|
||||
'ips': [{'ip': '10.0.0.3',
|
||||
'netmask':'255.255.255.0',
|
||||
'enabled':'1'}],
|
||||
'ip6s': [{'ip': 'fe80::a8bb:ccff:fedd:eeff',
|
||||
'netmask': '120',
|
||||
'enabled': '1',
|
||||
'gateway': 'fe80::a00:1'}],
|
||||
'mac': 'aa:bb:cc:dd:ee:ff',
|
||||
'dns': ['10.0.0.2'],
|
||||
'gateway': '10.0.0.1'})
|
||||
|
||||
def check_vm_params_for_windows(self):
|
||||
self.assertEquals(self.vm['platform']['nx'], 'true')
|
||||
@@ -347,9 +342,9 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
|
||||
def _test_spawn(self, image_id, kernel_id, ramdisk_id,
|
||||
instance_type="m1.large", os_type="linux",
|
||||
check_injection=False):
|
||||
instance_id=1, check_injection=False):
|
||||
stubs.stubout_loopingcall_start(self.stubs)
|
||||
values = {'id': 1,
|
||||
values = {'id': instance_id,
|
||||
'project_id': self.project.id,
|
||||
'user_id': self.user.id,
|
||||
'image_id': image_id,
|
||||
@@ -360,7 +355,7 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
'os_type': os_type}
|
||||
instance = db.instance_create(self.context, values)
|
||||
self.conn.spawn(instance)
|
||||
self.create_vm_record(self.conn, os_type)
|
||||
self.create_vm_record(self.conn, os_type, instance_id)
|
||||
self.check_vm_record(self.conn, check_injection)
|
||||
|
||||
def test_spawn_not_enough_memory(self):
|
||||
@@ -505,6 +500,28 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
# guest agent is detected
|
||||
self.assertFalse(self._tee_executed)
|
||||
|
||||
def test_spawn_vlanmanager(self):
|
||||
self.flags(xenapi_image_service='glance',
|
||||
network_manager='nova.network.manager.VlanManager',
|
||||
network_driver='nova.network.xenapi_net',
|
||||
vlan_interface='fake0')
|
||||
# Reset network table
|
||||
xenapi_fake.reset_table('network')
|
||||
# Instance id = 2 will use vlan network (see db/fakes.py)
|
||||
fake_instance_id = 2
|
||||
network_bk = self.network
|
||||
# Ensure we use xenapi_net driver
|
||||
self.network = utils.import_object(FLAGS.network_manager)
|
||||
self.network.setup_compute_network(None, fake_instance_id)
|
||||
self._test_spawn(glance_stubs.FakeGlance.IMAGE_MACHINE,
|
||||
glance_stubs.FakeGlance.IMAGE_KERNEL,
|
||||
glance_stubs.FakeGlance.IMAGE_RAMDISK,
|
||||
instance_id=fake_instance_id)
|
||||
# TODO(salvatore-orlando): a complete test here would require
|
||||
# a check for making sure the bridge for the VM's VIF is
|
||||
# consistent with bridge specified in nova db
|
||||
self.network = network_bk
|
||||
|
||||
def test_spawn_with_network_qos(self):
|
||||
self._create_instance()
|
||||
for vif_ref in xenapi_fake.get_all('VIF'):
|
||||
@@ -551,9 +568,7 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
|
||||
|
||||
class XenAPIDiffieHellmanTestCase(test.TestCase):
|
||||
"""
|
||||
Unit tests for Diffie-Hellman code
|
||||
"""
|
||||
"""Unit tests for Diffie-Hellman code."""
|
||||
def setUp(self):
|
||||
super(XenAPIDiffieHellmanTestCase, self).setUp()
|
||||
self.alice = SimpleDH()
|
||||
@@ -577,9 +592,7 @@ class XenAPIDiffieHellmanTestCase(test.TestCase):
|
||||
|
||||
|
||||
class XenAPIMigrateInstance(test.TestCase):
|
||||
"""
|
||||
Unit test for verifying migration-related actions
|
||||
"""
|
||||
"""Unit test for verifying migration-related actions."""
|
||||
|
||||
def setUp(self):
|
||||
super(XenAPIMigrateInstance, self).setUp()
|
||||
@@ -634,9 +647,7 @@ class XenAPIMigrateInstance(test.TestCase):
|
||||
|
||||
|
||||
class XenAPIDetermineDiskImageTestCase(test.TestCase):
|
||||
"""
|
||||
Unit tests for code that detects the ImageType
|
||||
"""
|
||||
"""Unit tests for code that detects the ImageType."""
|
||||
def setUp(self):
|
||||
super(XenAPIDetermineDiskImageTestCase, self).setUp()
|
||||
glance_stubs.stubout_glance_client(self.stubs,
|
||||
@@ -655,9 +666,7 @@ class XenAPIDetermineDiskImageTestCase(test.TestCase):
|
||||
self.assertEqual(disk_type, dt)
|
||||
|
||||
def test_instance_disk(self):
|
||||
"""
|
||||
If a kernel is specified then the image type is DISK (aka machine)
|
||||
"""
|
||||
"""If a kernel is specified, the image type is DISK (aka machine)."""
|
||||
FLAGS.xenapi_image_service = 'objectstore'
|
||||
self.fake_instance.image_id = glance_stubs.FakeGlance.IMAGE_MACHINE
|
||||
self.fake_instance.kernel_id = glance_stubs.FakeGlance.IMAGE_KERNEL
|
||||
|
Reference in New Issue
Block a user