2018-03-23 21:57:28 +08:00
|
|
|
|
|
|
|
from ansible.plugins.action import ActionBase
|
|
|
|
|
|
|
|
import notario
|
|
|
|
from notario.exceptions import Invalid
|
2018-04-24 00:06:22 +08:00
|
|
|
from notario.validators import types, chainable, iterables, recursive
|
|
|
|
from notario.decorators import optional
|
2018-04-19 02:29:25 +08:00
|
|
|
from notario.store import store as notario_store
|
2018-03-23 21:57:28 +08:00
|
|
|
|
|
|
|
try:
|
|
|
|
from __main__ import display
|
|
|
|
except ImportError:
|
|
|
|
from ansible.utils.display import Display
|
|
|
|
display = Display()
|
|
|
|
|
|
|
|
|
|
|
|
class ActionModule(ActionBase):
|
|
|
|
|
|
|
|
def run(self, tmp=None, task_vars=None):
|
2018-04-12 04:03:53 +08:00
|
|
|
# we must use vars, since task_vars will have un-processed variables
|
|
|
|
host_vars = task_vars['vars']
|
|
|
|
host = host_vars['ansible_hostname']
|
2018-03-23 21:57:28 +08:00
|
|
|
mode = self._task.args.get('mode', 'permissive')
|
|
|
|
|
2018-04-27 04:47:33 +08:00
|
|
|
print host_vars['groups']
|
|
|
|
|
2018-03-23 21:57:28 +08:00
|
|
|
self._supports_check_mode = False # XXX ?
|
2018-04-12 04:03:53 +08:00
|
|
|
self._supports_async = True
|
2018-03-23 21:57:28 +08:00
|
|
|
|
|
|
|
result = {}
|
|
|
|
result['_ansible_verbose_always'] = True
|
|
|
|
|
2018-04-12 04:03:53 +08:00
|
|
|
try:
|
|
|
|
notario.validate(host_vars, install_options, defined_keys=True)
|
|
|
|
|
|
|
|
if host_vars["ceph_origin"] == "repository":
|
|
|
|
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)
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
2018-04-19 02:29:25 +08:00
|
|
|
# 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)
|
|
|
|
|
|
|
|
notario.validate(host_vars, monitor_options, defined_keys=True)
|
|
|
|
|
2018-04-24 00:06:22 +08:00
|
|
|
# validate osd scenario setup
|
|
|
|
notario.validate(host_vars, osd_options, defined_keys=True)
|
|
|
|
notario_store['osd_objectstore'] = host_vars["osd_objectstore"]
|
|
|
|
if host_vars["osd_scenario"] == "collocated":
|
|
|
|
notario.validate(host_vars, collocated_osd_scenario, defined_keys=True)
|
|
|
|
|
|
|
|
if host_vars["osd_scenario"] == "non-collocated":
|
|
|
|
notario.validate(host_vars, non_collocated_osd_scenario, defined_keys=True)
|
|
|
|
|
|
|
|
if host_vars["osd_scenario"] == "lvm":
|
|
|
|
notario.validate(host_vars, lvm_osd_scenario, defined_keys=True)
|
|
|
|
|
2018-04-12 04:03:53 +08:00
|
|
|
except Invalid as error:
|
|
|
|
display.vvvv("Notario Failure: %s" % str(error))
|
2018-04-19 02:29:25 +08:00
|
|
|
display.warning("[%s] Validation failed for variable: %s" % (host, error.path[0]))
|
2018-04-12 04:03:53 +08:00
|
|
|
msg = "Invalid variable assignment in host: %s\n" % host
|
2018-04-19 02:29:25 +08:00
|
|
|
msg += " %s = %s\n" % (error.path, error.path)
|
|
|
|
msg += " %s %s\n" % (" " * len(str(error.path)), "^" * len(str(error.path)))
|
2018-04-12 04:03:53 +08:00
|
|
|
msg += "Reason: %s" % error.reason
|
|
|
|
result['failed'] = mode == 'strict'
|
|
|
|
result['msg'] = msg
|
|
|
|
result['stderr_lines'] = msg.split('\n')
|
|
|
|
|
|
|
|
return result
|
2018-03-23 21:57:28 +08:00
|
|
|
|
|
|
|
# Schemas
|
|
|
|
|
2018-04-12 04:03:53 +08:00
|
|
|
|
|
|
|
def osd_objectstore_choices(value):
|
|
|
|
assert value in ['bluestore', 'filestore'], "osd_objectstore must be either 'bluestore' or 'filestore'"
|
|
|
|
|
|
|
|
|
|
|
|
def ceph_origin_choices(value):
|
|
|
|
assert value in ['repository', 'distro', 'local'], "ceph_origin must be either 'repository', 'distro' or 'local'"
|
|
|
|
|
|
|
|
|
|
|
|
def ceph_repository_choices(value):
|
|
|
|
assert value in ['community', 'rhcs', 'dev'], "ceph_repository must be either 'community', 'rhcs' or 'dev'"
|
|
|
|
|
|
|
|
|
|
|
|
def ceph_repository_type_choices(value):
|
|
|
|
assert value in ['cdn', 'iso'], "ceph_repository_type must be either 'cdn' or 'iso'"
|
|
|
|
|
|
|
|
|
2018-04-19 02:29:25 +08:00
|
|
|
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"
|
|
|
|
monitor_interface_given = notario_store["monitor_interface"] != "interface"
|
|
|
|
|
|
|
|
msg = "Either monitor_address, monitor_address_block or monitor_interface must be provided"
|
|
|
|
|
2018-04-24 00:06:22 +08:00
|
|
|
assert any([monitor_address_given, monitor_address_block_given, monitor_interface_given]), msg
|
|
|
|
|
|
|
|
|
|
|
|
def validate_osd_scenarios(value):
|
|
|
|
assert value in ["collocated", "non-collocated", "lvm"], "osd_scenario must be set to 'collocated', 'non-collocated' or 'lvm'"
|
|
|
|
|
|
|
|
|
|
|
|
def validate_objectstore(value):
|
|
|
|
assert value in ["filestore", "bluestore"], "objectstore must be set to 'filestore' or 'bluestore'"
|
|
|
|
|
|
|
|
|
|
|
|
def validate_lvm_volumes(value):
|
|
|
|
if notario_store['osd_objectstore'] == "filestore":
|
|
|
|
assert isinstance(value, basestring), "lvm_volumes must contain a 'journal' key when the objectstore is 'filestore'"
|
2018-04-19 02:29:25 +08:00
|
|
|
|
|
|
|
|
2018-04-27 04:47:33 +08:00
|
|
|
def validate_ceph_stable_release(value):
|
|
|
|
assert value in ['jewel', 'kraken', 'luminous', 'mimic'], "ceph_stable_release must be set to 'jewel', 'kraken', 'lumious' or 'mimic'"
|
|
|
|
|
|
|
|
|
2018-04-12 04:03:53 +08:00
|
|
|
install_options = (
|
|
|
|
("ceph_origin", ceph_origin_choices),
|
|
|
|
('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),
|
2018-04-27 04:47:33 +08:00
|
|
|
("ceph_stable_release", validate_ceph_stable_release),
|
2018-04-12 04:03:53 +08:00
|
|
|
("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),
|
2018-03-23 21:57:28 +08:00
|
|
|
)
|
2018-04-19 02:29:25 +08:00
|
|
|
|
|
|
|
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),
|
2018-04-24 00:06:22 +08:00
|
|
|
("public_network", types.string),
|
|
|
|
)
|
|
|
|
|
|
|
|
osd_options = (
|
|
|
|
(optional("dmcrypt"), types.boolean),
|
|
|
|
("osd_scenario", validate_osd_scenarios),
|
|
|
|
(optional("objectstore"), validate_objectstore),
|
2018-04-19 02:29:25 +08:00
|
|
|
)
|
2018-04-24 00:06:22 +08:00
|
|
|
|
|
|
|
collocated_osd_scenario = ("devices", iterables.AllItems(types.string))
|
|
|
|
|
|
|
|
non_collocated_osd_scenario = (
|
|
|
|
(optional("bluestore_wal_devices"), iterables.AllItems(types.string)),
|
|
|
|
("devices", iterables.AllItems(types.string)),
|
|
|
|
(optional("dedicated_devices"), iterables.AllItems(types.string)),
|
|
|
|
)
|
|
|
|
|
|
|
|
lvm_osd_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),
|
|
|
|
('journal', optional(validate_lvm_volumes)),
|
|
|
|
(optional('journal_vg'), types.string),
|
|
|
|
(optional('wal'), types.string),
|
|
|
|
(optional('wal_vg'), types.string),
|
|
|
|
)))
|