diff options
| author | Cerberus <matt.dietz@rackspace.com> | 2011-02-02 11:38:22 -0600 |
|---|---|---|
| committer | Cerberus <matt.dietz@rackspace.com> | 2011-02-02 11:38:22 -0600 |
| commit | f300958eed8f3ddd65ccd2330fb38d30e900d7d2 (patch) | |
| tree | 0b5b14584f0148038e483a268d9aed0597fe4374 | |
| parent | 6d2e2c52012abac8cab322357ce0ffd0ffc2fbaf (diff) | |
| parent | 75e052e2c0bb7f470b959ea1a6168a6c5cddd8fd (diff) | |
| download | nova-f300958eed8f3ddd65ccd2330fb38d30e900d7d2.tar.gz nova-f300958eed8f3ddd65ccd2330fb38d30e900d7d2.tar.xz nova-f300958eed8f3ddd65ccd2330fb38d30e900d7d2.zip | |
Merge from trunk
| -rw-r--r-- | nova/api/ec2/__init__.py | 19 | ||||
| -rw-r--r-- | nova/api/openstack/__init__.py | 4 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/api.py | 16 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/models.py | 6 | ||||
| -rw-r--r-- | nova/log.py | 7 | ||||
| -rw-r--r-- | nova/tests/test_compute.py | 55 | ||||
| -rw-r--r-- | nova/version.py | 2 |
7 files changed, 86 insertions, 23 deletions
diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index e25943a13..ddcdc673c 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -171,7 +171,7 @@ class Authenticate(wsgi.Middleware): req.path) # Be explicit for what exceptions are 403, the rest bubble as 500 except (exception.NotFound, exception.NotAuthorized) as ex: - LOG.audit(_("Authentication Failure: %s"), ex.args[0]) + LOG.audit(_("Authentication Failure: %s"), unicode(ex)) raise webob.exc.HTTPForbidden() # Authenticated! @@ -316,30 +316,31 @@ class Executor(wsgi.Application): try: result = api_request.invoke(context) except exception.InstanceNotFound as ex: - LOG.info(_('InstanceNotFound raised: %s'), ex.args[0], + LOG.info(_('InstanceNotFound raised: %s'), unicode(ex), context=context) ec2_id = cloud.id_to_ec2_id(ex.instance_id) message = _('Instance %s not found') % ec2_id return self._error(req, context, type(ex).__name__, message) except exception.VolumeNotFound as ex: - LOG.info(_('VolumeNotFound raised: %s'), ex.args[0], + LOG.info(_('VolumeNotFound raised: %s'), unicode(ex), context=context) ec2_id = cloud.id_to_ec2_id(ex.volume_id, 'vol-%08x') message = _('Volume %s not found') % ec2_id return self._error(req, context, type(ex).__name__, message) except exception.NotFound as ex: - LOG.info(_('NotFound raised: %s'), ex.args[0], context=context) - return self._error(req, context, type(ex).__name__, ex.args[0]) + LOG.info(_('NotFound raised: %s'), unicode(ex), context=context) + return self._error(req, context, type(ex).__name__, unicode(ex)) except exception.ApiError as ex: - LOG.exception(_('ApiError raised: %s'), ex.args[0], + LOG.exception(_('ApiError raised: %s'), unicode(ex), context=context) if ex.code: - return self._error(req, context, ex.code, ex.args[0]) + return self._error(req, context, ex.code, unicode(ex)) else: - return self._error(req, context, type(ex).__name__, ex.args[0]) + return self._error(req, context, type(ex).__name__, + unicode(ex)) except Exception as ex: extra = {'environment': req.environ} - LOG.exception(_('Unexpected error raised: %s'), ex.args[0], + LOG.exception(_('Unexpected error raised: %s'), unicode(ex), extra=extra, context=context) return self._error(req, context, diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index c70bb39ed..056c7dd27 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -51,8 +51,8 @@ class FaultWrapper(wsgi.Middleware): try: return req.get_response(self.application) except Exception as ex: - LOG.exception(_("Caught error: %s"), str(ex)) - exc = webob.exc.HTTPInternalServerError(explanation=str(ex)) + LOG.exception(_("Caught error: %s"), unicode(ex)) + exc = webob.exc.HTTPInternalServerError(explanation=unicode(ex)) return faults.Fault(exc) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 895e7eabe..85250d56e 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -19,6 +19,7 @@ Implementation of SQLAlchemy backend. """ +import datetime import warnings from nova import db @@ -670,8 +671,14 @@ def instance_data_get_for_project(context, project_id): def instance_destroy(context, instance_id): session = get_session() with session.begin(): - instance_ref = instance_get(context, instance_id, session=session) - instance_ref.delete(session=session) + session.execute('update instances set deleted=1,' + 'deleted_at=:at where id=:id', + {'id': instance_id, + 'at': datetime.datetime.utcnow()}) + session.execute('update security_group_instance_association ' + 'set deleted=1,deleted_at=:at where instance_id=:id', + {'id': instance_id, + 'at': datetime.datetime.utcnow()}) @require_context @@ -1583,6 +1590,11 @@ def security_group_destroy(context, security_group_id): # TODO(vish): do we have to use sql here? session.execute('update security_groups set deleted=1 where id=:id', {'id': security_group_id}) + session.execute('update security_group_instance_association ' + 'set deleted=1,deleted_at=:at ' + 'where security_group_id=:id', + {'id': security_group_id, + 'at': datetime.datetime.utcnow()}) session.execute('update security_group_rules set deleted=1 ' 'where group_id=:id', {'id': security_group_id}) diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index c54ebe3ba..7efb36c0e 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -311,10 +311,14 @@ class SecurityGroup(BASE, NovaBase): secondary="security_group_instance_association", primaryjoin='and_(' 'SecurityGroup.id == ' - 'SecurityGroupInstanceAssociation.security_group_id,' + 'SecurityGroupInstanceAssociation.security_group_id,' + 'SecurityGroupInstanceAssociation.deleted == False,' 'SecurityGroup.deleted == False)', secondaryjoin='and_(' 'SecurityGroupInstanceAssociation.instance_id == Instance.id,' + # (anthony) the condition below shouldn't be necessary now that the + # association is being marked as deleted. However, removing this + # may cause existing deployments to choke, so I'm leaving it 'Instance.deleted == False)', backref='security_groups') diff --git a/nova/log.py b/nova/log.py index e1c9f46f4..b541488bd 100644 --- a/nova/log.py +++ b/nova/log.py @@ -31,6 +31,7 @@ import cStringIO import json import logging import logging.handlers +import sys import traceback from nova import flags @@ -191,6 +192,12 @@ class NovaLogger(logging.Logger): kwargs.pop('exc_info') self.error(message, **kwargs) + +def handle_exception(type, value, tb): + logging.root.critical(str(value), exc_info=(type, value, tb)) + + +sys.excepthook = handle_exception logging.setLoggerClass(NovaLogger) diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 09f6ee94a..2aa0690e7 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -49,7 +49,7 @@ class ComputeTestCase(test.TestCase): self.manager = manager.AuthManager() self.user = self.manager.create_user('fake', 'fake', 'fake') self.project = self.manager.create_project('fake', 'fake', 'fake') - self.context = context.get_admin_context() + self.context = context.RequestContext('fake', 'fake', False) def tearDown(self): self.manager.delete_user(self.user) @@ -69,6 +69,13 @@ class ComputeTestCase(test.TestCase): inst['ami_launch_index'] = 0 return db.instance_create(self.context, inst)['id'] + def _create_group(self): + values = {'name': 'testgroup', + 'description': 'testgroup', + 'user_id': self.user.id, + 'project_id': self.project.id} + return db.security_group_create(self.context, values) + def test_create_instance_defaults_display_name(self): """Verify that an instance cannot be created without a display_name.""" cases = [dict(), dict(display_name=None)] @@ -82,21 +89,53 @@ class ComputeTestCase(test.TestCase): def test_create_instance_associates_security_groups(self): """Make sure create associates security groups""" - values = {'name': 'default', - 'description': 'default', - 'user_id': self.user.id, - 'project_id': self.project.id} - group = db.security_group_create(self.context, values) + group = self._create_group() ref = self.compute_api.create( self.context, instance_type=FLAGS.default_instance_type, image_id=None, - security_group=['default']) + security_group=['testgroup']) try: self.assertEqual(len(db.security_group_get_by_instance( - self.context, ref[0]['id'])), 1) + self.context, ref[0]['id'])), 1) + group = db.security_group_get(self.context, group['id']) + self.assert_(len(group.instances) == 1) + finally: + db.security_group_destroy(self.context, group['id']) + db.instance_destroy(self.context, ref[0]['id']) + + def test_destroy_instance_disassociates_security_groups(self): + """Make sure destroying disassociates security groups""" + group = self._create_group() + + ref = self.compute_api.create( + self.context, + instance_type=FLAGS.default_instance_type, + image_id=None, + security_group=['testgroup']) + try: + db.instance_destroy(self.context, ref[0]['id']) + group = db.security_group_get(self.context, group['id']) + self.assert_(len(group.instances) == 0) finally: db.security_group_destroy(self.context, group['id']) + + def test_destroy_security_group_disassociates_instances(self): + """Make sure destroying security groups disassociates instances""" + group = self._create_group() + + ref = self.compute_api.create( + self.context, + instance_type=FLAGS.default_instance_type, + image_id=None, + security_group=['testgroup']) + + try: + db.security_group_destroy(self.context, group['id']) + group = db.security_group_get(context.get_admin_context( + read_deleted=True), group['id']) + self.assert_(len(group.instances) == 0) + finally: db.instance_destroy(self.context, ref[0]['id']) def test_run_terminate(self): diff --git a/nova/version.py b/nova/version.py index 7b27acb6a..48ac84a03 100644 --- a/nova/version.py +++ b/nova/version.py @@ -24,7 +24,7 @@ except ImportError: NOVA_VERSION = ['2011', '1'] YEAR, COUNT = NOVA_VERSION -FINAL = False # This becomes true at Release Candidate time +FINAL = True # This becomes true at Release Candidate time def canonical_version_string(): |
