diff options
-rw-r--r-- | nova/api/openstack/compute/limits.py | 28 | ||||
-rw-r--r-- | nova/compute/utils.py | 1 | ||||
-rw-r--r-- | nova/db/sqlalchemy/migrate_repo/versions/153_instance_type_in_system_metadata.py | 13 | ||||
-rw-r--r-- | nova/tests/api/openstack/compute/test_limits.py | 27 | ||||
-rw-r--r-- | nova/tests/fake_network.py | 3 | ||||
-rw-r--r-- | nova/tests/test_libvirt.py | 33 | ||||
-rw-r--r-- | nova/tests/test_migrations.py | 8 | ||||
-rw-r--r-- | nova/tests/test_xenapi.py | 52 | ||||
-rw-r--r-- | nova/virt/libvirt/blockinfo.py | 6 | ||||
-rwxr-xr-x | nova/virt/libvirt/driver.py | 3 | ||||
-rw-r--r-- | nova/virt/libvirt/vif.py | 18 | ||||
-rw-r--r-- | nova/virt/powervm/blockdev.py | 5 | ||||
-rw-r--r-- | nova/virt/xenapi/agent.py | 19 | ||||
-rw-r--r-- | nova/virt/xenapi/vmops.py | 3 |
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 |