Hello community, here is the log from the commit of package openstack-nova for openSUSE:Factory checked in at 2013-03-08 09:29:13 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/openstack-nova (Old) and /work/SRC/openSUSE:Factory/.openstack-nova.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "openstack-nova", Maintainer is "[email protected]" Changes: -------- --- /work/SRC/openSUSE:Factory/openstack-nova/openstack-nova.changes 2013-02-28 10:19:31.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.openstack-nova.new/openstack-nova.changes 2013-03-08 09:29:15.000000000 +0100 @@ -1,0 +2,21 @@ +Thu Mar 7 12:58:51 UTC 2013 - [email protected] + +- Install polkit rules file in /usr/share/polkit-1/rules.d/ since + it's not a configuration file, and use 10 instead of 50 as + priority to make sure it is taken into account. + +-------------------------------------------------------------------- +Wed Mar 6 15:26:14 UTC 2013 - [email protected] + +- Update to version 2012.2.4+git.1362583574.da38af5: + + VNC Token Validation (CVE-2013-0335) + +-------------------------------------------------------------------- +Tue Mar 5 16:57:22 UTC 2013 - [email protected] + +- Update to version 2012.2.4+git.1362502642.8c4df00: + + Ensure we add a new line when appending to rc.local + + Handle compute node not available for live migration + + remove intermediate libvirt downloaded images + +------------------------------------------------------------------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ openstack-nova-doc.spec ++++++ --- /var/tmp/diff_new_pack.bySYCK/_old 2013-03-08 09:29:17.000000000 +0100 +++ /var/tmp/diff_new_pack.bySYCK/_new 2013-03-08 09:29:17.000000000 +0100 @@ -20,7 +20,7 @@ %define majorversion 2012.2.3 Name: openstack-%{component}-doc -Version: 2012.2.4+git.1361527907.d5e7f55 +Version: 2012.2.4+git.1362583574.da38af5 Release: 1 License: Apache-2.0 Summary: OpenStack Compute (Nova) - Documentation ++++++ openstack-nova.spec ++++++ --- /var/tmp/diff_new_pack.bySYCK/_old 2013-03-08 09:29:17.000000000 +0100 +++ /var/tmp/diff_new_pack.bySYCK/_new 2013-03-08 09:29:17.000000000 +0100 @@ -22,7 +22,7 @@ %define username openstack-%{component} Name: openstack-%{component} -Version: 2012.2.4+git.1361527907.d5e7f55 +Version: 2012.2.4+git.1362583574.da38af5 Release: 1 License: Apache-2.0 Summary: OpenStack Compute (Nova) @@ -301,7 +301,7 @@ cp -a %{SOURCE9} %{buildroot}%{_localstatedir}/lib/polkit-1/localauthority/10-vendor.d/ %endif %if 0%{?suse_version} >= 1230 - install -D -m 644 %{SOURCE12} %{buildroot}%{_sysconfdir}/polkit-1/rules.d/50-openstack-nova-compute.rules + install -D -m 644 %{SOURCE12} %{buildroot}%{_datadir}/polkit-1/rules.d/10-openstack-nova-compute.rules %endif %pre @@ -503,7 +503,7 @@ %{_localstatedir}/lib/polkit-1/localauthority/10-vendor.d/org.openstack.nova.compute.pkla %endif %if 0%{?suse_version} >= 1230 -%config %{_sysconfdir}/polkit-1/rules.d/50-openstack-nova-compute.rules +%{_datadir}/polkit-1/rules.d/10-openstack-nova-compute.rules %endif %files network ++++++ nova-stable-folsom.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/AUTHORS new/nova-2012.2.4/AUTHORS --- old/nova-2012.2.4/AUTHORS 2013-02-21 20:52:30.000000000 +0100 +++ new/nova-2012.2.4/AUTHORS 2013-03-06 02:08:02.000000000 +0100 @@ -70,6 +70,7 @@ Daniel P. Berrange <[email protected]> Darren Worrall <[email protected]> Davanum Srinivas <[email protected]> +Davanum Srinivas <[email protected]> Dave Lapsley <[email protected]> Dave Walker (Daviey) <[email protected]> David Besen <[email protected]> @@ -129,6 +130,7 @@ Jason Koelker <[email protected]> Jay Pipes <[email protected]> Jesse Andrews <[email protected]> +Jian Wen <[email protected]> Jian Wen <[email protected]> Jim Fehlig <[email protected]> Jimmy Bergman <[email protected]> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/ChangeLog new/nova-2012.2.4/ChangeLog --- old/nova-2012.2.4/ChangeLog 2013-02-21 20:52:29.000000000 +0100 +++ new/nova-2012.2.4/ChangeLog 2013-03-06 02:08:02.000000000 +0100 @@ -1,3 +1,127 @@ +commit da38af5b79e7e3f9584cb79154aa0740badd6efb +Merge: 8c4df00 05a3374 +Author: Jenkins <[email protected]> +Date: Wed Mar 6 01:00:26 2013 +0000 + + Merge "VNC Token Validation" into stable/folsom + +commit 8c4df00a378ad6e2586a361355d4580a4901ada0 +Merge: 994dc75 889e9c0 +Author: Jenkins <[email protected]> +Date: Mon Mar 4 10:43:50 2013 +0000 + + Merge "remove intermediate libvirt downloaded images" into stable/folsom + +commit 994dc7501da040213c2fd25f5bf7efe84d26df19 +Merge: 8289d6c 2029427 +Author: Jenkins <[email protected]> +Date: Sat Mar 2 03:49:38 2013 +0000 + + Merge "Handle compute node not available for live migration" into stable/folsom + +commit 8289d6c7834415878ae7524e8a718abbce49a1b0 +Author: Davanum Srinivas <[email protected]> +Date: Wed Dec 12 21:11:06 2012 -0500 + + Ensure we add a new line when appending to rc.local + + When we add content to rc.local, if the file already + exists then we need to make sure we add the content + after a new line explicitly + + Fixes LP #1089668 + + Change-Id: I35be1496703b302f732363fa76ce832505eed599 + (cherry picked from commit f393a513d7894ddb800e4dfc87da896600fb7421) + + nova/virt/disk/api.py | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +commit 889e9c0be4852fa4b96bdceba889f9584ac3b716 +Author: Pádraig Brady <[email protected]> +Date: Thu Feb 14 10:37:21 2013 +0000 + + remove intermediate libvirt downloaded images + + * nova/virt/images.py (fetch_to_raw): When converting a downloaded + image to raw, ensure we delete the original download image. + I.E. the .part file. The regression was introduced in 7c265343. + * nova/tests/test_libvirt.py (test_fetch_raw_image): A new test + for this function which wasn't tested previously. + + Conflicts: + + nova/tests/test_libvirt.py + nova/virt/images.py + + Fixes bug: 1125068 + Change-Id: Ie6f2cff1a554b8500fd66f0832566ae1b317be40 + (cherry picked from commit 1501a4e4f75efb63385a1dadc728c2ef245bf7de) + + nova/tests/test_libvirt.py | 73 ++++++++++++++++++++++++++++++++++++++++++++ + nova/virt/images.py | 2 +- + 2 files changed, 74 insertions(+), 1 deletion(-) + +commit 20294279ee1d6d82dbb87c4c29e3a8b9fd0cb8bd +Author: Jian Wen <[email protected]> +Date: Mon Jan 14 19:13:24 2013 +0800 + + Handle compute node not available for live migration + + This patch handles exception.ComputeServiceUnavailable by restoring + instance's vm_state and instance's task_state after live migration + failure caused by unavailable source/dest compute node. + + Raises detailed HTTPBadRequest explanation for this exception. + + Fixes bug 973393 and bug 1051881 + + Conflicts: + nova/scheduler/driver.py + nova/scheduler/manager.py + nova/tests/api/openstack/compute/contrib/test_admin_actions.py + nova/tests/scheduler/test_scheduler.py + + Change-Id: If825b61fad9c4e3030f2e6c5002907255eaf3661 + + .../api/openstack/compute/contrib/admin_actions.py | 2 + + nova/exception.py | 2 +- + nova/scheduler/driver.py | 7 ++- + nova/scheduler/manager.py | 11 ++++ + .../compute/contrib/test_admin_actions.py | 61 ++++++++++++++++---- + nova/tests/scheduler/test_scheduler.py | 55 ++++++++++++++++++ + 6 files changed, 125 insertions(+), 13 deletions(-) + +commit 05a3374992bc8ba53ddc9c491b51c4b59eed0a72 +Author: John Herndon <[email protected]> +Date: Fri Feb 22 20:43:58 2013 +0000 + + VNC Token Validation + + Force console auth service to flush all tokens + associated with an instance when it is deleted. + This will fix a bug where the console for the + wrong instance can be connected to via the console + if the correct circumstances occur. This change also + makes a call to veriry vnc console tokens when a + user attempts to connect to a console. This ensures + the user is connecting to the correct console. + + bug 1125378 + Change-Id: I0d83ec6c4dbfef1af912a200ee15f8052f72da96 + + nova/common/memorycache.py | 5 +++ + nova/compute/api.py | 3 +- + nova/compute/manager.py | 12 +++++ + nova/compute/rpcapi.py | 7 +++ + nova/consoleauth/manager.py | 41 ++++++++++++++++- + nova/consoleauth/rpcapi.py | 10 ++++- + nova/tests/compute/test_compute.py | 52 ++++++++++++++++++++- + nova/tests/compute/test_rpcapi.py | 5 +++ + nova/tests/consoleauth/test_consoleauth.py | 67 +++++++++++++++++++++++++++- + nova/tests/consoleauth/test_rpcapi.py | 6 ++- + 10 files changed, 200 insertions(+), 8 deletions(-) + commit d5e7f5512435fe0ca264be28ef23fe2ebb449d1c Author: Vishvananda Ishaya <[email protected]> Date: Thu Feb 21 10:40:45 2013 -0800 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/nova/api/openstack/compute/contrib/admin_actions.py new/nova-2012.2.4/nova/api/openstack/compute/contrib/admin_actions.py --- old/nova-2012.2.4/nova/api/openstack/compute/contrib/admin_actions.py 2013-02-21 20:47:14.000000000 +0100 +++ new/nova-2012.2.4/nova/api/openstack/compute/contrib/admin_actions.py 2013-03-06 02:03:10.000000000 +0100 @@ -286,6 +286,8 @@ instance = self.compute_api.get(context, id) self.compute_api.live_migrate(context, instance, block_migration, disk_over_commit, host) + except exception.ComputeServiceUnavailable as ex: + raise exc.HTTPBadRequest(explanation=str(ex)) except Exception: msg = _("Live migration of instance %(id)s to host %(host)s" " failed") % locals() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/nova/common/memorycache.py new/nova-2012.2.4/nova/common/memorycache.py --- old/nova-2012.2.4/nova/common/memorycache.py 2013-02-21 20:47:14.000000000 +0100 +++ new/nova-2012.2.4/nova/common/memorycache.py 2013-03-06 02:03:10.000000000 +0100 @@ -62,3 +62,8 @@ new_value = int(value) + delta self.cache[key] = (self.cache[key][0], str(new_value)) return new_value + + def delete(self, key, time=0): + """Deletes the value associated with a key.""" + if key in self.cache: + del self.cache[key] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/nova/compute/api.py new/nova-2012.2.4/nova/compute/api.py --- old/nova-2012.2.4/nova/compute/api.py 2013-02-21 20:47:14.000000000 +0100 +++ new/nova-2012.2.4/nova/compute/api.py 2013-03-06 02:03:10.000000000 +0100 @@ -1853,7 +1853,8 @@ self.consoleauth_rpcapi.authorize_console(context, connect_info['token'], console_type, connect_info['host'], - connect_info['port'], connect_info['internal_access_path']) + connect_info['port'], connect_info['internal_access_path'], + instance["uuid"]) return {'url': connect_info['access_url']} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/nova/compute/manager.py new/nova-2012.2.4/nova/compute/manager.py --- old/nova-2012.2.4/nova/compute/manager.py 2013-02-21 20:47:22.000000000 +0100 +++ new/nova-2012.2.4/nova/compute/manager.py 2013-03-06 02:03:10.000000000 +0100 @@ -52,6 +52,7 @@ from nova.compute import task_states from nova.compute import utils as compute_utils from nova.compute import vm_states +from nova import consoleauth import nova.context from nova import exception from nova import flags @@ -235,6 +236,7 @@ self.compute_api = compute.API() self.compute_rpcapi = compute_rpcapi.ComputeAPI() self.scheduler_rpcapi = scheduler_rpcapi.SchedulerAPI() + self.consoleauth_rpcapi = consoleauth.rpcapi.ConsoleAuthAPI() super(ComputeManager, self).__init__(service_name="compute", *args, **kwargs) @@ -926,6 +928,10 @@ self._notify_about_instance_usage(context, instance, "delete.end", system_metadata=system_meta) + if FLAGS.vnc_enabled: + self.consoleauth_rpcapi.delete_tokens_for_instance(context, + instance["uuid"]) + @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) @wrap_instance_fault def terminate_instance(self, context, instance): @@ -1989,6 +1995,12 @@ return connection_info @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) + @wrap_instance_fault + def validate_console_port(self, ctxt, instance, port, console_type): + console_info = self.driver.get_vnc_console(instance) + return console_info['port'] == port + + @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) @reverts_task_state @wrap_instance_fault def reserve_block_device_name(self, context, instance, device): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/nova/compute/rpcapi.py new/nova-2012.2.4/nova/compute/rpcapi.py --- old/nova-2012.2.4/nova/compute/rpcapi.py 2013-02-21 20:47:14.000000000 +0100 +++ new/nova-2012.2.4/nova/compute/rpcapi.py 2013-03-06 02:03:10.000000000 +0100 @@ -259,6 +259,13 @@ instance=instance_p, console_type=console_type), topic=_compute_topic(self.topic, ctxt, None, instance)) + def validate_console_port(self, ctxt, instance, port, console_type): + instance_p = jsonutils.to_primitive(instance) + return self.call(ctxt, self.make_msg('validate_console_port', + instance=instance_p, port=port, console_type=console_type), + topic=_compute_topic(self.topic, ctxt, + None, instance)) + def host_maintenance_mode(self, ctxt, host_param, mode, host): '''Set host maintenance mode diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/nova/consoleauth/manager.py new/nova-2012.2.4/nova/consoleauth/manager.py --- old/nova-2012.2.4/nova/consoleauth/manager.py 2013-02-21 20:47:14.000000000 +0100 +++ new/nova-2012.2.4/nova/consoleauth/manager.py 2013-03-06 02:03:10.000000000 +0100 @@ -20,6 +20,8 @@ import time +from nova.compute import rpcapi as compute_rpcapi +from nova.db import api as db from nova import flags from nova import manager from nova.openstack.common import cfg @@ -56,10 +58,21 @@ from nova.common import memorycache as memcache self.mc = memcache.Client(FLAGS.memcached_servers, debug=0) + self.compute_rpcapi = compute_rpcapi.ComputeAPI() + + def _get_tokens_for_instance(self, instance_uuid): + tokens_str = self.mc.get(instance_uuid.encode('UTF-8')) + if not tokens_str: + tokens = [] + else: + tokens = jsonutils.loads(tokens_str) + return tokens def authorize_console(self, context, token, console_type, host, port, - internal_access_path): + internal_access_path, instance_uuid=None): + token_dict = {'token': token, + 'instance_uuid': instance_uuid, 'console_type': console_type, 'host': host, 'port': port, @@ -67,11 +80,35 @@ 'last_activity_at': time.time()} data = jsonutils.dumps(token_dict) self.mc.set(token.encode('UTF-8'), data, FLAGS.console_token_ttl) + if instance_uuid is not None: + tokens = self._get_tokens_for_instance(instance_uuid) + tokens.append(token) + self.mc.set(instance_uuid.encode('UTF-8'), + jsonutils.dumps(tokens)) + LOG.audit(_("Received Token: %(token)s, %(token_dict)s)"), locals()) + def _validate_token(self, context, token): + instance_uuid = token['instance_uuid'] + if instance_uuid is None: + return False + instance = db.instance_get_by_uuid(context, instance_uuid) + return self.compute_rpcapi.validate_console_port(context, + instance, + token['port'], + token['console_type']) + def check_token(self, context, token): token_str = self.mc.get(token.encode('UTF-8')) token_valid = (token_str is not None) LOG.audit(_("Checking Token: %(token)s, %(token_valid)s)"), locals()) if token_valid: - return jsonutils.loads(token_str) + token = jsonutils.loads(token_str) + if self._validate_token(context, token): + return token + + def delete_tokens_for_instance(self, context, instance_uuid): + tokens = self._get_tokens_for_instance(instance_uuid) + for token in tokens: + self.mc.delete(token) + self.mc.delete(instance_uuid.encode('UTF-8')) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/nova/consoleauth/rpcapi.py new/nova-2012.2.4/nova/consoleauth/rpcapi.py --- old/nova-2012.2.4/nova/consoleauth/rpcapi.py 2013-02-21 20:47:14.000000000 +0100 +++ new/nova-2012.2.4/nova/consoleauth/rpcapi.py 2013-03-06 02:03:10.000000000 +0100 @@ -49,14 +49,20 @@ default_version=self.BASE_RPC_API_VERSION) def authorize_console(self, ctxt, token, console_type, host, port, - internal_access_path): + internal_access_path, instance_uuid=None): # The remote side doesn't return anything, but we want to block # until it completes. return self.call(ctxt, self.make_msg('authorize_console', token=token, console_type=console_type, host=host, port=port, - internal_access_path=internal_access_path)) + internal_access_path=internal_access_path, + instance_uuid=instance_uuid)) def check_token(self, ctxt, token): return self.call(ctxt, self.make_msg('check_token', token=token)) + + def delete_tokens_for_instance(self, ctxt, instance_uuid): + return self.call(ctxt, + self.make_msg('delete_tokens_for_instance', + instance_uuid=instance_uuid)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/nova/exception.py new/nova-2012.2.4/nova/exception.py --- old/nova-2012.2.4/nova/exception.py 2013-02-21 20:47:14.000000000 +0100 +++ new/nova-2012.2.4/nova/exception.py 2013-03-06 02:03:10.000000000 +0100 @@ -359,7 +359,7 @@ class ComputeServiceUnavailable(ServiceUnavailable): - message = _("Compute service is unavailable at this time.") + message = _("Compute service of %(host)s is unavailable at this time.") class UnableToMigrateToSelf(Invalid): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/nova/scheduler/driver.py new/nova-2012.2.4/nova/scheduler/driver.py --- old/nova-2012.2.4/nova/scheduler/driver.py 2013-02-21 20:47:14.000000000 +0100 +++ new/nova-2012.2.4/nova/scheduler/driver.py 2013-03-06 02:03:10.000000000 +0100 @@ -274,8 +274,11 @@ """ # Checking dest exists and compute node. - dservice_refs = db.service_get_all_compute_by_host(context, dest) - dservice_ref = dservice_refs[0] + try: + dservice_refs = db.service_get_all_compute_by_host(context, dest) + dservice_ref = dservice_refs[0] + except exception.NotFound: + raise exception.ComputeServiceUnavailable(host=dest) # Checking dest host is alive. if not utils.service_is_up(dservice_ref): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/nova/scheduler/manager.py new/nova-2012.2.4/nova/scheduler/manager.py --- old/nova-2012.2.4/nova/scheduler/manager.py 2013-02-21 20:47:14.000000000 +0100 +++ new/nova-2012.2.4/nova/scheduler/manager.py 2013-03-06 02:03:10.000000000 +0100 @@ -24,6 +24,7 @@ import functools import sys +from nova.compute import task_states from nova.compute import utils as compute_utils from nova.compute import vm_states from nova import db @@ -88,6 +89,16 @@ return self.driver.schedule_live_migration( context, instance, dest, block_migration, disk_over_commit) + except exception.ComputeServiceUnavailable as ex: + request_spec = {'instance_properties': { + 'uuid': instance['uuid'], }, + } + with excutils.save_and_reraise_exception(): + self._set_vm_state_and_notify('live_migration', + dict(vm_state=instance['vm_state'], + task_state=None, + expected_task_state=task_states.MIGRATING,), + context, ex, request_spec) except Exception as ex: with excutils.save_and_reraise_exception(): self._set_vm_state_and_notify('live_migration', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/nova/tests/api/openstack/compute/contrib/test_admin_actions.py new/nova-2012.2.4/nova/tests/api/openstack/compute/contrib/test_admin_actions.py --- old/nova-2012.2.4/nova/tests/api/openstack/compute/contrib/test_admin_actions.py 2013-02-21 20:47:14.000000000 +0100 +++ new/nova-2012.2.4/nova/tests/api/openstack/compute/contrib/test_admin_actions.py 2013-03-06 02:03:10.000000000 +0100 @@ -62,13 +62,6 @@ 'task_state': None} -def fake_scheduler_api_live_migration(self, context, dest, - block_migration=False, - disk_over_commit=False, instance=None, - instance_id=None, topic=None): - return None - - class AdminActionsTest(test.TestCase): _actions = ('pause', 'unpause', 'suspend', 'resume', 'migrate', @@ -91,9 +84,10 @@ self.UUID = utils.gen_uuid() for _method in self._methods: self.stubs.Set(compute.API, _method, fake_compute_api) - self.stubs.Set(scheduler_rpcapi.SchedulerAPI, - 'live_migration', - fake_scheduler_api_live_migration) + self.flags( + osapi_compute_extension=[ + 'nova.api.openstack.compute.contrib.select_extensions'], + osapi_compute_ext_list=['Admin_actions']) def test_admin_api_actions(self): app = fakes.wsgi_app() @@ -144,7 +138,16 @@ task_state, expected_task_state): return None + def fake_scheduler_api_live_migration(self, context, dest, + block_migration=False, + disk_over_commit=False, instance=None, + instance_id=None, topic=None): + return None + self.stubs.Set(compute.API, 'update', fake_update) + self.stubs.Set(scheduler_rpcapi.SchedulerAPI, + 'live_migration', + fake_scheduler_api_live_migration) res = req.get_response(app) self.assertEqual(res.status_int, 202) @@ -168,6 +171,44 @@ res = req.get_response(app) self.assertEqual(res.status_int, 400) + def test_migrate_live_compute_service_unavailable(self): + ctxt = context.get_admin_context() + ctxt.user_id = 'fake' + ctxt.project_id = 'fake' + ctxt.is_admin = True + app = fakes.wsgi_app(fake_auth_context=ctxt) + req = webob.Request.blank('/v2/fake/servers/%s/action' % self.UUID) + req.method = 'POST' + req.body = jsonutils.dumps({ + 'os-migrateLive': { + 'host': 'hostname', + 'block_migration': False, + 'disk_over_commit': False, + } + }) + req.content_type = 'application/json' + + def fake_update(inst, context, instance, + task_state, expected_task_state): + return None + + def fake_scheduler_api_live_migration(context, dest, + block_migration=False, + disk_over_commit=False, instance=None, + instance_id=None, topic=None): + raise exception.ComputeServiceUnavailable(host='host') + + self.stubs.Set(compute.API, 'update', fake_update) + self.stubs.Set(scheduler_rpcapi.SchedulerAPI, + 'live_migration', + fake_scheduler_api_live_migration) + + res = req.get_response(app) + self.assertEqual(res.status_int, 400) + self.assertIn( + unicode(exception.ComputeServiceUnavailable(host='host')), + res.body) + class CreateBackupTests(test.TestCase): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/nova/tests/compute/test_compute.py new/nova-2012.2.4/nova/tests/compute/test_compute.py --- old/nova-2012.2.4/nova/tests/compute/test_compute.py 2013-02-21 20:47:15.000000000 +0100 +++ new/nova-2012.2.4/nova/tests/compute/test_compute.py 2013-03-06 02:03:10.000000000 +0100 @@ -1372,6 +1372,24 @@ self.compute._delete_instance(self.context, instance=jsonutils.to_primitive(instance)) + def test_delete_instance_deletes_console_auth_tokens(self): + instance = self._create_fake_instance() + self.flags(vnc_enabled=True) + + self.tokens_deleted = False + + def fake_delete_tokens(*args, **kwargs): + self.tokens_deleted = True + + cauth_rpcapi = self.compute.consoleauth_rpcapi + self.stubs.Set(cauth_rpcapi, 'delete_tokens_for_instance', + fake_delete_tokens) + + self.compute._delete_instance(self.context, + instance=jsonutils.to_primitive(instance)) + + self.assertTrue(self.tokens_deleted) + def test_instance_termination_exception_sets_error(self): """Test that we handle InstanceTerminationFailure which is propagated up from the underlying driver. @@ -4505,7 +4523,9 @@ 'console_type': fake_console_type, 'host': 'fake_console_host', 'port': 'fake_console_port', - 'internal_access_path': 'fake_access_path'} + 'internal_access_path': 'fake_access_path', + 'instance_uuid': fake_instance["uuid"]} + fake_connect_info2 = copy.deepcopy(fake_connect_info) fake_connect_info2['access_url'] = 'fake_console_url' @@ -4539,6 +4559,36 @@ db.instance_destroy(self.context, instance['uuid']) + def test_validate_console_port(self): + self.flags(vnc_enabled=True) + instance = jsonutils.to_primitive(self._create_fake_instance()) + + def fake_driver_get_console(*args, **kwargs): + return {'host': "fake_host", 'port': "5900", + 'internal_access_path': None} + self.stubs.Set(self.compute.driver, "get_vnc_console", + fake_driver_get_console) + + self.assertTrue(self.compute.validate_console_port(self.context, + instance, + "5900", + "novnc")) + + def test_validate_console_port_wrong_port(self): + self.flags(vnc_enabled=True) + instance = jsonutils.to_primitive(self._create_fake_instance()) + + def fake_driver_get_console(*args, **kwargs): + return {'host': "fake_host", 'port': "5900", + 'internal_access_path': None} + self.stubs.Set(self.compute.driver, "get_vnc_console", + fake_driver_get_console) + + self.assertFalse(self.compute.validate_console_port(self.context, + instance, + "wrongport", + "novnc")) + def test_console_output(self): fake_instance = {'uuid': 'fake_uuid', 'host': 'fake_compute_host'} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/nova/tests/compute/test_rpcapi.py new/nova-2012.2.4/nova/tests/compute/test_rpcapi.py --- old/nova-2012.2.4/nova/tests/compute/test_rpcapi.py 2013-02-21 20:47:15.000000000 +0100 +++ new/nova-2012.2.4/nova/tests/compute/test_rpcapi.py 2013-03-06 02:03:10.000000000 +0100 @@ -168,6 +168,11 @@ self._test_compute_api('get_vnc_console', 'call', instance=self.fake_instance, console_type='type') + def test_validate_console_port(self): + self._test_compute_api('validate_console_port', 'call', + instance=self.fake_instance, port="5900", + console_type="novnc") + def test_host_maintenance_mode(self): self._test_compute_api('host_maintenance_mode', 'call', host_param='param', mode='mode', host='host') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/nova/tests/consoleauth/test_consoleauth.py new/nova-2012.2.4/nova/tests/consoleauth/test_consoleauth.py --- old/nova-2012.2.4/nova/tests/consoleauth/test_consoleauth.py 2013-02-21 20:47:15.000000000 +0100 +++ new/nova-2012.2.4/nova/tests/consoleauth/test_consoleauth.py 2013-03-06 02:03:10.000000000 +0100 @@ -45,8 +45,73 @@ """Test that tokens expire correctly.""" token = 'mytok' self.flags(console_token_ttl=1) + + def fake_validate_token(*args, **kwargs): + return True + self.stubs.Set(self.manager, + "_validate_token", + fake_validate_token) + self.manager.authorize_console(self.context, token, 'novnc', - '127.0.0.1', 'host', '') + '127.0.0.1', '8080', 'host', "1234") self.assertTrue(self.manager.check_token(self.context, token)) time.sleep(1.1) self.assertFalse(self.manager.check_token(self.context, token)) + + def test_multiple_tokens_for_instance(self): + tokens = ["token" + str(i) for i in xrange(10)] + instance = "12345" + + def fake_validate_token(*args, **kwargs): + return True + + self.stubs.Set(self.manager, "_validate_token", + fake_validate_token) + for token in tokens: + self.manager.authorize_console(self.context, token, 'novnc', + '127.0.0.1', '8080', 'host', + instance) + + for token in tokens: + self.assertTrue(self.manager.check_token(self.context, token)) + + def test_delete_tokens_for_instance(self): + instance = "12345" + tokens = ["token" + str(i) for i in xrange(10)] + + def fake_validate_token(*args, **kwargs): + return True + self.stubs.Set(self.manager, "_validate_token", + fake_validate_token) + + for token in tokens: + self.manager.authorize_console(self.context, token, 'novnc', + '127.0.0.1', '8080', 'host', + instance) + self.manager.delete_tokens_for_instance(self.context, instance) + stored_tokens = self.manager._get_tokens_for_instance(instance) + + self.assertEqual(len(stored_tokens), 0) + + for token in tokens: + self.assertFalse(self.manager.check_token(self.context, token)) + + def test_wrong_token_has_port(self): + token = 'mytok' + + def fake_validate_token(*args, **kwargs): + return False + + self.stubs.Set(self.manager, "_validate_token", + fake_validate_token) + + self.manager.authorize_console(self.context, token, 'novnc', + '127.0.0.1', '8080', 'host', + instance_uuid='instance') + self.assertFalse(self.manager.check_token(self.context, token)) + + def test_console_no_instance_uuid(self): + self.manager.authorize_console(self.context, "token", 'novnc', + '127.0.0.1', '8080', 'host', + instance_uuid=None) + self.assertFalse(self.manager.check_token(self.context, "token")) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/nova/tests/consoleauth/test_rpcapi.py new/nova-2012.2.4/nova/tests/consoleauth/test_rpcapi.py --- old/nova-2012.2.4/nova/tests/consoleauth/test_rpcapi.py 2013-02-21 20:47:15.000000000 +0100 +++ new/nova-2012.2.4/nova/tests/consoleauth/test_rpcapi.py 2013-03-06 02:03:10.000000000 +0100 @@ -68,7 +68,11 @@ def test_authorize_console(self): self._test_consoleauth_api('authorize_console', token='token', console_type='ctype', host='h', port='p', - internal_access_path='iap') + internal_access_path='iap', instance_uuid="1234") def test_check_token(self): self._test_consoleauth_api('check_token', token='t') + + def test_delete_tokens_for_instnace(self): + self._test_consoleauth_api('delete_tokens_for_instance', + instance_uuid="instance") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/nova/tests/scheduler/test_scheduler.py new/nova-2012.2.4/nova/tests/scheduler/test_scheduler.py --- old/nova-2012.2.4/nova/tests/scheduler/test_scheduler.py 2013-02-21 20:47:15.000000000 +0100 +++ new/nova-2012.2.4/nova/tests/scheduler/test_scheduler.py 2013-03-06 02:03:11.000000000 +0100 @@ -24,6 +24,7 @@ from nova.compute import api as compute_api from nova.compute import power_state from nova.compute import rpcapi as compute_rpcapi +from nova.compute import task_states from nova.compute import utils as compute_utils from nova.compute import vm_states from nova import context @@ -187,6 +188,37 @@ self.assertRaises(exception.NoValidHost, self.manager.create_volume, self.context, '1', '2') + def test_live_migration_compute_service_notavailable(self): + inst = {"uuid": "fake-instance-id", + "vm_state": vm_states.ACTIVE, + "task_state": task_states.MIGRATING, } + + dest = 'fake_host' + block_migration = False + disk_over_commit = False + + self._mox_schedule_method_helper('schedule_live_migration') + self.mox.StubOutWithMock(compute_utils, 'add_instance_fault_from_exc') + self.mox.StubOutWithMock(db, 'instance_update_and_get_original') + + self.manager.driver.schedule_live_migration(self.context, + inst, dest, block_migration, disk_over_commit).AndRaise( + exception.ComputeServiceUnavailable(host="src")) + db.instance_update_and_get_original(self.context, inst["uuid"], + {"vm_state": inst['vm_state'], + "task_state": None, + "expected_task_state": task_states.MIGRATING, + }).AndReturn((inst, inst)) + compute_utils.add_instance_fault_from_exc(self.context, inst["uuid"], + mox.IsA(exception.ComputeServiceUnavailable), + mox.IgnoreArg()) + + self.mox.ReplayAll() + self.assertRaises(exception.ComputeServiceUnavailable, + self.manager.live_migration, + self.context, inst, dest, block_migration, + disk_over_commit) + def test_prep_resize_no_valid_host_back_in_active_state(self): fake_instance_uuid = 'fake-instance-id' inst = {"vm_state": "", "task_state": ""} @@ -472,6 +504,29 @@ self.mox.ReplayAll() self.assertRaises(exception.ComputeServiceUnavailable, + self.driver.schedule_live_migration, self.context, + instance=instance, dest=dest, + block_migration=block_migration, + disk_over_commit=disk_over_commit) + + def test_live_migration_compute_dest_not_exist(self): + # Raise exception when dest compute node does not exist. + + self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') + self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host') + + dest = 'fake_host2' + block_migration = False + disk_over_commit = False + instance = self._live_migration_instance() + + self.driver._live_migration_src_check(self.context, instance) + # Compute down + db.service_get_all_compute_by_host(self.context, + dest).AndRaise(exception.NotFound()) + + self.mox.ReplayAll() + self.assertRaises(exception.ComputeServiceUnavailable, self.driver.schedule_live_migration, self.context, instance=instance, dest=dest, block_migration=block_migration, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/nova/tests/test_libvirt.py new/nova-2012.2.4/nova/tests/test_libvirt.py --- old/nova-2012.2.4/nova/tests/test_libvirt.py 2013-02-21 20:47:15.000000000 +0100 +++ new/nova-2012.2.4/nova/tests/test_libvirt.py 2013-03-06 02:03:11.000000000 +0100 @@ -3810,6 +3810,79 @@ libvirt_utils.fetch_image(context, target, image_id, user_id, project_id) + def test_fetch_raw_image(self): + + def fake_execute(*cmd, **kwargs): + self.executes.append(cmd) + return None, None + + def fake_rename(old, new): + self.executes.append(('mv', old, new)) + + def fake_unlink(path): + self.executes.append(('rm', path)) + + def fake_rm_on_errror(path): + self.executes.append(('rm', '-f', path)) + + def fake_qemu_img_info(path): + class FakeImgInfo(object): + def get(self, attr): + return getattr(self, attr.replace(' ', '_'), None) + pass + + file_format = path.split('.')[-1] + if file_format == 'part': + file_format = path.split('.')[-2] + elif file_format == 'converted': + file_format = 'raw' + if 'backing' in path: + backing_file = 'backing' + else: + backing_file = None + + FakeImgInfo.file_format = file_format + FakeImgInfo.backing_file = backing_file + + return FakeImgInfo() + + self.stubs.Set(utils, 'execute', fake_execute) + self.stubs.Set(os, 'rename', fake_rename) + self.stubs.Set(os, 'unlink', fake_unlink) + self.stubs.Set(images, 'fetch', lambda *_: None) + self.stubs.Set(images, 'qemu_img_info', fake_qemu_img_info) + self.stubs.Set(utils, 'delete_if_exists', fake_rm_on_errror) + + context = 'opaque context' + image_id = '4' + user_id = 'fake' + project_id = 'fake' + + target = 't.qcow2' + self.executes = [] + expected_commands = [('qemu-img', 'convert', '-O', 'raw', + 't.qcow2.part', 't.qcow2.converted'), + ('rm', 't.qcow2.part'), + ('mv', 't.qcow2.converted', 't.qcow2')] + images.fetch_to_raw(context, image_id, target, user_id, project_id) + self.assertEqual(self.executes, expected_commands) + + target = 't.raw' + self.executes = [] + expected_commands = [('mv', 't.raw.part', 't.raw')] + images.fetch_to_raw(context, image_id, target, user_id, project_id) + self.assertEqual(self.executes, expected_commands) + + target = 'backing.qcow2' + self.executes = [] + expected_commands = [('rm', '-f', 'backing.qcow2.part')] + self.assertRaises(exception.ImageUnacceptable, + images.fetch_to_raw, + context, image_id, target, user_id, project_id) + self.assertEqual(self.executes, expected_commands) + + del self.executes + def test_get_disk_backing_file(self): with_actual_path = False diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/nova/virt/disk/api.py new/nova-2012.2.4/nova/virt/disk/api.py --- old/nova-2012.2.4/nova/virt/disk/api.py 2013-02-21 20:47:15.000000000 +0100 +++ new/nova-2012.2.4/nova/virt/disk/api.py 2013-03-06 02:03:11.000000000 +0100 @@ -415,11 +415,14 @@ # and so to append there you'd need something like: # utils.execute('sed', '-i', '${/^exit 0$/d}' rclocal, run_as_root=True) restorecon = [ - '#!/bin/sh\n', + '\n', '# Added by Nova to ensure injected ssh keys have the right context\n', 'restorecon -RF /root/.ssh/ 2>/dev/null || :\n', ] + if not fs.has_file(rclocal): + restorecon.insert(0, '#!/bin/sh') + rclocal_rel = os.path.relpath(rclocal, fs) _inject_file_into_fs(fs, rclocal_rel, ''.join(restorecon), append=True) utils.execute('chmod', 'a+x', rclocal, run_as_root=True) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nova-2012.2.4/nova/virt/images.py new/nova-2012.2.4/nova/virt/images.py --- old/nova-2012.2.4/nova/virt/images.py 2013-02-21 20:47:15.000000000 +0100 +++ new/nova-2012.2.4/nova/virt/images.py 2013-03-06 02:03:11.000000000 +0100 @@ -106,6 +106,7 @@ with utils.remove_path_on_error(staged): utils.execute('qemu-img', 'convert', '-O', 'raw', path_tmp, staged) + os.unlink(path_tmp) data = qemu_img_info(staged) if data.get('file format') != "raw": @@ -114,6 +115,5 @@ data.get('file format')) os.rename(staged, path) - else: os.rename(path_tmp, path) -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
