Add multi backend support

Adds multi-backend support to Glance. Currently supported backends
are local, Swift and RBD. The order of preference for default backend
is RBD --> Swift --> Local. Backend can be selected explicitly by the
operator when creating an image.

Change-Id: I78ecad0e8e12fc1ff7d716b7e43d84ca4d5b0ee1
This commit is contained in:
Gabriel Adrian Samfira 2020-09-08 12:23:22 +00:00
parent 6099da7ba5
commit be8c4e00a9
4 changed files with 213 additions and 0 deletions

View File

@ -164,6 +164,68 @@ class CinderStoreContext(OSContextGenerator):
return {}
class MultiBackendContext(OSContextGenerator):
def _get_ceph_config(self):
ceph_ctx = CephGlanceContext()()
if not ceph_ctx:
return
ctx = {
"rbd_store_chunk_size": 8,
"rbd_store_pool": ceph_ctx["rbd_pool"],
"rbd_store_user": ceph_ctx["rbd_user"],
"rados_connect_timeout": 0,
"rbd_store_ceph_conf": "/etc/ceph/ceph.conf",
}
return ctx
def _get_swift_config(self):
swift_ctx = ObjectStoreContext()()
if not swift_ctx or swift_ctx.get("swift_store", False) is False:
return
ctx = {
"default_swift_reference": "swift",
"swift_store_config_file": "/etc/glance/glance-swift.conf",
"swift_store_create_container_on_put": "true",
}
return ctx
def __call__(self):
ctxt = {
"enabled_backend_configs": {},
"enabled_backends": None,
"default_store_backend": None,
}
backends = []
local_fs = config('filesystem-store-datadir')
if local_fs:
backends.append("local:file")
ctxt["enabled_backend_configs"]["local"] = {
"filesystem_store_datadir": local_fs,
"store_description": "Local filesystem store",
}
ceph_ctx = self._get_ceph_config()
if ceph_ctx:
backends.append("ceph:rbd")
ctxt["enabled_backend_configs"]["ceph"] = ceph_ctx
ctxt["default_store_backend"] = "ceph"
swift_ctx = self._get_swift_config()
if swift_ctx:
backends.append("swift:swift")
ctxt["enabled_backend_configs"]["swift"] = swift_ctx
if not ctxt["default_store_backend"]:
ctxt["default_store_backend"] = "swift"
if local_fs and not ctxt["default_store_backend"]:
ctxt["default_store_backend"] = "local"
if len(backends) > 0:
ctxt["enabled_backends"] = ", ".join(backends)
return ctxt
class MultiStoreContext(OSContextGenerator):
def __call__(self):

View File

@ -183,6 +183,7 @@ CONFIG_FILES = OrderedDict([
glance_contexts.GlanceIPv6Context(),
context.WorkerConfigContext(),
glance_contexts.MultiStoreContext(),
glance_contexts.MultiBackendContext(),
context.OSConfigFlagContext(
charm_flag='api-config-flags',
template_flag='api_config_flags'),

View File

@ -41,7 +41,15 @@ db_enforce_mysql_charset = False
image_size_cap = {{ image_size_cap }}
{% endif -%}
{% if enabled_backends %}
enabled_backends = {{ enabled_backends }}
{% endif %}
[glance_store]
{% if default_store_backend %}
default_backend = {{ default_store_backend }}
{% endif %}
{%- if use_internal_endpoints %}
catalog_info = {{ volume_catalog_info }}
{%- endif %}
@ -96,3 +104,10 @@ auth_endpoint = {{ service_protocol }}://{{ service_host }}:{{ service_port }}/v
{% include "section-oslo-middleware" %}
{% include "parts/section-storage" %}
{% for name, cfg in enabled_backend_configs.items() %}
[{{name}}]
{% for key, val in cfg.items() -%}
{{ key }} = {{ val }}
{% endfor -%}
{% endfor%}

View File

@ -192,6 +192,141 @@ class TestGlanceContexts(CharmTestCase):
{'known_stores': "glance.store.filesystem.Store,"
"glance.store.http.Store"})
def test_multi_backend_no_relations_no_data_dir(self):
self.relation_ids.return_value = []
self.is_relation_made.return_value = False
data_dir = ''
conf_dict = {
'filesystem-store-datadir': data_dir,
}
self.config.side_effect = lambda x: conf_dict.get(x)
self.assertEqual(
contexts.MultiBackendContext()(),
{
'enabled_backend_configs': {},
'enabled_backends': None,
'default_store_backend': None,
})
def test_multi_backend_no_relations(self):
self.relation_ids.return_value = []
self.is_relation_made.return_value = False
data_dir = '/some/data/dir'
conf_dict = {
'filesystem-store-datadir': data_dir,
}
self.config.side_effect = lambda x: conf_dict.get(x)
self.assertEqual(
contexts.MultiBackendContext()(),
{
'enabled_backend_configs': {
'local': {
'filesystem_store_datadir': data_dir,
'store_description': 'Local filesystem store',
}
},
'enabled_backends': 'local:file',
'default_store_backend': 'local',
})
def test_multi_backend_with_swift(self):
self.maxDiff = None
self.relation_ids.return_value = ["object-store:0"]
self.is_relation_made.return_value = False
data_dir = '/some/data/dir'
conf_dict = {
'filesystem-store-datadir': data_dir,
}
swift_conf = "/etc/glance/glance-swift.conf"
self.config.side_effect = lambda x: conf_dict.get(x)
self.assertEqual(
contexts.MultiBackendContext()(),
{
'enabled_backend_configs': {
'local': {
'filesystem_store_datadir': data_dir,
'store_description': 'Local filesystem store',
},
'swift': {
"default_swift_reference": "swift",
"swift_store_config_file": swift_conf,
"swift_store_create_container_on_put": "true",
}
},
'enabled_backends': 'local:file, swift:swift',
'default_store_backend': 'swift',
})
def test_multi_backend_with_ceph_no_swift(self):
self.maxDiff = None
self.relation_ids.return_value = []
self.is_relation_made.return_value = True
service = 'glance'
self.service_name.return_value = service
data_dir = '/some/data/dir'
conf_dict = {
'filesystem-store-datadir': data_dir,
'rbd-pool-name': 'mypool',
}
self.config.side_effect = lambda x: conf_dict.get(x)
self.assertEqual(
contexts.MultiBackendContext()(),
{
'enabled_backend_configs': {
'local': {
'filesystem_store_datadir': data_dir,
'store_description': 'Local filesystem store',
},
'ceph': {
"rbd_store_chunk_size": 8,
"rbd_store_pool": 'mypool',
"rbd_store_user": service,
"rados_connect_timeout": 0,
"rbd_store_ceph_conf": "/etc/ceph/ceph.conf",
}
},
'enabled_backends': 'local:file, ceph:rbd',
'default_store_backend': 'ceph',
})
def test_multi_backend_with_ceph_and_swift(self):
self.maxDiff = None
self.relation_ids.return_value = ["object-store:0"]
self.is_relation_made.return_value = True
service = 'glance'
self.service_name.return_value = service
data_dir = '/some/data/dir'
swift_conf = "/etc/glance/glance-swift.conf"
conf_dict = {
'filesystem-store-datadir': data_dir,
'rbd-pool-name': 'mypool',
}
self.config.side_effect = lambda x: conf_dict.get(x)
self.assertEqual(
contexts.MultiBackendContext()(),
{
'enabled_backend_configs': {
'local': {
'filesystem_store_datadir': data_dir,
'store_description': 'Local filesystem store',
},
'ceph': {
"rbd_store_chunk_size": 8,
"rbd_store_pool": 'mypool',
"rbd_store_user": service,
"rados_connect_timeout": 0,
"rbd_store_ceph_conf": "/etc/ceph/ceph.conf",
},
'swift': {
"default_swift_reference": "swift",
"swift_store_config_file": swift_conf,
"swift_store_create_container_on_put": "true",
}
},
'enabled_backends': 'local:file, ceph:rbd, swift:swift',
'default_store_backend': 'ceph',
})
@patch('charmhelpers.contrib.openstack.context.relation_ids')
@patch('charmhelpers.contrib.hahelpers.cluster.config_get')
@patch('charmhelpers.contrib.openstack.context.https')