Application Data Protection as a Service in OpenStack
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

provider.py 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  2. # not use this file except in compliance with the License. You may obtain
  3. # a copy of the License at
  4. #
  5. # http://www.apache.org/licenses/LICENSE-2.0
  6. #
  7. # Unless required by applicable law or agreed to in writing, software
  8. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  9. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  10. # License for the specific language governing permissions and limitations
  11. # under the License.
  12. import os
  13. from karbor import exception
  14. from karbor.i18n import _
  15. from karbor.services.protection import bank_plugin
  16. from karbor.services.protection.checkpoint import CheckpointCollection
  17. from karbor import utils
  18. from oslo_config import cfg
  19. from oslo_log import log as logging
  20. provider_opts = [
  21. cfg.MultiStrOpt('plugin',
  22. default='',
  23. help='plugins to use for protection'),
  24. cfg.StrOpt('bank',
  25. default='',
  26. help='bank plugin to use for storage'),
  27. cfg.StrOpt('description',
  28. default='',
  29. help='the description of provider'),
  30. cfg.StrOpt('name',
  31. default='',
  32. help='the name of provider'),
  33. cfg.StrOpt('id',
  34. default='',
  35. help='the provider id'),
  36. cfg.BoolOpt('enabled',
  37. default=False,
  38. help='enabled or not'),
  39. ]
  40. CONF = cfg.CONF
  41. LOG = logging.getLogger(__name__)
  42. PROTECTION_NAMESPACE = 'karbor.protections'
  43. CONF.register_opt(cfg.StrOpt('provider_config_dir',
  44. default='providers.d',
  45. help='Configuration directory for providers.'
  46. ' Absolute path, or relative to karbor '
  47. ' configuration directory.'))
  48. class PluggableProtectionProvider(object):
  49. def __init__(self, provider_config):
  50. super(PluggableProtectionProvider, self).__init__()
  51. self._config = provider_config
  52. self._id = self._config.provider.id
  53. self._name = self._config.provider.name
  54. self._description = self._config.provider.description
  55. self._extended_info_schema = {'options_schema': {},
  56. 'restore_schema': {},
  57. 'saved_info_schema': {}}
  58. self.checkpoint_collection = None
  59. self._bank_plugin = None
  60. self._plugin_map = {}
  61. if (hasattr(self._config.provider, 'bank') and
  62. not self._config.provider.bank):
  63. raise ImportError(_("Empty bank"))
  64. self._load_bank(self._config.provider.bank)
  65. self._bank = bank_plugin.Bank(self._bank_plugin)
  66. self.checkpoint_collection = CheckpointCollection(
  67. self._bank)
  68. if hasattr(self._config.provider, 'plugin'):
  69. for plugin_name in self._config.provider.plugin:
  70. if not plugin_name:
  71. raise ImportError(_("Empty protection plugin"))
  72. self._register_plugin(plugin_name)
  73. @property
  74. def id(self):
  75. return self._id
  76. @property
  77. def name(self):
  78. return self._name
  79. @property
  80. def description(self):
  81. return self._description
  82. @property
  83. def extended_info_schema(self):
  84. return self._extended_info_schema
  85. @property
  86. def bank(self):
  87. return self._bank
  88. @property
  89. def plugins(self):
  90. return self._plugin_map
  91. def load_plugins(self):
  92. return {
  93. plugin_type: plugin_class(self._config)
  94. for plugin_type, plugin_class in self.plugins.items()
  95. }
  96. def _load_bank(self, bank_name):
  97. try:
  98. plugin = utils.load_plugin(PROTECTION_NAMESPACE, bank_name,
  99. self._config)
  100. except Exception:
  101. LOG.exception("Load bank plugin: '%s' failed.", bank_name)
  102. raise
  103. else:
  104. self._bank_plugin = plugin
  105. def _register_plugin(self, plugin_name):
  106. try:
  107. plugin = utils.load_class(PROTECTION_NAMESPACE, plugin_name)
  108. except Exception:
  109. LOG.exception("Load protection plugin: '%s' failed.", plugin_name)
  110. raise
  111. else:
  112. for resource in plugin.get_supported_resources_types():
  113. self._plugin_map[resource] = plugin
  114. if hasattr(plugin, 'get_options_schema'):
  115. self._extended_info_schema['options_schema'][resource] \
  116. = plugin.get_options_schema(resource)
  117. if hasattr(plugin, 'get_restore_schema'):
  118. self._extended_info_schema['restore_schema'][resource] \
  119. = plugin.get_restore_schema(resource)
  120. if hasattr(plugin, 'get_saved_info_schema'):
  121. self._extended_info_schema['saved_info_schema'][resource] \
  122. = plugin.get_saved_info_schema(resource)
  123. def get_checkpoint_collection(self):
  124. return self.checkpoint_collection
  125. def get_checkpoint(self, checkpoint_id, context=None):
  126. return self.get_checkpoint_collection().get(checkpoint_id,
  127. context=context)
  128. def list_checkpoints(self, project_id, provider_id, limit=None,
  129. marker=None, plan_id=None, start_date=None,
  130. end_date=None, sort_dir=None, context=None):
  131. checkpoint_collection = self.get_checkpoint_collection()
  132. return checkpoint_collection.list_ids(
  133. project_id=project_id, provider_id=provider_id, limit=limit,
  134. marker=marker, plan_id=plan_id, start_date=start_date,
  135. end_date=end_date, sort_dir=sort_dir, context=context)
  136. class ProviderRegistry(object):
  137. def __init__(self):
  138. super(ProviderRegistry, self).__init__()
  139. self.providers = {}
  140. self._load_providers()
  141. def _load_providers(self):
  142. """load provider"""
  143. config_dir = utils.find_config(CONF.provider_config_dir)
  144. for config_file in os.listdir(config_dir):
  145. if not config_file.endswith('.conf'):
  146. continue
  147. config_path = os.path.abspath(os.path.join(config_dir,
  148. config_file))
  149. provider_config = cfg.ConfigOpts()
  150. provider_config(args=['--config-file=' + config_path])
  151. provider_config.register_opts(provider_opts, 'provider')
  152. provider_enabled = provider_config.provider.enabled
  153. if not provider_enabled:
  154. LOG.info('Provider {0} is not enabled'.format(
  155. provider_config.provider.name)
  156. )
  157. continue
  158. try:
  159. provider = PluggableProtectionProvider(provider_config)
  160. except Exception as e:
  161. LOG.error("Load provider: %(provider)s failed. "
  162. "Reason: %(reason)s",
  163. {'provider': provider_config.provider.name,
  164. 'reason': e})
  165. else:
  166. LOG.info('Loaded provider: %s successfully.',
  167. provider_config.provider.name)
  168. self.providers[provider.id] = provider
  169. def list_providers(self, marker=None, limit=None, sort_keys=None,
  170. sort_dirs=None, filters=None):
  171. # TODO(jiaopengju) How to use sort_keys, sort_dirs and filters
  172. provider_ids = sorted(self.providers.keys())
  173. provider_list = sorted(
  174. self.providers.values(), key=lambda item: item.id)
  175. if marker is not None and marker in provider_ids:
  176. provider_list = provider_list[provider_ids.index(marker) + 1:]
  177. filters = filters if filters else {}
  178. valid_providers = []
  179. for provider in provider_list:
  180. provider_dict = dict(
  181. id=provider.id,
  182. name=provider.name,
  183. description=provider.description,
  184. extended_info_schema=provider.extended_info_schema
  185. )
  186. for key, value in filters.items():
  187. if key in provider_dict.keys() and \
  188. value != provider_dict[key]:
  189. break
  190. else:
  191. valid_providers.append(provider_dict)
  192. if limit is not None and len(valid_providers) == limit:
  193. return valid_providers
  194. return valid_providers
  195. def show_provider(self, provider_id):
  196. try:
  197. return self.providers[provider_id]
  198. except KeyError:
  199. raise exception.ProviderNotFound(provider_id=provider_id)