summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nova/api/openstack/compute/limits.py28
-rw-r--r--nova/compute/utils.py1
-rw-r--r--nova/db/sqlalchemy/migrate_repo/versions/153_instance_type_in_system_metadata.py13
-rw-r--r--nova/tests/api/openstack/compute/test_limits.py27
-rw-r--r--nova/tests/fake_network.py3
-rw-r--r--nova/tests/test_libvirt.py33
-rw-r--r--nova/tests/test_migrations.py8
-rw-r--r--nova/tests/test_xenapi.py52
-rw-r--r--nova/virt/libvirt/blockinfo.py6
-rwxr-xr-xnova/virt/libvirt/driver.py3
-rw-r--r--nova/virt/libvirt/vif.py18
-rw-r--r--nova/virt/powervm/blockdev.py5
-rw-r--r--nova/virt/xenapi/agent.py19
-rw-r--r--nova/virt/xenapi/vmops.py3
14 files changed, 168 insertions, 51 deletions
diff --git a/nova/api/openstack/compute/limits.py b/nova/api/openstack/compute/limits.py
index 2f69d5737..07e791306 100644
--- a/nova/api/openstack/compute/limits.py
+++ b/nova/api/openstack/compute/limits.py
@@ -75,15 +75,11 @@ class LimitsTemplate(xmlutil.TemplateBuilder):
class LimitsController(object):
- """
- Controller for accessing limits in the OpenStack API.
- """
+ """Controller for accessing limits in the OpenStack API."""
@wsgi.serializers(xml=LimitsTemplate)
def index(self, req):
- """
- Return all global and rate limit information.
- """
+ """Return all global and rate limit information."""
context = req.environ['nova.context']
quotas = QUOTAS.get_project_quotas(context, context.project_id,
usages=False)
@@ -93,6 +89,26 @@ class LimitsController(object):
builder = self._get_view_builder(req)
return builder.build(rate_limits, abs_limits)
+ def create(self, req, body):
+ """Create a new limit."""
+ raise webob.exc.HTTPNotImplemented()
+
+ def delete(self, req, id):
+ """Delete the limit."""
+ raise webob.exc.HTTPNotImplemented()
+
+ def detail(self, req):
+ """Return limit details."""
+ raise webob.exc.HTTPNotImplemented()
+
+ def show(self, req, id):
+ """Show limit information."""
+ raise webob.exc.HTTPNotImplemented()
+
+ def update(self, req, id, body):
+ """Update existing limit."""
+ raise webob.exc.HTTPNotImplemented()
+
def _get_view_builder(self, req):
return limits_views.ViewBuilder()
diff --git a/nova/compute/utils.py b/nova/compute/utils.py
index bd4cd869e..77f7b6931 100644
--- a/nova/compute/utils.py
+++ b/nova/compute/utils.py
@@ -71,6 +71,7 @@ def pack_action_start(context, instance_uuid, action_name):
'instance_uuid': instance_uuid,
'request_id': context.request_id,
'user_id': context.user_id,
+ 'project_id': context.project_id,
'start_time': context.timestamp}
return values
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/153_instance_type_in_system_metadata.py b/nova/db/sqlalchemy/migrate_repo/versions/153_instance_type_in_system_metadata.py
index 36545b435..806a1580d 100644
--- a/nova/db/sqlalchemy/migrate_repo/versions/153_instance_type_in_system_metadata.py
+++ b/nova/db/sqlalchemy/migrate_repo/versions/153_instance_type_in_system_metadata.py
@@ -33,15 +33,20 @@ def upgrade(migrate_engine):
q = select(select_columns, from_obj=instances.join(
instance_types,
- instances.c.instance_type_id == instance_types.c.id))
+ instances.c.instance_type_id == instance_types.c.id)).where(
+ instances.c.deleted == 0)
i = sys_meta.insert()
for values in q.execute():
+ insert_rows = []
for index in range(0, len(instance_type_props)):
value = values[index + 1]
- i.execute({"key": "instance_type_%s" % instance_type_props[index],
- "value": None if value is None else str(value),
- "instance_uuid": values[0]})
+ insert_rows.append({
+ "key": "instance_type_%s" % instance_type_props[index],
+ "value": None if value is None else str(value),
+ "instance_uuid": values[0],
+ })
+ i.execute(insert_rows)
def downgrade(migration_engine):
diff --git a/nova/tests/api/openstack/compute/test_limits.py b/nova/tests/api/openstack/compute/test_limits.py
index 70c37e745..e51601e31 100644
--- a/nova/tests/api/openstack/compute/test_limits.py
+++ b/nova/tests/api/openstack/compute/test_limits.py
@@ -30,6 +30,7 @@ from nova.api.openstack import xmlutil
import nova.context
from nova.openstack.common import jsonutils
from nova import test
+from nova.tests.api.openstack import fakes
from nova.tests import matchers
@@ -76,6 +77,7 @@ class LimitsControllerTest(BaseLimitTestSuite):
"""Run before each test."""
super(LimitsControllerTest, self).setUp()
self.controller = limits.create_resource()
+ self.ctrler = limits.LimitsController()
def _get_index_request(self, accept_header="application/json"):
"""Helper to set routing arguments."""
@@ -284,6 +286,31 @@ class LimitsControllerTest(BaseLimitTestSuite):
}
self._test_index_absolute_limits_json(expected)
+ def test_limit_create(self):
+ req = fakes.HTTPRequest.blank('/v2/fake/limits')
+ self.assertRaises(webob.exc.HTTPNotImplemented, self.ctrler.create,
+ req, {})
+
+ def test_limit_delete(self):
+ req = fakes.HTTPRequest.blank('/v2/fake/limits')
+ self.assertRaises(webob.exc.HTTPNotImplemented, self.ctrler.delete,
+ req, 1)
+
+ def test_limit_detail(self):
+ req = fakes.HTTPRequest.blank('/v2/fake/limits')
+ self.assertRaises(webob.exc.HTTPNotImplemented, self.ctrler.detail,
+ req)
+
+ def test_limit_show(self):
+ req = fakes.HTTPRequest.blank('/v2/fake/limits')
+ self.assertRaises(webob.exc.HTTPNotImplemented, self.ctrler.show,
+ req, 1)
+
+ def test_limit_update(self):
+ req = fakes.HTTPRequest.blank('/v2/fake/limits')
+ self.assertRaises(webob.exc.HTTPNotImplemented, self.ctrler.update,
+ req, 1, {})
+
class TestLimiter(limits.Limiter):
pass
diff --git a/nova/tests/fake_network.py b/nova/tests/fake_network.py
index a51a40f16..42ce71ded 100644
--- a/nova/tests/fake_network.py
+++ b/nova/tests/fake_network.py
@@ -54,8 +54,7 @@ class FakeVIFDriver(object):
def setattr(self, key, val):
self.__setattr__(key, val)
- def get_config(self, instance, network, mapping, image_meta,
- inst_type=None):
+ def get_config(self, instance, network, mapping, image_meta):
conf = libvirt_config.LibvirtConfigGuestInterface()
for attr, val in conf.__dict__.iteritems():
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index 86f2fe914..fa691c2e1 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -980,6 +980,10 @@ class LibvirtConnTestCase(test.TestCase):
instance_data = dict(self.test_instance)
self._check_xml_and_disk_prefix(instance_data)
+ def test_xml_user_specified_disk_prefix(self):
+ instance_data = dict(self.test_instance)
+ self._check_xml_and_disk_prefix(instance_data, 'sd')
+
def test_xml_disk_driver(self):
instance_data = dict(self.test_instance)
self._check_xml_and_disk_driver(instance_data)
@@ -1711,28 +1715,39 @@ class LibvirtConnTestCase(test.TestCase):
target = tree.find('./devices/filesystem/source').get('dir')
self.assertTrue(len(target) > 0)
- def _check_xml_and_disk_prefix(self, instance):
+ def _check_xml_and_disk_prefix(self, instance, prefix=None):
user_context = context.RequestContext(self.user_id,
self.project_id)
instance_ref = db.instance_create(user_context, instance)
+ def _get_prefix(p, default):
+ if p:
+ return p + 'a'
+ return default
+
type_disk_map = {
'qemu': [
- (lambda t: t.find('.').get('type'), 'qemu'),
- (lambda t: t.find('./devices/disk/target').get('dev'), 'vda')],
+ (lambda t: t.find('.').get('type'), 'qemu'),
+ (lambda t: t.find('./devices/disk/target').get('dev'),
+ _get_prefix(prefix, 'vda'))],
'xen': [
- (lambda t: t.find('.').get('type'), 'xen'),
- (lambda t: t.find('./devices/disk/target').get('dev'), 'sda')],
+ (lambda t: t.find('.').get('type'), 'xen'),
+ (lambda t: t.find('./devices/disk/target').get('dev'),
+ _get_prefix(prefix, 'sda'))],
'kvm': [
- (lambda t: t.find('.').get('type'), 'kvm'),
- (lambda t: t.find('./devices/disk/target').get('dev'), 'vda')],
+ (lambda t: t.find('.').get('type'), 'kvm'),
+ (lambda t: t.find('./devices/disk/target').get('dev'),
+ _get_prefix(prefix, 'vda'))],
'uml': [
- (lambda t: t.find('.').get('type'), 'uml'),
- (lambda t: t.find('./devices/disk/target').get('dev'), 'ubda')]
+ (lambda t: t.find('.').get('type'), 'uml'),
+ (lambda t: t.find('./devices/disk/target').get('dev'),
+ _get_prefix(prefix, 'ubda'))]
}
for (libvirt_type, checks) in type_disk_map.iteritems():
self.flags(libvirt_type=libvirt_type)
+ if prefix:
+ self.flags(libvirt_disk_prefix=prefix)
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
network_info = _fake_network_info(self.stubs, 1)
diff --git a/nova/tests/test_migrations.py b/nova/tests/test_migrations.py
index 60975c68c..8a8dc93f4 100644
--- a/nova/tests/test_migrations.py
+++ b/nova/tests/test_migrations.py
@@ -794,10 +794,10 @@ class TestNovaMigrations(BaseMigrationTestCase, CommonTestsMixIn):
]
fake_instances = [
- dict(uuid='m153-uuid1', instance_type_id=10),
- dict(uuid='m153-uuid2', instance_type_id=11),
- dict(uuid='m153-uuid3', instance_type_id=12),
- dict(uuid='m153-uuid4', instance_type_id=13),
+ dict(uuid='m153-uuid1', instance_type_id=10, deleted=0),
+ dict(uuid='m153-uuid2', instance_type_id=11, deleted=0),
+ dict(uuid='m153-uuid3', instance_type_id=12, deleted=0),
+ dict(uuid='m153-uuid4', instance_type_id=13, deleted=0),
# NOTE(danms): no use of type5
]
diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py
index 6714161f1..4d02da6cd 100644
--- a/nova/tests/test_xenapi.py
+++ b/nova/tests/test_xenapi.py
@@ -622,7 +622,8 @@ class XenAPIVMTestCase(stubs.XenAPITestBase):
create_record=True, empty_dns=False,
image_meta={'id': IMAGE_VHD,
'disk_format': 'vhd'},
- block_device_info=None):
+ block_device_info=None,
+ key_data=None):
if injected_files is None:
injected_files = []
@@ -634,16 +635,17 @@ class XenAPIVMTestCase(stubs.XenAPITestBase):
if create_record:
instance_values = {'id': instance_id,
- 'project_id': self.project_id,
- 'user_id': self.user_id,
- 'image_ref': image_ref,
- 'kernel_id': kernel_id,
- 'ramdisk_id': ramdisk_id,
- 'root_gb': 20,
- 'instance_type_id': instance_type_id,
- 'os_type': os_type,
- 'hostname': hostname,
- 'architecture': architecture}
+ 'project_id': self.project_id,
+ 'user_id': self.user_id,
+ 'image_ref': image_ref,
+ 'kernel_id': kernel_id,
+ 'ramdisk_id': ramdisk_id,
+ 'root_gb': 20,
+ 'instance_type_id': instance_type_id,
+ 'os_type': os_type,
+ 'hostname': hostname,
+ 'key_data': key_data,
+ 'architecture': architecture}
instance = create_instance_with_system_metadata(self.context,
instance_values)
else:
@@ -885,6 +887,34 @@ class XenAPIVMTestCase(stubs.XenAPITestBase):
self.assertEquals(vif_rec['qos_algorithm_params']['kbps'],
str(3 * 10 * 1024))
+ def test_spawn_ssh_key_injection(self):
+ # Test spawning with key_data on an instance. Should use
+ # agent file injection.
+ actual_injected_files = []
+
+ def fake_inject_file(self, method, args):
+ path = base64.b64decode(args['b64_path'])
+ contents = base64.b64decode(args['b64_contents'])
+ actual_injected_files.append((path, contents))
+ return jsonutils.dumps({'returncode': '0', 'message': 'success'})
+
+ def noop(*args, **kwargs):
+ pass
+
+ self.stubs.Set(stubs.FakeSessionForVMTests,
+ '_plugin_agent_inject_file', fake_inject_file)
+ self.stubs.Set(agent.XenAPIBasedAgent,
+ 'set_admin_password', noop)
+
+ expected_data = ('\n# The following ssh key was injected by '
+ 'Nova\nfake_keydata\n')
+
+ injected_files = [('/root/.ssh/authorized_keys', expected_data)]
+ self._test_spawn(IMAGE_VHD, None, None,
+ os_type="linux", architecture="x86-64",
+ key_data='fake_keydata')
+ self.assertEquals(actual_injected_files, injected_files)
+
def test_spawn_injected_files(self):
# Test spawning with injected_files.
actual_injected_files = []
diff --git a/nova/virt/libvirt/blockinfo.py b/nova/virt/libvirt/blockinfo.py
index 88f97a271..fc39fc99d 100644
--- a/nova/virt/libvirt/blockinfo.py
+++ b/nova/virt/libvirt/blockinfo.py
@@ -65,6 +65,8 @@ variables / types used
"""
+from oslo.config import cfg
+
from nova import block_device
from nova.compute import instance_types
from nova import exception
@@ -75,6 +77,8 @@ from nova.virt import driver
LOG = logging.getLogger(__name__)
+CONF = cfg.CONF
+
def has_disk_dev(mapping, disk_dev):
"""Determine if a disk device name has already been used.
@@ -103,6 +107,8 @@ def get_dev_prefix_for_disk_bus(disk_bus):
Returns the dev prefix or raises an
exception if the disk bus is unknown."""
+ if CONF.libvirt_disk_prefix:
+ return CONF.libvirt_disk_prefix
if disk_bus == "ide":
return "hd"
elif disk_bus == "virtio":
diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py
index 4ad7f2619..eabe75c73 100755
--- a/nova/virt/libvirt/driver.py
+++ b/nova/virt/libvirt/driver.py
@@ -2247,8 +2247,7 @@ class LibvirtDriver(driver.ComputeDriver):
for (network, mapping) in network_info:
cfg = self.vif_driver.get_config(instance,
network, mapping,
- image_meta,
- inst_type)
+ image_meta)
guest.add_device(cfg)
if CONF.libvirt_type == "qemu" or CONF.libvirt_type == "kvm":
diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py
index 1fe7385e1..68b0505aa 100644
--- a/nova/virt/libvirt/vif.py
+++ b/nova/virt/libvirt/vif.py
@@ -92,8 +92,7 @@ class LibvirtBaseVIFDriver(object):
return mapping['vif_devname']
return ("nic" + mapping['vif_uuid'])[:network_model.NIC_NAME_LEN]
- def get_config(self, instance, network, mapping, image_meta,
- inst_type=None):
+ def get_config(self, instance, network, mapping, image_meta):
conf = vconfig.LibvirtConfigGuestInterface()
# Default to letting libvirt / the hypervisor choose the model
model = None
@@ -160,15 +159,13 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver):
return True
return False
- def get_config_bridge(self, instance, network, mapping, image_meta,
- inst_type=None):
+ def get_config_bridge(self, instance, network, mapping, image_meta):
"""Get VIF configurations for bridge type."""
conf = super(LibvirtGenericVIFDriver,
self).get_config(instance,
network,
mapping,
- image_meta,
- inst_type)
+ image_meta)
designer.set_vif_host_backend_bridge_config(
conf, self.get_bridge_name(network),
@@ -178,8 +175,7 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver):
name = "nova-instance-" + instance['name'] + "-" + mac_id
if self.get_firewall_required():
conf.filtername = name
- if inst_type and inst_type.get('extra_specs') is not None:
- designer.set_vif_bandwidth_config(conf, inst_type['extra_specs'])
+ designer.set_vif_bandwidth_config(conf, instance)
return conf
@@ -262,8 +258,7 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver):
return conf
- def get_config(self, instance, network, mapping, image_meta,
- inst_type=None):
+ def get_config(self, instance, network, mapping, image_meta):
vif_type = mapping.get('vif_type')
LOG.debug(_("vif_type=%(vif_type)s instance=%(instance)s "
@@ -278,8 +273,7 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver):
if vif_type == network_model.VIF_TYPE_BRIDGE:
return self.get_config_bridge(instance,
network, mapping,
- image_meta,
- inst_type)
+ image_meta)
elif vif_type == network_model.VIF_TYPE_OVS:
return self.get_config_ovs(instance,
network, mapping,
diff --git a/nova/virt/powervm/blockdev.py b/nova/virt/powervm/blockdev.py
index 247746faa..6c746cc83 100644
--- a/nova/virt/powervm/blockdev.py
+++ b/nova/virt/powervm/blockdev.py
@@ -399,7 +399,10 @@ class PowerVMLocalVolumeAdapter(PowerVMDiskAdapter):
source_cksum = hasher.hexdigest()
comp_path = os.path.join(remote_path, os.path.basename(source_path))
- uncomp_path = comp_path.rstrip(".gz")
+ if comp_path.endswith(".gz"):
+ uncomp_path = os.path.splitext(comp_path)[0]
+ else:
+ uncomp_path = comp_path
if not decompress:
final_path = comp_path
else:
diff --git a/nova/virt/xenapi/agent.py b/nova/virt/xenapi/agent.py
index 1fe6dff7e..a8074e8d0 100644
--- a/nova/virt/xenapi/agent.py
+++ b/nova/virt/xenapi/agent.py
@@ -224,6 +224,25 @@ class XenAPIBasedAgent(object):
return resp['message']
+ def inject_ssh_key(self):
+ sshkey = self.instance.get('key_data')
+ if not sshkey:
+ return
+ if self.instance['os_type'] == 'windows':
+ LOG.warning(_("Skipping setting of ssh key for Windows."),
+ instance=self.instance)
+ return
+ sshkey = str(sshkey)
+ keyfile = '/root/.ssh/authorized_keys'
+ key_data = ''.join([
+ '\n',
+ '# The following ssh key was injected by Nova',
+ '\n',
+ sshkey.strip(),
+ '\n',
+ ])
+ return self.inject_file(keyfile, key_data)
+
def inject_file(self, path, contents):
LOG.debug(_('Injecting file path: %r'), path, instance=self.instance)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index cd7311678..028b20910 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -651,6 +651,9 @@ class VMOps(object):
# instance, but skip the admin password configuration
no_agent = version is None
+ # Inject ssh key.
+ agent.inject_ssh_key()
+
# Inject files, if necessary
if injected_files:
# Inject any files, if specified