2
0

provider_development.rst 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. Provider Development Walkthrough
  2. ================================
  3. This guide will walk you through the basic process of developing a new provider
  4. for CloudBridge.
  5. 1. We start off by creating a new folder for the provider within the
  6. ``cloudbridge/cloud/providers`` folder. In this case: ``gce``. Further, install
  7. the native cloud provider Python library, here
  8. ``pip install google-api-python-client==1.4.2`` and a couple of its requirements
  9. ``oauth2client==1.5.2`` and ``pycrypto==2.6.1``.
  10. 2. Add a ``provider.py`` file. This file will contain the main implementation
  11. of the cloud provider and will be the entry point that CloudBridge uses for all
  12. provider related services. You will need to subclass ``BaseCloudProvider`` and
  13. add a class variable named ``PROVIDER_ID``.
  14. .. code-block:: python
  15. from cloudbridge.cloud.base import BaseCloudProvider
  16. class GCECloudProvider(BaseCloudProvider):
  17. PROVIDER_ID = 'gce'
  18. def __init__(self, config):
  19. super(GCECloudProvider, self).__init__(config)
  20. 3. Add an ``__init__.py`` to the ``cloudbridge/cloud/providers/gce`` folder
  21. and export the provider.
  22. .. code-block:: python
  23. from .provider import GCECloudProvider # noqa
  24. .. tip ::
  25. You can view the code so far here: `commit 1`_
  26. 4. Next, we need to register the provider with the factory.
  27. This only requires that you register the provider's ID in the ``ProviderList``.
  28. Add GCE to the ``ProviderList`` class in ``cloudbridge/cloud/factory.py``.
  29. 5. Run the test suite. We will get the tests passing on py27 first.
  30. .. code-block:: bash
  31. export CB_TEST_PROVIDER=gce
  32. tox -e py27
  33. You should see the tests fail with the following message:
  34. .. code-block:: bash
  35. TypeError: Can't instantiate abstract class GCECloudProvider with abstract
  36. methods block_store, compute, object_store, security, network
  37. 6. Therefore, our next step is to implement these methods. We can start off by
  38. implementing these methods in ``provider.py`` and raising a
  39. ``NotImplementedError``.
  40. .. code-block:: python
  41. @property
  42. def compute(self):
  43. raise NotImplementedError(
  44. "GCECloudProvider does not implement this service")
  45. @property
  46. def network(self):
  47. raise NotImplementedError(
  48. "GCECloudProvider does not implement this service")
  49. @property
  50. def security(self):
  51. raise NotImplementedError(
  52. "GCECloudProvider does not implement this service")
  53. @property
  54. def block_store(self):
  55. raise NotImplementedError(
  56. "GCECloudProvider does not implement this service")
  57. @property
  58. def object_store(self):
  59. raise NotImplementedError(
  60. "GCECloudProvider does not implement this service")
  61. Running the tests now will complain as much. We will next implement each
  62. Service in turn.
  63. 7. We will start with the compute service. Add a ``services.py`` file.
  64. .. code-block:: python
  65. from cloudbridge.cloud.base.services import BaseSecurityService
  66. class GCESecurityService(BaseSecurityService):
  67. def __init__(self, provider):
  68. super(GCESecurityService, self).__init__(provider)
  69. 8. We can now return this new service from the security property in
  70. ``provider.py`` as follows:
  71. .. code-block:: python
  72. def __init__(self, config):
  73. super(GCECloudProvider, self).__init__(config)
  74. self._security = GCESecurityService(self)
  75. @property
  76. def security(self):
  77. return self._security
  78. .. tip ::
  79. You can view the code so far here: `commit 2`_
  80. 9. Run the tests, and the following message will cause all security service
  81. tests to fail:
  82. .. code-block:: bash
  83. TypeError: Can't instantiate abstract class GCESecurityService with abstract
  84. methods key_pairs, security_groups
  85. The Abstract Base Classes are doing their job and flagging all methods that
  86. need to be implemented.
  87. 10. Since the security service simply provides organisational structure, and is
  88. a container for the ``key_pairs`` and ``security_groups`` services, we must
  89. next implement these services.
  90. .. code-block:: python
  91. from cloudbridge.cloud.base.services import BaseKeyPairService
  92. from cloudbridge.cloud.base.services import BaseSecurityGroupService
  93. from cloudbridge.cloud.base.services import BaseSecurityService
  94. class GCESecurityService(BaseSecurityService):
  95. def __init__(self, provider):
  96. super(GCESecurityService, self).__init__(provider)
  97. # Initialize provider services
  98. self._key_pairs = GCEKeyPairService(provider)
  99. self._security_groups = GCESecurityGroupService(provider)
  100. @property
  101. def key_pairs(self):
  102. return self._key_pairs
  103. @property
  104. def security_groups(self):
  105. return self._security_groups
  106. class GCEKeyPairService(BaseKeyPairService):
  107. def __init__(self, provider):
  108. super(GCEKeyPairService, self).__init__(provider)
  109. class GCESecurityGroupService(BaseSecurityGroupService):
  110. def __init__(self, provider):
  111. super(GCESecurityGroupService, self).__init__(provider)
  112. .. tip ::
  113. You can view the code so far here: `commit 3`_
  114. Once again, running the tests will complain of missing methods:
  115. .. code-block:: bash
  116. TypeError: Can't instantiate abstract class GCEKeyPairService with abstract
  117. methods create, find, get, list
  118. 11. Keep implementing the methods till the security service works, and the
  119. tests pass.
  120. .. note ::
  121. We start off by implementing the list keypairs method. Therefore, to obtain
  122. the keypair, we need to have a connection to the cloud provider. For this,
  123. we need to install the Google sdk, and thereafter, to obtain the desired
  124. connection via the sdk. While the design and structure of that connection
  125. is up to the implementor, a general design we have followed is to have the
  126. cloud connection globally available within the provider.
  127. To add the sdk, we edit CloudBridge's main ``setup.py`` and list the
  128. dependencies.
  129. .. code-block:: python
  130. gce_reqs = ['google-api-python-client==1.4.2']
  131. full_reqs = base_reqs + aws_reqs + openstack_reqs + gce_reqs
  132. We will also register the provider in ``cloudbridge/cloud/factory.py``'s
  133. provider list.
  134. .. code-block:: python
  135. class ProviderList(object):
  136. AWS = 'aws'
  137. OPENSTACK = 'openstack'
  138. ...
  139. GCE = 'gce'
  140. .. tip ::
  141. You can view the code so far here: `commit 4`_
  142. 12. Thereafter, we create the actual connection through the sdk. In the case of
  143. GCE, we need a Compute API client object. We will make this connection
  144. available as a public property named ``gce_compute`` in the provider. We will
  145. then lazily initialize this connection.
  146. A full implementation of the KeyPair service can now be made in a provider
  147. specific manner.
  148. .. tip ::
  149. You can view the code so far here: `commit 5`_
  150. .. _commit 1: https://github.com/gvlproject/cloudbridge/commit/54c67e93a3cd9d51e7d2b1195ebf4e257d165297
  151. .. _commit 2: https://github.com/gvlproject/cloudbridge/commit/82c0244aa4229ae0aecfe40d769eb93b06470dc7
  152. .. _commit 3: https://github.com/gvlproject/cloudbridge/commit/e90a7f6885814a3477cd0b38398d62af64f91093
  153. .. _commit 4: https://github.com/gvlproject/cloudbridge/commit/2d5c14166a538d320e54eed5bc3fa04997828715
  154. .. _commit 5: https://github.com/gvlproject/cloudbridge/commit/98c9cf578b672867ee503027295f9d901411e496