224 lines
5.9 KiB
Plaintext
224 lines
5.9 KiB
Plaintext
# Mgmt
|
|
# Copyright (C) James Shubin and the project contributors
|
|
# Written by James Shubin <james@shubin.ca> and the project contributors
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
#
|
|
# Additional permission under GNU GPL version 3 section 7
|
|
#
|
|
# If you modify this program, or any covered work, by linking or combining it
|
|
# with embedded mcl code and modules (and that the embedded mcl code and
|
|
# modules which link with this program, contain a copy of their source code in
|
|
# the authoritative form) containing parts covered by the terms of any other
|
|
# license, the licensors of this program grant you additional permission to
|
|
# convey the resulting work. Furthermore, the licensors of this program grant
|
|
# the original author, James Shubin, additional permission to update this
|
|
# additional permission if he deems it necessary to achieve the goals of this
|
|
# additional permission.
|
|
|
|
import "deploy"
|
|
import "fmt"
|
|
import "golang"
|
|
import "local"
|
|
import "golang/strings" as golang_strings
|
|
import "os"
|
|
|
|
class server($st) {
|
|
$authoritative = $st->authoritative || true
|
|
$defaultleasetime = $st->defaultleasetime || 600
|
|
$maxleasetime = $st->maxleasetime || 7200
|
|
|
|
$tmpl = struct{
|
|
defaultleasetime => $defaultleasetime,
|
|
maxleasetime => $maxleasetime,
|
|
authoritative => $authoritative,
|
|
}
|
|
|
|
# TODO: add other os families and versions
|
|
$pkgs = {
|
|
"redhat" => "dhcp-server", # fedora
|
|
"debian" => "isc-dhcp-server", # debian
|
|
}
|
|
$pkg = $pkgs[os.family()] || ""
|
|
panic("${pkg}" == "") # not specified
|
|
pkg "${pkg}" {
|
|
state => "installed",
|
|
|
|
Before => File["/etc/dhcp/"],
|
|
}
|
|
|
|
file "/etc/dhcp/" {
|
|
state => $const.res.file.state.exists,
|
|
recurse => true,
|
|
purge => true,
|
|
owner => "root",
|
|
group => "root",
|
|
mode => "u=rwx,g=rx,o=", # dir
|
|
}
|
|
|
|
file "/etc/dhcp/dhcpd.conf" {
|
|
state => $const.res.file.state.exists,
|
|
content => golang.template(deploy.readfile("/files/dhcpd.conf.tmpl"), $tmpl),
|
|
owner => "root",
|
|
group => "root",
|
|
mode => "u=rw,go=",
|
|
|
|
Notify => Svc["dhcpd"],
|
|
}
|
|
|
|
svc "dhcpd" {
|
|
state => "running",
|
|
startup => "enabled",
|
|
}
|
|
|
|
$vardir = local.vardir("dhcp/")
|
|
|
|
include host_base
|
|
}
|
|
|
|
class server:subnet_base() {
|
|
file "${vardir}subnets.d/" {
|
|
state => $const.res.file.state.exists,
|
|
recurse => true,
|
|
purge => true,
|
|
owner => "root",
|
|
group => "root",
|
|
mode => "u=rwx,g=rx,o=", # dir
|
|
}
|
|
|
|
file "${vardir}subnets.header" {
|
|
state => $const.res.file.state.exists,
|
|
content => deploy.readfile("/files/subnets.header"), # static, no template!
|
|
owner => "root",
|
|
group => "root",
|
|
mode => "u=rw,go=",
|
|
}
|
|
|
|
|
|
file "/etc/dhcp/subnets.conf" {
|
|
state => $const.res.file.state.exists,
|
|
fragments => [
|
|
"${vardir}subnets.header",
|
|
"${vardir}subnets.d/",
|
|
],
|
|
|
|
Notify => Svc["dhcpd"],
|
|
}
|
|
}
|
|
|
|
class server:subnet($name, $st) {
|
|
include subnet_base
|
|
|
|
# TODO: We could compute many defaults from a single network CIDR.
|
|
|
|
$network str = $st->network # TODO: improve type unification
|
|
$netmask = $st->netmask || "255.255.255.0"
|
|
$broadcast = $st->broadcast || ""
|
|
$router = $st->router || "" # TODO: eventually this could be a list
|
|
$dns = $st->dns || [] # []str, local 'option domain-name-servers'
|
|
$range = $st->range || struct{start => "", end => "",} # struct with start, end fields
|
|
$range_start = $range->start || ""
|
|
$range_end = $range->end || ""
|
|
|
|
$comment = $st->comment || ""
|
|
|
|
$valid_range = if $range_start != "" and $range_end != "" {
|
|
"${range_start} ${range_end}"
|
|
} else {
|
|
"" # invalid
|
|
}
|
|
|
|
$tmpl = struct{
|
|
name => "${name}",
|
|
network => "${network}", # the subnet
|
|
netmask => "${netmask}",
|
|
broadcast => "${broadcast}",
|
|
router => "${router}", # TODO: support multiple
|
|
dns => golang_strings.join($dns, ", "),
|
|
range => $valid_range,
|
|
#nextserver => "${nextserver}",
|
|
#filename => "${filename}",
|
|
comment => "${comment}",
|
|
}
|
|
|
|
file "${vardir}subnets.d/${name}.subnet" {
|
|
state => $const.res.file.state.exists,
|
|
content => golang.template(deploy.readfile("/files/subnet.frag.tmpl"), $tmpl),
|
|
owner => "root",
|
|
group => "root",
|
|
mode => "u=rwx,g=rx,o=",
|
|
}
|
|
}
|
|
|
|
class server:host_base() {
|
|
file "${vardir}hosts.d/" {
|
|
state => $const.res.file.state.exists,
|
|
recurse => true,
|
|
purge => true,
|
|
owner => "root",
|
|
group => "root",
|
|
mode => "u=rwx,g=rx,o=", # dir
|
|
}
|
|
|
|
file "${vardir}hosts.header" {
|
|
state => $const.res.file.state.exists,
|
|
content => deploy.readfile("/files/hosts.header"), # static, no template!
|
|
owner => "root",
|
|
group => "root",
|
|
mode => "u=rw,go=",
|
|
}
|
|
|
|
|
|
file "/etc/dhcp/hosts.conf" {
|
|
state => $const.res.file.state.exists,
|
|
fragments => [
|
|
"${vardir}hosts.header",
|
|
"${vardir}hosts.d/",
|
|
],
|
|
|
|
Notify => Svc["dhcpd"],
|
|
}
|
|
}
|
|
|
|
class server:host($name, $st) {
|
|
include host_base
|
|
|
|
$macaddress = $st->macaddress
|
|
$fixedaddress = $st->fixedaddress # []str
|
|
$hostname = $st->hostname || ""
|
|
$nextserver = $st->nextserver || ""
|
|
$filename = $st->filename || ""
|
|
$comment = $st->comment || ""
|
|
|
|
$tmpl = struct{
|
|
name => "${name}",
|
|
macaddress => "${macaddress}",
|
|
valid_fixedaddress => golang_strings.join($fixedaddress, ","),
|
|
#fixedaddress => $fixedaddress, # TODO: when it's a list
|
|
hostname => "${hostname}",
|
|
nextserver => "${nextserver}",
|
|
filename => "${filename}",
|
|
veo => false, # TODO
|
|
comment => "${comment}",
|
|
}
|
|
|
|
file "${vardir}hosts.d/${name}.host" {
|
|
state => $const.res.file.state.exists,
|
|
content => golang.template(deploy.readfile("/files/host.frag.tmpl"), $tmpl),
|
|
owner => "root",
|
|
group => "root",
|
|
mode => "u=rwx,g=rx,o=",
|
|
}
|
|
}
|