+++ /dev/null
-
-from ansible.plugins.action import ActionBase
-from distutils.version import LooseVersion
-from ansible.module_utils.six import string_types
-from ansible.errors import AnsibleUndefinedVariable
-
-try:
- from __main__ import display
-except ImportError:
- from ansible.utils.display import Display
- display = Display()
-
-try:
- import notario
-except ImportError:
- msg = "The python-notario library is missing. Please install it on the node you are running ceph-ansible to continue." # noqa E501
- display.error(msg)
- raise SystemExit(msg)
-
-if LooseVersion(notario.__version__) < LooseVersion("0.0.13"):
- msg = "The python-notario libary has an incompatible version. Version >= 0.0.13 is needed, current version: %s" % notario.__version__
- display.error(msg)
- raise SystemExit(msg)
-
-from notario.exceptions import Invalid
-from notario.validators import types, chainable, iterables
-from notario.decorators import optional
-from notario.store import store as notario_store
-
-
-CEPH_RELEASES = ['jewel', 'kraken', 'luminous', 'mimic', 'nautilus', 'octopus']
-
-
-class ActionModule(ActionBase):
-
- def run(self, tmp=None, task_vars=None):
- # we must use vars, since task_vars will have un-processed variables
- host_vars = self.expand_all_jinja2_templates(task_vars['vars'])
- host = host_vars['ansible_hostname']
- mode = self._task.args.get('mode', 'permissive')
-
- self._supports_check_mode = False # XXX ?
- self._supports_async = True
-
- result = {}
- result['_ansible_verbose_always'] = True
-
- try:
- notario_store["groups"] = host_vars["groups"]
- notario_store["ansible_distribution"] = host_vars["ansible_distribution"]
- notario_store["containerized_deployment"] = host_vars["containerized_deployment"] # noqa E501
- notario.validate(host_vars, install_options, defined_keys=True)
-
- if host_vars["ceph_origin"] == "repository" and not host_vars["containerized_deployment"]:
- notario.validate(
- host_vars, ceph_origin_repository, defined_keys=True)
-
- if host_vars["ceph_repository"] == "community":
- notario.validate(
- host_vars, ceph_repository_community, defined_keys=True) # noqa E501
-
- if host_vars["ceph_repository"] == "rhcs":
- notario.validate(
- host_vars, ceph_repository_rhcs, defined_keys=True)
-
- if host_vars["ceph_repository"] == "dev":
- notario.validate(
- host_vars, ceph_repository_dev, defined_keys=True)
-
- if host_vars["ceph_repository"] == "obs":
- notario.validate(
- host_vars, ceph_repository_obs, defined_keys=True)
-
- if host_vars["ceph_repository"] == "custom":
- notario.validate(host_vars, ceph_repository_custom, defined_keys=True)
-
- # store these values because one must be defined
- # and the validation method
- # will need access to all three through the store
- notario_store["monitor_address"] = host_vars.get(
- "monitor_address", None)
- notario_store["monitor_address_block"] = host_vars.get(
- "monitor_address_block", None)
- notario_store["monitor_interface"] = host_vars.get(
- "monitor_interface", None)
-
- if host_vars["mon_group_name"] in host_vars["group_names"]:
- notario.validate(host_vars, monitor_options, defined_keys=True)
-
- notario_store["radosgw_address"] = host_vars.get(
- "radosgw_address", None)
- notario_store["radosgw_address_block"] = host_vars.get(
- "radosgw_address_block", None)
- notario_store["radosgw_interface"] = host_vars.get(
- "radosgw_interface", None)
-
- if host_vars["rgw_group_name"] in host_vars["group_names"]:
- notario.validate(host_vars, rados_options, defined_keys=True)
-
- # validate osd scenario setup
- if host_vars["osd_group_name"] in host_vars["group_names"]:
- notario.validate(host_vars, osd_options, defined_keys=True)
- notario_store['osd_objectstore'] = host_vars["osd_objectstore"]
- if not host_vars.get('osd_auto_discovery'):
- if host_vars.get("devices"):
- notario.validate(
- host_vars, lvm_batch_scenario, defined_keys=True)
- elif notario_store['osd_objectstore'] == 'filestore':
- notario.validate(
- host_vars, lvm_filestore_scenario, defined_keys=True) # noqa E501
- elif notario_store['osd_objectstore'] == 'bluestore':
- notario.validate(
- host_vars, lvm_bluestore_scenario, defined_keys=True) # noqa E501
-
- except Invalid as error:
- display.vvvv("Notario Failure: %s" % str(error))
- msg = "[{}] Validation failed for variable: {}".format(
- host, error.path[0])
- display.error(msg)
- reason = "[{}] Reason: {}".format(host, error.reason)
- try:
- if "schema is missing" not in str(error):
- for i in range(0, len(error.path)):
- if i == 0:
- given = "[{}] Given value for {}".format(
- host, error.path[0])
- else:
- given = given + ": {}".format(error.path[i])
- if given:
- display.error(given)
- else:
- given = ""
- reason = "[{}] Reason: {}".format(host, error.message)
- except KeyError:
- given = ""
- display.error(reason)
- result['failed'] = mode == 'strict'
- result['msg'] = "\n".join([s for s in (msg, reason, given) if len(s) > 0])
- result['stderr_lines'] = result['msg'].split('\n')
-
-
- return result
-
- def expand_all_jinja2_templates(self, variables):
- for k, v in variables.items():
- try:
- if self._templar.is_template(v):
- variables[k] = self.expand_jinja2_template(v)
- except AnsibleUndefinedVariable as e:
- variables[k] = u"VARIABLE IS NOT DEFINED!"
-
- return variables
-
- def expand_jinja2_template(self, var):
- expanded_var = self._templar.template(var, convert_bare=True,
- fail_on_undefined=True)
- if expanded_var == var:
- if not isinstance(expanded_var, string_types):
- raise AnsibleUndefinedVariable
- expanded_var = self._templar.template("{{%s}}" % expanded_var,
- convert_bare=True,
- fail_on_undefined=True)
- return expanded_var
-
-# Schemas
-
-
-def osd_objectstore_choices(value):
- assert value in [
- 'bluestore', 'filestore'], "osd_objectstore must be either 'bluestore' or 'filestore'" # noqa E501
-
-
-def ceph_origin_choices(value):
- if not notario_store["containerized_deployment"]:
- assert value in ['repository', 'distro',
- 'local'], "ceph_origin must be either 'repository', 'distro' or 'local'" # noqa E501
-
-
-def ceph_repository_choices(value):
- msg = "ceph_repository must be either 'community', 'rhcs', 'dev', 'custom', 'uca' or 'obs'"
- assert value in ['community', 'rhcs', 'dev', 'custom', 'uca', 'obs'], msg
-
-
-def ceph_repository_type_choices(value):
- assert value in [
- 'cdn', 'iso'], "ceph_repository_type must be either 'cdn' or 'iso'"
-
-
-def validate_monitor_options(value):
- """
- Either monitor_address, monitor_address_block or monitor_interface must
- be defined.
- """
- monitor_address_given = notario_store["monitor_address"] != "0.0.0.0"
- monitor_address_block_given = notario_store["monitor_address_block"] != "subnet" # noqa E501
- monitor_interface_given = notario_store["monitor_interface"] != "interface"
-
- msg = "Either monitor_address, monitor_address_block or monitor_interface must be provided" # noqa E501
-
- assert any([monitor_address_given, monitor_address_block_given,
- monitor_interface_given]), msg
-
-
-def validate_dmcrypt_bool_value(value):
- assert value in ["true", True, "false",
- False], "dmcrypt can be set to true/True or false/False (default)"
-
-
-def validate_osd_auto_discovery_bool_value(value):
- assert value in ["true", True, "false",
- False], "osd_auto_discovery can be set to true/True or false/False (default)"
-
-
-def validate_objectstore(value):
- assert value in [
- "filestore", "bluestore"], "objectstore must be set to 'filestore' or 'bluestore'" # noqa E501
-
-
-def validate_ceph_stable_release(value):
- assert value in CEPH_RELEASES, "ceph_stable_release must be set to one of the following: %s" % ", ".join( # noqa E501
- CEPH_RELEASES)
-
-
-def validate_rados_options(value):
- """
- Either radosgw_interface, radosgw_address or radosgw_address_block must
- be defined.
- """
- radosgw_address_given = notario_store["radosgw_address"] != "0.0.0.0"
- radosgw_address_block_given = notario_store["radosgw_address_block"] != "subnet"
- radosgw_interface_given = notario_store["radosgw_interface"] != "interface"
-
- msg = "Either radosgw_address, radosgw_address_block or radosgw_interface must be provided" # noqa E501
-
- assert any([radosgw_address_given, radosgw_address_block_given,
- radosgw_interface_given]), msg
-
-
-install_options = (
- ("ceph_origin", ceph_origin_choices),
- ("containerized_deployment", types.boolean),
- ('osd_objectstore', osd_objectstore_choices),
-)
-
-ceph_origin_repository = ("ceph_repository", ceph_repository_choices)
-
-ceph_repository_community = (
- ("ceph_mirror", types.string),
- ("ceph_stable_key", types.string),
- ("ceph_stable_release", validate_ceph_stable_release),
- ("ceph_stable_repo", types.string),
-)
-
-ceph_repository_rhcs = (
- ("ceph_repository_type", ceph_repository_type_choices),
- ("ceph_rhcs_version", chainable.AnyIn(types.string, types.integer)),
-)
-
-ceph_repository_dev = (
- ("ceph_dev_branch", types.string),
- ("ceph_dev_sha1", types.string),
-)
-
-ceph_repository_obs = (
- ("ansible_distribution", "openSUSE Leap"),
- ("ceph_obs_repo", types.string),
-)
-
-ceph_repository_custom = (
- ("ceph_custom_key", types.string),
- ("ceph_custom_repo", types.string),
-)
-
-ceph_repository_uca = (
- ("ceph_stable_openstack_release_uca", types.string),
- ("ceph_stable_release_uca", types.string),
- ("ceph_stable_repo_uca", types.string),
-)
-
-monitor_options = (
- ("cluster_network", types.string),
- ("fsid", types.string),
- ("monitor_address", validate_monitor_options),
- ("monitor_address_block", validate_monitor_options),
- ("monitor_interface", validate_monitor_options),
- ("public_network", types.string),
-)
-
-rados_options = (
- ("radosgw_address", validate_rados_options),
- ("radosgw_address_block", validate_rados_options),
- ("radosgw_interface", validate_rados_options),
-)
-
-osd_options = (
- (optional("dmcrypt"), validate_dmcrypt_bool_value),
- (optional("osd_auto_discovery"), types.boolean),
-)
-
-lvm_batch_scenario = ("devices", iterables.AllItems(types.string))
-
-lvm_filestore_scenario = ("lvm_volumes", iterables.AllItems((
- (optional('crush_device_class'), types.string),
- ('data', types.string),
- (optional('data_vg'), types.string),
- ('journal', types.string),
- (optional('journal_vg'), types.string),
-)))
-
-lvm_bluestore_scenario = ("lvm_volumes", iterables.AllItems((
- (optional('crush_device_class'), types.string),
- ('data', types.string),
- (optional('data_vg'), types.string),
- (optional('db'), types.string),
- (optional('db_vg'), types.string),
- (optional('wal'), types.string),
- (optional('wal_vg'), types.string),
-)))
---
-- name: validate provided configuration
- validate:
- mode: strict
+- name: validate ceph_origin
+ fail:
+ msg: "ceph_origin must be either 'repository', 'distro' or 'local'"
+ when:
+ - not containerized_deployment | bool
+ - ceph_origin not in ['repository', 'distro', 'local']
+
+- name: validate ceph_repository
+ fail:
+ msg: "ceph_repository must be either 'community', 'rhcs', 'dev', 'custom' or 'uca'"
+ when:
+ - ceph_origin == 'repository'
+ - ceph_repository not in ['community', 'rhcs', 'dev', 'custom', 'uca']
+
+- name: validate ceph_repository_community
+ fail:
+ msg: "ceph_stable_release must be either 'nautilus' or 'octopus'"
+ when:
+ - ceph_origin == 'repository'
+ - ceph_repository == 'community'
+ - ceph_stable_release not in ['nautilus', 'octopus']
+
+- name: validate ceph_repository_type
+ fail:
+ msg: "ceph_repository_type must be either 'cdn' or 'iso'"
+ when:
+ - ceph_origin == 'repository'
+ - ceph_repository == 'rhcs'
+ - ceph_repository_type not in ['cdn', 'iso']
+
+- name: validate osd_objectstore
+ fail:
+ msg: "osd_objectstore must be either 'bluestore' or 'filestore'"
+ when: osd_objectstore not in ['bluestore', 'filestore']
+
+- name: validate monitor network configuration
+ fail:
+ msg: "Either monitor_address, monitor_address_block or monitor_interface must be provided"
+ when:
+ - mon_group_name in group_names
+ - monitor_address == '0.0.0.0'
+ - monitor_address_block == 'subnet'
+ - monitor_interface == 'interface'
+
+- name: validate radosgw network configuration
+ fail:
+ msg: "Either radosgw_address, radosgw_address_block or radosgw_interface must be provided"
+ when:
+ - rgw_group_name in group_names
+ - radosgw_address == '0.0.0.0'
+ - radosgw_address_block == 'subnet'
+ - radosgw_interface == 'interface'
+
+- name: validate osd nodes
+ when: osd_group_name in group_names
+ block:
+ - name: validate lvm osd scenario
+ fail:
+ msg: 'devices or lvm_volumes must be defined for lvm osd scenario'
+ when:
+ - not osd_auto_discovery | default(false) | bool
+ - devices is undefined
+ - lvm_volumes is undefined
+
+ - name: validate filestore lvm osd scenario
+ fail:
+ msg: 'data and journal keys must be defined in lvm_volumes'
+ when:
+ - osd_objectstore == 'filestore'
+ - not osd_auto_discovery | default(false) | bool
+ - lvm_volumes is defined
+ - lvm_volumes | length > 0
+ - item.data is undefined or item.journal is undefined
+ with_items: '{{ lvm_volumes }}'
+
+ - name: validate bluestore lvm osd scenario
+ fail:
+ msg: 'data key must be defined in lvm_volumes'
+ when:
+ - osd_objectstore == 'bluestore'
+ - not osd_auto_discovery | default(false) | bool
+ - lvm_volumes is defined
+ - lvm_volumes | length > 0
+ - item.data is undefined
+ with_items: '{{ lvm_volumes }}'
- name: warning deprecation for fqdn configuration
fail: