2
0

provider.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. """Provider implementation based on OpenStack Python clients for OpenStack."""
  2. import os
  3. from cinderclient import client as cinder_client
  4. from keystoneauth1 import session
  5. from keystoneclient import client as keystone_client
  6. from neutronclient.v2_0 import client as neutron_client
  7. from novaclient import client as nova_client
  8. from novaclient import shell as nova_shell
  9. from swiftclient import client as swift_client
  10. from cloudbridge.cloud.base import BaseCloudProvider
  11. from .services import OpenStackBlockStoreService
  12. from .services import OpenStackComputeService
  13. from .services import OpenStackNetworkService
  14. from .services import OpenStackObjectStoreService
  15. from .services import OpenStackSecurityService
  16. class OpenStackCloudProvider(BaseCloudProvider):
  17. """OpenStack provider implementation."""
  18. PROVIDER_ID = 'openstack'
  19. def __init__(self, config):
  20. super(OpenStackCloudProvider, self).__init__(config)
  21. self.cloud_type = 'openstack'
  22. # Initialize cloud connection fields
  23. self.username = self._get_config_value(
  24. 'os_username', os.environ.get('OS_USERNAME', None))
  25. self.password = self._get_config_value(
  26. 'os_password', os.environ.get('OS_PASSWORD', None))
  27. self.project_name = self._get_config_value(
  28. 'os_project_name', os.environ.get('OS_PROJECT_NAME', None) or
  29. os.environ.get('OS_TENANT_NAME', None))
  30. self.auth_url = self._get_config_value(
  31. 'os_auth_url', os.environ.get('OS_AUTH_URL', None))
  32. self.region_name = self._get_config_value(
  33. 'os_region_name', os.environ.get('OS_REGION_NAME', None))
  34. self.project_domain_name = self._get_config_value(
  35. 'os_project_domain_name',
  36. os.environ.get('OS_PROJECT_DOMAIN_NAME', None))
  37. self.user_domain_name = self._get_config_value(
  38. 'os_user_domain_name', os.environ.get('OS_USER_DOMAIN_NAME', None))
  39. self.identity_api_version = self._get_config_value(
  40. 'os_identity_api_version',
  41. os.environ.get('OS_IDENTITY_API_VERSION', None))
  42. # Service connections, lazily initialized
  43. self._nova = None
  44. self._keystone = None
  45. self._glance = None
  46. self._cinder = None
  47. self._swift = None
  48. self._neutron = None
  49. # Additional cached variables
  50. self._cached_keystone_session = None
  51. # Initialize provider services
  52. self._compute = OpenStackComputeService(self)
  53. self._network = OpenStackNetworkService(self)
  54. self._security = OpenStackSecurityService(self)
  55. self._block_store = OpenStackBlockStoreService(self)
  56. self._object_store = OpenStackObjectStoreService(self)
  57. @property
  58. def nova(self):
  59. if not self._nova:
  60. self._nova = self._connect_nova()
  61. return self._nova
  62. @property
  63. def keystone(self):
  64. if not self._keystone:
  65. self._keystone = self._connect_keystone()
  66. return self._keystone
  67. @property
  68. def _keystone_version(self):
  69. """
  70. Return the numeric version of remote Keystone server.
  71. :rtype: ``int``
  72. :return: Keystone version as an int (currently, 2 or 3).
  73. """
  74. ks_version = keystone_client.Client(auth_url=self.auth_url).version
  75. if ks_version == 'v3':
  76. return 3
  77. return 2
  78. @property
  79. def _keystone_session(self):
  80. """
  81. Connect to Keystone and return a session object.
  82. :rtype: :class:`keystoneauth1.session.Session`
  83. :return: A Keystone session object.
  84. """
  85. if self._cached_keystone_session:
  86. return self._cached_keystone_session
  87. if self._keystone_version == 3:
  88. from keystoneauth1.identity.v3 import Password as Password_v3
  89. auth = Password_v3(auth_url=self.auth_url,
  90. username=self.username,
  91. password=self.password,
  92. user_domain_name=self.user_domain_name,
  93. project_domain_name=self.project_domain_name,
  94. project_name=self.project_name)
  95. self._cached_keystone_session = session.Session(auth=auth)
  96. else:
  97. from keystoneauth1.identity.v2 import Password as Password_v2
  98. auth = Password_v2(self.auth_url, username=self.username,
  99. password=self.password,
  100. tenant_name=self.project_name)
  101. self._cached_keystone_session = session.Session(auth=auth)
  102. return self._cached_keystone_session
  103. # @property
  104. # def glance(self):
  105. # if not self._glance:
  106. # self._glance = self._connect_glance()
  107. # return self._glance
  108. @property
  109. def cinder(self):
  110. if not self._cinder:
  111. self._cinder = self._connect_cinder()
  112. return self._cinder
  113. @property
  114. def swift(self):
  115. if not self._swift:
  116. self._swift = self._connect_swift()
  117. return self._swift
  118. @property
  119. def neutron(self):
  120. if not self._neutron:
  121. self._neutron = self._connect_neutron()
  122. return self._neutron
  123. @property
  124. def compute(self):
  125. return self._compute
  126. @property
  127. def network(self):
  128. return self._network
  129. @property
  130. def security(self):
  131. return self._security
  132. @property
  133. def block_store(self):
  134. return self._block_store
  135. @property
  136. def object_store(self):
  137. return self._object_store
  138. def _connect_nova(self):
  139. return self._connect_nova_region(self.region_name)
  140. def _connect_nova_region(self, region_name):
  141. """Get an OpenStack Nova (compute) client object."""
  142. # Force reauthentication with Keystone
  143. self._cached_keystone_session = None
  144. api_version = self._get_config_value(
  145. 'os_compute_api_version',
  146. os.environ.get('OS_COMPUTE_API_VERSION', 2))
  147. service_name = self._get_config_value(
  148. 'nova_service_name',
  149. os.environ.get('NOVA_SERVICE_NAME', None))
  150. if self.config.debug_mode:
  151. nova_shell.OpenStackComputeShell().setup_debugging(True)
  152. nova = nova_client.Client(
  153. api_version, session=self._keystone_session,
  154. region_name=region_name,
  155. service_name=service_name,
  156. http_log_debug=True if self.config.debug_mode else False)
  157. return nova
  158. def _connect_keystone(self):
  159. """Get an OpenStack Keystone (identity) client object."""
  160. if self._keystone_version == 3:
  161. return keystone_client.Client(session=self._keystone_session,
  162. auth_url=self.auth_url)
  163. else:
  164. # Wow, the internal keystoneV2 implementation is terribly buggy. It
  165. # needs both a separate Session object and the username, password
  166. # again for things to work correctly. Plus, a manual call to
  167. # authenticate() is also required if the service catalog needs
  168. # to be queried.
  169. keystone = keystone_client.Client(
  170. session=self._keystone_session,
  171. auth_url=self.auth_url,
  172. username=self.username,
  173. password=self.password,
  174. project_name=self.project_name,
  175. region_name=self.region_name)
  176. keystone.authenticate()
  177. return keystone
  178. def _connect_cinder(self):
  179. """Get an OpenStack Cinder (block storage) client object."""
  180. api_version = self._get_config_value(
  181. 'os_volume_api_version',
  182. os.environ.get('OS_VOLUME_API_VERSION', 2))
  183. return cinder_client.Client(api_version,
  184. session=self._keystone_session,
  185. region_name=self.region_name)
  186. # def _connect_glance(self):
  187. # """
  188. # Get an OpenStack Glance (VM images) client object for the given
  189. # cloud.
  190. # """
  191. # api_version = self._get_config_value(
  192. # 'os_image_api_version',
  193. # os.environ.get('OS_IMAGE_API_VERSION', 1))
  194. #
  195. # return glance_client.Client(version=api_version,
  196. # session=self.keystone.session)
  197. def _connect_swift(self):
  198. """Get an OpenStack Swift (object store) client object cloud."""
  199. return swift_client.Connection(session=self._keystone_session)
  200. def _connect_neutron(self):
  201. """Get an OpenStack Neutron (networking) client object cloud."""
  202. return neutron_client.Client(session=self._keystone_session,
  203. region_name=self.region_name)