Page MenuHomeDevCentral

No OneTemporary

diff --git a/_modules/node.py b/_modules/node.py
index 9b3f567..28fc3c9 100644
--- a/_modules/node.py
+++ b/_modules/node.py
@@ -1,220 +1,261 @@
# -*- 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
diff --git a/_modules/opensearch.py b/_modules/opensearch.py
index e47df07..23bd341 100644
--- a/_modules/opensearch.py
+++ b/_modules/opensearch.py
@@ -1,112 +1,113 @@
# -*- coding: utf-8 -*-
# -------------------------------------------------------------
# Salt — PaaS OpenSearch execution module
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Project: Nasqueron
# Description: Functions related to OpenSearch configuration
# License: BSD-2-Clause
# -------------------------------------------------------------
from salt.exceptions import CommandExecutionError, SaltCloudConfigError
+from .node import resolve_network
def get_config(node_name=None):
"""
A function to get relevant values for OpenSearch configuration.
CLI Example:
salt * opensearch.get_config
"""
if node_name is None:
node_name = __grains__["id"]
try:
clusters = __pillar__["opensearch_clusters"]
except KeyError:
clusters = []
for _, cluster in clusters.items():
if node_name in cluster["nodes"]:
return _expand_cluster_config(node_name, cluster)
raise CommandExecutionError(
SaltCloudConfigError(
"Node {0} not declared in pillar opensearch_clusters.".format(node_name)
)
)
def _expand_cluster_config(node_name, config):
config = dict(config)
nodes = _convert_to_ip(config["nodes"])
config.update(
{
"nodes": nodes,
"nodes_certificates": _get_nodes_info(config["nodes"]),
"node_name": node_name,
"network_host": _get_ip(node_name),
"lead_nodes": nodes,
"dashboards_nodes": nodes,
}
)
return config
def _convert_to_ip(node_names):
return [_get_ip(node_name) for node_name in node_names]
def _get_ip(node_name):
try:
- network = __pillar__["nodes"][node_name]["network"]
+ network = resolve_network()
except KeyError:
raise CommandExecutionError(
SaltCloudConfigError(
"Node {0} not declared in pillar nodes.".format(node_name)
)
)
for field in ["ipv4_address", "ipv6_address"]:
if field in network:
return network[field]
def _get_nodes_info(node_names):
return [_get_node_info(id) for node_name in node_names]
def _get_node_info(node_name):
return {
"id": node_name,
"fqdn": __pillar__["nodes"][node_name]["hostname"],
"ip": _get_ip(node_name),
}
def hash_password(clear_password):
command = (
"/opt/opensearch/plugins/opensearch-security/tools/hash.sh -p '{0}'".format(
clear_password
)
)
env = {
"JAVA_HOME": "/opt/opensearch/jdk",
}
return __salt__["cmd.shell"](command, env=env)
def list_certificates(node_name=None):
config = get_config(node_name)
certificates = ["admin", "root-ca"]
for node in config["nodes_certificates"]:
certificates.extend([node["id"], node["id"] + "_http"])
return certificates
diff --git a/_tests/data/forests.yaml b/_tests/data/forests.yaml
index 96b3298..2f85dcb 100644
--- a/_tests/data/forests.yaml
+++ b/_tests/data/forests.yaml
@@ -1,65 +1,82 @@
forests:
- brethil
- fangorn
- lothlorien
nodes:
egladil:
forest: lothlorien
hostname: egladil.lothlorien.forest
roles:
- treecity
+ network:
+ interfaces:
+ net01:
+ ipv4:
+ address: 1.2.3.4 #public
+ gateway: 1.2.3.254
+ net02:
+ ipv4:
+ address: 10.100.0.4 #private
+ gateway: 10.100.0.1
+
entwash:
forest: fangorn
hostname: entwash.node
roles:
- border
+ network:
+ interfaces:
+ net02:
+ ipv4:
+ address: 10.100.0.5 #private
+ gateway: 10.100.0.1
items_by_role:
treecity:
- Caras Galadhon
border:
- Onodlo
items_by_role_with_star:
'*':
- Air
treecity:
- Caras Galadhon
border:
- Onodlo
items_by_name:
egladil:
- Caras Galadhon
items_by_name_with_star:
'*':
- Air
egladil:
- Caras Galadhon
shellgroups_ubiquity:
- ubiquity
shellgroups_by_forest:
lothlorien:
- caras_galadhon
shellgroups:
ubiquity: {}
caras_galadhon:
members:
- amdir
- amroth
shellusers:
amdir: {}
amroth: {}
galadriel: {}
web_content_sls:
treecity:
- .ll/carasgaladhon
border:
- .arda/onodlo
diff --git a/_tests/modules/test_node.py b/_tests/modules/test_node.py
index d2b01b9..8b195d6 100755
--- a/_tests/modules/test_node.py
+++ b/_tests/modules/test_node.py
@@ -1,109 +1,156 @@
#!/usr/bin/env python3
from importlib.machinery import SourceFileLoader
+from unittest_data_provider import data_provider
import unittest
salt_test_case = SourceFileLoader("salt_test_case", "salt_test_case.py").load_module()
node = SourceFileLoader("node", "../_modules/node.py").load_module()
class Testinstance(unittest.TestCase, salt_test_case.SaltTestCase):
def setUp(self):
self.initialize_mocks()
self.instance = node
self.mock_pillar("data/forests.yaml")
self.mock_grains()
self.grains["id"] = "egladil"
def test_get_wwwroot(self):
self.assertEqual("wwwroot/lothlorien.forest/egladil", node.get_wwwroot())
self.assertEqual("wwwroot/entwash.node/www", node.get_wwwroot("entwash"))
def test_has_web_content(self):
self.assertTrue(node.has_web_content(".ll/carasgaladhon"))
self.assertFalse(node.has_web_content(".arda/onodlo"))
self.assertTrue(node.has_web_content(".arda/onodlo", "entwash"))
self.assertFalse(node.has_web_content("notexisting"))
def test_filter_by_role(self):
node_key = self.grains["id"]
self.assertEqual(["Caras Galadhon"], node.filter_by_role("items_by_role"))
self.assertEqual(["Onodlo"], node.filter_by_role("items_by_role", "entwash"))
# No role
self.pillar["nodes"][node_key]["roles"] = []
self.assertEqual([], node.filter_by_role("items_by_role"))
# More than one role
self.pillar["nodes"][node_key]["roles"] = ["border", "treecity"]
self.assertEqual(
["Caras Galadhon", "Onodlo"], sorted(node.filter_by_role("items_by_role"))
)
def test_filter_by_role_with_star(self):
node_key = self.grains["id"]
self.assertEqual(
["Air", "Caras Galadhon"], node.filter_by_role("items_by_role_with_star")
)
self.assertEqual(
["Air", "Onodlo"], node.filter_by_role("items_by_role_with_star", "entwash")
)
# No role
self.pillar["nodes"][node_key]["roles"] = []
self.assertEqual(["Air"], node.filter_by_role("items_by_role_with_star"))
# More than one role
self.pillar["nodes"][node_key]["roles"] = ["border", "treecity"]
self.assertEqual(
["Air", "Caras Galadhon", "Onodlo"],
sorted(node.filter_by_role("items_by_role_with_star")),
)
def test_filter_by_name(self):
self.assertEqual(["Caras Galadhon"], node.filter_by_name("items_by_name"))
self.assertEqual(
["Caras Galadhon"], node.filter_by_name("items_by_name", "egladil")
)
self.grains["id"] = "entwash"
self.assertEqual([], node.filter_by_name("items_by_name"))
def test_filter_by_name_with_star(self):
self.assertEqual(
["Air", "Caras Galadhon"], node.filter_by_name("items_by_name_with_star")
)
self.assertEqual(
["Air", "Caras Galadhon"],
node.filter_by_name("items_by_name_with_star", "egladil"),
)
self.grains["id"] = "entwash"
self.assertEqual(["Air"], node.filter_by_name("items_by_name_with_star"))
def test_get_ipv6_list(self):
self.grains["ipv6"] = [
"::1",
"2001:470:1f13:ce7:ca5:cade:fab:1e",
"2001:470:1f12:ce7::2",
]
self.assertEqual(
"[::1] [2001:470:1f13:ce7:ca5:cade:fab:1e] [2001:470:1f12:ce7::2]",
node.get_ipv6_list(),
)
+ resolved_networks = lambda: (
+ (
+ "egladil",
+ {
+ "ipv4_address": "1.2.3.4",
+ "ipv4_gateway": "1.2.3.254",
+ },
+ ),
+ (
+ "entwash",
+ {
+ "ipv4_address": "10.100.0.5",
+ "ipv4_gateway": "10.100.0.1",
+ },
+ ),
+ )
+
+ @data_provider(resolved_networks)
+ def test_resolve_network(self, id, expected):
+ self.grains["id"] = id
+ self.assertEqual(expected, node.resolve_network())
+
+ def test_resolve_network_without_gateway(self):
+ expected = {
+ "ipv4_address": "10.100.0.5",
+ "ipv4_gateway": "",
+ }
+
+ self.grains["id"] = "entwash"
+ del self.pillar["nodes"]["entwash"]["network"]["interfaces"]["net02"]["ipv4"][
+ "gateway"
+ ]
+
+ self.assertEqual(expected, node.resolve_network())
+
+ def test_resolve_network_without_any_network(self):
+ expected = {
+ "ipv4_address": "",
+ "ipv4_gateway": "",
+ }
+
+ self.grains["id"] = "entwash"
+ del self.pillar["nodes"]["entwash"]["network"]
+
+ self.assertEqual(expected, node.resolve_network())
+
if __name__ == "__main__":
unittest.main()
diff --git a/pillar/nodes/nodes.sls b/pillar/nodes/nodes.sls
index c2bfdbf..7448a2c 100644
--- a/pillar/nodes/nodes.sls
+++ b/pillar/nodes/nodes.sls
@@ -1,154 +1,204 @@
# -------------------------------------------------------------
# Salt — Nodes
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Project: Nasqueron
# Created: 2017-10-20
# License: Trivial work, not eligible to copyright
# -------------------------------------------------------------
nodes:
##
## Forest: Nasqueron
## Semantic field: https://devcentral.nasqueron.org/P27
##
cloudhugger:
forest: nasqueron-infra
hostname: cloudhugger.nasqueron.org
roles:
- opensearch
network:
- ipv4_interface: eno1
- ipv4_address: 188.165.200.229
- ipv4_gateway: 188.165.200.254
-
- ipv6_interface: eno1
- ipv6_address: fe80::ec4:7aff:fe6a:36e8
- ipv6_gateway: fe80::ee30:91ff:fee0:df80
- ipv6_prefix: 64
ipv6_native: True
-
ipv6_tunnel: False
+ canonical_public_ipv4: 188.165.200.229
+
+ interfaces:
+ eno1:
+ device: eno1
+ ipv4:
+ address: 188.165.200.229
+ gateway: 188.165.200.254
+ ipv6:
+ address: fe80::ec4:7aff:fe6a:36e8
+ prefix: 64
+ gateway: fe80::ee30:91ff:fee0:df80
+
dwellers:
forest: nasqueron-infra
hostname: dwellers.nasqueron.org
roles:
- paas-lxc
- paas-docker
- mastodon
flags:
install_docker_devel_tools: True
network:
- ipv4_address: 51.255.124.11
- ipv4_gateway: 91.121.86.254
-
- private_interface:
- uuid: 8e8ca793-b2eb-46d8-9266-125aba6d06c4
- device: ens224
- address: 172.27.27.4
- netmask: 255.255.255.0
-
ipv6_tunnel: True
+ canonical_public_ipv4: 51.255.124.11
+
+ interfaces:
+ ens192:
+ device: ens192
+ uuid: 6e05ebea-f2fd-4ca1-a21f-78a778664d8c
+ ipv4:
+ address: 51.255.124.11
+ netmask: 255.255.255.252
+ gateway: 91.121.86.254
+
+ ens224:
+ device: ens224
+ uuid: 8e8ca793-b2eb-46d8-9266-125aba6d06c4
+ ipv4:
+ address: 172.27.27.4
+ netmask: &intranought_netmask 255.255.255.240
+ gateway: 172.27.27.1
+
docker-001:
forest: nasqueron-infra
hostname: docker-001.nasqueron.org
roles:
- paas-docker
network:
- ipv4_address: 51.255.124.9
- ipv4_gateway: 91.121.86.254
-
- private_interface:
- uuid: 3fd0b9f8-ecc3-400d-bc61-3ba21d0b6337
- device: ens224
- address: 172.27.27.6
- netmask: 255.255.255.0
-
ipv6_tunnel: False
+ canonical_public_ipv4: 51.255.124.9
+
+ interfaces:
+ ens192:
+ device: ens192
+ uuid: ef7370c5-5060-4d89-82bb-dbeabf4a35f6
+ ipv4:
+ address: 51.255.124.9
+ netmask: 255.255.255.252
+ gateway: 91.121.86.254
+
+ ens224:
+ device: ens224
+ uuid: 3fd0b9f8-ecc3-400d-bc61-3ba21d0b6337
+ ipv4:
+ address: 172.27.27.6
+ netmask: *intranought_netmask
+ gateway: 172.27.27.1
+
router-001:
forest: nasqueron-infra
hostname: router-001.nasqueron.org
roles:
- router
network:
- ipv4_interface: vmx0
- ipv4_address: 51.255.124.8
- ipv4_netmask: 255.255.255.255
- ipv4_gateway: 91.121.86.254
ipv4_ovh_failover: True
+ ipv6_tunnel: False
- private_interface:
- device: vmx1
- address: 172.27.27.1
- netmask: 255.255.255.0
+ canonical_public_ipv4: 51.255.124.8
- ipv6_tunnel: False
+ interfaces:
+ vmx0:
+ device: vmx0
+ ipv4:
+ address: 51.255.124.8
+ netmask: 255.255.255.252
+ gateway: 91.121.86.254
+
+ vmx1:
+ device: vmx1
+ ipv4:
+ address: 172.27.27.1
+ netmask: *intranought_netmask
ysul:
forest: nasqueron-dev
hostname: ysul.nasqueron.org
roles:
- devserver
- saltmaster
- dbserver-mysql
- webserver-legacy
zfs:
pool: arcology
network:
- ipv4_interface: igb0
- ipv4_address: 163.172.49.16
- ipv4_gateway: 163.172.49.1
- ipv4_aliases:
- - 212.83.187.132
-
ipv6_tunnel: True
ipv6_gateway: 2001:470:1f12:9e1::1
+ canonical_public_ipv4: 212.83.187.132
+
+ interfaces:
+ igb0:
+ device: igb0
+ ipv4:
+ address: 163.172.49.16
+ netmask: 255.255.255.255
+ gateway: 163.172.49.1
+ aliases:
+ - 212.83.187.132
+
windriver:
forest: nasqueron-dev
hostname: windriver.nasqueron.org
roles:
- devserver
- saltmaster
- dbserver-mysql
- webserver-legacy
zfs:
pool: arcology
network:
- ipv4_interface: igb0
- ipv4_address: 51.159.18.59
- ipv4_gateway: 51.159.18.1
-
- ipv6_interface: igb0
- ipv6_address: 2001:0bc8:6005:0005:aa1e:84ff:fef3:5d9c
- ipv6_gateway: fe80::a293:51ff:feb7:5073
- ipv6_prefix: 128
ipv6_native: True
-
ipv6_tunnel: False
+ canonical_public_ipv4: 51.159.18.59
+
+ interfaces:
+ igb0:
+ device: igb0
+ ipv4:
+ address: 51.159.18.59
+ netmask: 255.255.255.255
+ gateway: 51.159.18.1
+ ipv6:
+ address: 2001:0bc8:6005:0005:aa1e:84ff:fef3:5d9c
+ gateway: fe80::a293:51ff:feb7:5073
+ prefix: 128
+
##
## Forest: Eglide
## Semantic field: ? (P27 used for "Eglide" too)
##
## This forest is intended to separate credentials
## between Eglide and Nasqueron servers.
##
eglide:
forest: eglide
hostname: eglide.org
roles:
- shellserver
network:
- ipv4_interface: ens2
- ipv4_address: 51.159.150.221
- ipv4_gateway: ""
-
ipv6_tunnel: True
+
+ canonical_public_ipv4: 51.159.150.221
+
+ interfaces:
+ ens2:
+ device: ens2
+ ipv4:
+ address: 51.159.150.221
+ gateway: ""
+ flags:
+ # This interface is configured by cloud-init
+ - skip_interface_configuration
+
fixes:
rsyslog_xconsole: True
diff --git a/roles/core/motd/init.sls b/roles/core/motd/init.sls
index 2293225..25ca27c 100644
--- a/roles/core/motd/init.sls
+++ b/roles/core/motd/init.sls
@@ -1,58 +1,58 @@
# -------------------------------------------------------------
# Salt — MOTD
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Project: Nasqueron
# Created: 2016-04-10
# License: Trivial work, not eligible to copyright
# -------------------------------------------------------------
{% set motd_path = salt['motd.get_path']() %}
-{% set network = salt['node.get']('network') %}
+{% set network = salt['node.resolve_network()'] %}
motd:
file.managed:
- name: {{ motd_path }}
- source: salt://roles/core/motd/files/{{ grains['id'] }}
- template: jinja
- context:
ipv4_address: {{ network['ipv4_address'] }}
ipv4_gateway: {{ network['ipv4_gateway'] }}
# -------------------------------------------------------------
# Provide a `motd` command to read /etc/motd
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/usr/local/bin/motd:
file.managed:
- source: salt://roles/core/motd/files/motd.sh
- mode: 755
{% if motd_path != "/etc/motd" %}
/etc/motd:
file.symlink:
- target: {{ motd_path }}
{% endif %}
# -------------------------------------------------------------
# Scaleway instances
#
# Fixes T858.
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
get_rid_of_scaleway_motd:
file.absent:
- name: /etc/update-motd.d/50-scw
# -------------------------------------------------------------
# Generate MOTD from templates
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{% if grains['os_family'] == 'FreeBSD' and grains['osmajorrelease'] >= 13 %}
update_motd:
cmd.run:
- name: service motd restart
- onchanges:
- file: motd
{% endif %}
diff --git a/roles/core/network/files/FreeBSD/netif_ipv4.rc b/roles/core/network/files/Debian/10-net.jinja
similarity index 58%
copy from roles/core/network/files/FreeBSD/netif_ipv4.rc
copy to roles/core/network/files/Debian/10-net.jinja
index ba5ad9e..36a04ea 100644
--- a/roles/core/network/files/FreeBSD/netif_ipv4.rc
+++ b/roles/core/network/files/Debian/10-net.jinja
@@ -1,19 +1,22 @@
# -------------------------------------------------------------
-# Network — rc configuration
+# Network — interfaces configuration
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Project: Nasqueron
# License: Trivial work, not eligible to copyright
-# Source file: roles/core/network/files/FreeBSD/netif_ipv4.rc
+# Source file: roles/core/network/files/Debian/10-net.jinja
# -------------------------------------------------------------
#
# <auto-generated>
# This file is managed by our rOPS SaltStack repository.
#
# Changes to this file may cause incorrect behavior
# and will be lost if the state is redeployed.
# </auto-generated>
-ifconfig_{{ interface }}="inet {{ ipv4_address }} netmask {{ ipv4_netmask }}"
-{%- for ip in ipv4_aliases %}
-ifconfig_{{ interface }}_alias{{ loop.index0 }}="inet {{ ip }} netmask 255.255.255.255"
-{% endfor -%}
+auto {{ interface.device }}
+iface {{ interface.device }} inet static
+ address {{ interface.ipv4.address }}
+ netmask {{ interface.ipv4.netmask }}
+ {% if "gateway" in interface.ipv4 %}
+ gateway {{ interface.ipv4.gateway }}
+ {% endif %}
diff --git a/roles/core/network/files/FreeBSD/netif_ipv4.rc b/roles/core/network/files/FreeBSD/netif_ipv4.rc
index ba5ad9e..f79ba21 100644
--- a/roles/core/network/files/FreeBSD/netif_ipv4.rc
+++ b/roles/core/network/files/FreeBSD/netif_ipv4.rc
@@ -1,19 +1,19 @@
# -------------------------------------------------------------
# Network — rc configuration
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Project: Nasqueron
# License: Trivial work, not eligible to copyright
# Source file: roles/core/network/files/FreeBSD/netif_ipv4.rc
# -------------------------------------------------------------
#
# <auto-generated>
# This file is managed by our rOPS SaltStack repository.
#
# Changes to this file may cause incorrect behavior
# and will be lost if the state is redeployed.
# </auto-generated>
-ifconfig_{{ interface }}="inet {{ ipv4_address }} netmask {{ ipv4_netmask }}"
-{%- for ip in ipv4_aliases %}
-ifconfig_{{ interface }}_alias{{ loop.index0 }}="inet {{ ip }} netmask 255.255.255.255"
+ifconfig_{{ interface.device }}="inet {{ interface.ipv4.address }} netmask {{ interface.ipv4.netmask }}"
+{%- for ip in interface.get("ipv4.aliases", []) %}
+ifconfig_{{ interface.device }}_alias{{ loop.index0 }}="inet {{ ip }} netmask 255.255.255.255"
{% endfor -%}
diff --git a/roles/core/network/files/RedHat/ifcfg-private b/roles/core/network/files/RedHat/ifcfg
similarity index 87%
rename from roles/core/network/files/RedHat/ifcfg-private
rename to roles/core/network/files/RedHat/ifcfg
index 307b020..2338184 100644
--- a/roles/core/network/files/RedHat/ifcfg-private
+++ b/roles/core/network/files/RedHat/ifcfg
@@ -1,32 +1,32 @@
# -------------------------------------------------------------
# Network configuration
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Project: Nasqueron
# License: Trivial work, not eligible to copyright
-# Source file: roles/core/network/files/RedHat/ifcfg-private
+# Source file: roles/core/network/files/RedHat/ifcfg
# -------------------------------------------------------------
#
# <auto-generated>
# This file is managed by our rOPS SaltStack repository.
#
# Changes to this file may cause incorrect behavior
# and will be lost if the state is redeployed.
# </auto-generated>
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=none
DEFROUTE=yes
-IPV4_FAILURE_FATAL=no
+IPV4_FAILURE_FATAL=yes
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME={{ interface.device }}
UUID={{ interface.uuid }}
DEVICE={{ interface.device }}
ONBOOT=yes
+IPADDR={{ interface.ipv4.address }}
PREFIX={{ prefix }}
-IPADDR={{ interface.address }}
diff --git a/roles/core/network/init.sls b/roles/core/network/init.sls
index 5cc42c5..5cf86f5 100644
--- a/roles/core/network/init.sls
+++ b/roles/core/network/init.sls
@@ -1,20 +1,19 @@
# -------------------------------------------------------------
# Salt — Network
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Project: Nasqueron
# Created: 2020-09-20
# License: Trivial work, not eligible to copyright
# -------------------------------------------------------------
include:
- .ipv4
- .ipv6
- - .private
- .gre
# Drake can be configured as:
#
-# - private (e.g. IntraNought network cards on EXSi hypervisor VMs)
+# - ipv4 (e.g. IntraNought network cards on EXSi hypervisor VMs)
# - gre (e.g. isolated servers needing a tunnel)
#
# Both are needed for servers with router role.
diff --git a/roles/core/network/ipv4.sls b/roles/core/network/ipv4.sls
index dc3ccf0..16ea4d8 100644
--- a/roles/core/network/ipv4.sls
+++ b/roles/core/network/ipv4.sls
@@ -1,42 +1,52 @@
# -------------------------------------------------------------
# Salt — Network
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Project: Nasqueron
# Created: 2016-06-15
# License: Trivial work, not eligible to copyright
# -------------------------------------------------------------
+{% from "roles/core/network/map.jinja" import interface_config with context %}
{% set network = salt['node.get']('network') %}
# -------------------------------------------------------------
# Interface
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-{% if grains['os'] == 'FreeBSD' %}
-/etc/rc.conf.d/netif/ipv4_{{ network['ipv4_interface'] }}:
+{% for interface_name, interface in network["interfaces"].items() %}
+
+{% if "skip_interface_configuration" not in interface.get("flags", []) %}
+network_ipv4_{{ interface_name }}:
file.managed:
- - source: salt://roles/core/network/files/FreeBSD/netif_ipv4.rc
+ {% if interface_config["suffix"] == "interface" %}
+ - name : {{ interface_config["config_path"] }}{{ interface_name }}
+ {% else %}
+ - name : {{ interface_config["config_path"] }}{{ interface["device"] }}
+ {% endif %}
+ - source: salt://roles/core/network/files/{{ interface_config["source_path"] }}
- makedirs: True
- template: jinja
- - context:
- interface: {{ network['ipv4_interface'] }}
- ipv4_address: {{ network['ipv4_address'] }}
- ipv4_netmask: {{ network['ipv4_netmask'] | default('255.255.255.0') }}
- ipv4_aliases: {{ salt['node.get_list']('network:ipv4_aliases') }}
+ - defaults:
+ interface: {{ interface }}
+{% if grains['os_family'] == 'RedHat' %}
+ prefix: {{ salt['network_utils.netmask_to_cidr_prefix'](interface['ipv4']['netmask']) }}
{% endif %}
+{% endif %}
+
+{% endfor %}
# -------------------------------------------------------------
# Routes
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{% if grains['os'] == 'FreeBSD' %}
/etc/rc.conf.d/routing/ipv4:
file.managed:
- source: salt://roles/core/network/files/FreeBSD/routing_ipv4.rc
- makedirs: True
- template: jinja
- context:
ipv4_gateway: {{ network['ipv4_gateway'] }}
ipv4_interface: {{ network['ipv4_interface'] }}
ipv4_ovh_failover: {{ salt['node.has']('network:ipv4_ovh_failover') }}
{% endif %}
diff --git a/roles/core/network/ipv6.sls b/roles/core/network/ipv6.sls
index c7a9475..b56a727 100644
--- a/roles/core/network/ipv6.sls
+++ b/roles/core/network/ipv6.sls
@@ -1,73 +1,81 @@
# -------------------------------------------------------------
# Salt — Network
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Project: Nasqueron
# Created: 2016-06-15
# License: Trivial work, not eligible to copyright
# -------------------------------------------------------------
# -------------------------------------------------------------
# Table of contents
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#
# :: Native IPv6
# :: 4to6 tunnel
# :: Routes
#
# -------------------------------------------------------------
{% from "map.jinja" import dirs with context %}
{% set network = salt['node.get']('network') %}
# -------------------------------------------------------------
# Native IPv6
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{% if salt['node.has']('network:ipv6_native') %}
+ {% for interface_name, interface in network["interfaces"].items() %}
+ {% if "ipv6" in interface %}
-{% if grains['os'] == 'FreeBSD' %}
-/etc/rc.conf.d/netif/ipv6_{{ network['ipv6_interface'] }}:
- file.managed:
- - source: salt://roles/core/network/files/FreeBSD/netif_ipv6.rc
- - makedirs: True
- - template: jinja
- - context:
- interface: {{ network['ipv6_interface'] }}
- ipv6_address: {{ network['ipv6_address'] }}
- ipv6_prefix: {{ network['ipv6_prefix'] | default(64) }}
- has_native_ipv6: True
-{% endif %}
+ {% if "gateway" in interface["ipv6"] %}
+ {% set ipv6_gateway = interface["ipv6"]["gateway"] %}
+ {% endif %}
+
+ {% if grains['os'] == 'FreeBSD' %}
+ /etc/rc.conf.d/netif/ipv6_{{ interface['device'] }}:
+ file.managed:
+ - source: salt://roles/core/network/files/FreeBSD/netif_ipv6.rc
+ - makedirs: True
+ - template: jinja
+ - context:
+ interface: {{ interface['device'] }}
+ ipv6_address: {{ interface['ipv6']['address'] }}
+ ipv6_prefix: {{ interface['ipv6']['prefix'] | default(64) }}
+ has_native_ipv6: True
+ {% endif %}
+ {% endif %}
+ {% endfor %}
{% endif %}
# -------------------------------------------------------------
# 4to6 tunnel
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{% if salt['node.has']('network:ipv6_tunnel') %}
network_ipv6:
file.managed:
- name : {{ dirs.sbin }}/ipv6-setup-tunnel
- source: salt://roles/core/network/files/ipv6-tunnels/{{ grains['id'] }}.sh.jinja
- template: jinja
- mode: 755
{% endif %}
# -------------------------------------------------------------
# Routes
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{% if salt['node.has']('network:ipv6_gateway') %}
{% if grains['os'] == 'FreeBSD' %}
/etc/rc.conf.d/routing/ipv6:
file.managed:
- source: salt://roles/core/network/files/FreeBSD/routing_ipv6.rc
- makedirs: True
- template: jinja
- context:
- ipv6_gateway: {{ network['ipv6_gateway'] }}
+ ipv6_gateway: {{ ipv6_gateway }}
{% endif %}
{% endif %}
diff --git a/roles/core/network/map.jinja b/roles/core/network/map.jinja
new file mode 100644
index 0000000..6cb6f46
--- /dev/null
+++ b/roles/core/network/map.jinja
@@ -0,0 +1,34 @@
+# -------------------------------------------------------------
+# 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",
+ },
+}) %}
diff --git a/roles/core/network/private.sls b/roles/core/network/private.sls
deleted file mode 100644
index 4c075a8..0000000
--- a/roles/core/network/private.sls
+++ /dev/null
@@ -1,41 +0,0 @@
-# -------------------------------------------------------------
-# Salt — Network
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-# Project: Nasqueron
-# Created: 2020-09-24
-# License: Trivial work, not eligible to copyright
-# -------------------------------------------------------------
-
-{% set network = salt['node.get']('network') %}
-
-# -------------------------------------------------------------
-# Interface
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-{% if salt['node.has']('network:private_interface') %}
-{% set interface = network['private_interface'] %}
-
-{% if grains['os'] == 'FreeBSD' %}
-/etc/rc.conf.d/netif/ipv4_{{ network['private_interface'] }}:
- file.managed:
- - source: salt://roles/core/network/files/FreeBSD/netif_ipv4.rc
- - makedirs: True
- - template: jinja
- - context:
- interface: {{ interface['device'] }}
- ipv4_address: {{ interface['address'] }}
- ipv4_netmask: {{ interface['netmask'] | default('255.255.255.0') }}
- ipv4_aliases: {{ salt['node.get_list']('network:private_interface:aliases') }}
-{% endif %}
-
-{% if grains['os_family'] == 'RedHat' %}
-/etc/sysconfig/network-scripts/ifcfg-{{ interface['device'] }}:
- file.managed:
- - source: salt://roles/core/network/files/RedHat/ifcfg-private
- - template: jinja
- - context:
- interface: {{ interface }}
- prefix: {{ salt['network_utils.netmask_to_cidr_prefix'](interface['netmask']) }}
-{% endif %}
-
-{% endif %}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Nov 25, 09:33 (1 d, 15 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2259689
Default Alt Text
(38 KB)

Event Timeline