From d249fe1156d95abf3319d2d6389e096e161c3ad0 Mon Sep 17 00:00:00 2001 From: Vipin Balachandran Date: Mon, 7 May 2018 14:42:49 -0700 Subject: [PATCH] Fix session re-establish failure with PBM APIs PBM APIs break the API contract in vSphere 6.5 by raising NotAuthenticated fault instead of SecurityError when session is expired. We do catch NotAuthenticated faults (raised by VIM APIs), but PBM APIs use the 'vim25' namespace which result in not identifying the session expiry case. Therefore, the session is not re-established. Fixing it by matching the fault name suffix with 'NotAuthenticated' in the suds WebFault exception handler Closes-bug: #1769755 Change-Id: I35d48c12a5b1d5fe94a10b56b1ab06c34446de28 --- oslo_vmware/service.py | 7 ++++++- oslo_vmware/tests/test_service.py | 15 +++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/oslo_vmware/service.py b/oslo_vmware/service.py index 0f262ab2..7edc0d40 100644 --- a/oslo_vmware/service.py +++ b/oslo_vmware/service.py @@ -380,7 +380,12 @@ class Service(object): if detail: for fault in detail.getChildren(): fault_type = fault.get('type') - if fault_type.endswith(exceptions.SECURITY_ERROR): + # NOTE(vbala): PBM faults use vim25 namespace. Also, + # PBM APIs throw NotAuthenticated in vSphere 6.5 for + # session expiry. + if (fault_type.endswith(exceptions.SECURITY_ERROR) or + fault_type.endswith( + exceptions.NOT_AUTHENTICATED)): fault_type = exceptions.NOT_AUTHENTICATED fault_list.append(fault_type) for child in fault.getChildren(): diff --git a/oslo_vmware/tests/test_service.py b/oslo_vmware/tests/test_service.py index e20f96dd..a12a0fc9 100644 --- a/oslo_vmware/tests/test_service.py +++ b/oslo_vmware/tests/test_service.py @@ -15,13 +15,13 @@ import io +import ddt import mock import requests import six import six.moves.http_client as httplib import suds -import ddt from oslo_vmware import exceptions from oslo_vmware import service from oslo_vmware.tests import base @@ -56,6 +56,7 @@ class ServiceMessagePluginTest(base.TestCase): self.plugin.add_attribute_for_value) +@ddt.ddt class ServiceTest(base.TestCase): def setUp(self): @@ -209,8 +210,9 @@ class ServiceTest(base.TestCase): mock.call('/Envelope/Body/Fault/detail')] self.assertEqual(exp_calls, doc.childAtPath.call_args_list) - def test_request_handler_with_security_error(self): - managed_object = 'VirtualMachine' + @ddt.data('vim25:SecurityError', 'vim25:NotAuthenticated') + def test_request_handler_with_pbm_session_error(self, fault_name): + managed_object = 'ProfileManager' doc = mock.Mock() def side_effect(mo, **kwargs): @@ -222,7 +224,7 @@ class ServiceTest(base.TestCase): fault_children.name = "name" fault_children.getText.return_value = "value" child = mock.Mock() - child.get.return_value = 'vim25:SecurityError' + child.get.return_value = fault_name child.getChildren.return_value = [fault_children] detail = mock.Mock() detail.getChildren.return_value = [child] @@ -231,9 +233,10 @@ class ServiceTest(base.TestCase): svc_obj = service.Service() service_mock = svc_obj.client.service - setattr(service_mock, 'powerOn', side_effect) + setattr(service_mock, 'get_profile_id_by_name', side_effect) - ex = self.assertRaises(exceptions.VimFaultException, svc_obj.powerOn, + ex = self.assertRaises(exceptions.VimFaultException, + svc_obj.get_profile_id_by_name, managed_object) self.assertEqual([exceptions.NOT_AUTHENTICATED], ex.fault_list)