Esempio n. 1
0
 def test_terminate_connection(self, mock_host):
     vol_name = VOLUME["name"] + "-cinder"
     mock_host.return_value = {"name": "some-host"}
     # Branch with manually created host
     self.driver.terminate_connection(VOLUME, CONNECTOR)
     self.array.disconnect_host.assert_called_with("some-host", vol_name)
     self.assertFalse(self.array.list_host_connections.called)
     self.assertFalse(self.array.delete_host.called)
     # Branch with host added to host group
     self.array.reset_mock()
     self.array.list_host_connections.return_value = []
     mock_host.return_value = PURE_HOST.copy()
     mock_host.return_value.update(hgroup="some-group")
     self.driver.terminate_connection(VOLUME, CONNECTOR)
     self.array.disconnect_host.assert_called_with(PURE_HOST_NAME, vol_name)
     self.assertTrue(self.array.list_host_connections.called)
     self.assertTrue(self.array.delete_host.called)
     # Branch with host still having connected volumes
     self.array.reset_mock()
     self.array.list_host_connections.return_value = [{
         "lun": 2,
         "name": PURE_HOST_NAME,
         "vol": "some-vol"
     }]
     mock_host.return_value = PURE_HOST
     self.driver.terminate_connection(VOLUME, CONNECTOR)
     self.array.disconnect_host.assert_called_with(PURE_HOST_NAME, vol_name)
     self.array.list_host_connections.assert_called_with(PURE_HOST_NAME,
                                                         private=True)
     self.assertFalse(self.array.delete_host.called)
     # Branch where host gets deleted
     self.array.reset_mock()
     self.array.list_host_connections.return_value = []
     self.driver.terminate_connection(VOLUME, CONNECTOR)
     self.array.disconnect_host.assert_called_with(PURE_HOST_NAME, vol_name)
     self.array.list_host_connections.assert_called_with(PURE_HOST_NAME,
                                                         private=True)
     self.array.delete_host.assert_called_with(PURE_HOST_NAME)
     # Branch where connection is missing and the host is still deleted
     self.array.reset_mock()
     self.array.disconnect_host.side_effect = exception.PureAPIException(
         code=400, reason="reason")
     self.driver.terminate_connection(VOLUME, CONNECTOR)
     self.array.disconnect_host.assert_called_with(PURE_HOST_NAME, vol_name)
     self.array.list_host_connections.assert_called_with(PURE_HOST_NAME,
                                                         private=True)
     self.array.delete_host.assert_called_with(PURE_HOST_NAME)
     # Branch where an unexpected exception occurs
     self.array.reset_mock()
     self.array.disconnect_host.side_effect = exception.PureAPIException(
         code=500, reason="unexpected exception")
     self.assertRaises(exception.PureAPIException,
                       self.driver.terminate_connection, VOLUME, CONNECTOR)
     self.array.disconnect_host.assert_called_with(PURE_HOST_NAME, vol_name)
     self.assertFalse(self.array.list_host_connections.called)
     self.assertFalse(self.array.delete_host.called)
Esempio n. 2
0
 def test_delete_volume_already_deleted(self):
     self.array.list_volume_hosts.side_effect = exception.PureAPIException(
         code=400, reason="Volume does not exist")
     self.driver.delete_volume(VOLUME)
     self.assertFalse(self.array.destroy_volume.called)
     self.array.list_volume_hosts.side_effect = None
     self.assert_error_propagates([self.array.destroy_volume],
                                  self.driver.delete_volume, VOLUME)
     # Testing case where array.destroy_volume returns an exception
     #  because volume already deleted
     self.array.destroy_volume.side_effect = exception.PureAPIException(
         code=400, reason="Volume does not exist")
     self.driver.delete_volume(VOLUME)
     self.assertTrue(self.array.destroy_volume.called)
     self.array.destroy_volume.side_effect = None
     self.assert_error_propagates([self.array.destroy_volume],
                                  self.driver.delete_volume, VOLUME)
Esempio n. 3
0
 def _http_request(self, method, path, data=None, reestablish_session=True):
     """Perform HTTP request for REST API."""
     req = urllib2.Request(self._root_url + path,
                           headers={"Content-Type": "application/json"})
     req.get_method = lambda: method
     body = json.dumps(data)
     try:
         # Raises urllib2.HTTPError if response code != 200
         response = self._opener.open(req, body)
     except urllib2.HTTPError as err:
         if (reestablish_session and err.code == 401):
             self._start_session()
             return self._http_request(method,
                                       path,
                                       data,
                                       reestablish_session=False)
         elif err.code == 450:
             # Purity REST API version is bad
             new_version = self._choose_rest_version()
             if new_version == self._rest_version:
                 raise exception.PureAPIException(
                     code=err.code,
                     reason=(_LE("Unable to find usable REST API version. "
                                 "Response from Pure Storage REST API: ") +
                             err.read()))
             self._rest_version = new_version
             self._root_url = "https://%s/api/%s/" % (self._target,
                                                      self._rest_version)
             return self._http_request(method, path, data)
         else:
             raise exception.PureAPIException(code=err.code,
                                              reason=err.read())
     except urllib2.URLError as err:
         # Error outside scope of HTTP status codes,
         # e.g., unable to resolve domain name
         raise exception.PureDriverException(
             reason=_LE("Unable to connect to %r. Check san_ip.") %
             self._target)
     else:
         content = response.read()
         if "application/json" in response.info().get('Content-Type'):
             return json.loads(content)
         raise exception.PureAPIException(
             reason=(_LE("Response not in JSON: ") + content))
Esempio n. 4
0
 def test_delete_snapshot(self):
     snap_name = SNAPSHOT["volume_name"] + "-cinder." + SNAPSHOT["name"]
     self.driver.delete_snapshot(SNAPSHOT)
     expected = [mock.call.destroy_volume(snap_name)]
     self.array.assert_has_calls(expected)
     self.array.destroy_volume.side_effect = exception.PureAPIException(
         code=400, reason="reason")
     self.driver.delete_snapshot(SNAPSHOT)
     self.array.destroy_volume.side_effect = None
     self.assert_error_propagates([self.array.destroy_volume],
                                  self.driver.delete_snapshot, SNAPSHOT)
Esempio n. 5
0
    def assert_error_propagates(self, mocks, func, *args, **kwargs):
        """Assert that errors from mocks propogate to func.

        Fail if exceptions raised by mocks are not seen when calling
        func(*args, **kwargs). Ensure that we are really seeing exceptions
        from the mocks by failing if just running func(*args, **kargs) raises
        an exception itself.
        """
        func(*args, **kwargs)
        for mock_func in mocks:
            mock_func.side_effect = exception.PureAPIException(reason="reason")
            self.assertRaises(exception.PureAPIException, func, *args,
                              **kwargs)
            mock_func.side_effect = None
Esempio n. 6
0
 def test_terminate_connection(self, mock_host):
     vol_name = VOLUME["name"] + "-cinder"
     mock_host.return_value = HOST_NAME
     self.driver.terminate_connection(VOLUME, CONNECTOR)
     self.array.disconnect_host.assert_called_with(HOST_NAME, vol_name)
     self.array.disconnect_host.side_effect = exception.PureAPIException(
         code=400, reason="reason")
     self.driver.terminate_connection(VOLUME, CONNECTOR)
     self.array.disconnect_host.assert_called_with(HOST_NAME, vol_name)
     self.array.disconnect_host.side_effect = None
     self.array.disconnect_host.reset_mock()
     mock_host.side_effect = exception.PureDriverException(reason="reason")
     self.assertFalse(self.array.disconnect_host.called)
     mock_host.side_effect = None
     self.assert_error_propagates([self.array.disconnect_host],
                                  self.driver.terminate_connection, VOLUME,
                                  CONNECTOR)
Esempio n. 7
0
 def test_http_request_450_error(self, mock_choose):
     mock_choose.return_value = "1.1"
     error = urllib2.HTTPError(self.full_path, 450, self.error_msg, None,
                               self.response)
     self.array._opener.open.side_effect = iter([error, self.response])
     real_result = self.array._http_request(self.method, self.path,
                                            self.data)
     self.assertEqual(self.result, real_result)
     expected = [
         self.make_call(),
         self.make_call(
             path=self.path_template.format(TARGET, "1.1", self.path))
     ]
     self.assertEqual(self.array._opener.open.call_args_list, expected)
     mock_choose.assert_called_with(self.array)
     self.array._opener.open.side_effect = error
     self.assertRaises(exception.PureAPIException, self.array._http_request,
                       self.method, self.path, self.data)
     self.array._opener.open.reset_mock()
     mock_choose.reset_mock()
     self.array._opener.open.side_effect = error
     mock_choose.side_effect = exception.PureAPIException(reason="reason")
     self.assertRaises(exception.PureAPIException, self.array._http_request,
                       self.method, self.path, self.data)