diff options
Diffstat (limited to 'roles/openshift_facts/library/openshift_facts.py')
-rwxr-xr-x | roles/openshift_facts/library/openshift_facts.py | 256 |
1 files changed, 191 insertions, 65 deletions
diff --git a/roles/openshift_facts/library/openshift_facts.py b/roles/openshift_facts/library/openshift_facts.py index 40e54d706..0f25881f1 100755 --- a/roles/openshift_facts/library/openshift_facts.py +++ b/roles/openshift_facts/library/openshift_facts.py @@ -304,23 +304,6 @@ def normalize_provider_facts(provider, metadata): facts = normalize_openstack_facts(metadata, facts) return facts -def set_fluentd_facts_if_unset(facts): - """ Set fluentd facts if not already present in facts dict - dict: the facts dict updated with the generated fluentd facts if - missing - Args: - facts (dict): existing facts - Returns: - dict: the facts dict updated with the generated fluentd - facts if they were not already present - - """ - if 'common' in facts: - if 'use_fluentd' not in facts['common']: - use_fluentd = False - facts['common']['use_fluentd'] = use_fluentd - return facts - def set_flannel_facts_if_unset(facts): """ Set flannel facts if not already present in facts dict dict: the facts dict updated with the flannel facts if @@ -525,10 +508,11 @@ def set_url_facts_if_unset(facts): ports[prefix])) - r_lhn = "{0}:{1}".format(api_hostname, ports['api']).replace('.', '-') + r_lhn = "{0}:{1}".format(hostname, ports['api']).replace('.', '-') + r_lhu = "system:openshift-master/{0}:{1}".format(api_hostname, ports['api']).replace('.', '-') facts['master'].setdefault('loopback_cluster_name', r_lhn) facts['master'].setdefault('loopback_context_name', "default/{0}/system:openshift-master".format(r_lhn)) - facts['master'].setdefault('loopback_user', "system:openshift-master/{0}".format(r_lhn)) + facts['master'].setdefault('loopback_user', r_lhu) prefix_hosts = [('console', api_hostname), ('public_console', api_public_hostname)] for prefix, host in prefix_hosts: @@ -711,8 +695,8 @@ def set_deployment_facts_if_unset(facts): if 'node' in facts: deployment_type = facts['common']['deployment_type'] if 'storage_plugin_deps' not in facts['node']: - if deployment_type in ['openshift-enterprise', 'atomic-enterprise']: - facts['node']['storage_plugin_deps'] = ['ceph', 'glusterfs'] + if deployment_type in ['openshift-enterprise', 'atomic-enterprise', 'origin']: + facts['node']['storage_plugin_deps'] = ['ceph', 'glusterfs', 'iscsi'] else: facts['node']['storage_plugin_deps'] = [] @@ -720,7 +704,7 @@ def set_deployment_facts_if_unset(facts): def set_version_facts_if_unset(facts): """ Set version facts. This currently includes common.version and - common.version_greater_than_3_1_or_1_1. + common.version_gte_3_1_or_1_1. Args: facts (dict): existing facts @@ -732,16 +716,20 @@ def set_version_facts_if_unset(facts): facts['common']['version'] = version = get_openshift_version() if version is not None: if deployment_type == 'origin': - version_gt_3_1_or_1_1 = LooseVersion(version) > LooseVersion('1.0.6') - version_gt_3_1_1_or_1_1_1 = LooseVersion(version) > LooseVersion('1.1.1') + version_gte_3_1_or_1_1 = LooseVersion(version) >= LooseVersion('1.1.0') + version_gte_3_1_1_or_1_1_1 = LooseVersion(version) >= LooseVersion('1.1.1') + version_gte_3_2_or_1_2 = LooseVersion(version) >= LooseVersion('1.2.0') else: - version_gt_3_1_or_1_1 = LooseVersion(version) > LooseVersion('3.0.2.900') - version_gt_3_1_1_or_1_1_1 = LooseVersion(version) > LooseVersion('3.1.1') + version_gte_3_1_or_1_1 = LooseVersion(version) >= LooseVersion('3.0.2.905') + version_gte_3_1_1_or_1_1_1 = LooseVersion(version) >= LooseVersion('3.1.1') + version_gte_3_2_or_1_2 = LooseVersion(version) >= LooseVersion('3.1.1.901') else: - version_gt_3_1_or_1_1 = True - version_gt_3_1_1_or_1_1_1 = True - facts['common']['version_greater_than_3_1_or_1_1'] = version_gt_3_1_or_1_1 - facts['common']['version_greater_than_3_1_1_or_1_1_1'] = version_gt_3_1_1_or_1_1_1 + version_gte_3_1_or_1_1 = True + version_gte_3_1_1_or_1_1_1 = True + version_gte_3_2_or_1_2 = True + facts['common']['version_gte_3_1_or_1_1'] = version_gte_3_1_or_1_1 + facts['common']['version_gte_3_1_1_or_1_1_1'] = version_gte_3_1_1_or_1_1_1 + facts['common']['version_gte_3_2_or_1_2'] = version_gte_3_2_or_1_2 return facts @@ -756,12 +744,12 @@ def set_manageiq_facts_if_unset(facts): OpenShiftFactsInternalError: """ if 'common' not in facts: - if 'version_greater_than_3_1_or_1_1' not in facts['common']: + if 'version_gte_3_1_or_1_1' not in facts['common']: raise OpenShiftFactsInternalError( "Invalid invocation: The required facts are not set" ) if 'use_manageiq' not in facts['common']: - facts['common']['use_manageiq'] = facts['common']['version_greater_than_3_1_or_1_1'] + facts['common']['use_manageiq'] = facts['common']['version_gte_3_1_or_1_1'] return facts @@ -928,41 +916,79 @@ def apply_provider_facts(facts, provider_facts): facts['provider'] = provider_facts return facts - -def merge_facts(orig, new, additive_facts_to_overwrite): +# Disabling pylint too many branches. This function needs refactored +# but is a very core part of openshift_facts. +# pylint: disable=too-many-branches +def merge_facts(orig, new, additive_facts_to_overwrite, protected_facts_to_overwrite): """ Recursively merge facts dicts Args: orig (dict): existing facts new (dict): facts to update - additive_facts_to_overwrite (list): additive facts to overwrite in jinja '.' notation ex: ['master.named_certificates'] + protected_facts_to_overwrite (list): protected facts to overwrite in jinja + '.' notation ex: ['master.master_count'] Returns: dict: the merged facts """ additive_facts = ['named_certificates'] + protected_facts = ['ha', 'master_count'] facts = dict() for key, value in orig.iteritems(): + # Key exists in both old and new facts. if key in new: + # Continue to recurse if old and new fact is a dictionary. if isinstance(value, dict) and isinstance(new[key], dict): + # Collect the subset of additive facts to overwrite if + # key matches. These will be passed to the subsequent + # merge_facts call. relevant_additive_facts = [] - # Keep additive_facts_to_overwrite if key matches for item in additive_facts_to_overwrite: if '.' in item and item.startswith(key + '.'): relevant_additive_facts.append(item) - facts[key] = merge_facts(value, new[key], relevant_additive_facts) + + # Collect the subset of protected facts to overwrite + # if key matches. These will be passed to the + # subsequent merge_facts call. + relevant_protected_facts = [] + for item in protected_facts_to_overwrite: + if '.' in item and item.startswith(key + '.'): + relevant_protected_facts.append(item) + facts[key] = merge_facts(value, new[key], relevant_additive_facts, relevant_protected_facts) + # Key matches an additive fact and we are not overwriting + # it so we will append the new value to the existing value. elif key in additive_facts and key not in [x.split('.')[-1] for x in additive_facts_to_overwrite]: - # Fact is additive so we'll combine orig and new. if isinstance(value, list) and isinstance(new[key], list): new_fact = [] - for item in copy.deepcopy(value) + copy.copy(new[key]): + for item in copy.deepcopy(value) + copy.deepcopy(new[key]): if item not in new_fact: new_fact.append(item) facts[key] = new_fact + # Key matches a protected fact and we are not overwriting + # it so we will determine if it is okay to change this + # fact. + elif key in protected_facts and key not in [x.split('.')[-1] for x in protected_facts_to_overwrite]: + # The master count (int) can only increase unless it + # has been passed as a protected fact to overwrite. + if key == 'master_count': + if int(value) <= int(new[key]): + facts[key] = copy.deepcopy(new[key]) + else: + module.fail_json(msg='openshift_facts received a lower value for openshift.master.master_count') + # ha (bool) can not change unless it has been passed + # as a protected fact to overwrite. + if key == 'ha': + if bool(value) != bool(new[key]): + module.fail_json(msg='openshift_facts received a different value for openshift.master.ha') + else: + facts[key] = value + # No other condition has been met. Overwrite the old fact + # with the new value. else: - facts[key] = copy.copy(new[key]) + facts[key] = copy.deepcopy(new[key]) + # Key isn't in new so add it to facts to keep it. else: facts[key] = copy.deepcopy(value) new_keys = set(new.keys()) - set(orig.keys()) @@ -1070,6 +1096,28 @@ def set_container_facts_if_unset(facts): return facts +def set_installed_variant_rpm_facts(facts): + """ Set RPM facts of installed variant + Args: + facts (dict): existing facts + Returns: + dict: the facts dict updated with installed_variant_rpms + """ + installed_rpms = [] + for base_rpm in ['openshift', 'atomic-openshift', 'origin']: + optional_rpms = ['master', 'node', 'clients', 'sdn-ovs'] + variant_rpms = [base_rpm] + \ + ['{0}-{1}'.format(base_rpm, r) for r in optional_rpms] + \ + ['tuned-profiles-%s-node' % base_rpm] + for rpm in variant_rpms: + exit_code, _, _ = module.run_command(['rpm', '-q', rpm]) + if exit_code == 0: + installed_rpms.append(rpm) + + facts['common']['installed_variant_rpms'] = installed_rpms + return facts + + class OpenShiftFactsInternalError(Exception): """Origin Facts Error""" @@ -1104,13 +1152,20 @@ class OpenShiftFacts(object): local_facts (dict): local facts to set additive_facts_to_overwrite (list): additive facts to overwrite in jinja '.' notation ex: ['master.named_certificates'] + protected_facts_to_overwrite (list): protected facts to overwrite in jinja + '.' notation ex: ['master.master_count'] Raises: OpenShiftFactsUnsupportedRoleError: """ - known_roles = ['common', 'master', 'node', 'etcd', 'nfs'] - - def __init__(self, role, filename, local_facts, additive_facts_to_overwrite=False): + known_roles = ['common', 'master', 'node', 'etcd', 'hosted'] + + # Disabling too-many-arguments, this should be cleaned up as a TODO item. + # pylint: disable=too-many-arguments + def __init__(self, role, filename, local_facts, + additive_facts_to_overwrite=None, + openshift_env=None, + protected_facts_to_overwrite=None): self.changed = False self.filename = filename if role not in self.known_roles: @@ -1119,31 +1174,44 @@ class OpenShiftFacts(object): ) self.role = role self.system_facts = ansible_facts(module) - self.facts = self.generate_facts(local_facts, additive_facts_to_overwrite) - - def generate_facts(self, local_facts, additive_facts_to_overwrite): + self.facts = self.generate_facts(local_facts, + additive_facts_to_overwrite, + openshift_env, + protected_facts_to_overwrite) + + def generate_facts(self, + local_facts, + additive_facts_to_overwrite, + openshift_env, + protected_facts_to_overwrite): """ Generate facts Args: - local_facts (dict): local_facts for overriding generated - defaults + local_facts (dict): local_facts for overriding generated defaults additive_facts_to_overwrite (list): additive facts to overwrite in jinja '.' notation ex: ['master.named_certificates'] - + openshift_env (dict): openshift_env facts for overriding generated defaults + protected_facts_to_overwrite (list): protected facts to overwrite in jinja + '.' notation ex: ['master.master_count'] Returns: dict: The generated facts """ - local_facts = self.init_local_facts(local_facts, additive_facts_to_overwrite) + local_facts = self.init_local_facts(local_facts, + additive_facts_to_overwrite, + openshift_env, + protected_facts_to_overwrite) roles = local_facts.keys() defaults = self.get_defaults(roles) provider_facts = self.init_provider_facts() facts = apply_provider_facts(defaults, provider_facts) - facts = merge_facts(facts, local_facts, additive_facts_to_overwrite) + facts = merge_facts(facts, + local_facts, + additive_facts_to_overwrite, + protected_facts_to_overwrite) facts['current_config'] = get_current_config(facts) facts = set_url_facts_if_unset(facts) facts = set_project_cfg_facts_if_unset(facts) - facts = set_fluentd_facts_if_unset(facts) facts = set_flannel_facts_if_unset(facts) facts = set_nuage_facts_if_unset(facts) facts = set_node_schedulability(facts) @@ -1157,6 +1225,8 @@ class OpenShiftFacts(object): facts = set_aggregate_facts(facts) facts = set_etcd_facts_if_unset(facts) facts = set_container_facts_if_unset(facts) + if not facts['common']['is_containerized']: + facts = set_installed_variant_rpm_facts(facts) return dict(openshift=facts) def get_defaults(self, roles): @@ -1205,10 +1275,23 @@ class OpenShiftFacts(object): iptables_sync_period='5s', set_node_ip=False) defaults['node'] = node - if 'nfs' in roles: - nfs = dict(exports_dir='/var/export', registry_volume='regvol', - export_options='*(rw,sync,all_squash)') - defaults['nfs'] = nfs + defaults['hosted'] = dict( + registry=dict( + storage=dict( + kind=None, + volume=dict( + name='registry', + size='5Gi' + ), + nfs=dict( + directory='/exports', + options='*(rw,root_squash)'), + host=None, + access_modes=['ReadWriteMany'], + create_pv=True + ) + ) + ) return defaults @@ -1287,23 +1370,52 @@ class OpenShiftFacts(object): ) return provider_facts - def init_local_facts(self, facts=None, additive_facts_to_overwrite=False): + # Disabling too-many-branches. This should be cleaned up as a TODO item. + #pylint: disable=too-many-branches + def init_local_facts(self, facts=None, + additive_facts_to_overwrite=None, + openshift_env=None, + protected_facts_to_overwrite=None): """ Initialize the provider facts Args: facts (dict): local facts to set additive_facts_to_overwrite (list): additive facts to overwrite in jinja '.' notation ex: ['master.named_certificates'] + openshift_env (dict): openshift env facts to set + protected_facts_to_overwrite (list): protected facts to overwrite in jinja + '.' notation ex: ['master.master_count'] + Returns: dict: The result of merging the provided facts with existing local facts """ changed = False - facts_to_set = {self.role: dict()} + + facts_to_set = dict() + if facts is not None: facts_to_set[self.role] = facts + if openshift_env != {} and openshift_env != None: + for fact, value in openshift_env.iteritems(): + oo_env_facts = dict() + current_level = oo_env_facts + keys = fact.split('_')[1:] + if keys[0] != self.role: + continue + for key in keys: + if key == keys[-1]: + current_level[key] = value + elif key not in current_level: + current_level[key] = dict() + current_level = current_level[key] + facts_to_set = merge_facts(orig=facts_to_set, + new=oo_env_facts, + additive_facts_to_overwrite=[], + protected_facts_to_overwrite=[]) + local_facts = get_local_facts_from_file(self.filename) for arg in ['labels', 'annotations']: @@ -1311,14 +1423,18 @@ class OpenShiftFacts(object): basestring): facts_to_set[arg] = module.from_json(facts_to_set[arg]) - new_local_facts = merge_facts(local_facts, facts_to_set, additive_facts_to_overwrite) + new_local_facts = merge_facts(local_facts, + facts_to_set, + additive_facts_to_overwrite, + protected_facts_to_overwrite) for facts in new_local_facts.values(): keys_to_delete = [] - for fact, value in facts.iteritems(): - if value == "" or value is None: - keys_to_delete.append(fact) - for key in keys_to_delete: - del facts[key] + if isinstance(facts, dict): + for fact, value in facts.iteritems(): + if value == "" or value is None: + keys_to_delete.append(fact) + for key in keys_to_delete: + del facts[key] if new_local_facts != local_facts: self.validate_local_facts(new_local_facts) @@ -1406,6 +1522,8 @@ def main(): choices=OpenShiftFacts.known_roles), local_facts=dict(default=None, type='dict', required=False), additive_facts_to_overwrite=dict(default=[], type='list', required=False), + openshift_env=dict(default={}, type='dict', required=False), + protected_facts_to_overwrite=dict(default=[], type='list', required=False), ), supports_check_mode=True, add_file_common_args=True, @@ -1414,9 +1532,17 @@ def main(): role = module.params['role'] local_facts = module.params['local_facts'] additive_facts_to_overwrite = module.params['additive_facts_to_overwrite'] + openshift_env = module.params['openshift_env'] + protected_facts_to_overwrite = module.params['protected_facts_to_overwrite'] + fact_file = '/etc/ansible/facts.d/openshift.fact' - openshift_facts = OpenShiftFacts(role, fact_file, local_facts, additive_facts_to_overwrite) + openshift_facts = OpenShiftFacts(role, + fact_file, + local_facts, + additive_facts_to_overwrite, + openshift_env, + protected_facts_to_overwrite) file_params = module.params.copy() file_params['path'] = fact_file |