diff --git a/README.rst b/README.rst index 2e836bf..e805ac1 100644 --- a/README.rst +++ b/README.rst @@ -727,6 +727,60 @@ Syndicated master with multiple master of masters: - host: master-of-master-host2 timeout: 5 +Dynamic DNS configuration +------------------------- + +Salt master can register minions in DNS server using DDNS (dynamic DNS) +update mechanism via salt.runners.ddns module. DNS server with dynamic +updates allowed is required. Authorization via {tsig-key} is available. +Recommended is DNS server configured via salt-formula-bind. +Mechanism uses event-reactor system. + +Master pillar: + +.. code-block:: yaml + + salt: + master: + ddns: + enabled: True + keys: + key: + name: + reactor: + dns/node/register: + - salt://salt/reactor/ddns_node_register.sls + dns/static/records: + - salt://salt/reactor/ddns_static_records.sls + +Minion pillar: + +.. code-block:: yaml + + salt: + minion: + ddns: + server: + keyname: + ttl: 300 + dns_static: + zone.example.com: + - name: appname + type: CNAME + value: appserver01 + + +Manual calling: + +.. code-block:: bash + + # Minion register + salt '*' state.apply salt.minion.dns_register + # + # Static DNS records + salt '*' state.apply salt.minion.dns_static + + Salt Minion ----------- diff --git a/metadata/service/minion/dns_register.yml b/metadata/service/minion/dns_register.yml new file mode 100644 index 0000000..471aedd --- /dev/null +++ b/metadata/service/minion/dns_register.yml @@ -0,0 +1,2 @@ +applications: +- salt.minion.dns_register diff --git a/metadata/service/minion/dns_static.yml b/metadata/service/minion/dns_static.yml new file mode 100644 index 0000000..43e85cf --- /dev/null +++ b/metadata/service/minion/dns_static.yml @@ -0,0 +1,2 @@ +applications: +- salt.minion.dns_static diff --git a/salt/control/virt.sls b/salt/control/virt.sls index 08e6158..0805b2d 100644 --- a/salt/control/virt.sls +++ b/salt/control/virt.sls @@ -20,7 +20,7 @@ update-guestfs-appliance: {%- if cluster.engine == "virt" %} -salt_libvirt_service: +salt_libvirt_service_{{ cluster_name }}: service.running: - name: {{ control.virt_service }} - enable: true @@ -108,7 +108,7 @@ salt_control_virt_{{ cluster_name }}_{{ node_name }}: {%- endif %} - unless: virsh list --all --name| grep -E "^{{ node_name }}.{{ cluster.domain }}$" - require: - - salt_libvirt_service + - salt_libvirt_service_{{ cluster_name }} {%- if node.get("autostart", True) %} diff --git a/salt/files/ddns.keyring b/salt/files/ddns.keyring new file mode 100644 index 0000000..5d41dfa --- /dev/null +++ b/salt/files/ddns.keyring @@ -0,0 +1,6 @@ +{%- from "salt/map.jinja" import master with context -%} +{ +{%- for key in master.ddns.get('keys', []) %} +"{{ key.name }}.": "{{ key.key }}"{{ "," if not loop.last else "" }} +{%- endfor %} +} diff --git a/salt/map.jinja b/salt/map.jinja index 71f50c1..56b3834 100644 --- a/salt/map.jinja +++ b/salt/map.jinja @@ -30,9 +30,13 @@ default: Arch: pkgs: - salt + ddns_pkgs: + - python-dnspython Debian: pkgs: - salt-master + ddns_pkgs: + - python-dnspython Gentoo: pkgs: - app-admin/salt @@ -42,6 +46,8 @@ MacOS: RedHat: pkgs: - salt-master + ddns_pkgs: + - python-dnspython {%- endload %} {%- if pillar.salt.master is defined %} diff --git a/salt/master/ddns.sls b/salt/master/ddns.sls new file mode 100644 index 0000000..e28b4bc --- /dev/null +++ b/salt/master/ddns.sls @@ -0,0 +1,14 @@ +{%- from "salt/map.jinja" import master with context %} +{%- if master.get('ddns', {}).get('enabled', False) %} +ddns_packages: + pkg.installed: + - names: {{ master.ddns_pkgs }} + +ddns_keys_file: + file.managed: + - name: /etc/salt/ddns.keyring + - source: salt://salt/files/ddns.keyring + - template: jinja + - mode: 600 + +{%- endif %} diff --git a/salt/master/init.sls b/salt/master/init.sls index 0352299..cdc2f92 100644 --- a/salt/master/init.sls +++ b/salt/master/init.sls @@ -3,6 +3,9 @@ include: {%- if pillar.salt.master.reactor is defined %} - salt.master.reactor {%- endif %} +{%- if pillar.salt.master.ddns is defined %} +- salt.master.ddns +{%- endif %} - salt.master.env - salt.master.pillar - salt.master.minion diff --git a/salt/minion/dns_register.sls b/salt/minion/dns_register.sls new file mode 100644 index 0000000..8e4eaee --- /dev/null +++ b/salt/minion/dns_register.sls @@ -0,0 +1,5 @@ +send_dns_register_event: + event.send: + - name: dns/node/register + - net_info: {{ pillar.linux.network.get('host', {}) }} + - ddns: {{ pillar.salt.minion.get('ddns', {}) }} diff --git a/salt/minion/dns_static.sls b/salt/minion/dns_static.sls new file mode 100644 index 0000000..859d809 --- /dev/null +++ b/salt/minion/dns_static.sls @@ -0,0 +1,5 @@ +send_dns_static_event: + event.send: + - name: dns/static/records + - records: {{ pillar.salt.minion.get('dns_static', {}) }} + - ddns: {{ pillar.salt.minion.get('ddns', {}) }} diff --git a/salt/minion/init.sls b/salt/minion/init.sls index 0575952..f5ddb85 100644 --- a/salt/minion/init.sls +++ b/salt/minion/init.sls @@ -14,3 +14,9 @@ include: {%- if pillar.salt.minion.env_vars is defined %} - salt.minion.env_vars {%- endif %} +{%- if pillar.salt.minion.ddns is defined %} +- salt.minion.dns_register +{%- if pillar.salt.minion.dns_static is defined %} +- salt.minion.dns_static +{%- endif %} +{%- endif %} diff --git a/salt/reactor/ddns_node_register.sls b/salt/reactor/ddns_node_register.sls new file mode 100644 index 0000000..2529eae --- /dev/null +++ b/salt/reactor/ddns_node_register.sls @@ -0,0 +1,19 @@ +{%- set ddns = data.data.get('ddns', {}) %} +{%- for rec_name, record in data.data.get('net_info', {}).iteritems() %} +{%- for name in record.get('names', []) if '.' in name %} +{%- set hostname, domain = name.split('.',1) %} + +ddns_node_register_{{ name }}_{{ loop.index }}: + runner.ddns.add_host: + - args: + - zone: {{ domain }} + - name: {{ hostname }} + - ttl: {{ ddns.get('ttl', 300) }} + - ip: {{ record.get('address', '127.0.0.127') }} + - keyname: {{ ddns.get('keyname', 'salt-updates') }} + - keyfile: /etc/salt/ddns.keyring + - nameserver: {{ ddns.get('server', '127.0.0.1') }} + - keyalgorithm: 'HMAC-MD5.SIG-ALG.REG.INT' + - timeout: 10 +{%- endfor %} +{%- endfor %} diff --git a/salt/reactor/ddns_static_records.sls b/salt/reactor/ddns_static_records.sls new file mode 100644 index 0000000..8f8be5e --- /dev/null +++ b/salt/reactor/ddns_static_records.sls @@ -0,0 +1,19 @@ +{%- set ddns = data.data.get('ddns', {}) %} +{%- for zone_name, zone in data.data.get('records', {}).iteritems() %} +{%- for record in zone %} + +ddns_record_{{ zone_name }}_{{ loop.index }}: + runner.ddns.create: + - args: + - zone: {{ zone_name }} + - name: {{ record['name'] }} + - ttl: {{ ddns.get('ttl', 300) }} + - rdtype: {{ record['type'] }} + - data: {{ record['value'] }} + - keyname: {{ ddns.get('keyname', 'salt-updates') }} + - keyfile: /etc/salt/ddns.keyring + - nameserver: {{ ddns.get('server', '127.0.0.1') }} + - timeout: 10 + - keyalgorithm: 'HMAC-MD5.SIG-ALG.REG.INT' +{%- endfor %} +{%- endfor %} diff --git a/tests/pillar/master_dns.sls b/tests/pillar/master_dns.sls new file mode 100644 index 0000000..7df614a --- /dev/null +++ b/tests/pillar/master_dns.sls @@ -0,0 +1,26 @@ +git: + client: + enabled: true +linux: + system: + enabled: true +salt: + master: + enabled: true + command_timeout: 5 + worker_threads: 2 + reactor_worker_threads: 2 + source: + engine: pkg + pillar: + engine: salt + source: + engine: local + ddns: + enabled: True + keys: + key: 'yEdG9/x8Sb+efi27GyeXNg==' + name: salt-updates + reactor: + dns/node/register: + - salt://salt/reactor/node_ddns_register.sls