From 7b34f59ef8d2f6a752dcd94be3f5d14f0f93d3b2 Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Thu, 27 Jan 2011 22:51:36 -0800 Subject: fixes for bug #709057 --- nova/db/sqlalchemy/api.py | 6 +++++ nova/db/sqlalchemy/models.py | 6 ++++- nova/tests/test_compute.py | 58 ++++++++++++++++++++++++++++++++++++++------ 3 files changed, 61 insertions(+), 9 deletions(-) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 895e7eabe..50c4b2189 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -672,6 +672,9 @@ def instance_destroy(context, instance_id): with session.begin(): instance_ref = instance_get(context, instance_id, session=session) instance_ref.delete(session=session) + session.execute('update security_group_instance_association' + ' set deleted=1 where instance_id=:id', + {'id': instance_id}) @require_context @@ -1583,6 +1586,9 @@ 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 where security_group_id=:id', + {'id': security_group_id}) 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..1399e29ad 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/tests/test_compute.py b/nova/tests/test_compute.py index 09f6ee94a..ad2ac8375 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,23 +89,58 @@ 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']) + instance = db.instance_get(context.get_admin_context( + read_deleted=True), 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): """Make sure it is possible to run and terminate instance""" instance_id = self._create_instance() -- cgit From af343a09b66ecded610051a443cb24f6b63e48ec Mon Sep 17 00:00:00 2001 From: Ilya Alekseyev Date: Fri, 28 Jan 2011 20:10:03 +0300 Subject: Changed default handler for uncaughted exceptions. Logging with level critical instead of print to stderr --- nova/log.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nova/log.py b/nova/log.py index e1c9f46f4..70719e95b 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,10 @@ 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) -- cgit From 5850b1505cbd9e63418d9edaf003d3bd426279a2 Mon Sep 17 00:00:00 2001 From: Ilya Alekseyev Date: Fri, 28 Jan 2011 20:46:46 +0300 Subject: Fixed pep8 errors --- nova/log.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nova/log.py b/nova/log.py index 70719e95b..b541488bd 100644 --- a/nova/log.py +++ b/nova/log.py @@ -192,9 +192,11 @@ 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) -- cgit From 29931605602e0eba562f870cd14cb6f16d3a215d Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Fri, 28 Jan 2011 09:55:58 -0800 Subject: remove extraneous line --- nova/tests/test_compute.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index ad2ac8375..2aa0690e7 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -115,9 +115,6 @@ class ComputeTestCase(test.TestCase): security_group=['testgroup']) try: db.instance_destroy(self.context, ref[0]['id']) - instance = db.instance_get(context.get_admin_context( - read_deleted=True), ref[0]['id']) - group = db.security_group_get(self.context, group['id']) self.assert_(len(group.instances) == 0) finally: -- cgit From 5becf2ad3dbbb7074202406fdd6f7f05dfef53cc Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Fri, 28 Jan 2011 15:31:23 -0800 Subject: incorporate feedback from devin - use sql consistently in instance_destroy also, set deleted_at --- nova/db/sqlalchemy/api.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 50c4b2189..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,11 +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 security_group_instance_association' - ' set deleted=1 where instance_id=:id', - {'id': instance_id}) + 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 @@ -1586,9 +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 where security_group_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}) -- cgit From b1caafa03d0fb36c9df5502282c4267974d1b889 Mon Sep 17 00:00:00 2001 From: Tushar Patil Date: Mon, 31 Jan 2011 14:36:40 -0800 Subject: Fix for LP Bug #709510 --- nova/api/ec2/__init__.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 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, -- cgit From cf5e4de7019091ee931ea911d69732c25a2cc1dd Mon Sep 17 00:00:00 2001 From: Tushar Patil Date: Mon, 31 Jan 2011 14:43:03 -0800 Subject: Fix for LP Bug #709510 --- nova/api/openstack/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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) -- cgit From 199e511e17af5e1a0659cc9ca65e9d55a5296947 Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Tue, 1 Feb 2011 08:09:34 -0800 Subject: fix pep8 error :/ --- nova/db/sqlalchemy/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 1399e29ad..7efb36c0e 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -316,7 +316,7 @@ class SecurityGroup(BASE, NovaBase): 'SecurityGroup.deleted == False)', secondaryjoin='and_(' 'SecurityGroupInstanceAssociation.instance_id == Instance.id,' - # (anthony) the condition below shouldn't be necessary now that the + # (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)', -- cgit From c98a298c3aefb1f465530537ee4773bd04673fe4 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Wed, 2 Feb 2011 11:16:00 +0100 Subject: Set FINAL = True in version.py. --- nova/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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(): -- cgit