From a1d319bd0d9d102dd9556d343bbed7fc67dc7a77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20Beaupr=C3=A9?= <anarcat@koumbit.org> Date: Mon, 23 Aug 2010 18:40:47 +0200 Subject: [PATCH] change the data structure storage to be more logical and efficient a complete zonefile can now be described like this: $zonefile = array('www' => array('a' => array('1.2.3.3', '1.2.3.4')), '@' => array('SOA' => array('hostmaster' => 'localhost', 'email' => 'admin.localhost', 'serial' => '2010082301', 'refresh' => 21600 3600 604800 86400 )'), 'A' => array('1.2.3.3'), 'MX' => array('mail.localhost'), 'NS' => array('localhost', 'ns2.localhost'), ) ); i had to change the provision storage class to merge with existing records in some cases for that to work. --- dns/NOTES | 20 ++++++++++++++++++- dns/bind/zone.tpl.php | 32 +++++++++++++++++++----------- dns/dns.config.inc | 8 ++------ dns/dns.drush.inc | 46 +++++++++++++++++++------------------------ provision.service.inc | 12 ++++++++++- 5 files changed, 73 insertions(+), 45 deletions(-) diff --git a/dns/NOTES b/dns/NOTES index 7e502e59b..834ce1c5d 100644 --- a/dns/NOTES +++ b/dns/NOTES @@ -24,10 +24,28 @@ Bugs: 1. since the rewrite of the parser, some fields in the SOA are missing (retry, refresh, etc) because we lack the context from the server (switching to create_config() shoudl fix that) + 2. there's a duplicate serial in PHP storage (patched?) + 3. the internal data structure is confusing and not efficient. here's + a proposed change: + +$zonefile = array('www' => array('a' => array('1.2.3.3', '1.2.3.4')), + '@' => array('SOA' => array('hostmaster' => 'localhost', 'email' => 'admin.localhost', 'serial' => '2010082301', 'refresh' => 21600 3600 604800 86400 )'), + 'A' => array('1.2.3.3'), + 'MX' => array('mail.localhost'), + 'NS' => array('localhost', 'ns2.localhost'), + ) + ); + (patched, needs testing and verification) + 4. removing the last record in a zonefile doesn't remove the zone + 5. removing records doesn't work either + 6. we increment the serial in two places, it seems Caveats: - 1. only targeting bind right now + 1. there's duplicate storage altogether: we could parse zonefiles and + use that as storage, not PHP files, but that would make switching + engines more difficult and would require writing parsers for all + engines. Todo: diff --git a/dns/bind/zone.tpl.php b/dns/bind/zone.tpl.php index 6eb4b3ffa..2b319f97b 100644 --- a/dns/bind/zone.tpl.php +++ b/dns/bind/zone.tpl.php @@ -4,29 +4,39 @@ $TTL <?php print $server->dns_ttl; ?> <?php -print("@ IN SOA $server->remote_host $dns_email - $serial ; serial +print("@ IN SOA $server->remote_host $dns_email ( + " . $records['@']['SOA']['serial'] . " ; serial $server->dns_refresh; refresh $server->dns_retry ; retry $server->dns_expire ; expire $server->dns_negativettl ; minimum )\n"); -?> +print "@\tIN\tNS\t" . $server->remote_host . " ; primary DNS\n"; - IN NS <?php print $server->remote_host ?>. ; primary DNS - IN NS ns2.example.com. ; secondary DNS - IN MX 10 <?php print $server->remote_host ?>. ; external mail provider -; non server domain hosts -<?php +foreach ($server->dns_slaves as $slave) { + print "@\tIN\tNS\t$slave ; slave DNS\n"; +} -foreach ($records['A'] as $ip) { - print " IN A {$ip}\n"; +foreach ($records['@'] as $type => $destinations) { + if ($type != 'SOA' && $type != 'NS') { + foreach ($destinations as $destination) { + print "@\tIN\t$type\t$destination\n"; + } + } } +foreach ($records as $name => $record) { + if ($name != '@') { + foreach ($record as $type => $destinations) { + foreach ($destinations as $destination) { + print "$name\tIN\t$type\t$destination\n"; + } + } + } +} foreach ($hosts as $host => $info) { foreach ($info['A'] as $ip) { print "{$info['sub']} IN A {$ip}\n"; } } -?> diff --git a/dns/dns.config.inc b/dns/dns.config.inc index 322860e95..9a5a5561e 100644 --- a/dns/dns.config.inc +++ b/dns/dns.config.inc @@ -95,13 +95,9 @@ class provisionConfig_dns_zone extends provisionConfig_dns { $this->data['dns_email'] = str_replace('@', '.', $this->data['server']->admin_email); // increment the serial. - $this->store->records['serial'] = $this->data['serial'] = provisionService_dns::increment_serial($records['serial']); + $this->store->records['@']['SOA']['serial'] = $records['serial'] = provisionService_dns::increment_serial($records['@']['SOA']['serial']); - foreach ($records as $key => $record) { - if (preg_match('/^host:/', $key)) { - $this->data['hosts'][$record['host']] = $record; - } - } + $this->data['records'] = $records; } function write() { diff --git a/dns/dns.drush.inc b/dns/dns.drush.inc index fdfe2351d..75de93205 100644 --- a/dns/dns.drush.inc +++ b/dns/dns.drush.inc @@ -14,6 +14,7 @@ include_once(dirname(__FILE__) . '/../provision.service.inc'); /** * Implementation of hok_drush_command(). + */ function dns_drush_command() { $items['provision-zone'] = array( 'arguments' => array('operation' => dt('The operation to perform on a zone (verify, delete, rr-add, rr-delete)')), @@ -39,18 +40,14 @@ function drush_dns_provision_zone($action, $zone, $name = null, $type = null, $d $status = d()->service('dns')->delete_zone($zone); break; case 'rr-add': - d()->service('dns')->config('zone', $zone)->record_set("host:$host", array( - 'sub' => $sub, - 'A' => $ips, - 'host' => $host, - )); - $status = d()->service('dns')->add_record($zone, $name, $type, $destination); + $record = d()->service('dns')->config('zone', $zone)->record_get($name); + $record[$type] = array_merge($record[$type], array($destination)); + d()->service('dns')->config('zone', $zone)->record_set($name, $record)->write(); break; case 'rr-modify': - $status = d()->service('dns')->modify_record($zone, $name, $type, $destination); + d()->service('dns')->config('zone', $zone)->record_set($name, array($type => array($destination)))->write(); break; case 'rr-delete': - $status = d()->service('dns')->delete_record($zone, $name, $type, $destination); break; } $status = $status && d()->service('dns')->commit($zone); @@ -58,8 +55,6 @@ function drush_dns_provision_zone($action, $zone, $name = null, $type = null, $d return $status; } - */ - function dns_provision_services() { return array('dns' => NULL); } @@ -236,8 +231,7 @@ class provisionService_dns extends provisionService { $this->config('server')->record_set($zone, $zone)->write(); - $soa['serial'] = $this->increment_serial($soa['serial']); - $this->config('zone', $zone)->record_set('soa', $soa)->write(); + $this->config('zone', $zone)->record_set('serial', $this->increment_serial())->write(); } /** @@ -278,19 +272,17 @@ class provisionService_dns extends provisionService { $ips = array('127.0.0.1'); } - if (is_array($ips)) { - if ($sub) { - $this->config('zone', $zone)->record_set("host:$host", array( - 'sub' => $sub, - 'A' => $ips, - 'host' => $host, - )); - } - else { - $this->config('zone', $zone)->record_set("A", $ips); - } + // XXX: kill me? + if (!is_array($ips)) { + $ips = array($ips); // backward compatibility? + } + + if (empty($sub)) { + $sub = '@'; } - + drush_log("zone: $zone, sub: $sub"); + $this->config('zone', $zone)->record_set($sub, array('A' => $ips)); + $this->create_zone($zone); $this->create_config('host'); } @@ -320,9 +312,11 @@ class provisionService_dns extends provisionService { // remove the records from the zone store $this->config('zone', $zone)-> - record_del("host:$host"); + record_set($host, array('A' => null)); - $this->create_zone($zone); + // XXX: need to guess the number of records left now and remove only if + // there are no more records + //$this->delete_zone($zone); $this->delete_config('host'); } diff --git a/provision.service.inc b/provision.service.inc index 4f9d870c6..92ecd725b 100644 --- a/provision.service.inc +++ b/provision.service.inc @@ -131,7 +131,17 @@ class provisionService extends provisionChainedState { $this->_config->store->records = array_merge($this->_config->store->records, $arg1); } elseif (!is_numeric($arg1)) { - $this->_config->store->records[$arg1] = $arg2; + if (is_array($arg2)) { + if (!is_array($this->_config->store->loaded_records[$arg1])) { + $this->_config->store->loaded_records[$arg1] = array(); + } + if (!is_array($this->_config->store->records[$arg1])) { + $this->_config->store->records[$arg1] = array(); + } + $this->_config->store->records[$arg1] = array_merge($this->_config->store->loaded_records[$arg1], $this->_config->store->records[$arg1], $arg2); + } else { + $this->_config->store->records[$arg1] = $arg2; + } } } } -- GitLab