Пример #1
0
def add_reclass_parameter(paths, key, value, verbose=False, merge=False):
    """Add a value to the specified key to all the files in the paths

    if merge=False (default):
      - new value replaces previous key content completely.

    if merge=True:
      - if the specified key type is list, then value will be appended
        to the list. Value examples:
          '1000'
          'new_lab_name'
          'cluster.virtual_cluster_name.infra'
          'http://archive.ubuntu.com'
          '[a, b, c]'   # a list in the list
          '{a:1, b:2, c:3}' # a dict in the list
      - if the specified key type is an existing dict, then the dict
        will be extended with the dict in the value. Value example:
          '{address: 192.168.1.1, netmask: 255.255.255.0}'

    - If the specified key type is string/int/bool - it will replace previous
      value
    """
    add_key = key.split('.')

    for path in paths:
        for fyml in walkfiles(path, verbose=verbose):
            if fyml.fname.endswith('.yml'):
                model = helpers.yaml_read(fyml.fname)
                if model is not None:

                    nested_key = helpers.get_nested_key(model, add_key)

                    if nested_key is not None:
                        if merge is False:
                            nested_key = value
                        else:
                            if type(nested_key) is list:
                                nested_key.append(value)
                            elif type(nested_key) is dict:
                                nested_key.update(value)
                            else:
                                nested_key = value
                    else:
                        nested_key = value

                    helpers.create_nested_key(model, path=add_key,
                                              value=nested_key)

                    with open(fyml.fname, 'w') as f:
                        f.write(
                            yaml.dump(
                                model, default_flow_style=False, width=255
                            )
                        )
Пример #2
0
def vcp_list(domain=None, inventory=None):
    """List VCP node names

    Scan all nodes for the object salt.control.cluster.internal.node.XXX.name
    Return set of tuples ((nodename1, domain), (nodename2, domain), ...)
    """

    inventory = inventory or inventory_list(domain=domain)
    vcp_path = 'parameters.salt.control.cluster.internal.node'.split('.')
    domain_path = 'parameters._param.cluster_domain'.split('.')

    vcp_node_names = set()

    for node_name, node in inventory.items():
        vcp_nodes = helpers.get_nested_key(node, path=vcp_path)
        if vcp_nodes is not None:
            for vcp_node_name, vcp_node in vcp_nodes.items():
                vcp_node_names.add((vcp_node['name'],
                                    helpers.get_nested_key(node,
                                                           path=domain_path)))
    return vcp_node_names
Пример #3
0
    def _recurse_entity(self,
                        entity,
                        merge_base=None,
                        seen=None,
                        nodename=None):
        def _new_merge_dict(self, cur, new, path):
            try:
                return orig_merge_dict(self, cur, new, path)
            except TypeError as e:
                if "Current value:" not in e.message:
                    e.message += "\nValue path: {}\nCurrent value: {}\nNew value: {}\n".format(
                        path, cur, new)
                raise TypeError(e.message)

        if seen is None:
            seen = {}
        if '__visited' not in seen:
            seen['__visited'] = []

        orig_visited = copy.deepcopy(seen['__visited'])
        seen['__visited'].append(entity.name)

        orig_merge_dict = reclass_parameters.Parameters._merge_dict
        with mock.patch.object(reclass_parameters.Parameters,
                               '_merge_dict',
                               new=_new_merge_dict):
            try:
                result = super(ReclassCore,
                               self)._recurse_entity(entity, merge_base, seen,
                                                     nodename)
            except Exception:
                print("### Interpolation failed in the class: " +
                      ' < '.join(seen['__visited']))
                raise
        if self.track_key_path:
            key = helpers.get_nested_key(entity.parameters.as_dict(),
                                         path=self.track_key_path)
            if key is not None:
                print("# " + ' < '.join(seen['__visited']))
                out_dict = {}
                helpers.create_nested_key(out_dict,
                                          ['parameters'] + self.track_key_path,
                                          key)
                print(yaml.dump(out_dict, default_flow_style=False, width=255))

        # Reset the data collected by child entries
        seen['__visited'] = orig_visited

        return result
Пример #4
0
def remove_reclass_parameter(paths, key,
                             verbose=False,
                             pretend=False):
    """Removes specified key from parameters from all reclass models

    :param key: string with point-separated nested objects, for
                example: parameters.linux.network.interface
    :rtype dict: { 'file path': {nested_key}, ...}
    """
    remove_key = key.split('.')
    # found_keys = {}

    for path in paths:
        for fyml in walkfiles(path, verbose=verbose):
            if fyml.fname.endswith('.yml'):

                try:
                    model = helpers.yaml_read(fyml.fname)
                except yaml.scanner.ScannerError as e:
                    print(e, file=sys.stderr)
                    continue

                if model is not None:
                    # Clear linux.network.interfaces
                    nested_key = helpers.get_nested_key(model, remove_key)
                    if nested_key is not None:
                        # found_keys[fyml.fname] = copy.deepcopy(nested_key)
                        if pretend:
                            print("\n---\n# Found {0} in {1}"
                                  .format('.'.join(remove_key), fyml.fname))
                            print(yaml.dump(nested_key,
                                            default_flow_style=False,
                                            width=255))
                        else:
                            print("\n---\n# Removing {0} from {1}"
                                  .format('.'.join(remove_key), fyml.fname))
                            print(yaml.dump(nested_key,
                                            default_flow_style=False,
                                            width=255))

                            helpers.remove_nested_key(model, remove_key)

                            with open(fyml.fname, 'w') as f:
                                f.write(
                                    yaml.dump(
                                        model, default_flow_style=False,
                                        width=255
                                    )
                                )
Пример #5
0
def reclass_storage(domain=None, inventory=None):
    """List VCP node names

    Scan all nodes for the object salt.control.cluster.internal.node.XXX.name
    """

    inventory = inventory or inventory_list(domain=domain)
    storage_path = 'parameters.reclass.storage.node'.split('.')

    res = dict()
    for node_name, node in inventory.items():
        storage_nodes = helpers.get_nested_key(node, path=storage_path)
        if storage_nodes is not None:
            for storage_node_name, storage_node in storage_nodes.items():
                if storage_node['domain'] not in res:
                    res[storage_node['domain']] = dict()
                res[storage_node['domain']][storage_node_name] = storage_node
    return res
Пример #6
0
    def _nodeinfo(self, nodename):
        if self.track_key_path:
            print("\n" + nodename)
            print("-" * len(nodename))

        result = super(ReclassCore, self)._nodeinfo(nodename)

        if self.track_key_path:
            key = helpers.get_nested_key(result.parameters.as_dict(),
                                         path=self.track_key_path)
            if key is not None:
                print("### Final result after interpolation: ###")
                out_dict = {}
                helpers.create_nested_key(out_dict,
                                          ['parameters'] + self.track_key_path,
                                          key)
                print(yaml.dump(out_dict, default_flow_style=False, width=255))
        return result
Пример #7
0
def get_all_reclass_params(paths, verbose=False):
    """Return dict with all used values for each param"""
    _params = dict()
    for path in paths:
        for log in walkfiles(path, verbose):
            if log.fname.endswith('.yml'):
                model = helpers.yaml_read(log.fname)
                if model is not None:
                    # Collect all params from the models
                    _param = helpers.get_nested_key(
                        model,
                        ['parameters', '_param'])
                    if _param:
                        for key, val in _param.items():
                            if key in _params:
                                # Keep list values sorted
                                _params[key].append(val)
                                _params[key] = sorted(_params[key])
                            else:
                                _params[key] = [val]
    return _params
Пример #8
0
def create_inventory_context(domain=None, keys=None):
    """Dumps the current inventory per domain

    Example of context:

    <global_settings>: # only if required
      ...
    current_clusters:
      <cluster_names>:
        # here are cluster settings if required
        nodes:
          <node_names>:
            name: ctl01
            reclass_storage_name: openstack_control_node01
            roles:
            - vcp        # 'vcp' or None
            parameters:  # specified keys to dump, for example
                         # parameters.linux.network.interface below:
              linux:
                network:
                  interfaces:
                    ..
    """
    inventory = reclass_models.inventory_list(domain=domain)
    vcp_list = reclass_models.vcp_list(domain=domain, inventory=inventory)
    reclass_storage = reclass_models.reclass_storage(domain=domain,
                                                     inventory=inventory)

    if domain is None:
        sys.exit("Error: please specify a domain name from: \n{}".format(
            '\n'.join(reclass_storage.keys())))

    for storage_domain, storage_nodes in reclass_storage.items():
        if storage_domain != domain:
            continue

        current_cluster_nodes = {}
        for storage_node_name, storage_node in storage_nodes.items():
            inventory_node_name = "{0}.{1}".format(storage_node['name'],
                                                   storage_node['domain'])
            current_cluster_nodes[inventory_node_name] = {
                'name': storage_node['name'],
                'reclass_storage_name': storage_node_name,
                'roles': list(),
                'parameters': dict(),
            }

            if (storage_node['name'], storage_node['domain']) in vcp_list:
                # Add role 'vcp' to mark the VM nodes.
                current_cluster_nodes[inventory_node_name]['roles'].append(
                    'vcp')

            if keys:
                # Dump specified parameters for the node
                # Will fail with KeyError if 'inventory_node_name' doesn't
                # exists in reclass inventory
                # (wasn't generated with reclass.storage yet, for example)
                node = inventory[inventory_node_name]
                for key in keys:
                    key_path = key.split('.')
                    reclass_key = helpers.get_nested_key(node, path=key_path)
                    if reclass_key:
                        helpers.create_nested_key(
                            current_cluster_nodes[inventory_node_name],
                            path=key_path,
                            value=reclass_key)

        current_underlay_context = {
            'cookiecutter': {
                'cluster_name': storage_domain,
                'nodes': current_cluster_nodes,
            }
        }

    return current_underlay_context