Commit 767c8827 authored by anarcat's avatar anarcat Committed by Adrian Rossouw

make SOA parsing work properly, implement add_line so record edition works

parent 40924800
......@@ -18,7 +18,7 @@ class provisionService_dns_bind extends provisionService_dns {
function init() {
parent::init();
$this->server->setProperty('bind_conf_path', $this->server->config_path . '/bind.d/');
$this->server->setProperty('bind_conf_path', $this->server->config_path . '/bind.conf');
$this->server->setProperty('bind_zone_master_path', $this->server->config_path . '/zones/master');
$this->server->setProperty('bind_restart_cmd', _bind_default_restart_cmd());
}
......@@ -32,7 +32,6 @@ class provisionService_dns_bind extends provisionService_dns {
}
function verify() {
provision_file()->create_dir($this->server->bind_conf_path, dt("Bind configuration"), 0700);
provision_file()->create_dir($this->server->bind_zone_master_path, dt("Bind zone files"), 0700);
}
......@@ -49,33 +48,38 @@ class provisionService_dns_bind extends provisionService_dns {
function create_zone($zonename) {
$zone = new provisionConfig_bind_zone($this->context, array('name' => $zonename));
if (!$zone->exists() || drush_get_option('force')) {
if (!$zone->exists()) {
drush_log("creating zone");
//$zone->add_line_if_not_exists($zone->zone_declaration(), '/zone\s*"'. $zonename . '"/');
$zone->write();
foreach (array('ttl', 'serial', 'refresh', 'retry', 'expire', 'negativettl') as $param) {
if (isset($zone->data[$param])) {
drush_log("got param $param from zone, value: " . $zone->data[$param]);
if ($param == 'serial') {
$this->$param = provisionService_dns::increment_serial($zone->data['serial']);
} else {
$this->$param = $zone->data[$param];
}
} else {
if ($param == 'serial') {
$this->$param = provisionService_dns::increment_serial();
} else {
$longparam = "dns_" . $param;
$this->$param = $this->server->$longparam;
}
drush_log("param $param missing from zone, using default: " . $this->$param);
}
}
parent::create_zone($zonename);
} else {
drush_log("zone already exists");
}
$this->load_from_zone($zone);
parent::create_zone($zonename);
}
function load_from_zone($zone) {
// load parameters from zone
foreach (array('ttl', 'serial', 'refresh', 'retry', 'expire', 'negativettl') as $param) {
if (isset($zone->data[$param])) {
drush_log("got param $param from zone, value: " . $zone->data[$param]);
if ($param == 'serial') {
$this->$param = provisionService_dns::increment_serial($zone->data['serial']);
} else {
$this->$param = $zone->data[$param];
}
} else {
if ($param == 'serial') {
$this->$param = provisionService_dns::increment_serial();
} else {
$longparam = "dns_" . $param;
$this->$param = $this->server->$longparam;
}
drush_log("param $param missing from zone, using default: " . $this->$param);
}
}
}
function delete_zone($zonename) {
......@@ -88,7 +92,7 @@ class provisionService_dns_bind extends provisionService_dns {
function add_record($zonename, $name, $destination, $type = 'A') {
$zone = new provisionConfig_bind_zone($this->context, array('name' => $zonename));
if ($type == 'SOA') { // only one SOA per file
return $zone->add_line_if_not_exists($name . ' IN SOA ' . $destination, 'SOA');
return $zone->add_line_if_not_exists($name . ' IN SOA ' . $destination, '/(?:@\s+)?IN\s+SOA\s+/');
} else {
return $zone->add_line($name . "\tIN\t" . $type . "\t" . $destination);
}
......@@ -96,11 +100,11 @@ class provisionService_dns_bind extends provisionService_dns {
function edit_record($zonename, $name, $destination, $type = 'A') {
$zone = new provisionConfig_bind_zone($this->context, array('name' => $zonename));
if ($type == 'SOA') { // only one SOA per file
return $zone->add_line_if_not_exists($name . ' IN SOA ' . $destination, '/\sIN\sSOA\s/');
} else {
return $zone->replace_line($name . "\tIN\t" . $type . "\t" . $destination, "/^$name\s\s*IN\s\s*$type\s\s*");
$pattern = "/^\s*$name\s+IN\s+$type\s+.*$/im";
if ($type == 'SOA') {
$pattern = "/^(?:@\s+)?IN\s+SOA\s+[\w.]+\s+[\w.]+\s+\(([^)]*)\)\s*$/ims";
}
return $zone->replace_or_add_line($name . "\tIN\t" . $type . "\t" . $destination, $pattern);
}
function delete_record($zonename, $name, $destination = null, $type = null) {
......@@ -203,6 +207,41 @@ class provisionConfig_bind_zone extends provisionConfig {
return $found;
}
/**
* add a line to a file if the file (or pattern) is not in the file
* already
*
* This is bound to be called repeatedly so it needs to be fast.
*/
function add_line($line) {
$file = $this->filename();
// XXX: we should do exponential backoff here to limit contention
$fd = fopen($file, 'a'); // read/write, beginning of file
flock($fd, LOCK_EX);
$line = trim($line);
fwrite($fd, $line . "\n");
fclose($fd);
}
function replace_or_add_line($replacement, $pattern) {
$file = $this->filename();
$fd = fopen($file, 'r+');
flock($fd, LOCK_EX);
$body = fread($fd, filesize($file));
$newbody = preg_replace($pattern, $replacement, $body);
if ($body === $newbody) {
drush_log("pattern $pattern not found in $file, adding at the end");
fseek($fd, 0, SEEK_END);
fwrite($fd, $replacement . "\n");
} else {
drush_log("pattern $pattern found and replaced with $replacement");
fseek($fd, 0);
fwrite($fd, $newbody);
ftruncate($fd, strlen($newbody));
}
fclose($fd);
}
function zone_declaration() {
return 'zone "' . $this->data['name'] . '" { type master; file "' . $this->filename() . '"; allow-query { any; }; };';
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment