Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F3768235
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
38 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Nov 25, 07:13 (1 d, 11 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2259689
Default Alt Text
(38 KB)
Attached To
Mode
rOPS Nasqueron Operations
Attached
Detach File
Event Timeline
Log In to Comment