Introduce the network(s) parameter in the ceph spec module

This change introduces a new option on the CephDaemonSpec definition.
Now a list of networks can be specified and rendered using the related
top level field.
The networks field cannot be logically considered part of extra parameter,
because except for the monitors and osds (they have the cluster and public
networks defined), all the other daemons should provide this kind of field.
The ceph_mkspec module and the rgw tasks are modified accordingly and as
per [1] only rgw is supported for now.

[1] https://github.com/ceph/ceph/pull/40048

Change-Id: I71f1a0e995c0d92d73625cd863488fc183bda7b3
This commit is contained in:
Francesco Pantano 2021-03-26 14:22:25 +01:00
parent 6bfeb06341
commit 5ab03f393b
No known key found for this signature in database
GPG Key ID: 0458D4D1F41BD75C
4 changed files with 57 additions and 10 deletions

View File

@ -14,7 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import argparse
import ipaddress
import json
import sys
@ -97,7 +97,6 @@ class CephPlacementSpec(object):
else:
spec_template = {}
# TODO: Add count to the list of placement parameters
return spec_template
@ -136,6 +135,7 @@ class CephDaemonSpec(object):
daemon_name: str,
hosts: list,
placement_pattern: str,
networks: list,
spec: dict,
labels: list,
**kwargs: dict):
@ -147,6 +147,12 @@ class CephDaemonSpec(object):
self.placement = placement_pattern
self.labels = labels
# network list where the current daemon should be bound
if not networks:
self.networks = []
else:
self.networks = networks
# extra keywords definition (e.g. data_devices for OSD(s)
self.extra = {}
for k, v in kwargs.items():
@ -158,11 +164,22 @@ class CephDaemonSpec(object):
def __setattr__(self, key, value):
self.__dict__[key] = value
def validate_networks(self):
if len(self.networks) < 1:
return False
for network in self.networks:
try:
ipaddress.ip_network(network)
except ValueError as e:
raise Exception(f'Cannot parse network {network}: {e}')
return True
def make_daemon_spec(self):
# the placement dictionary
# the placement dict
pl = {}
# the spec dictionary
# the spec dict
sp = {}
place = CephPlacementSpec(self.hosts, self.placement, 0, self.labels)
@ -175,6 +192,14 @@ class CephDaemonSpec(object):
'service_id': self.daemon_id,
}
# the networks dict
ntw = {}
if self.validate_networks():
ntw = {
'networks': self.networks
}
# process extra parameters if present
if not self.validate_keys(self.extra.keys(), ALLOWED_EXTRA_KEYS):
raise Exception("Fatal: the spec should be composed by only allowed keywords")
@ -187,7 +212,7 @@ class CephDaemonSpec(object):
raise Exception("Fatal: the spec should be composed by only allowed keywords")
# build the resulting daemon template
spec_template = {**spec_template, **self.extra, **pl, **sp}
spec_template = {**spec_template, **ntw, **self.extra, **pl, **sp}
return spec_template
def validate_keys(self, spec, ALLOWED_KEYS):

View File

@ -85,6 +85,11 @@ options:
- The host pattern where the daemon is going to be applied
required: false
type: str
networks:
description:
- The list of networks on the host where the daemon is bound.
required: false
type: list
labels:
description:
- The list of labels used to apply the daemon on the Ceph custer
@ -144,6 +149,18 @@ EXAMPLES = '''
labels:
- "controller"
apply: true
- name: create the Ceph RGW daemon spec
ceph_spec:
service_type: rgw
service_id: rgw.default
service_name: rgw.default
networks:
- 1.2.3.0/24
- 4.5.6.0/24
render_path: '/home/ceph-admin/specs'
labels:
- "controller"
apply: true
'''
RETURN = '''# '''
@ -187,6 +204,7 @@ def run_module():
service_name = module.params.get('service_name')
hosts = module.params.get('hosts')
host_pattern = module.params.get('host_pattern')
networks = module.params.get('networks')
labels = module.params.get('labels')
spec = module.params.get('spec')
extra = module.params.get('extra')
@ -225,15 +243,18 @@ def run_module():
if labels is None:
labels = []
# no networks are defined
if networks is None:
networks = []
d = ceph_spec.CephDaemonSpec(service_type, service_id, service_name,
hosts, host_pattern, spec, labels, **extra)
hosts, host_pattern, networks, spec, labels, **extra)
if apply:
container_image = is_containerized()
render('{}/{}'.format(render_path, service_type), d.make_daemon_spec())
cmd = generate_orch_cli(cluster, '{}/{}'.format(render_path, service_type), container_image)
rc, cmd, out, err = exec_command(module, cmd)
# module.exit_json(changed=True, result=cmd)
exit_module(module=module, out=out, rc=rc, cmd=cmd, err=err, startd=startd, changed=changed)
else:
# render the dict as the output of the module

View File

@ -333,7 +333,7 @@ def get_specs(hosts_to_ips, label_map, ceph_service_types, osd_spec={}):
host_list.append(host)
if svc in ['mon', 'mgr']:
d = ceph_spec.CephDaemonSpec(svc, svc, svc, host_list,
placement_pattern,
placement_pattern, None,
spec_dict, labels)
if svc in ['osd']:
if osd_spec == {}:
@ -346,7 +346,7 @@ def get_specs(hosts_to_ips, label_map, ceph_service_types, osd_spec={}):
d = ceph_spec.CephDaemonSpec(svc, 'default_drive_group',
'osd.default_drive_group',
host_list, placement_pattern,
spec_dict, labels, **osd_spec)
None, spec_dict, labels, **osd_spec)
specs.append(d.make_daemon_spec())
return specs

View File

@ -36,10 +36,11 @@
apply: true
hosts: "{{ _hosts }}"
spec:
rgw_frontend_port: 8080
rgw_frontend_port: "{{ radosgw_frontend_port }}"
rgw_realm: 'default'
rgw_zone: 'default'
render_path: "{{ tripleo_cephadm_spec_home }}"
networks: "{{ radosgw_address_block }}"
register: spc
environment:
CEPH_CONTAINER_IMAGE: "{{ tripleo_cephadm_container_ns + '/' + tripleo_cephadm_container_image + ':' + tripleo_cephadm_container_tag }}"