diff options
| author | Dan Prince <dan.prince@rackspace.com> | 2011-03-22 11:44:33 -0400 |
|---|---|---|
| committer | Dan Prince <dan.prince@rackspace.com> | 2011-03-22 11:44:33 -0400 |
| commit | a235ee2166981bd935f830e50b1bbb4d72fbc343 (patch) | |
| tree | 3b16c320b921ebb0bbc2d30f9ea01ad137f8596f | |
| parent | 94ef3c04a56427af5b4f3d0405c21d780ac8ff07 (diff) | |
| parent | e40d692c55a02fa686e83bd87eca29a3cfa3d15e (diff) | |
Merge w/ trunk.
| -rw-r--r-- | nova/compute/manager.py | 14 | ||||
| -rw-r--r-- | nova/image/local.py | 17 | ||||
| -rw-r--r-- | nova/network/linux_net.py | 1 | ||||
| -rw-r--r-- | nova/tests/api/openstack/test_images.py | 12 | ||||
| -rw-r--r-- | nova/virt/xenapi/vm_utils.py | 4 | ||||
| -rw-r--r-- | nova/virt/xenapi/vmops.py | 127 | ||||
| -rw-r--r-- | plugins/xenserver/xenapi/etc/xapi.d/plugins/glance | 3 |
7 files changed, 103 insertions, 75 deletions
diff --git a/nova/compute/manager.py b/nova/compute/manager.py index c2781f6fb..576937cd8 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -39,6 +39,7 @@ import os import random import string import socket +import sys import tempfile import time import functools @@ -114,7 +115,13 @@ class ComputeManager(manager.Manager): # and redocument the module docstring if not compute_driver: compute_driver = FLAGS.compute_driver - self.driver = utils.import_object(compute_driver) + + try: + self.driver = utils.import_object(compute_driver) + except ImportError: + LOG.error("Unable to load the virtualization driver.") + sys.exit(1) + self.network_manager = utils.import_object(FLAGS.network_manager) self.volume_manager = utils.import_object(FLAGS.volume_manager) super(ComputeManager, self).__init__(*args, **kwargs) @@ -221,8 +228,9 @@ class ComputeManager(manager.Manager): instance_id, {'launched_at': now}) except Exception: # pylint: disable=W0702 - LOG.exception(_("instance %s: Failed to spawn"), instance_id, - context=context) + LOG.exception(_("Instance '%s' failed to spawn. Is virtualization" + " enabled in the BIOS?"), instance_id, + context=context) self.db.instance_set_state(context, instance_id, power_state.SHUTDOWN) diff --git a/nova/image/local.py b/nova/image/local.py index c4ac3baaa..609d6c42a 100644 --- a/nova/image/local.py +++ b/nova/image/local.py @@ -20,8 +20,9 @@ import os.path import random import shutil -from nova import flags from nova import exception +from nova import flags +from nova import log as logging from nova.image import service @@ -29,6 +30,8 @@ FLAGS = flags.FLAGS flags.DEFINE_string('images_path', '$state_path/images', 'path to decrypted images') +LOG = logging.getLogger('nova.image.local') + class LocalImageService(service.BaseImageService): """Image service storing images to local disk. @@ -47,7 +50,17 @@ class LocalImageService(service.BaseImageService): def _ids(self): """The list of all image ids.""" - return [int(i, 16) for i in os.listdir(self._path)] + images = [] + for image_dir in os.listdir(self._path): + try: + unhexed_image_id = int(image_dir, 16) + except ValueError: + LOG.error( + _("%s is not in correct directory naming format"\ + % image_dir)) + else: + images.append(unhexed_image_id) + return images def index(self, context): return [dict(image_id=i['id'], name=i.get('name')) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 565732869..ee36407a6 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -557,6 +557,7 @@ def get_dhcp_hosts(context, network_id): # NOTE(ja): Sending a HUP only reloads the hostfile, so any # configuration options (like dchp-range, vlan, ...) # aren't reloaded. +@utils.synchronized('dnsmasq_start') def update_dhcp(context, network_id): """(Re)starts a dnsmasq server for a given network diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 76f758929..a674ccefe 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -22,6 +22,7 @@ and as a WSGI layer import json import datetime +import os import shutil import tempfile @@ -151,6 +152,17 @@ class LocalImageServiceTest(test.TestCase, self.stubs.UnsetAll() super(LocalImageServiceTest, self).tearDown() + def test_get_all_ids_with_incorrect_directory_formats(self): + # create some old-style image directories (starting with 'ami-') + for x in [1, 2, 3]: + tempfile.mkstemp(prefix='ami-', dir=self.tempdir) + # create some valid image directories names + for x in ["1485baed", "1a60f0ee", "3123a73d"]: + os.makedirs(os.path.join(self.tempdir, x)) + found_image_ids = self.service._ids() + self.assertEqual(True, isinstance(found_image_ids, list)) + self.assertEqual(3, len(found_image_ids), len(found_image_ids)) + class GlanceImageServiceTest(test.TestCase, BaseImageServiceTests): diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 7dbca321f..28ce215d8 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -234,11 +234,11 @@ class VMHelper(HelperBase): @classmethod def create_vif(cls, session, vm_ref, network_ref, mac_address, - dev="0", rxtx_cap=0): + dev, rxtx_cap=0): """Create a VIF record. Returns a Deferred that gives the new VIF reference.""" vif_rec = {} - vif_rec['device'] = dev + vif_rec['device'] = str(dev) vif_rec['network'] = network_ref vif_rec['VM'] = vm_ref vif_rec['MAC'] = mac_address diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 29f162ad1..61ff00903 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -81,11 +81,11 @@ class VMOps(object): instance.image_id, user, project, disk_image_type) return vdi_uuid - def spawn(self, instance): + def spawn(self, instance, network_info=None): vdi_uuid = self.create_disk(instance) - self._spawn_with_disk(instance, vdi_uuid=vdi_uuid) + self._spawn_with_disk(instance, vdi_uuid, network_info) - def _spawn_with_disk(self, instance, vdi_uuid): + def _spawn_with_disk(self, instance, vdi_uuid, network_info=None): """Create VM instance""" instance_name = instance.name vm_ref = VMHelper.lookup(self._session, instance_name) @@ -129,8 +129,12 @@ class VMOps(object): vdi_ref=vdi_ref, userdevice=0, bootable=True) # inject_network_info and create vifs - networks = self.inject_network_info(instance) - self.create_vifs(instance, networks) + # TODO(tr3buchet) - check to make sure we have network info, otherwise + # create it now. This goes away once nova-multi-nic hits. + if network_info is None: + network_info = self._get_network_info(instance) + self.create_vifs(vm_ref, network_info) + self.inject_network_info(instance, vm_ref, network_info) LOG.debug(_('Starting VM %s...'), vm_ref) self._start(instance, vm_ref) @@ -181,7 +185,7 @@ class VMOps(object): timer.f = _wait_for_boot # call to reset network to configure network from xenstore - self.reset_network(instance) + self.reset_network(instance, vm_ref) return timer.start(interval=0.5, now=True) @@ -685,24 +689,17 @@ class VMOps(object): # TODO: implement this! return 'http://fakeajaxconsole/fake_url' - def inject_network_info(self, instance): - """ - Generate the network info and make calls to place it into the - xenstore and the xenstore param list - - """ - # TODO(tr3buchet) - remove comment in multi-nic - # I've decided to go ahead and consider multiple IPs and networks - # at this stage even though they aren't implemented because these will - # be needed for multi-nic and there was no sense writing it for single - # network/single IP and then having to turn around and re-write it - vm_ref = self._get_vm_opaque_ref(instance.id) - logging.debug(_("injecting network info to xenstore for vm: |%s|"), - vm_ref) + # TODO(tr3buchet) - remove this function after nova multi-nic + def _get_network_info(self, instance): + """creates network info list for instance""" admin_context = context.get_admin_context() - IPs = db.fixed_ip_get_all_by_instance(admin_context, instance['id']) + IPs = db.fixed_ip_get_all_by_instance(admin_context, + instance['id']) networks = db.network_get_all_by_instance(admin_context, instance['id']) + flavor = db.instance_type_get_by_name(admin_context, + instance['instance_type']) + network_info = [] for network in networks: network_IPs = [ip for ip in IPs if ip.network_id == network.id] @@ -719,67 +716,64 @@ class VMOps(object): "gateway": ip6.gatewayV6, "enabled": "1"} - mac_id = instance.mac_address.replace(':', '') - location = 'vm-data/networking/%s' % mac_id - mapping = { + info = { 'label': network['label'], 'gateway': network['gateway'], 'mac': instance.mac_address, + 'rxtx_cap': flavor['rxtx_cap'], 'dns': [network['dns']], 'ips': [ip_dict(ip) for ip in network_IPs], 'ip6s': [ip6_dict(ip) for ip in network_IPs]} + network_info.append((network, info)) + return network_info + + def inject_network_info(self, instance, vm_ref, network_info): + """ + Generate the network info and make calls to place it into the + xenstore and the xenstore param list + """ + logging.debug(_("injecting network info to xs for vm: |%s|"), vm_ref) - self.write_to_param_xenstore(vm_ref, {location: mapping}) + # this function raises if vm_ref is not a vm_opaque_ref + self._session.get_xenapi().VM.get_record(vm_ref) + for (network, info) in network_info: + location = 'vm-data/networking/%s' % info['mac'].replace(':', '') + self.write_to_param_xenstore(vm_ref, {location: info}) try: - self.write_to_xenstore(vm_ref, location, mapping['location']) + # TODO(tr3buchet): fix function call after refactor + #self.write_to_xenstore(vm_ref, location, info) + self._make_plugin_call('xenstore.py', 'write_record', instance, + location, {'value': json.dumps(info)}, + vm_ref) except KeyError: # catch KeyError for domid if instance isn't running pass - return networks + def create_vifs(self, vm_ref, network_info): + """Creates vifs for an instance""" + logging.debug(_("creating vif(s) for vm: |%s|"), vm_ref) - def create_vifs(self, instance, networks=None): - """ - Creates vifs for an instance + # this function raises if vm_ref is not a vm_opaque_ref + self._session.get_xenapi().VM.get_record(vm_ref) - """ - vm_ref = self._get_vm_opaque_ref(instance['id']) - admin_context = context.get_admin_context() - flavor = db.instance_type_get_by_name(admin_context, - instance.instance_type) - logging.debug(_("creating vif(s) for vm: |%s|"), vm_ref) - rxtx_cap = flavor['rxtx_cap'] - if networks is None: - networks = db.network_get_all_by_instance(admin_context, - instance['id']) - # TODO(tr3buchet) - remove comment in multi-nic - # this bit here about creating the vifs will be updated - # in multi-nic to handle multiple IPs on the same network - # and multiple networks - # for now it works as there is only one of each - for network in networks: + for device, (network, info) in enumerate(network_info): + mac_address = info['mac'] bridge = network['bridge'] + rxtx_cap = info.pop('rxtx_cap') network_ref = \ NetworkHelper.find_network_with_bridge(self._session, bridge) - if network_ref: - try: - device = "1" if instance._rescue else "0" - except AttributeError: - device = "0" - - VMHelper.create_vif(self._session, vm_ref, network_ref, - instance.mac_address, device, - rxtx_cap=rxtx_cap) + VMHelper.create_vif(self._session, vm_ref, network_ref, + mac_address, device, rxtx_cap) - def reset_network(self, instance): - """ - Creates uuid arg to pass to make_agent_call and calls it. - - """ + def reset_network(self, instance, vm_ref): + """Creates uuid arg to pass to make_agent_call and calls it.""" args = {'id': str(uuid.uuid4())} - resp = self._make_agent_call('resetnetwork', instance, '', args) + # TODO(tr3buchet): fix function call after refactor + #resp = self._make_agent_call('resetnetwork', instance, '', args) + resp = self._make_plugin_call('agent', 'resetnetwork', instance, '', + args, vm_ref) def list_from_xenstore(self, vm, path): """Runs the xenstore-ls command to get a listing of all records @@ -820,25 +814,26 @@ class VMOps(object): """ self._make_xenstore_call('delete_record', vm, path) - def _make_xenstore_call(self, method, vm, path, addl_args={}): + def _make_xenstore_call(self, method, vm, path, addl_args=None): """Handles calls to the xenstore xenapi plugin.""" return self._make_plugin_call('xenstore.py', method=method, vm=vm, path=path, addl_args=addl_args) - def _make_agent_call(self, method, vm, path, addl_args={}): + def _make_agent_call(self, method, vm, path, addl_args=None): """Abstracts out the interaction with the agent xenapi plugin.""" return self._make_plugin_call('agent', method=method, vm=vm, path=path, addl_args=addl_args) - def _make_plugin_call(self, plugin, method, vm, path, addl_args={}): + def _make_plugin_call(self, plugin, method, vm, path, addl_args=None, + vm_ref=None): """Abstracts out the process of calling a method of a xenapi plugin. Any errors raised by the plugin will in turn raise a RuntimeError here. """ instance_id = vm.id - vm_ref = self._get_vm_opaque_ref(vm) + vm_ref = vm_ref or self._get_vm_opaque_ref(vm) vm_rec = self._session.get_xenapi().VM.get_record(vm_ref) args = {'dom_id': vm_rec['domid'], 'path': path} - args.update(addl_args) + args.update(addl_args or {}) try: task = self._session.async_call_plugin(plugin, method, args) ret = self._session.wait_for_task(task, instance_id) diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance b/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance index db39cb0f4..0a45f3873 100644 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance @@ -216,8 +216,7 @@ def _upload_tarball(staging_path, image_id, glance_host, glance_port, os_type): 'x-image-meta-status': 'queued', 'x-image-meta-disk-format': 'vhd', 'x-image-meta-container-format': 'ovf', - 'x-image-meta-property-os-type': os_type, - } + 'x-image-meta-property-os-type': os_type} for header, value in headers.iteritems(): conn.putheader(header, value) |
