summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Authors1
-rw-r--r--MANIFEST.in10
-rw-r--r--locale/nova.pot2
-rw-r--r--nova/api/ec2/cloud.py3
-rw-r--r--nova/compute/api.py12
-rw-r--r--nova/compute/manager.py2
-rw-r--r--nova/compute/power_state.py4
-rw-r--r--nova/context.py5
-rw-r--r--nova/db/sqlalchemy/migrate_repo/versions/001_austin.py14
-rw-r--r--nova/db/sqlalchemy/migrate_repo/versions/002_bexar.py7
-rw-r--r--nova/flags.py2
-rw-r--r--nova/image/s3.py2
-rw-r--r--nova/log.py19
-rw-r--r--nova/network/linux_net.py2
-rw-r--r--nova/tests/test_api.py35
-rw-r--r--nova/tests/test_log.py21
-rw-r--r--nova/tests/test_xenapi.py11
-rw-r--r--nova/twistd.py2
-rw-r--r--nova/utils.py2
-rw-r--r--nova/virt/xenapi/fake.py4
-rw-r--r--nova/virt/xenapi/vm_utils.py20
-rw-r--r--nova/virt/xenapi/vmops.py32
-rw-r--r--nova/volume/manager.py8
-rwxr-xr-xplugins/xenserver/xenapi/etc/xapi.d/plugins/agent7
-rw-r--r--plugins/xenserver/xenapi/etc/xapi.d/plugins/glance71
-rw-r--r--plugins/xenserver/xenapi/etc/xapi.d/plugins/objectstore46
-rw-r--r--setup.py7
27 files changed, 242 insertions, 109 deletions
diff --git a/Authors b/Authors
index b359fec22..c338a9b3e 100644
--- a/Authors
+++ b/Authors
@@ -56,6 +56,7 @@ Thierry Carrez <thierry@openstack.org>
Todd Willey <todd@ansolabs.com>
Trey Morris <trey.morris@rackspace.com>
Tushar Patil <tushar.vitthal.patil@gmail.com> <tpatil@vertex.co.in>
+Vasiliy Shlykov <vash@vasiliyshlykov.org>
Vishvananda Ishaya <vishvananda@gmail.com>
Youcef Laribi <Youcef.Laribi@eu.citrix.com>
Zhixue Wu <Zhixue.Wu@citrix.com>
diff --git a/MANIFEST.in b/MANIFEST.in
index 3908830d7..f0a9cffb3 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -6,14 +6,23 @@ graft doc
graft smoketests
graft tools
graft etc
+graft bzrplugins
+graft contrib
+graft po
+graft plugins
include nova/api/openstack/notes.txt
+include nova/auth/*.schema
include nova/auth/novarc.template
+include nova/auth/opendj.sh
include nova/auth/slap.sh
include nova/cloudpipe/bootscript.sh
include nova/cloudpipe/client.ovpn.template
+include nova/cloudpipe/bootscript.template
include nova/compute/fakevirtinstance.xml
include nova/compute/interfaces.template
+include nova/console/xvp.conf.template
include nova/db/sqlalchemy/migrate_repo/migrate.cfg
+include nova/db/sqlalchemy/migrate_repo/README
include nova/virt/interfaces.template
include nova/virt/libvirt*.xml.template
include nova/tests/CA/
@@ -25,6 +34,7 @@ include nova/tests/bundle/1mb.manifest.xml
include nova/tests/bundle/1mb.no_kernel_or_ramdisk.manifest.xml
include nova/tests/bundle/1mb.part.0
include nova/tests/bundle/1mb.part.1
+include nova/tests/db/nova.austin.sqlite
include plugins/xenapi/README
include plugins/xenapi/etc/xapi.d/plugins/objectstore
include plugins/xenapi/etc/xapi.d/plugins/pluginlib_nova.py
diff --git a/locale/nova.pot b/locale/nova.pot
index a96411e33..53e38c619 100644
--- a/locale/nova.pot
+++ b/locale/nova.pot
@@ -1826,7 +1826,7 @@ msgstr ""
#: nova/virt/xenapi/vm_utils.py:290
#, python-format
-msgid "PV Kernel in VDI:%d"
+msgid "PV Kernel in VDI:%s"
msgstr ""
#: nova/virt/xenapi/vm_utils.py:318
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index 16a3a4521..6919cd8d2 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -883,6 +883,9 @@ class CloudController(object):
% attribute)
try:
image = self.image_service.show(context, image_id)
+ image = self._format_image(context,
+ self.image_service.show(context,
+ image_id))
except IndexError:
raise exception.ApiError(_('invalid id: %s') % image_id)
result = {'image_id': image_id, 'launchPermission': []}
diff --git a/nova/compute/api.py b/nova/compute/api.py
index ac02dbcfa..495ae93bf 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -67,10 +67,10 @@ class API(base.Base):
"""Get the network topic for an instance."""
try:
instance = self.get(context, instance_id)
- except exception.NotFound as e:
+ except exception.NotFound:
LOG.warning(_("Instance %d was not found in get_network_topic"),
instance_id)
- raise e
+ raise
host = instance['host']
if not host:
@@ -103,9 +103,9 @@ class API(base.Base):
if not is_vpn:
image = self.image_service.show(context, image_id)
if kernel_id is None:
- kernel_id = image.get('kernelId', None)
+ kernel_id = image.get('kernel_id', None)
if ramdisk_id is None:
- ramdisk_id = image.get('ramdiskId', None)
+ ramdisk_id = image.get('ramdisk_id', None)
# No kernel and ramdisk for raw images
if kernel_id == str(FLAGS.null_kernel):
kernel_id = None
@@ -293,10 +293,10 @@ class API(base.Base):
LOG.debug(_("Going to try to terminate %s"), instance_id)
try:
instance = self.get(context, instance_id)
- except exception.NotFound as e:
+ except exception.NotFound:
LOG.warning(_("Instance %d was not found during terminate"),
instance_id)
- raise e
+ raise
if (instance['state_description'] == 'terminating'):
LOG.warning(_("Instance %d is already being terminated"),
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index f4418af26..bb999931c 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -127,7 +127,7 @@ class ComputeManager(manager.Manager):
info = self.driver.get_info(instance_ref['name'])
state = info['state']
except exception.NotFound:
- state = power_state.NOSTATE
+ state = power_state.FAILED
self.db.instance_set_state(context, instance_id, state)
def get_console_topic(self, context, **_kwargs):
diff --git a/nova/compute/power_state.py b/nova/compute/power_state.py
index 37039d2ec..adfc2dff0 100644
--- a/nova/compute/power_state.py
+++ b/nova/compute/power_state.py
@@ -27,6 +27,7 @@ SHUTDOWN = 0x04
SHUTOFF = 0x05
CRASHED = 0x06
SUSPENDED = 0x07
+FAILED = 0x08
def name(code):
@@ -38,5 +39,6 @@ def name(code):
SHUTDOWN: 'shutdown',
SHUTOFF: 'shutdown',
CRASHED: 'crashed',
- SUSPENDED: 'suspended'}
+ SUSPENDED: 'suspended',
+ FAILED: 'failed to spawn'}
return d[code]
diff --git a/nova/context.py b/nova/context.py
index f2669c9f1..0256bf448 100644
--- a/nova/context.py
+++ b/nova/context.py
@@ -28,7 +28,6 @@ from nova import utils
class RequestContext(object):
-
def __init__(self, user, project, is_admin=None, read_deleted=False,
remote_address=None, timestamp=None, request_id=None):
if hasattr(user, 'id'):
@@ -53,7 +52,7 @@ class RequestContext(object):
self.read_deleted = read_deleted
self.remote_address = remote_address
if not timestamp:
- timestamp = datetime.datetime.utcnow()
+ timestamp = utils.utcnow()
if isinstance(timestamp, str) or isinstance(timestamp, unicode):
timestamp = utils.parse_isotime(timestamp)
self.timestamp = timestamp
@@ -101,7 +100,7 @@ class RequestContext(object):
return cls(**values)
def elevated(self, read_deleted=False):
- """Return a version of this context with admin flag set"""
+ """Return a version of this context with admin flag set."""
return RequestContext(self.user_id,
self.project_id,
True,
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/001_austin.py b/nova/db/sqlalchemy/migrate_repo/versions/001_austin.py
index 366944591..9e7ab3554 100644
--- a/nova/db/sqlalchemy/migrate_repo/versions/001_austin.py
+++ b/nova/db/sqlalchemy/migrate_repo/versions/001_austin.py
@@ -508,17 +508,19 @@ def upgrade(migrate_engine):
# bind migrate_engine to your metadata
meta.bind = migrate_engine
- for table in (auth_tokens, export_devices, fixed_ips, floating_ips,
- instances, key_pairs, networks,
- projects, quotas, security_groups, security_group_inst_assoc,
- security_group_rules, services, users,
- user_project_association, user_project_role_association,
- user_role_association, volumes):
+ tables = [auth_tokens,
+ instances, key_pairs, networks, fixed_ips, floating_ips,
+ quotas, security_groups, security_group_inst_assoc,
+ security_group_rules, services, users, projects,
+ user_project_association, user_project_role_association,
+ user_role_association, volumes, export_devices]
+ for table in tables:
try:
table.create()
except Exception:
logging.info(repr(table))
logging.exception('Exception while creating table')
+ meta.drop_all(tables=tables)
raise
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/002_bexar.py b/nova/db/sqlalchemy/migrate_repo/versions/002_bexar.py
index 699b837f8..413536a59 100644
--- a/nova/db/sqlalchemy/migrate_repo/versions/002_bexar.py
+++ b/nova/db/sqlalchemy/migrate_repo/versions/002_bexar.py
@@ -209,13 +209,16 @@ def upgrade(migrate_engine):
# Upgrade operations go here. Don't create your own engine;
# bind migrate_engine to your metadata
meta.bind = migrate_engine
- for table in (certificates, consoles, console_pools, instance_actions,
- iscsi_targets):
+
+ tables = [certificates, console_pools, consoles, instance_actions,
+ iscsi_targets]
+ for table in tables:
try:
table.create()
except Exception:
logging.info(repr(table))
logging.exception('Exception while creating table')
+ meta.drop_all(tables=tables)
raise
auth_tokens.c.user_id.alter(type=String(length=255,
diff --git a/nova/flags.py b/nova/flags.py
index 3ba3fe6fa..f64a62da9 100644
--- a/nova/flags.py
+++ b/nova/flags.py
@@ -282,6 +282,8 @@ DEFINE_integer('auth_token_ttl', 3600, 'Seconds for auth tokens to linger')
DEFINE_string('state_path', os.path.join(os.path.dirname(__file__), '../'),
"Top-level directory for maintaining nova's state")
+DEFINE_string('logdir', None, 'output to a per-service log file in named '
+ 'directory')
DEFINE_string('sql_connection',
'sqlite:///$state_path/nova.sqlite',
diff --git a/nova/image/s3.py b/nova/image/s3.py
index 71304cdd6..14135a1ee 100644
--- a/nova/image/s3.py
+++ b/nova/image/s3.py
@@ -94,7 +94,7 @@ class S3ImageService(service.BaseImageService):
if FLAGS.connection_type == 'fake':
return {'imageId': 'bar'}
result = self.index(context)
- result = [i for i in result if i['imageId'] == image_id]
+ result = [i for i in result if i['id'] == image_id]
if not result:
raise exception.NotFound(_('Image %s could not be found')
% image_id)
diff --git a/nova/log.py b/nova/log.py
index b541488bd..90c40cca7 100644
--- a/nova/log.py
+++ b/nova/log.py
@@ -28,9 +28,11 @@ It also allows setting of formatting information through flags.
import cStringIO
+import inspect
import json
import logging
import logging.handlers
+import os
import sys
import traceback
@@ -111,6 +113,18 @@ def _dictify_context(context):
return context
+def _get_binary_name():
+ return os.path.basename(inspect.stack()[-1][1])
+
+
+def get_log_file_path(binary=None):
+ if FLAGS.logfile:
+ return FLAGS.logfile
+ if FLAGS.logdir:
+ binary = binary or _get_binary_name()
+ return '%s.log' % (os.path.join(FLAGS.logdir, binary),)
+
+
def basicConfig():
logging.basicConfig()
for handler in logging.root.handlers:
@@ -123,8 +137,9 @@ def basicConfig():
syslog = SysLogHandler(address='/dev/log')
syslog.setFormatter(_formatter)
logging.root.addHandler(syslog)
- if FLAGS.logfile:
- logfile = FileHandler(FLAGS.logfile)
+ logpath = get_log_file_path()
+ if logpath:
+ logfile = FileHandler(logpath)
logfile.setFormatter(_formatter)
logging.root.addHandler(logfile)
diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py
index ed37e8ba7..c1cbff7d8 100644
--- a/nova/network/linux_net.py
+++ b/nova/network/linux_net.py
@@ -54,6 +54,8 @@ flags.DEFINE_string('routing_source_ip', '$my_ip',
'Public IP of network host')
flags.DEFINE_bool('use_nova_chains', False,
'use the nova_ routing chains instead of default')
+flags.DEFINE_string('input_chain', 'INPUT',
+ 'chain to add nova_input to')
flags.DEFINE_string('dns_server', None,
'if set, uses specific dns server for dnsmasq')
diff --git a/nova/tests/test_api.py b/nova/tests/test_api.py
index 2569e262b..fa27825cd 100644
--- a/nova/tests/test_api.py
+++ b/nova/tests/test_api.py
@@ -248,16 +248,14 @@ class ApiEc2TestCase(test.TestCase):
self.mox.ReplayAll()
rv = self.ec2.get_all_security_groups()
- # I don't bother checkng that we actually find it here,
- # because the create/delete unit test further up should
- # be good enough for that.
- for group in rv:
- if group.name == security_group_name:
- self.assertEquals(len(group.rules), 1)
- self.assertEquals(int(group.rules[0].from_port), 80)
- self.assertEquals(int(group.rules[0].to_port), 81)
- self.assertEquals(len(group.rules[0].grants), 1)
- self.assertEquals(str(group.rules[0].grants[0]), '0.0.0.0/0')
+
+ group = [grp for grp in rv if grp.name == security_group_name][0]
+
+ self.assertEquals(len(group.rules), 1)
+ self.assertEquals(int(group.rules[0].from_port), 80)
+ self.assertEquals(int(group.rules[0].to_port), 81)
+ self.assertEquals(len(group.rules[0].grants), 1)
+ self.assertEquals(str(group.rules[0].grants[0]), '0.0.0.0/0')
self.expect_http()
self.mox.ReplayAll()
@@ -314,16 +312,13 @@ class ApiEc2TestCase(test.TestCase):
self.mox.ReplayAll()
rv = self.ec2.get_all_security_groups()
- # I don't bother checkng that we actually find it here,
- # because the create/delete unit test further up should
- # be good enough for that.
- for group in rv:
- if group.name == security_group_name:
- self.assertEquals(len(group.rules), 1)
- self.assertEquals(int(group.rules[0].from_port), 80)
- self.assertEquals(int(group.rules[0].to_port), 81)
- self.assertEquals(len(group.rules[0].grants), 1)
- self.assertEquals(str(group.rules[0].grants[0]), '::/0')
+
+ group = [grp for grp in rv if grp.name == security_group_name][0]
+ self.assertEquals(len(group.rules), 1)
+ self.assertEquals(int(group.rules[0].from_port), 80)
+ self.assertEquals(int(group.rules[0].to_port), 81)
+ self.assertEquals(len(group.rules[0].grants), 1)
+ self.assertEquals(str(group.rules[0].grants[0]), '::/0')
self.expect_http()
self.mox.ReplayAll()
diff --git a/nova/tests/test_log.py b/nova/tests/test_log.py
index 868a5ead3..c2c9d7772 100644
--- a/nova/tests/test_log.py
+++ b/nova/tests/test_log.py
@@ -46,6 +46,27 @@ class RootLoggerTestCase(test.TestCase):
self.assert_(True) # didn't raise exception
+class LogHandlerTestCase(test.TestCase):
+ def test_log_path_logdir(self):
+ self.flags(logdir='/some/path')
+ self.assertEquals(log.get_log_file_path(binary='foo-bar'),
+ '/some/path/foo-bar.log')
+
+ def test_log_path_logfile(self):
+ self.flags(logfile='/some/path/foo-bar.log')
+ self.assertEquals(log.get_log_file_path(binary='foo-bar'),
+ '/some/path/foo-bar.log')
+
+ def test_log_path_none(self):
+ self.assertTrue(log.get_log_file_path(binary='foo-bar') is None)
+
+ def test_log_path_logfile_overrides_logdir(self):
+ self.flags(logdir='/some/other/path',
+ logfile='/some/path/foo-bar.log')
+ self.assertEquals(log.get_log_file_path(binary='foo-bar'),
+ '/some/path/foo-bar.log')
+
+
class NovaFormatterTestCase(test.TestCase):
def setUp(self):
super(NovaFormatterTestCase, self).setUp()
diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py
index 9f5b266f3..d5660c5d1 100644
--- a/nova/tests/test_xenapi.py
+++ b/nova/tests/test_xenapi.py
@@ -243,7 +243,8 @@ class XenAPIVMTestCase(test.TestCase):
# Check that the VM is running according to XenAPI.
self.assertEquals(vm['power_state'], 'Running')
- def _test_spawn(self, image_id, kernel_id, ramdisk_id):
+ def _test_spawn(self, image_id, kernel_id, ramdisk_id,
+ instance_type="m1.large"):
stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests)
values = {'name': 1,
'id': 1,
@@ -252,7 +253,7 @@ class XenAPIVMTestCase(test.TestCase):
'image_id': image_id,
'kernel_id': kernel_id,
'ramdisk_id': ramdisk_id,
- 'instance_type': 'm1.large',
+ 'instance_type': instance_type,
'mac_address': 'aa:bb:cc:dd:ee:ff',
}
conn = xenapi_conn.get_connection(False)
@@ -260,6 +261,12 @@ class XenAPIVMTestCase(test.TestCase):
conn.spawn(instance)
self.check_vm_record(conn)
+ def test_spawn_not_enough_memory(self):
+ FLAGS.xenapi_image_service = 'glance'
+ self.assertRaises(Exception,
+ self._test_spawn,
+ 1, 2, 3, "m1.xlarge")
+
def test_spawn_raw_objectstore(self):
FLAGS.xenapi_image_service = 'objectstore'
self._test_spawn(1, None, None)
diff --git a/nova/twistd.py b/nova/twistd.py
index 6390a8144..60ff7879a 100644
--- a/nova/twistd.py
+++ b/nova/twistd.py
@@ -43,8 +43,6 @@ else:
FLAGS = flags.FLAGS
-flags.DEFINE_string('logdir', None, 'directory to keep log files in '
- '(will be prepended to $logfile)')
class TwistdServerOptions(ServerOptions):
diff --git a/nova/utils.py b/nova/utils.py
index 8d7ff1f64..ba71ebf39 100644
--- a/nova/utils.py
+++ b/nova/utils.py
@@ -25,7 +25,6 @@ import inspect
import json
import os
import random
-import subprocess
import socket
import struct
import sys
@@ -36,6 +35,7 @@ import netaddr
from eventlet import event
from eventlet import greenthread
+from eventlet.green import subprocess
from nova import exception
from nova.exception import ProcessExecutionError
diff --git a/nova/virt/xenapi/fake.py b/nova/virt/xenapi/fake.py
index e8352771c..018d0dcd3 100644
--- a/nova/virt/xenapi/fake.py
+++ b/nova/virt/xenapi/fake.py
@@ -286,6 +286,10 @@ class SessionBase(object):
rec['currently_attached'] = False
rec['device'] = ''
+ def host_compute_free_memory(self, _1, ref):
+ #Always return 12GB available
+ return 12 * 1024 * 1024 * 1024
+
def xenapi_request(self, methodname, params):
if methodname.startswith('login'):
self._login(methodname, params)
diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py
index 4bbd522c1..80cc3035d 100644
--- a/nova/virt/xenapi/vm_utils.py
+++ b/nova/virt/xenapi/vm_utils.py
@@ -139,6 +139,16 @@ class VMHelper(HelperBase):
return vm_ref
@classmethod
+ def ensure_free_mem(cls, session, instance):
+ instance_type = instance_types.INSTANCE_TYPES[instance.instance_type]
+ mem = long(instance_type['memory_mb']) * 1024 * 1024
+ #get free memory from host
+ host = session.get_xenapi_host()
+ host_free_mem = long(session.get_xenapi().host.
+ compute_free_memory(host))
+ return host_free_mem >= mem
+
+ @classmethod
def create_vbd(cls, session, vm_ref, vdi_ref, userdevice, bootable):
"""Create a VBD record. Returns a Deferred that gives the new
VBD reference."""
@@ -384,7 +394,7 @@ class VMHelper(HelperBase):
pv = True
elif pv_str.lower() == 'false':
pv = False
- LOG.debug(_("PV Kernel in VDI:%d"), pv)
+ LOG.debug(_("PV Kernel in VDI:%s"), pv)
return pv
@classmethod
@@ -440,6 +450,14 @@ class VMHelper(HelperBase):
return None
@classmethod
+ def lookup_kernel_ramdisk(cls, session, vm):
+ vm_rec = session.get_xenapi().VM.get_record(vm)
+ if 'PV_kernel' in vm_rec and 'PV_ramdisk' in vm_rec:
+ return (vm_rec['PV_kernel'], vm_rec['PV_ramdisk'])
+ else:
+ return (None, None)
+
+ @classmethod
def compile_info(cls, record):
"""Fill record with VM status information"""
LOG.info(_("(VM_UTILS) xenserver vm state -> |%s|"),
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index e84ce20c4..98f8ab46e 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -66,7 +66,15 @@ class VMOps(object):
if vm is not None:
raise exception.Duplicate(_('Attempted to create'
' non-unique name %s') % instance.name)
-
+ #ensure enough free memory is available
+ if not VMHelper.ensure_free_mem(self._session, instance):
+ name = instance['name']
+ LOG.exception(_('instance %(name)s: not enough free memory')
+ % locals())
+ db.instance_set_state(context.get_admin_context(),
+ instance['id'],
+ power_state.SHUTDOWN)
+ return
bridge = db.network_get_by_instance(context.get_admin_context(),
instance['id'])['bridge']
network_ref = \
@@ -161,7 +169,8 @@ class VMOps(object):
instance_name = instance_or_vm.name
vm = VMHelper.lookup(self._session, instance_name)
if vm is None:
- raise Exception(_('Instance not present %s') % instance_name)
+ raise exception.NotFound(
+ _('Instance not present %s') % instance_name)
return vm
def snapshot(self, instance, image_id):
@@ -286,8 +295,23 @@ class VMOps(object):
def _destroy_vm(self, instance, vm):
"""Destroys a VM record """
try:
- task = self._session.call_xenapi('Async.VM.destroy', vm)
- self._session.wait_for_task(instance.id, task)
+ kernel = None
+ ramdisk = None
+ if instance.kernel_id or instance.ramdisk_id:
+ (kernel, ramdisk) = VMHelper.lookup_kernel_ramdisk(
+ self._session, vm)
+ task1 = self._session.call_xenapi('Async.VM.destroy', vm)
+ LOG.debug(_("Removing kernel/ramdisk files"))
+ fn = "remove_kernel_ramdisk"
+ args = {}
+ if kernel:
+ args['kernel-file'] = kernel
+ if ramdisk:
+ args['ramdisk-file'] = ramdisk
+ task2 = self._session.async_call_plugin('glance', fn, args)
+ self._session.wait_for_task(instance.id, task1)
+ self._session.wait_for_task(instance.id, task2)
+ LOG.debug(_("kernel/ramdisk files removed"))
except self.XenAPI.Failure, exc:
LOG.exception(exc)
diff --git a/nova/volume/manager.py b/nova/volume/manager.py
index 6e70ec881..d2f02e4e0 100644
--- a/nova/volume/manager.py
+++ b/nova/volume/manager.py
@@ -111,10 +111,10 @@ class VolumeManager(manager.Manager):
LOG.debug(_("volume %s: creating export"), volume_ref['name'])
self.driver.create_export(context, volume_ref)
- except Exception as e:
+ except Exception:
self.db.volume_update(context,
volume_ref['id'], {'status': 'error'})
- raise e
+ raise
now = datetime.datetime.utcnow()
self.db.volume_update(context,
@@ -137,11 +137,11 @@ class VolumeManager(manager.Manager):
self.driver.remove_export(context, volume_ref)
LOG.debug(_("volume %s: deleting"), volume_ref['name'])
self.driver.delete_volume(volume_ref)
- except Exception as e:
+ except Exception:
self.db.volume_update(context,
volume_ref['id'],
{'status': 'error_deleting'})
- raise e
+ raise
self.db.volume_destroy(context, volume_id)
LOG.debug(_("volume %s: deleted successfully"), volume_ref['name'])
diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent b/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent
index 12c3a19c8..031a49708 100755
--- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent
+++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent
@@ -73,8 +73,8 @@ def key_init(self, arg_dict):
@jsonify
def password(self, arg_dict):
"""Writes a request to xenstore that tells the agent to set
- the root password for the given VM. The password should be
- encrypted using the shared secret key that was returned by a
+ the root password for the given VM. The password should be
+ encrypted using the shared secret key that was returned by a
previous call to key_init. The encrypted password value should
be passed as the value for the 'enc_pass' key in arg_dict.
"""
@@ -108,7 +108,8 @@ def _wait_for_agent(self, request_id, arg_dict):
# First, delete the request record
arg_dict["path"] = "data/host/%s" % request_id
xenstore.delete_record(self, arg_dict)
- raise TimeoutError("TIMEOUT: No response from agent within %s seconds." %
+ raise TimeoutError(
+ "TIMEOUT: No response from agent within %s seconds." %
AGENT_TIMEOUT)
ret = xenstore.read_record(self, arg_dict)
# Note: the response for None with be a string that includes
diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance b/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance
index aadacce57..8cb439259 100644
--- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance
+++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance
@@ -43,32 +43,47 @@ CHUNK_SIZE = 8192
KERNEL_DIR = '/boot/guest'
FILE_SR_PATH = '/var/run/sr-mount'
-def copy_kernel_vdi(session,args):
+
+def remove_kernel_ramdisk(session, args):
+ """Removes kernel and/or ramdisk from dom0's file system"""
+ kernel_file = exists(args, 'kernel-file')
+ ramdisk_file = exists(args, 'ramdisk-file')
+ if kernel_file:
+ os.remove(kernel_file)
+ if ramdisk_file:
+ os.remove(ramdisk_file)
+ return "ok"
+
+
+def copy_kernel_vdi(session, args):
vdi = exists(args, 'vdi-ref')
- size = exists(args,'image-size')
+ size = exists(args, 'image-size')
#Use the uuid as a filename
- vdi_uuid=session.xenapi.VDI.get_uuid(vdi)
- copy_args={'vdi_uuid':vdi_uuid,'vdi_size':int(size)}
- filename=with_vdi_in_dom0(session, vdi, False,
+ vdi_uuid = session.xenapi.VDI.get_uuid(vdi)
+ copy_args = {'vdi_uuid': vdi_uuid, 'vdi_size': int(size)}
+ filename = with_vdi_in_dom0(session, vdi, False,
lambda dev:
- _copy_kernel_vdi('/dev/%s' % dev,copy_args))
+ _copy_kernel_vdi('/dev/%s' % dev, copy_args))
return filename
-def _copy_kernel_vdi(dest,copy_args):
- vdi_uuid=copy_args['vdi_uuid']
- vdi_size=copy_args['vdi_size']
- logging.debug("copying kernel/ramdisk file from %s to /boot/guest/%s",dest,vdi_uuid)
- filename=KERNEL_DIR + '/' + vdi_uuid
+
+def _copy_kernel_vdi(dest, copy_args):
+ vdi_uuid = copy_args['vdi_uuid']
+ vdi_size = copy_args['vdi_size']
+ logging.debug("copying kernel/ramdisk file from %s to /boot/guest/%s",
+ dest, vdi_uuid)
+ filename = KERNEL_DIR + '/' + vdi_uuid
#read data from /dev/ and write into a file on /boot/guest
- of=open(filename,'wb')
- f=open(dest,'rb')
+ of = open(filename, 'wb')
+ f = open(dest, 'rb')
#copy only vdi_size bytes
- data=f.read(vdi_size)
+ data = f.read(vdi_size)
of.write(data)
f.close()
- of.close()
- logging.debug("Done. Filename: %s",filename)
- return filename
+ of.close()
+ logging.debug("Done. Filename: %s", filename)
+ return filename
+
def put_vdis(session, args):
params = pickle.loads(exists(args, 'params'))
@@ -76,22 +91,23 @@ def put_vdis(session, args):
image_id = params["image_id"]
glance_host = params["glance_host"]
glance_port = params["glance_port"]
-
+
sr_path = get_sr_path(session)
#FIXME(sirp): writing to a temp file until Glance supports chunked-PUTs
- tmp_file = "%s.tar.gz" % os.path.join('/tmp', str(image_id))
+ tmp_file = "%s.tar.gz" % os.path.join('/tmp', str(image_id))
tar_cmd = ['tar', '-zcf', tmp_file, '--directory=%s' % sr_path]
- paths = [ "%s.vhd" % vdi_uuid for vdi_uuid in vdi_uuids ]
+ paths = ["%s.vhd" % vdi_uuid for vdi_uuid in vdi_uuids]
tar_cmd.extend(paths)
logging.debug("Bundling image with cmd: %s", tar_cmd)
subprocess.call(tar_cmd)
- logging.debug("Writing to test file %s", tmp_file)
+ logging.debug("Writing to test file %s", tmp_file)
put_bundle_in_glance(tmp_file, image_id, glance_host, glance_port)
- return "" # FIXME(sirp): return anything useful here?
+ # FIXME(sirp): return anything useful here?
+ return ""
def put_bundle_in_glance(tmp_file, image_id, glance_host, glance_port):
- size = os.path.getsize(tmp_file)
+ size = os.path.getsize(tmp_file)
basename = os.path.basename(tmp_file)
bundle = open(tmp_file, 'r')
@@ -112,12 +128,11 @@ def put_bundle_in_glance(tmp_file, image_id, glance_host, glance_port):
for header, value in headers.iteritems():
conn.putheader(header, value)
conn.endheaders()
-
+
chunk = bundle.read(CHUNK_SIZE)
while chunk:
conn.send(chunk)
chunk = bundle.read(CHUNK_SIZE)
-
res = conn.getresponse()
#FIXME(sirp): should this be 201 Created?
@@ -126,6 +141,7 @@ def put_bundle_in_glance(tmp_file, image_id, glance_host, glance_port):
finally:
bundle.close()
+
def get_sr_path(session):
sr_ref = find_sr(session)
@@ -156,5 +172,6 @@ def find_sr(session):
if __name__ == '__main__':
- XenAPIPlugin.dispatch({'put_vdis': put_vdis,
- 'copy_kernel_vdi': copy_kernel_vdi})
+ XenAPIPlugin.dispatch({'put_vdis': put_vdis,
+ 'copy_kernel_vdi': copy_kernel_vdi,
+ 'remove_kernel_ramdisk': remove_kernel_ramdisk})
diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/objectstore b/plugins/xenserver/xenapi/etc/xapi.d/plugins/objectstore
index 8ee2f748d..d0313b4ed 100644
--- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/objectstore
+++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/objectstore
@@ -43,34 +43,37 @@ SECTOR_SIZE = 512
MBR_SIZE_SECTORS = 63
MBR_SIZE_BYTES = MBR_SIZE_SECTORS * SECTOR_SIZE
-def is_vdi_pv(session,args):
+
+def is_vdi_pv(session, args):
logging.debug("Checking wheter VDI has PV kernel")
vdi = exists(args, 'vdi-ref')
- pv=with_vdi_in_dom0(session, vdi, False,
+ pv = with_vdi_in_dom0(session, vdi, False,
lambda dev: _is_vdi_pv('/dev/%s' % dev))
if pv:
return 'true'
else:
return 'false'
+
def _is_vdi_pv(dest):
- logging.debug("Running pygrub against %s",dest)
- output=os.popen('pygrub -qn %s' % dest)
- pv=False
+ logging.debug("Running pygrub against %s", dest)
+ output = os.popen('pygrub -qn %s' % dest)
+ pv = False
for line in output.readlines():
#try to find kernel string
- m=re.search('(?<=kernel:)/.*(?:>)',line)
+ m = re.search('(?<=kernel:)/.*(?:>)', line)
if m:
- if m.group(0).find('xen')!=-1:
- pv=True
- logging.debug("PV:%d",pv)
- return pv
-
+ if m.group(0).find('xen') != -1:
+ pv = True
+ logging.debug("PV:%d", pv)
+ return pv
+
+
def get_vdi(session, args):
src_url = exists(args, 'src_url')
username = exists(args, 'username')
password = exists(args, 'password')
- raw_image=validate_bool(args, 'raw', 'false')
+ raw_image = validate_bool(args, 'raw', 'false')
add_partition = validate_bool(args, 'add_partition', 'false')
(proto, netloc, url_path, _, _, _) = urlparse.urlparse(src_url)
sr = find_sr(session)
@@ -88,16 +91,17 @@ def get_vdi(session, args):
vdi = create_vdi(session, sr, src_url, vdi_size, False)
with_vdi_in_dom0(session, vdi, False,
lambda dev: get_vdi_(proto, netloc, url_path,
- username, password, add_partition,raw_image,
+ username, password,
+ add_partition, raw_image,
virtual_size, '/dev/%s' % dev))
return session.xenapi.VDI.get_uuid(vdi)
-def get_vdi_(proto, netloc, url_path, username, password, add_partition,raw_image,
- virtual_size, dest):
+def get_vdi_(proto, netloc, url_path, username, password,
+ add_partition, raw_image, virtual_size, dest):
- #Salvatore: vdi should not be partitioned for raw images
- if (add_partition and not raw_image):
+ #vdi should not be partitioned for raw images
+ if add_partition and not raw_image:
write_partition(virtual_size, dest)
offset = (add_partition and not raw_image and MBR_SIZE_BYTES) or 0
@@ -144,7 +148,7 @@ def get_kernel(session, args):
password = exists(args, 'password')
(proto, netloc, url_path, _, _, _) = urlparse.urlparse(src_url)
-
+
dest = os.path.join(KERNEL_DIR, url_path[1:])
# Paranoid check against people using ../ to do rude things.
@@ -154,8 +158,8 @@ def get_kernel(session, args):
dirname = os.path.dirname(dest)
try:
os.makedirs(dirname)
- except os.error, e:
- if e.errno != errno.EEXIST:
+ except os.error, e:
+ if e.errno != errno.EEXIST:
raise
if not os.path.isdir(dirname):
raise Exception('Cannot make directory %s', dirname)
@@ -248,5 +252,5 @@ def download_all(response, length, dest_file, offset):
if __name__ == '__main__':
XenAPIPlugin.dispatch({'get_vdi': get_vdi,
- 'get_kernel': get_kernel,
+ 'get_kernel': get_kernel,
'is_vdi_pv': is_vdi_pv})
diff --git a/setup.py b/setup.py
index e3c45ce3e..4e25f43ed 100644
--- a/setup.py
+++ b/setup.py
@@ -85,9 +85,13 @@ setup(name='nova',
packages=find_packages(exclude=['bin', 'smoketests']),
include_package_data=True,
test_suite='nose.collector',
- scripts=['bin/nova-api',
+ scripts=['bin/nova-ajax-console-proxy',
+ 'bin/nova-api',
+ 'bin/nova-combined',
'bin/nova-compute',
+ 'bin/nova-console',
'bin/nova-dhcpbridge',
+ 'bin/nova-direct-api',
'bin/nova-import-canonical-imagestore',
'bin/nova-instancemonitor',
'bin/nova-logspool',
@@ -96,5 +100,6 @@ setup(name='nova',
'bin/nova-objectstore',
'bin/nova-scheduler',
'bin/nova-spoolsentry',
+ 'bin/stack',
'bin/nova-volume',
'tools/nova-debug'])