test_openstack.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. # -*- coding: utf-8 -*-
  2. """
  3. :codeauthor: `Tyler Johnson <tjohnson@saltstack.com>`
  4. tests.unit.cloud.clouds.openstack_test
  5. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  6. """
  7. from __future__ import absolute_import, print_function, unicode_literals
  8. from salt.cloud.clouds import openstack
  9. from salt.utils import dictupdate
  10. from tests.support.mixins import LoaderModuleMockMixin
  11. from tests.support.mock import MagicMock, patch
  12. from tests.support.unit import TestCase
  13. # pylint: disable=confusing-with-statement
  14. class MockImage(object):
  15. name = "image name"
  16. id = "image id"
  17. class MockNode(object):
  18. name = "node name"
  19. id = "node id"
  20. flavor = MockImage()
  21. status = "node status"
  22. def __init__(self, image):
  23. self.image = image
  24. def __iter__(self):
  25. return iter(())
  26. class MockConn(object):
  27. def __init__(self, image):
  28. self.node = MockNode(image)
  29. def get_image(self, *args, **kwargs):
  30. return self.node.image
  31. def get_flavor(self, *args, **kwargs):
  32. return self.node.flavor
  33. def get_server(self, *args, **kwargs):
  34. return self.node
  35. def list_servers(self, *args, **kwargs):
  36. return [self.node]
  37. class OpenstackTestCase(TestCase, LoaderModuleMockMixin):
  38. """
  39. Unit TestCase for salt.cloud.clouds.openstack module.
  40. """
  41. def setup_loader_modules(self):
  42. return {
  43. openstack: {
  44. "__active_provider_name__": "",
  45. "__opts__": {
  46. "providers": {
  47. "my-openstack-cloud": {
  48. "openstack": {
  49. "auth": "daenerys",
  50. "region_name": "westeros",
  51. "cloud": "openstack",
  52. }
  53. }
  54. }
  55. },
  56. }
  57. }
  58. def test_get_configured_provider_bad(self):
  59. with patch.dict(openstack.__opts__, {"providers": {}}):
  60. result = openstack.get_configured_provider()
  61. self.assertEqual(result, False)
  62. def test_get_configured_provider_auth(self):
  63. config = {
  64. "region_name": "westeros",
  65. "auth": "daenerys",
  66. }
  67. with patch.dict(
  68. openstack.__opts__,
  69. {"providers": {"my-openstack-cloud": {"openstack": config}}},
  70. ):
  71. result = openstack.get_configured_provider()
  72. self.assertEqual(config, result)
  73. def test_get_configured_provider_cloud(self):
  74. config = {
  75. "region_name": "westeros",
  76. "cloud": "foo",
  77. }
  78. with patch.dict(
  79. openstack.__opts__,
  80. {"providers": {"my-openstack-cloud": {"openstack": config}}},
  81. ):
  82. result = openstack.get_configured_provider()
  83. self.assertEqual(config, result)
  84. def test_get_dependencies(self):
  85. HAS_SHADE = (True, "Please install newer version of shade: >= 1.19.0")
  86. with patch("salt.cloud.clouds.openstack.HAS_SHADE", HAS_SHADE):
  87. result = openstack.get_dependencies()
  88. self.assertEqual(result, True)
  89. def test_get_dependencies_no_shade(self):
  90. HAS_SHADE = (False, "Install pypi module shade >= 1.19.0")
  91. with patch("salt.cloud.clouds.openstack.HAS_SHADE", HAS_SHADE):
  92. result = openstack.get_dependencies()
  93. self.assertEqual(result, False)
  94. def test_list_nodes_full_image_str(self):
  95. node_image = "node image"
  96. conn = MockConn(node_image)
  97. with patch("salt.cloud.clouds.openstack._get_ips", return_value=[]):
  98. ret = openstack.list_nodes_full(conn=conn)
  99. self.assertEqual(ret[conn.node.name]["image"], node_image)
  100. def test_list_nodes_full_image_obj(self):
  101. conn = MockConn(MockImage())
  102. with patch("salt.cloud.clouds.openstack._get_ips", return_value=[]):
  103. ret = openstack.list_nodes_full(conn=conn)
  104. self.assertEqual(ret[conn.node.name]["image"], MockImage.name)
  105. def test_show_instance(self):
  106. conn = MockConn(MockImage())
  107. with patch("salt.cloud.clouds.openstack._get_ips", return_value=[]):
  108. ret = openstack.show_instance(conn.node.name, conn=conn, call="action")
  109. self.assertEqual(ret["image"], MockImage.name)
  110. def test_request_instance_should_use_provided_connection_if_not_None(self):
  111. fake_conn = MagicMock()
  112. patch_get_conn = patch("salt.cloud.clouds.openstack.get_conn", autospec=True)
  113. patch_utils = patch.dict(
  114. openstack.__utils__,
  115. {"cloud.check_name": MagicMock(), "dictupdate.update": dictupdate.update},
  116. )
  117. patch_shade = patch.object(
  118. openstack, "shade.exc.OpenStackCloudException", Exception, create=True
  119. )
  120. with patch_get_conn as fake_get_conn, patch_utils, patch_shade:
  121. openstack.request_instance(
  122. vm_={"name": "fnord", "driver": "fnord"}, conn=fake_conn
  123. )
  124. fake_get_conn.assert_not_called()
  125. def test_request_instance_should_create_conn_if_provided_is_None(self):
  126. none_conn = None
  127. patch_get_conn = patch("salt.cloud.clouds.openstack.get_conn", autospec=True)
  128. patch_utils = patch.dict(
  129. openstack.__utils__,
  130. {"cloud.check_name": MagicMock(), "dictupdate.update": dictupdate.update},
  131. )
  132. patch_shade = patch.object(
  133. openstack, "shade.exc.OpenStackCloudException", Exception, create=True
  134. )
  135. with patch_get_conn as fake_get_conn, patch_utils, patch_shade:
  136. openstack.request_instance(
  137. vm_={"name": "fnord", "driver": "fnord"}, conn=none_conn
  138. )
  139. fake_get_conn.assert_called_once_with()
  140. # According to
  141. # https://docs.openstack.org/shade/latest/user/usage.html#shade.OpenStackCloud.create_server
  142. # the `network` parameter can be:
  143. # (optional) Network dict or name or ID to attach the server to.
  144. # Mutually exclusive with the nics parameter. Can also be be a list of
  145. # network names or IDs or network dicts.
  146. #
  147. # Here we're testing a normal dictionary
  148. def test_request_instance_should_be_able_to_provide_a_dictionary_for_network(self):
  149. fake_conn = MagicMock()
  150. expected_network = {"foo": "bar"}
  151. vm_ = {"name": "fnord", "driver": "fnord", "network": expected_network}
  152. patch_utils = patch.dict(
  153. openstack.__utils__,
  154. {"cloud.check_name": MagicMock(), "dictupdate.update": dictupdate.update},
  155. )
  156. with patch_utils:
  157. openstack.request_instance(vm_=vm_, conn=fake_conn)
  158. call = fake_conn.create_server.mock_calls[0]
  159. self.assertDictEqual(call.kwargs["network"], expected_network)
  160. # Here we're testing the list of dictionaries
  161. def test_request_instance_should_be_able_to_provide_a_list_of_dictionaries_for_network(
  162. self,
  163. ):
  164. fake_conn = MagicMock()
  165. expected_network = [{"foo": "bar"}, {"bang": "quux"}]
  166. vm_ = {"name": "fnord", "driver": "fnord", "network": expected_network}
  167. patch_utils = patch.dict(
  168. openstack.__utils__,
  169. {"cloud.check_name": MagicMock(), "dictupdate.update": dictupdate.update},
  170. )
  171. with patch_utils:
  172. openstack.request_instance(vm_=vm_, conn=fake_conn)
  173. call = fake_conn.create_server.mock_calls[0]
  174. assert call.kwargs["network"] == expected_network
  175. # Here we're testing for names/IDs
  176. def test_request_instance_should_be_able_to_provide_a_list_of_single_ids_or_names_for_network(
  177. self,
  178. ):
  179. fake_conn = MagicMock()
  180. expected_network = ["foo", "bar", "bang", "fnord1", "fnord2"]
  181. vm_ = {"name": "fnord", "driver": "fnord", "network": expected_network}
  182. patch_utils = patch.dict(
  183. openstack.__utils__,
  184. {"cloud.check_name": MagicMock(), "dictupdate.update": dictupdate.update},
  185. )
  186. with patch_utils:
  187. openstack.request_instance(vm_=vm_, conn=fake_conn)
  188. call = fake_conn.create_server.mock_calls[0]
  189. assert call.kwargs["network"] == expected_network