Page MenuHomeDevCentral

No OneTemporary

diff --git a/_modules/node.py b/_modules/node.py
index 28fc3c9..4ec9b53 100644
--- a/_modules/node.py
+++ b/_modules/node.py
@@ -1,261 +1,317 @@
# -*- coding: utf-8 -*-
# -------------------------------------------------------------
# Salt — Node execution module
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Project: Nasqueron
# Created: 2017-10-21
# Description: Functions related to the nodes' pillar entry
# License: BSD-2-Clause
# -------------------------------------------------------------
from salt.exceptions import CommandExecutionError, SaltCloudConfigError
from salt._compat import ipaddress
def _get_all_nodes():
return __pillar__.get("nodes", {})
def get_all_properties(nodename=None):
"""
A function to get a node pillar configuration.
CLI Example:
salt * node.get_all_properties
"""
if nodename is None:
nodename = __grains__["id"]
all_nodes = _get_all_nodes()
if nodename not in all_nodes:
raise CommandExecutionError(
SaltCloudConfigError("Node {0} not declared in pillar.".format(nodename))
)
return all_nodes[nodename]
def get(key, nodename=None):
"""
A function to get a node pillar configuration key.
CLI Example:
salt * node.get hostname
"""
return _get_property(key, nodename, None)
def _explode_key(k):
return k.split(":")
def _get_first_key(k):
return _explode_key(k)[0]
def _strip_first_key(k):
return ":".join(_explode_key(k)[1:])
def _get_property(key, nodename, default_value, parent=None):
if parent is None:
parent = get_all_properties(nodename)
if ":" in key:
first_key = _get_first_key(key)
if first_key in parent:
return _get_property(
_strip_first_key(key), nodename, default_value, parent[first_key]
)
elif key in parent:
return parent[key]
return default_value
def get_list(key, nodename=None):
"""
A function to get a node pillar configuration.
Returns a list if found, or an empty list if not found.
CLI Example:
salt * node.list network:ipv4_aliases
"""
return _get_property(key, nodename, [])
def has(key, nodename=None):
"""
A function to get a node pillar configuration.
Returns a boolean, False if not found.
CLI Example:
salt * node.has network:ipv6_tunnel
"""
value = _get_property(key, nodename, False)
return bool(value)
def has_role(role, nodename=None):
"""
A function to determine if a node has the specified role.
Returns a boolean, False if not found.
CLI Example:
salt * node.has_role devserver
"""
return role in get_list("roles", nodename)
def filter_by_role(pillar_key, nodename=None):
"""
A function to filter a dictionary by roles.
The dictionary must respect the following structure:
- keys are role to check the current node against
- values are list of items
If a key '*' is also present, it will be included
for every role.
Returns a list, extending all the filtered lists.
CLI Example:
salt * node.filter_by_role web_content_sls
"""
roles = get_list("roles", nodename)
dictionary = __pillar__.get(pillar_key, {})
filtered_list = []
for role, items in dictionary.items():
if role == "*" or role in roles:
filtered_list.extend(items)
return filtered_list
def filter_by_name(pillar_key, nodename=None):
"""
A function to filter a dictionary by node name.
The dictionary must respect the following structure:
- keys are names to check the current node against
- values are list of items
If a key '*' is also present, it will be included
for every node.
Returns a list, extending all the filtered lists.
CLI Example:
salt * node.filter_by_name mars
"""
if nodename is None:
nodename = __grains__["id"]
dictionary = __pillar__.get(pillar_key, {})
filtered_list = []
for name, items in dictionary.items():
if name == "*" or name == nodename:
filtered_list.extend(items)
return filtered_list
def has_web_content(content, nodename=None):
return content in filter_by_role("web_content_sls", nodename)
def get_wwwroot(nodename=None):
"""
A function to determine the wwwroot folder to use.
Returns a string depending on the FQDN.
CLI Example:
salt * node.get_wwwroot
"""
hostname = _get_property("hostname", nodename, None)
if hostname is None:
raise CommandExecutionError(
SaltCloudConfigError(
"Node {0} doesn't have a hostname property".format(nodename)
)
)
if hostname.count(".") < 2:
return "wwwroot/{0}/www".format(hostname)
fqdn = hostname.split(".")
return "wwwroot/{1}/{0}".format(".".join(fqdn[0:-2]), ".".join(fqdn[-2:]))
def get_ipv6_list():
"""
A function to get a list of IPv6, enclosed by [].
Returns a string depending on the IPv6 currently assigned.
CLI Example:
salt * node.get_ipv6_list
"""
ipv6 = __grains__.get("ipv6")
return " ".join(["[" + ip + "]" for ip in ipv6])
def resolve_network():
"""
A function to determine canonical properties of networks
from the nodes pillar.
CLI Example:
salt * node.resolve_network
"""
network = {
"ipv4_address": "",
"ipv4_gateway": "",
}
private_network = network.copy()
interfaces = _get_property("network:interfaces", __grains__["id"], {})
for interface_name, interface in interfaces.items():
if "ipv4" not in interface:
continue
ipv4 = interface["ipv4"]["address"]
if ipaddress.ip_address(ipv4).is_private:
target = private_network
else:
target = network
if target["ipv4_address"] != "":
continue
target["ipv4_address"] = ipv4
try:
target["ipv4_gateway"] = interface["ipv4"]["gateway"]
except KeyError:
pass
if network["ipv4_address"] == "":
return private_network
return network
+
+
+def _resolve_gre_tunnels_for_router(network, netmask):
+ tunnels = []
+
+ for node, tunnel in __pillar__.get(f"{network}_gre_tunnels", {}).items():
+ tunnels.append(
+ {
+ "description": f"{network}_to_{node}",
+ "interface": tunnel["router"]["interface"],
+ "src": tunnel["router"]["addr"],
+ "dst": tunnel["node"]["addr"],
+ "netmask": netmask,
+ "icann_src": get("network")["canonical_public_ipv4"],
+ "icann_dst": get("network", node)["canonical_public_ipv4"],
+ }
+ )
+
+ return tunnels
+
+
+def resolve_gre_tunnels():
+ """
+ A function to get the GRE tunnels for a node
+
+ CLI Example:
+ salt * node.resolve_gre_tunnels
+ """
+ gre_tunnels = []
+
+ for network, network_args in __pillar__.get("networks", {}).items():
+ if __grains__["id"] == network_args["router"]:
+ gre_tunnels += _resolve_gre_tunnels_for_router(
+ network, network_args["netmask"]
+ )
+ continue
+
+ tunnel = __salt__["pillar.get"](f"{network}_gre_tunnels:{__grains__['id']}")
+ if not tunnel:
+ continue
+
+ gre_tunnels.append(
+ {
+ "description": f"{network}_via_{network_args['router']}",
+ "interface": tunnel["node"].get("interface", "gre0"),
+ "src": tunnel["node"]["addr"],
+ "dst": tunnel["router"]["addr"],
+ "netmask": network_args["netmask"],
+ "icann_src": get("network")["canonical_public_ipv4"],
+ "icann_dst": get("network", network_args["router"])[
+ "canonical_public_ipv4"
+ ],
+ }
+ )
+
+ return gre_tunnels
diff --git a/pillar/core/network.sls b/pillar/core/network.sls
index 8afb63c..ab5e9b8 100644
--- a/pillar/core/network.sls
+++ b/pillar/core/network.sls
@@ -1,29 +1,49 @@
networks:
drake:
netmask: 255.255.255.0
- addr:
- cloudhugger: 172.27.27.28
- router-001: 172.27.27.1
- windriver: 172.27.27.35
- ysul: 172.27.27.33
+ router: router-001
-gre_tunnels:
- windriver:
- wind-cloud:
- interface: gre0
- network: drake
- to: cloudhugger
-
- wind-ysul:
- interface: gre0
- network: drake
- to: ysul
+# -------------------------------------------------------------
+# Drake - GRE tunnels
+#
+# Describe GRE tunnels between a node and {networks.drake.router}
+#
+# {id}:
+# router:
+# interface: gre0, gre1, ... / increment for each tunnel
+# addr: The tunnel IPv4 on the router in 172.27.27.240/28
+#
+# node:
+# interface: Not needed on Linux as the interface name will be
+# descriptive: gre-drake_via_{networks.drake.router}
+#
+# Not needed on FreeBSD if default value "gre0" is fine.
+# If there is several GRE tunnels, can be gre1, gre2, etc.
+#
+# addr: The canonical IPv4 for the server in 172.27.27.0/24
+#
+# IP should be sync between the pillar and the Operations grimoire
+# at https://agora.nasqueron.org/Operations_grimoire/Network
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+drake_gre_tunnels:
ysul:
- wind-ysul: &gre_drake_to_windriver
+ router:
interface: gre0
- network: drake
- to: windriver
+ addr: 172.27.27.252
+ node:
+ addr: 172.27.27.33
cloudhugger:
- wind-cloud: *gre_drake_to_windriver
+ router:
+ interface: gre1
+ addr: 172.27.27.253
+ node:
+ addr: 172.27.27.28
+
+ windriver:
+ router:
+ interface: gre2
+ addr: 172.27.27.254
+ node:
+ addr: 172.27.27.35
diff --git a/roles/core/network/gre.sls b/roles/core/network/gre.sls
index 0a6dd6f..2738cad 100644
--- a/roles/core/network/gre.sls
+++ b/roles/core/network/gre.sls
@@ -1,79 +1,54 @@
# -------------------------------------------------------------
# Salt — Network — GRE tunnels
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Project: Nasqueron
# Created: 2020-09-20
# License: Trivial work, not eligible to copyright
# -------------------------------------------------------------
-{% set network = salt['node.get']('network') %}
-{% set gre_tunnels = salt['pillar.get']("gre_tunnels:" + grains['id'], {}) %}
+{% from "roles/core/network/map.jinja" import gre with context %}
{% set boot_loader = namespace(gre=false) %}
# -------------------------------------------------------------
# Tunnels network configuration files
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-{% for description, tunnel in gre_tunnels.items() %}
+{% for tunnel in salt['node.resolve_gre_tunnels']() %}
{% set boot_loader.gre = True %}
-{% set tunnel_network = pillar['networks'][tunnel['network']] %}
-{% if grains['os'] == 'FreeBSD' %}
-/etc/rc.conf.d/netif/gre_{{ description }}:
+{{ gre.config_path }}{{ tunnel["description"] }}:
file.managed:
- - source: salt://roles/core/network/files/FreeBSD/netif_gre.rc
+ - source: salt://roles/core/network/files/{{ gre.source_path }}
- makedirs: True
- template: jinja
- - context:
- description: {{ description }}
- interface: {{ tunnel['interface'] }}
-
- src: {{ tunnel_network['addr'][grains['id']] }}
- dst: {{ tunnel_network['addr'][tunnel['to']] }}
-
- icann_src: {{ network['ipv4_address'] }}
- icann_dst: {{ salt['node.get']('network', tunnel['to'])['ipv4_address'] }}
-{% endif %}
-
+ - defaults: {{ tunnel }}
{% if grains['os_family'] == 'Debian' %}
-/etc/network/interfaces.d/10-gre-{{ description }}:
- file.managed:
- - source: salt://roles/core/network/files/Debian/10-gre.jinja
- - makedirs: True
- - template: jinja
- context:
interface: gre-{{ description }}
-
- src: {{ tunnel_network['addr'][grains['id']] }}
- dst: {{ tunnel_network['addr'][tunnel['to']] }}
- netmask: {{ tunnel_network['netmask'] }}
-
- icann_src: {{ network['ipv4_address'] }}
- icann_dst: {{ salt['node.get']('network', tunnel['to'])['ipv4_address'] }}
{% endif %}
{% endfor %}
# -------------------------------------------------------------
# Kernel configuration
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{% if boot_loader.gre %}
{% if grains['os'] == 'FreeBSD' %}
load_gre_kernel_module:
file.append:
- name: /boot/loader.conf
- text: |
if_gre_load="YES"
{% endif %}
{% if grains['os_family'] == 'Debian' %}
ip_gre:
kmod.present:
- persist: True
{% endif %}
{% endif %}
diff --git a/roles/core/network/map.jinja b/roles/core/network/map.jinja
index 6cb6f46..5961208 100644
--- a/roles/core/network/map.jinja
+++ b/roles/core/network/map.jinja
@@ -1,34 +1,51 @@
# -------------------------------------------------------------
# Salt — Network
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Project: Nasqueron
# License: Trivial work, not eligible to copyright
# -------------------------------------------------------------
# -------------------------------------------------------------
# Interface configuration by OS/distro
#
# config_path: the configuration file to write in OS
# source_path: in this repo, roles/core/network/files/<source_path>
#
# Don't set default value, so we MUST define them
# for EACH os/distro.
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{% set interface_config = salt['grains.filter_by']({
'FreeBSD': {
"config_path": "/etc/rc.conf.d/netif/ipv4_",
"source_path": "FreeBSD/netif_ipv4.rc",
"suffix": "interface",
},
'RedHat': {
"config_path": "/etc/sysconfig/network-scripts/ifcfg-",
"source_path": "RedHat/ifcfg",
"suffix": "device",
},
'Debian': {
"config_path": "/etc/network/interfaces.d/10-net-",
"source_path": "Debian/10-net.jinja",
"suffix": "device",
},
}) %}
+
+# -------------------------------------------------------------
+# GRE tunnels configuration by OS/distro
+#
+# See interface configuration for the documentation.
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+{% set gre = salt['grains.filter_by']({
+ 'FreeBSD': {
+ "config_path": "/etc/rc.conf.d/netif/gre_",
+ "source_path": "FreeBSD/netif_gre.rc",
+ },
+ 'Debian': {
+ "config_path": "/etc/network/interfaces.d/10-gre-",
+ "source_path": "Debian/10-gre.jinja",
+ },
+}) %}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Nov 25, 14:16 (1 d, 7 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2260339
Default Alt Text
(14 KB)

Event Timeline