示例#1
0
function domain_server_del($options = "")
{
    // The important globals
    global $conf, $self, $onadb;
    // Version - UPDATE on every edit!
    $version = '1.02';
    printmsg("DEBUG => domain_server_del({$options}) called", 3);
    // Parse incoming options string to an array
    $options = parse_options($options);
    // Sanitize options[commit] (default is yes)
    $options['commit'] = sanitize_YN($options['commit'], 'N');
    // Return the usage summary if we need to
    if ($options['help'] or !($options['domain'] and $options['server'])) {
        // NOTE: Help message lines should not exceed 80 characters for proper display on a console
        $self['error'] = 'ERROR => Insufficient parameters';
        return array(1, <<<EOM

domain_server_del-v{$version}
Removes a domain record from a DNS server

  Synopsis: domain_server_del [KEY=VALUE] ...

  Required:
    domain=NAME or ID               domain name or ID
    server=NAME[.DOMAIN] or ID      server name or ID

  Optional:
    commit=[Y|N]                    commit db transaction (no)

EOM
);
    }
    if (is_numeric($options['domain'])) {
        $domainsearch['id'] = $options['domain'];
    } else {
        $domainsearch['name'] = strtoupper($options['domain']);
    }
    // Determine the entry itself exists
    list($status, $rows, $domain) = ona_get_domain_record($domainsearch);
    // Test to see that we were able to find the specified record
    if (!$domain['id']) {
        printmsg("DEBUG => Unable to find the domain record using {$options['domain']}!", 3);
        $self['error'] = "ERROR => Unable to find the domain record using {$options['domain']}!";
        return array(4, $self['error'] . "\n");
    }
    printmsg("DEBUG => domain_server_del(): Found domain, {$domain['name']}", 3);
    if ($options['server']) {
        // Determine the server is valid
        list($status, $rows, $host) = ona_find_host($options['server']);
        if (!$host['id']) {
            printmsg("DEBUG => The server ({$options['server']}) does not exist!", 3);
            $self['error'] = "ERROR => The server specified, {$options['server']}, does not exist!";
            return array(2, $self['error'] . "\n");
        }
    }
    // Test that this domain is even assigned to the server
    list($status, $rows, $domainserver) = ona_get_dns_server_domain_record(array('host_id' => $host['id'], 'domain_id' => $domain['id']));
    if (!$rows) {
        printmsg("DEBUG => Unable to find {$domain['name']} on server {$host['fqdn']}", 3);
        $self['error'] = "ERROR => Unable to find {$domain['name']} on server {$host['fqdn']}";
        return array(11, $self['error'] . "\n");
    }
    // Test that there are no NS records for this pair
    // ASSUMPTION: MP this will always be just one record??
    // depending on how the user has their NS records set up, we may not find anything.
    list($status, $dnsrows, $dnsrec) = db_get_record($onadb, 'dns', "domain_id = {$domain['id']} AND type = 'NS' AND interface_id in (select id from interfaces where host_id = {$host['id']})");
    // If "commit" is yes, delete the record
    if ($options['commit'] == 'Y') {
        // Check permissions
        if (!auth('advanced') or !authlvl($host['LVL']) or !authlvl($domain['LVL'])) {
            $self['error'] = "Permission denied!";
            printmsg($self['error'], 0);
            return array(10, $self['error'] . "\n");
        }
        // delete record from domain_server_domains
        list($status, $rows) = db_delete_records($onadb, 'dns_server_domains', array('id' => $domainserver['id']));
        if ($status) {
            $self['error'] = "ERROR => domain_server_del() SQL Query failed:" . $self['error'];
            printmsg($self['error'], 0);
            return array(9, $self['error'] . "\n");
        }
        // Run the module to delete the associated NS record.. Only if we found a dns record for NS
        if ($dnsrec['id']) {
            list($status, $output) = run_module('dns_record_del', array('name' => $dnsrec['id'], 'type' => 'NS', 'commit' => 'Y'));
            if ($status) {
                $self['error'] = "ERROR => domain_server_del() NS record delete failed:" . $output;
                printmsg($self['error'], 0);
                return array(9, $self['error'] . "\n");
            } else {
                // add the output to self error for display
                $add_to_error = $output;
            }
        }
        // Return the success notice
        $self['error'] = "INFO => DNS Domain/Server Pair DELETED: {$domain['name']}/{$host['fqdn']} ";
        printmsg($self['error'], 0);
        return array(0, $add_to_error . $self['error'] . "\n");
    }
    // Otherwise display the record that would have been deleted
    $text = <<<EOL
    Record(s) NOT DELETED (see "commit" option)
    Displaying record(s) that would have been removed:

    {$domain['name']} from: {$host['fqdn']}


EOL;
    if ($dnsrows) {
        $text .= "    Removing related NS record, if any. Please double check your NS records for this domain.\n";
    }
    return array(6, $text);
}
示例#2
0
function dns_record_del($options = "")
{
    global $conf, $self, $onadb;
    printmsg("DEBUG => dns_record_del({$options}) called", 3);
    // Version - UPDATE on every edit!
    $version = '1.03';
    // Parse incoming options string to an array
    $options = parse_options($options);
    // Sanitize options[commit] (default is no)
    $options['commit'] = sanitize_YN($options['commit'], 'N');
    // Return the usage summary if we need to
    if ($options['help'] or !$options['name']) {
        // NOTE: Help message lines should not exceed 80 characters for proper display on a console
        $self['error'] = 'ERROR => Insufficient parameters';
        return array(1, <<<EOM

dns_record_del-v{$version}
Deletes a DNS record from the database

  Synopsis: dns_record_del [KEY=VALUE] ...

  Required:
    name=NAME[.DOMAIN] or ID      hostname or ID of the record to delete
    type=TYPE                     record type (A,CNAME,PTR...)

  Optional:
    ip=ADDRESS                    ip address (numeric or dotted)
    commit=[yes|no]               commit db transaction (no)



EOM
);
    }
    /*
    thoughts on the flow of things:
    A records:
        remove any CNAMES using this A record
        remove any PTR records using this A record
        test that it is not a primary_dns_id, if it is, it must be reassigned
    should make a find_dns_record(s) function.  a find by host option would be good.
    need to do a better delete of DNS records when deleting a host.. currently its a problem.
    MP: TODO:  this delete will not handle DNS views unless you use the ID of the record to delete.  add a view option at some point.
    */
    // If the name we were passed has a leading . in it then remove the dot.
    $options['name'] = preg_replace("/^\\./", '', $options['name']);
    // FIXME: MP Fix this to use a find_dns_record function  ID only for now
    // Find the DNS record from $options['name']
    list($status, $rows, $dns) = ona_find_dns_record($options['name'], $options['type']);
    printmsg("DEBUG => dns_record_del() DNS record: {$options['name']}", 3);
    if (!$dns['id']) {
        printmsg("DEBUG => Unknown DNS record: {$options['name']} ({$options['type']})", 3);
        $self['error'] = "ERROR => Unknown DNS record: {$options['name']} ({$options['type']})";
        return array(2, $self['error'] . "\n");
    }
    // Check permissions
    if (!auth('host_del') or !authlvl($host['LVL'])) {
        $self['error'] = "Permission denied!";
        printmsg($self['error'], 0);
        return array(10, $self['error'] . "\n");
    }
    // If "commit" is yes, delete the host
    if ($options['commit'] == 'Y') {
        $text = "";
        $add_to_error = "";
        // SUMMARY:
        //   Display any associated PTR records for an A record
        //   Display any associated CNAMEs for an A record
        // Test if it is used as a primary_dns_id unless it is the host_del module calling
        if (!isset($options['delete_by_module'])) {
            list($status, $rows, $srecord) = db_get_record($onadb, 'hosts', array('primary_dns_id' => $dns['id']));
            if ($rows) {
                $self['error'] = "ERROR => dns_record_del() The DNS record, {$dns['name']}.{$dns['domain_fqdn']}[{$dns['id']}], is a primary A record for a host! You can not delete it until you associate a new primary record, or delete the host.";
                printmsg($self['error'], 0);
                return array(5, $self['error'] . "\n");
            }
        }
        // Delete related Points to records
        // get list for logging
        list($status, $rows, $records) = db_get_records($onadb, 'dns', array('dns_id' => $dns['id']));
        // do the delete
        list($status, $rows) = db_delete_records($onadb, 'dns', array('dns_id' => $dns['id']));
        if ($status) {
            $self['error'] = "ERROR => dns_record_del() Child record delete SQL Query failed: {$self['error']}";
            printmsg($self['error'], 0);
            return array(5, $self['error'] . "\n");
        }
        if ($rows) {
            // log deletions
            // FIXME: do better logging here
            printmsg("INFO => {$rows} child DNS record(s) DELETED from {$dns['fqdn']}", 0);
            $add_to_error .= "INFO => {$rows} child record(s) DELETED from {$dns['fqdn']}\n";
        }
        // TRIGGER: flag the domains for rebuild
        foreach ($records as $record) {
            list($status, $rows) = db_update_record($onadb, 'dns_server_domains', array('domain_id' => $record['domain_id']), array('rebuild_flag' => 1));
            if ($status) {
                $self['error'] = "ERROR => dns_record_del() Unable to update rebuild flags for domain.: {$self['error']}";
                printmsg($self['error'], 0);
                return array(7, $self['error'] . "\n");
            }
        }
        // Delete the DNS record
        list($status, $rows) = db_delete_records($onadb, 'dns', array('id' => $dns['id']));
        if ($status) {
            $self['error'] = "ERROR => dns_record_del() DNS record delete SQL Query failed: {$self['error']}";
            printmsg($self['error'], 0);
            return array(5, $add_to_error . $self['error'] . "\n");
        }
        // TRIGGER: flag the current dnsrecords domain for rebuild
        list($status, $rows) = db_update_record($onadb, 'dns_server_domains', array('domain_id' => $dns['domain_id']), array('rebuild_flag' => 1));
        if ($status) {
            $self['error'] = "ERROR => dns_record_del() Unable to update rebuild flags for domain.: {$self['error']}";
            printmsg($self['error'], 0);
            return array(7, $self['error'] . "\n");
        }
        // FIXME: if it is a NS or something display a proper FQDN message here
        // Display proper PTR information
        if ($dns['type'] == 'PTR') {
            list($status, $rows, $pointsto) = ona_get_dns_record(array('id' => $dns['dns_id']), '');
            list($status, $rows, $ptrint) = ona_get_interface_record(array('id' => $dns['interface_id']), '');
            $ipflip = ip_mangle($ptrint['ip_addr'], 'flip');
            $octets = explode(".", $ipflip);
            if (count($octets) > 4) {
                $arpa = '.ip6.arpa';
                $octcount = 31;
            } else {
                $arpa = '.in-addr.arpa';
                $octcount = 3;
            }
            $dns['fqdn'] = "{$ipflip}{$arpa} -> {$pointsto['fqdn']}";
        }
        // Return the success notice
        $self['error'] = "INFO => DNS {$dns['type']} record DELETED: {$dns['fqdn']}";
        printmsg($self['error'], 0);
        return array(0, $add_to_error . $self['error'] . "\n");
    }
    //
    // We are just displaying records that would have been deleted
    //
    // SUMMARY:
    //   Display any associated PTR records for an A record
    //   Display any associated CNAMEs for an A record
    // Otherwise just display the host record for the host we would have deleted
    $text = "Record(s) NOT DELETED (see \"commit\" option)\n" . "Displaying record(s) that would have been deleted:\n";
    // Test if it is used as a primary_dns_id
    list($status, $rows, $srecord) = db_get_record($onadb, 'hosts', array('primary_dns_id' => $dns['id']));
    if ($rows) {
        $text .= "\nWARNING!  This DNS record is a primary A record for a host\n";
    }
    // Display the complete dns record
    list($status, $tmp) = dns_record_display("name={$dns['id']}&verbose=N");
    $text .= "\n" . $tmp;
    // Display associated Child records
    list($status, $rows, $records) = db_get_records($onadb, 'dns', array('dns_id' => $dns['id']));
    if ($rows) {
        $text .= "\nASSOCIATED POINTS-TO RECORDS ({$rows}):\n";
    }
    foreach ($records as $record) {
        if ($record['type'] == 'NS') {
            $record['name'] = '';
        }
        // FIXME:I could fix this but I'm lazy
        if ($record['type'] == 'PTR') {
            $record['name'] = '??';
        }
        list($status, $rows, $domain) = ona_get_domain_record(array('id' => $record['domain_id']), '');
        $text .= " {$record['type']}: {$record['name']}.{$domain['fqdn']} -> {$dns['fqdn']}\n";
    }
    return array(7, $text);
}
示例#3
0
function ws_delete_configs($window_name, $form = '')
{
    global $conf, $self, $onadb;
    global $images, $color, $style;
    // If the user supplied an array in a string, build the array and store it in $form
    $form = parse_options_string($form);
    // Load the host record
    list($status, $rows, $host) = ona_find_host($form['host_id']);
    if (!$host['id']) {
        array_pop($_SESSION['ona']['work_space']['history']);
        $html .= "<br><center><font color=\"red\"><b>Host doesn't exist!</b></font></center>";
        $response = new xajaxResponse();
        $response->addAssign("work_space_content", "innerHTML", $html);
        return $response->getXML();
    }
    // Check permissions
    if (!(auth('host_config_admin') and authlvl($host['lvl']))) {
        $response = new xajaxResponse();
        $response->addScript("alert('Permission denied!');");
        return $response->getXML();
    }
    // Load the config type
    list($status, $rows, $type) = ona_get_config_type_record(array('id' => $form['type_id']));
    if ($status or !$rows) {
        $response = new xajaxResponse();
        $response->addScript("alert('ERROR => Invalid config type!');");
        return $response->getXML();
    }
    // Delete the config text records that match
    // FIXME, this should probably use a module, but there isn't one!
    list($status, $rows) = db_delete_records($onadb, 'configurations', array('host_id' => $host['id'], 'configuration_type_id' => $type['id']));
    if ($status or !$rows) {
        $response = new xajaxResponse();
        $response->addScript("alert('Delete failed!');");
        return $response->getXML();
    }
    // Insert the new html into the window
    // Instantiate the xajaxResponse object
    $response = new xajaxResponse();
    if ($form['js']) {
        $response->addScript($form['js']);
    }
    return $response->getXML();
}
示例#4
0
function dhcp_server_del($options = "")
{
    // The important globals
    global $conf, $self, $onadb;
    // Version - UPDATE on every edit!
    $version = '1.03';
    printmsg("DEBUG => dhcp_server_del({$options}) called", 3);
    // Parse incoming options string to an array
    $options = parse_options($options);
    // Sanitize options[commit] (default is yes)
    $options['commit'] = sanitize_YN($options['commit'], 'N');
    // Return the usage summary if we need to
    if ($options['help'] or !($options['subnet'] and $options['server'])) {
        // NOTE: Help message lines should not exceed 80 characters for proper display on a console
        $self['error'] = 'ERROR => Insufficient parameters';
        return array(1, <<<EOM

dhcp_server_del-v{$version}
Removes a subnet record from a DHCP server

  Synopsis: dhcp_server_del [KEY=VALUE] ...

  Required:
    subnet=NAME or ID               subnet name or ID
    server=NAME[.DOMAIN] or ID      server name or ID

  Optional:
    commit=[Y|N]                    commit db transaction (no)

  Notes:
    DOMAIN will default to {$conf['dns_defaultdomain']} if not specified


EOM
);
    }
    // Determine the entry itself exists
    list($status, $rows, $subnet) = ona_find_subnet($options['subnet']);
    // Test to see that we were able to find the specified record
    if (!$subnet['id']) {
        printmsg("DEBUG => Unable to find the subnet record using {$options['subnet']}!", 3);
        $self['error'] = "ERROR => Unable to find the subnet record using {$options['subnet']}!";
        return array(4, $self['error'] . "\n");
    }
    printmsg("DEBUG => dhcp_server_del(): Found subnet, {$subnet['name']}", 3);
    if ($options['server']) {
        // Determine the server is valid
        list($status, $rows, $host) = ona_find_host($options['server']);
        if (!$host['id']) {
            printmsg("DEBUG => The server ({$options['server']}) does not exist!", 3);
            $self['error'] = "ERROR => The server specified, {$options['server']}, does not exist!";
            return array(2, $self['error'] . "\n");
        }
    }
    //printmsg("DEBUG => dhcp_server_del(): Found server, {$host['FQDN']}", 3);
    // Test that this subnet is even assigned to the server
    list($status, $rows, $dhcpserver) = ona_get_dhcp_server_subnet_record(array('host_id' => $host['id'], 'subnet_id' => $subnet['id']));
    if (!$rows) {
        printmsg("DEBUG => Unable to find {$subnet['name']} on server {$host['fqdn']}", 3);
        $self['error'] = "ERROR => Unable to find {$subnet['name']} on server {$host['fqdn']}";
        return array(11, $self['error'] . "\n");
    }
    // If "commit" is yes, delete the record
    if ($options['commit'] == 'Y') {
        // Check permissions
        if (!auth('advanced') or !authlvl($host['LVL']) or !authlvl($subnet['LVL'])) {
            $self['error'] = "Permission denied!";
            printmsg($self['error'], 0);
            return array(10, $self['error'] . "\n");
        }
        // check if allowed to remove subnet from server
        // check for pool assigned to the server itself
        list($status, $rows, $pools) = db_get_records($onadb, 'dhcp_pools', array('subnet_id' => $subnet['id']));
        foreach ($pools as $pool) {
            if ($pool['dhcp_failover_group_id']) {
                $foundfg = 0;
                list($status, $rows, $primary) = ona_get_dhcp_failover_group_record(array('id' => $pool['dhcp_failover_group_id'], 'primary_server_id' => $host['id']));
                if ($rows) {
                    $foundfg++;
                }
                list($status, $rows, $secondary) = ona_get_dhcp_failover_group_record(array('id' => $pool['dhcp_failover_group_id'], 'secondary_server_id' => $host['id']));
                if ($rows) {
                    $foundfg++;
                }
                // if a subnet/server pair is found in dhcp pools, don't allow removal
                if ($foundfg > 0) {
                    printmsg("DEBUG => Subnet ({$subnet['name']}) has a pool assigned to this Server ({$host['fqdn']}), which is part of a failover group.  The server must be removed from the failover group first.", 3);
                    $self['error'] = "ERROR => Subnet ({$subnet['name']}) has a pool assigned to this Server ({$host['fqdn']}), which is part of a failover group.  The server must be removed from the failover group first.";
                    return array(12, $self['error'] . "\n");
                }
            }
        }
        // MP: remove this after testing.  dhcp options should not stop us from dis-associating a subnet from a server
        //     Not really sure why I have this.. probably left over cruft from old thoughts
        //         // check if there are any DHCP parameters assigned to the subnet
        //         list($status, $rows, $tmp) = ona_get_dhcp_option_entry_record(array('subnet_id' => $subnet['id']));
        //
        //         // if so, check that this is not the last DHCP server that services this subnet
        //         if ($rows > 0) {
        //             list($status, $rows, $tmp) = ona_get_dhcp_server_subnet_record(array('subnet_id' => $subnet['id']));
        //
        //             // If this is the last DHCP server that services this subnet, don't allow removal until DHCP parameters are removed
        //             if($rows <= 1){
        //                 printmsg("DEBUG => Subnet ({$subnet['name']}) has DHCP parameters assigned which need to be removed first",3);
        //                 $self['error'] = "ERROR => Subnet ({$subnet['name']}) has DHCP parameters assigned which need to be removed first";
        //                 return(array(12, $self['error'] . "\n"));
        //             }
        //         }
        // delete record from dhcp_server_subnets
        list($status, $rows) = db_delete_records($onadb, 'dhcp_server_subnets', array('id' => $dhcpserver['id']));
        if ($status) {
            $self['error'] = "ERROR => dhcp_server_del() SQL Query failed:" . $self['error'];
            printmsg($self['error'], 0);
            return array(9, $self['error'] . "\n");
        }
        // Return the success notice
        $self['error'] = "INFO => DHCP Subnet/Server Pair DELETED: {$subnet['name']}/{$host['fqdn']} ";
        printmsg($self['error'], 0);
        return array(0, $self['error'] . "\n");
    }
    // Otherwise display the record that would have been deleted
    $text = <<<EOL
    Record(s) NOT DELETED (see "commit" option)
    Displaying record(s) that would have been removed:

    {$subnet['name']} from: {$host['fqdn']}

EOL;
    return array(6, $text);
}
示例#5
0
文件: host.inc.php 项目: edt82/ona
function host_del($options = "")
{
    global $conf, $self, $onadb;
    printmsg("DEBUG => host_del({$options}) called", 3);
    // Version - UPDATE on every edit!
    $version = '1.19';
    // Parse incoming options string to an array
    $options = parse_options($options);
    // Sanitize options[commit] (default is no)
    $options['commit'] = sanitize_YN($options['commit'], 'N');
    // Return the usage summary if we need to
    if ($options['help'] or !$options['host']) {
        // NOTE: Help message lines should not exceed 80 characters for proper display on a console
        $self['error'] = 'ERROR => Insufficient parameters';
        return array(1, <<<EOM

host_del-v{$version}
Deletes a host, and all related records from the database

  Synopsis: host_del [KEY=VALUE] ...

  Required:
    host=NAME[.DOMAIN] or ID      Hostname or ID of the host to delete

  Optional:
    commit=[yes|no]               Commit db transaction (no)

  Notes:
    * A host won't be deleted if it has config text records
    * A host won't be deleted if it's configured as a dns or dhcp server


EOM
);
    }
    // Find the host (and domain) record from $options['host']
    list($status, $rows, $host) = ona_find_host($options['host']);
    printmsg("DEBUG => host_del() Host: {$host['fqdn']} ({$host['id']})", 3);
    if (!$host['id']) {
        printmsg("DEBUG => Unknown host: {$host['fqdn']}", 3);
        $self['error'] = "ERROR => Unknown host: {$host['fqdn']}";
        return array(2, $self['error'] . "\n");
    }
    // Check permissions
    if (!auth('host_del') or !authlvl($host['LVL'])) {
        $self['error'] = "Permission denied!";
        printmsg($self['error'], 0);
        return array(10, $self['error'] . "\n");
    }
    // If "commit" is yes, delete the host
    if ($options['commit'] == 'Y') {
        $text = "";
        $add_to_error = "";
        $add_to_status = 0;
        // SUMMARY:
        //   Don't allow a delete if it is performing server duties
        //   Don't allow a delete if config text entries exist
        //   Delete Interfaces
        //   Delete interface cluster entries
        //   Delete dns records
        //   Delete custom attributes
        //   Delete DHCP entries
        //   Delete device record if it is the last host associated with it.
        //
        // IDEA: If it's the last host in a domain (maybe do the same for or a networks & vlans in the interface delete)
        //       It could just print a notice or something.
        // Check that it is the host is not performing server duties
        // FIXME: MP mostly fixed..needs testing
        $serverrow = 0;
        // check ALL the places server_id is used and remove the entry from server_b if it is not used
        list($status, $rows, $srecord) = db_get_record($onadb, 'dhcp_server_subnets', array('host_id' => $host['id']));
        if ($rows) {
            $serverrow++;
        }
        list($status, $rows, $srecord) = db_get_record($onadb, 'dhcp_failover_groups', array('primary_server_id' => $host['id']));
        if ($rows) {
            $serverrow++;
        }
        list($status, $rows, $srecord) = db_get_record($onadb, 'dhcp_failover_groups', array('secondary_server_id' => $host['id']));
        if ($rows) {
            $serverrow++;
        }
        if ($serverrow > 0) {
            printmsg("DEBUG => Host ({$host['fqdn']}) cannot be deleted, it is performing duties as a DHCP server!", 3);
            $self['error'] = "ERROR => Host ({$host['fqdn']}) cannot be deleted, it is performing duties as a DHCP server!";
            return array(5, $self['error'] . "\n");
        }
        // Check if host is a dns server
        $serverrow = 0;
        list($status, $rows, $srecord) = db_get_record($onadb, 'dns_server_domains', array('host_id' => $host['id']));
        if ($rows) {
            $serverrow++;
        }
        if ($serverrow > 0) {
            printmsg("DEBUG => Host ({$host['fqdn']}) cannot be deleted, it is performing duties as a DNS server!", 3);
            $self['error'] = "ERROR => Host ({$host['fqdn']}) cannot be deleted, it is performing duties as a DNS server!";
            return array(5, $self['error'] . "\n");
        }
        // Display an error if it has any entries in configurations
        list($status, $rows, $server) = db_get_record($onadb, 'configurations', array('host_id' => $host['id']));
        if ($rows) {
            printmsg("DEBUG => Host ({$host['fqdn']}) cannot be deleted, it has config archives!", 3);
            $self['error'] = "ERROR => Host ({$host['fqdn']}) cannot be deleted, it has config archives!";
            return array(5, $self['error'] . "\n");
        }
        // Delete interface(s)
        // get list for logging
        $clustcount = 0;
        $dnscount = 0;
        list($status, $rows, $interfaces) = db_get_records($onadb, 'interfaces', array('host_id' => $host['id']));
        // Cant delete if one of the interfaces is primary for a cluster
        foreach ($interfaces as $int) {
            list($status, $rows, $records) = db_get_records($onadb, 'interface_clusters', array('interface_id' => $int['id']));
            $clustcount = $clustcount + $rows;
        }
        if ($clustcount) {
            $self['error'] = "ERROR => host_del() An interface on this host is primary for some interface shares, delete the share or move the interface first.";
            printmsg($self['error'], 0);
            return array(5, $self['error'] . "\n");
        }
        // do the interface_cluster delete.  This just removes this host from the cluster, not the whole cluster itself
        // It will error out as well if this interface is the primary in the cluster
        list($status, $rows) = db_delete_records($onadb, 'interface_clusters', array('host_id' => $host['id']));
        if ($status) {
            $self['error'] = "ERROR => host_del() interface_cluster delete SQL Query failed: {$self['error']}";
            printmsg($self['error'], 0);
            return array(5, $self['error'] . "\n");
        }
        // log deletions
        printmsg("INFO => {$rows} Shared interface(s) DELETED from {$host['fqdn']}", 0);
        $add_to_error .= "INFO => {$rows} Shared interface(s) DELETED from {$host['fqdn']}\n";
        // Delete each DNS record associated with this hosts interfaces.
        //         foreach ($interfaces as $int) {
        //             // Loop through each dns record associated with this interface.
        //             list($status, $rows, $records) = db_get_records($onadb, 'dns', array('interface_id' => $int['id']));
        //             if ($rows) {
        //                 foreach($records as $record) {
        //                     // Run the module
        //                     list($status, $output) = run_module('dns_record_del', array('name' => $record['id'], 'type' => $record['type'], 'commit' => 'Y', 'delete_by_module' => 'Y'));
        //                     $add_to_error .= $output;
        //                     $add_to_status = $add_to_status + $status;
        //                 }
        //             }
        //         }
        // Delete messages
        // get list for logging
        list($status, $rows, $records) = db_get_records($onadb, 'messages', array('table_name_ref' => 'hosts', 'table_id_ref' => $host['id']));
        // do the delete
        list($status, $rows) = db_delete_records($onadb, 'messages', array('table_name_ref' => 'hosts', 'table_id_ref' => $host['id']));
        if ($status) {
            $self['error'] = "ERROR => host_del() message delete SQL Query failed: {$self['error']}";
            printmsg($self['error'], 0);
            return array(5, $self['error'] . "\n");
        }
        // log deletions
        printmsg("INFO => {$rows} Message(s) DELETED from {$host['fqdn']}", 0);
        $add_to_error .= "INFO => {$rows} Message(s) DELETED from {$host['fqdn']}\n";
        // Delete the interfaces.. this should delete dns names and other things associated with interfaces..
        foreach ($interfaces as $record) {
            // Run the module
            list($status, $output) = run_module('interface_del', array('interface' => $record['id'], 'commit' => 'on', 'delete_by_module' => 'Y'));
            $add_to_error .= $output;
            $add_to_status = $add_to_status + $status;
        }
        // Delete device record
        // Count how many hosts use this same device
        list($status, $rows, $records) = db_get_records($onadb, 'hosts', array('device_id' => $host['device_id']));
        // if device count is just 1 do the delete
        if ($rows == 1) {
            list($status, $rows) = db_delete_records($onadb, 'devices', array('id' => $host['device_id']));
            if ($status) {
                $self['error'] = "ERROR => host_del() device delete SQL Query failed: {$self['error']}";
                printmsg($self['error'], 0);
                return array(5, $add_to_error . $self['error'] . "\n");
            }
            // log deletions
            printmsg("INFO => Device record DELETED: [{$record['id']}] no remaining hosts using this device", 0);
        } else {
            printmsg("INFO => Device record NOT DELETED: [{$record['id']}] there are other hosts using this device.", 1);
        }
        // Delete tag entries
        list($status, $rows, $records) = db_get_records($onadb, 'tags', array('type' => 'host', 'reference' => $host['id']));
        $log = array();
        $i = 0;
        foreach ($records as $record) {
            $log[$i] = "INFO => Tag DELETED: {$record['name']} from {$host['fqdn']}";
            $i++;
        }
        //do the delete
        list($status, $rows) = db_delete_records($onadb, 'tags', array('type' => 'host', 'reference' => $host['id']));
        if ($status) {
            $self['error'] = "ERROR => host_del() Tag delete SQL Query failed: {$self['error']}";
            printmsg($self['error'], 0);
            return array(5, $add_to_error . $self['error'] . "\n");
        }
        //log deletions
        foreach ($log as $log_msg) {
            printmsg($log_msg, 0);
            $add_to_error .= $log_msg . "\n";
        }
        // Delete custom attribute entries
        // get list for logging
        list($status, $rows, $records) = db_get_records($onadb, 'custom_attributes', array('table_name_ref' => 'hosts', 'table_id_ref' => $host['id']));
        $log = array();
        $i = 0;
        foreach ($records as $record) {
            list($status, $rows, $ca) = ona_get_custom_attribute_record(array('id' => $record['id']));
            $log[$i] = "INFO => Custom Attribute DELETED: {$ca['name']} ({$ca['value']}) from {$host['fqdn']}";
            $i++;
        }
        //do the delete
        list($status, $rows) = db_delete_records($onadb, 'custom_attributes', array('table_name_ref' => 'hosts', 'table_id_ref' => $host['id']));
        if ($status) {
            $self['error'] = "ERROR => host_del() Custom attribute delete SQL Query failed: {$self['error']}";
            printmsg($self['error'], 0);
            return array(5, $add_to_error . $self['error'] . "\n");
        }
        //log deletions
        foreach ($log as $log_msg) {
            printmsg($log_msg, 0);
            $add_to_error .= $log_msg . "\n";
        }
        // Delete DHCP options
        // get list for logging
        list($status, $rows, $records) = db_get_records($onadb, 'dhcp_option_entries', array('host_id' => $host['id']));
        $log = array();
        $i = 0;
        foreach ($records as $record) {
            list($status, $rows, $dhcp) = ona_get_dhcp_option_entry_record(array('id' => $record['id']));
            $log[$i] = "INFO => DHCP entry DELETED: {$dhcp['display_name']}={$dhcp['value']} from {$host['fqdn']}";
            $i++;
        }
        // do the delete
        list($status, $rows) = db_delete_records($onadb, 'dhcp_option_entries', array('host_id' => $host['id']));
        if ($status) {
            $self['error'] = "ERROR => host_del() DHCP option entry delete SQL Query failed: {$self['error']}";
            printmsg($self['error'], 0);
            return array(5, $add_to_error . $self['error'] . "\n");
        }
        // log deletions
        foreach ($log as $log_msg) {
            printmsg($log_msg, 0);
            $add_to_error .= $log_msg . "\n";
        }
        // Delete the host
        list($status, $rows) = db_delete_records($onadb, 'hosts', array('id' => $host['id']));
        if ($status) {
            $self['error'] = "ERROR => host_del() host delete SQL Query failed: {$self['error']}";
            printmsg($self['error'], 0);
            return array(5, $add_to_error . $self['error'] . "\n");
        }
        // Return the success notice
        if ($add_to_status == 0) {
            $self['error'] = "INFO => Host DELETED: {$host['fqdn']}";
        }
        printmsg($self['error'], 0);
        return array($add_to_status, $add_to_error . $self['error'] . "\n");
    }
    //
    // We are just displaying records that would have been deleted
    //
    // SUMMARY:
    //   Display a warning if it is a server
    //   Display a warning if it has config text entries
    //   Display Interfaces
    //   Display dns records
    //   Display custom attributes
    //   Display DHCP entries
    // Otherwise just display the host record for the host we would have deleted
    $text = "Record(s) NOT DELETED (see \"commit\" option)\n" . "Displaying record(s) that would have been deleted:\n";
    // Display a warning if host is performing server duties
    list($status, $rows, $srecord) = db_get_record($onadb, 'dhcp_server_subnets', array('host_id' => $host['id']));
    if ($rows) {
        $text .= "\nWARNING!  This host is a DHCP server for {$rows} subnet(s)\n";
    }
    list($status, $rows, $srecord) = db_get_record($onadb, 'dns_server_domains', array('host_id' => $host['id']));
    if ($rows) {
        $text .= "\nWARNING!  This host is a DNS server for one or more domains!\n";
    }
    list($status, $rows, $srecord) = db_get_record($onadb, 'dhcp_failover_groups', array('primary_server_id' => $host['id']));
    if ($rows) {
        $text .= "\nWARNING!  This host is a server that is primary in a DHCP failover group\n";
    }
    list($status, $rows, $srecord) = db_get_record($onadb, 'dhcp_failover_groups', array('secondary_server_id' => $host['id']));
    if ($rows) {
        $text .= "\nWARNING!  This host is a server that is secondary in a DHCP failover group\n";
    }
    // Display a warning if it has any configurations
    list($status, $rows, $server) = db_get_record($onadb, 'configurations', array('host_id' => $host['id']));
    if ($rows) {
        $text .= "\nWARNING!  Host can not be deleted, it has config archives!\n";
    }
    if ($rows) {
        $text .= "\nWARNING!  Host will NOT be deleted, due to previous warnings!\n";
    }
    // Display the Host's complete record
    list($status, $tmp) = host_display("host={$host['id']}&verbose=N");
    $text .= "\n" . $tmp;
    // Display count of messages
    list($status, $rows, $records) = db_get_records($onadb, 'messages', array('table_name_ref' => 'hosts', 'table_id_ref' => $host['id']));
    if ($rows) {
        $text .= "\nASSOCIATED MESSAGE RECORDS ({$rows}):\n";
    }
    // Display associated interface(s)
    list($status, $int_rows, $interfaces) = db_get_records($onadb, 'interfaces', array('host_id' => $host['id']));
    // show the dns records associated
    foreach ($interfaces as $record) {
        list($status, $rows, $dnsrec) = db_get_records($onadb, 'dns', array('interface_id' => $record['id']));
        if ($rows) {
            $text .= "\nASSOCIATED DNS RECORDS ({$rows}) ON INTERFACE (" . ip_mangle($record['ip_addr'], 'dotted') . "):\n";
            foreach ($dnsrec as $rec) {
                // show AAAA or A type as needed
                if ($record['ip_addr'] > 4294967295 and $rec['type'] == 'A') {
                    $rec['type'] = 'AAAA';
                }
                $text .= "  TYPE: [ID:{$rec['id']}] {$rec['type']}, {$rec['name']} -> " . ip_mangle($record['ip_addr'], 'dotted') . "\n";
            }
        }
    }
    if ($int_rows) {
        $text .= "\nASSOCIATED INTERFACE RECORDS ({$int_rows}):\n";
    }
    foreach ($interfaces as $record) {
        $text .= "  [ID:{$record['id']}] " . ip_mangle($record['ip_addr'], 'dotted') . "\n";
    }
    // Display associated interface_clusters(s)
    list($status, $clust_rows, $interfaceclusters) = db_get_records($onadb, 'interface_clusters', array('host_id' => $host['id']));
    if ($clust_rows) {
        $text .= "\nASSOCIATED SHARED INTERFACE RECORDS ({$clust_rows}):\n";
    }
    foreach ($interfaceclusters as $record) {
        list($status, $rows, $int) = ona_get_interface_record(array('id' => $record['interface_id']));
        $text .= "  [ID:{$int['id']}] {$int['ip_addr_text']}\n";
    }
    // Display associated tags
    list($status, $rows, $records) = db_get_records($onadb, 'tags', array('type' => 'host', 'reference' => $host['id']));
    if ($rows) {
        $text .= "\nASSOCIATED TAG RECORDS ({$rows}):\n";
    }
    foreach ($records as $record) {
        $text .= "  {$record['name']}\n";
    }
    // Display associated custom attributes
    list($status, $rows, $records) = db_get_records($onadb, 'custom_attributes', array('table_name_ref' => 'hosts', 'table_id_ref' => $host['id']));
    if ($rows) {
        $text .= "\nASSOCIATED CUSTOM ATTRIBUTE RECORDS ({$rows}):\n";
    }
    foreach ($records as $record) {
        list($status, $rows, $ca) = ona_get_custom_attribute_record(array('id' => $record['id']));
        $text .= "  {$ca['name']} => {$ca['value']}\n";
    }
    // Display associated DHCP entries
    list($status, $rows, $records) = db_get_records($onadb, 'dhcp_option_entries', array('host_id' => $host['id']));
    if ($rows) {
        $text .= "\nASSOCIATED DHCP OPTION RECORDS ({$rows}):\n";
    }
    foreach ($records as $record) {
        list($status, $rows, $dhcp) = ona_get_dhcp_option_entry_record(array('id' => $record['id']));
        $text .= "  {$dhcp['display_name']} => {$dhcp['value']}\n";
    }
    return array(7, $text);
}
示例#6
0
function dhcp_pool_modify($options = "")
{
    // The important globals
    global $conf, $self, $onadb;
    // Version - UPDATE on every edit!
    $version = '1.03';
    printmsg("DEBUG => dhcp_pool_modify({$options}) called", 3);
    // Parse incoming options string to an array
    $options = parse_options($options);
    // Return the usage summary if we need to
    if ($options['help'] or !($options['pool'] and ($options['set_failover_group'] or $options['set_start'] or $options['set_end'] or $options['set_llength'] or $options['set_lgrace'] or $options['set_lrenewal'] or $options['set_lrebind']))) {
        // NOTE: Help message lines should not exceed 80 characters for proper display on a console
        $self['error'] = 'ERROR => Insufficient parameters';
        return array(1, <<<EOM

dhcp_pool_modify-v{$version}
Updates a dhcp pool in the database pointing to the specified identifier

  Synopsis: dhcp_pool_modify [KEY=VALUE] ...

  Where:
    pool=ID                             Table ID for the pool

  Optional:
    set_failover_group=ID               group identifier
    set_server=NAME[.DOMAIN] or ID      server identifier
    set_start=IP                        Start ip address of pool
    set_end=IP                          End IP of pool
    set_llength=NUMBER                  Lease Time. Default ({$conf['dhcp_pool']['llength']})
    set_lgrace=NUMBER                   Lease Grace Period. Default ({$conf['dhcp_pool']['lgrace']})
    set_lrenewal=NUMBER                 Lease Renewal. Default ({$conf['dhcp_pool']['lrenewal']})
    set_lrebind=NUMBER                  Lease Rebind. Default ({$conf['dhcp_pool']['lrebind']})



EOM
);
    }
    // get the existing pool to edit
    list($status, $rows, $pool) = db_get_record($onadb, 'dhcp_pools', array('id' => $options['pool']));
    if (!$rows) {
        printmsg("DEBUG => Unable to find the DHCP pool record using id: {$options['id']}!", 3);
        $self['error'] = "ERROR => Unable to find a pool using id: {$options['pool']}";
        return array(1, $self['error'] . "\n");
    }
    // set the pool id in the set variable
    $SET['id'] = $pool['id'];
    // NOTE: currently modify pool does not allow you to change subnets
    // Get subnet info..
    list($status, $rows, $subnet) = ona_find_subnet($pool['subnet_id']);
    $SET['subnet_id'] = $subnet['id'];
    // make sure that the start address is actually part of an existing subnet
    if ($options['set_start']) {
        list($status, $rows, $subnetstart) = ona_find_subnet(ip_mangle($options['set_start'], 'dotted'));
        if (!$rows) {
            printmsg("DEBUG => Unable to find a subnet related to starting address ({$options['set_start']})!", 3);
            $self['error'] = "ERROR => Unable to find a subnet related to your starting address of {$options['set_start']}.";
            return array(1, $self['error'] . "\n");
        }
        if ($subnetstart['id'] != $pool['subnet_id']) {
            printmsg("DEBUG => The starting address ({$options['set_start']}) is not on the same subnet of the pool ({$pool['id']}) you are editing!", 3);
            $self['error'] = "ERROR => The starting address ({$options['set_start']}) is not on the same subnet of the pool ({$pool['id']}) you are editing!";
            return array(1, $self['error'] . "\n");
        }
    }
    // make sure that the end address is actually part of an existing subnet
    if ($options['set_end']) {
        list($status, $rows, $subnetend) = ona_find_subnet(ip_mangle($options['set_end'], 'dotted'));
        if (!$rows) {
            printmsg("DEBUG => Unable to find a subnet related to ending address ({$options['set_end']})!", 3);
            $self['error'] = "ERROR => Unable to find a subnet related to your ending address of {$options['set_end']}.";
            return array(1, $self['error'] . "\n");
        }
        if ($subnetend['id'] != $pool['subnet_id']) {
            printmsg("DEBUG => The ending address ({$options['set_end']}) is not on the same subnet of the pool ({$pool['id']}) you are editing!", 3);
            $self['error'] = "ERROR => The ending address ({$options['set_end']}) is not on the same subnet of the pool ({$pool['id']}) you are editing!";
            return array(1, $self['error'] . "\n");
        }
    }
    // Assign which failover group to use
    if ($options['set_failover_group'] == 0) {
        $desc = 'Not using a failover group';
        $SET['dhcp_failover_group_id'] = 0;
    } else {
        list($status, $rows, $fg) = ona_get_dhcp_failover_group_record(array('id' => $options['set_failover_group']));
        if (!$fg['id']) {
            printmsg("DEBUG => The failover_group specified ({$options['set_failover_group']}) does not exist", 3);
            $self['error'] = "ERROR => The failover_group specified ({$options['set_failover_group']}) does not exist!";
            return array(4, $self['error'] . "\n");
        }
        // get the server names for the two servers
        list($fail_host1, $fail_zone1) = ona_find_host($fg['primary_server_id']);
        list($fail_host2, $fail_zone2) = ona_find_host($fg['secondary_server_id']);
        $desc = $fail_host1['fqdn'] . '/' . $fail_host2['fqdn'];
        $SET['dhcp_failover_group_id'] = $fg['id'];
    }
    // check that start and end are not the same
    //if ($options['set_start'] and $options['set_end'] and $options['set_start'] == $options['set_end']) {
    //    printmsg("DEBUG => The start and end IP addresses (" . ip_mangle($options['set_start'],'dotted') . ") cannot be the same!",3);
    //    $self['error'] = "ERROR => The start and end IP addresses (" . ip_mangle($options['set_start'],'dotted') . ") cannot be the same!";
    //    return(array(2, $self['error'] . "\n"));
    //}
    if ($options['set_start']) {
        $start_dec = ip_mangle($options['set_start'], 'numeric');
    } else {
        $start_dec = $pool['ip_addr_start'];
    }
    if ($options['set_end']) {
        $end_dec = ip_mangle($options['set_end'], 'numeric');
    } else {
        $end_dec = $pool['ip_addr_end'];
    }
    $net_end = 4294967295 - $subnet['ip_mask'] + $subnet['ip_addr'];
    // Validate that the IP address supplied isn't the base or broadcast of the subnet
    if ($start_dec == $subnet['ip_addr'] or $end_dec == $subnet['ip_addr']) {
        printmsg("DEBUG => IP address can't be a subnet's base address (" . ip_mangle($subnet['ip_addr'], 'dotted') . ")!", 3);
        $self['error'] = "ERROR => IP address can't be a subnet's base address (" . ip_mangle($subnet['ip_addr'], 'dotted') . ")!";
        return array(7, $self['error'] . "\n");
    }
    if ($start_dec == $net_end or $end_dec == $net_end) {
        printmsg("DEBUG => IP address can't be a subnet's broadcast address (" . ip_mangle($net_end, 'dotted') . ")!", 3);
        $self['error'] = "ERROR => IP address can't be the subnet broadcast address(" . ip_mangle($net_end, 'dotted') . ")!";
        return array(8, $self['error'] . "\n");
    }
    // check that start is not after the end
    if ($start_dec > $end_dec) {
        printmsg("DEBUG => The start IP addresses (" . ip_mangle($start_dec, 'dotted') . ") falls after the end IP address (" . ip_mangle($end_dec, 'dotted') . ")!", 3);
        $self['error'] = "ERROR => The start IP addresses (" . ip_mangle($start_dec, 'dotted') . ") falls after the end IP address(" . ip_mangle($end_dec, 'dotted') . ")!";
        return array(2, $self['error'] . "\n");
    }
    // check for existing hosts inside the pool range
    list($status, $rows, $interface) = db_get_records($onadb, 'interfaces', 'subnet_id = ' . $subnet['id'] . ' AND ip_addr BETWEEN ' . $start_dec . ' AND ' . $end_dec, '', 0);
    if ($rows) {
        printmsg("DEBUG => IP conflict: Specified range (" . ip_mangle($start_dec, 'dotted') . "-" . ip_mangle($end_dec, 'dotted') . ") encompasses {$rows} host(s)!", 3);
        $self['error'] = "ERROR => IP conflict: Specified range (" . ip_mangle($start_dec, 'dotted') . "-" . ip_mangle($end_dec, 'dotted') . ") encompasses {$rows} host(s)";
        return array(4, $self['error'] . "\n");
    }
    // *** Check to see if the new pool overlaps any existing pools *** //
    // Look for overlaps like this (where new pool address starts inside an existing pool):
    //            [ -- new pool -- ]
    //    [ -- old pool --]
    list($status, $rows, $tmp) = db_get_record($onadb, 'dhcp_pools', 'id != ' . $SET['id'] . ' AND ' . $start_dec . ' BETWEEN ip_addr_start AND ip_addr_end');
    if ($rows != 0) {
        printmsg("DEBUG =>  Pool address conflict: New pool (" . ip_mangle($start_dec, 'dotted') . "-" . ip_mangle($end_dec, 'dotted') . ") starts inside an existing pool!", 3);
        $self['error'] = "ERROR => Pool address conflict! New pool (" . ip_mangle($start_dec, 'dotted') . "-" . ip_mangle($end_dec, 'dotted') . ") starts inside an existing pool.";
        return array(5, $self['error'] . "\n" . "INFO  => Conflicting pool record ID: {$tmp['id']}\n");
    }
    // Look for overlaps like this (where the new pool ends inside an existing pool):
    //    [ -- new pool -- ]
    //           [ -- old pool --]
    list($status, $rows, $tmp) = db_get_record($onadb, 'dhcp_pools', 'id != ' . $SET['id'] . ' AND ' . $end_dec . ' BETWEEN ip_addr_start AND ip_addr_end');
    if ($rows != 0) {
        printmsg("DEBUG =>  Pool address conflict: New pool (" . ip_mangle($start_dec, 'dotted') . "-" . ip_mangle($end_dec, 'dotted') . ") ends inside an existing pool!", 3);
        $self['error'] = "ERROR => Pool address conflict! New pool (" . ip_mangle($start_dec, 'dotted') . "-" . ip_mangle($end_dec, 'dotted') . ") ends inside an existing pool.";
        return array(6, $self['error'] . "\n" . "INFO  => Conflicting pool record ID: {$tmp['id']}\n");
    }
    // Look for overlaps like this (where the new pool entirely overlaps an existing pool):
    //    [ -------- new pool --------- ]
    //           [ -- old pool --]
    list($status, $rows, $tmp) = db_get_record($onadb, 'dhcp_pools', 'id != ' . $SET['id'] . ' AND (ip_addr_start BETWEEN ' . $start_dec . ' AND ' . $end_dec . ' OR ip_addr_end BETWEEN ' . $start_dec . ' AND ' . $end_dec . ')');
    if ($rows != 0) {
        printmsg("DEBUG =>  Pool address conflict: New pool (" . ip_mangle($start_dec, 'dotted') . "-" . ip_mangle($end_dec, 'dotted') . ") would encompass an existing pool!", 3);
        $self['error'] = "ERROR => Pool address conflict! New pool (" . ip_mangle($start_dec, 'dotted') . "-" . ip_mangle($end_dec, 'dotted') . ") would encompass an existing pool.";
        return array(7, $self['error'] . "\n" . "INFO  => Conflicting pool record ID: {$tmp['id']}\n");
    }
    // Check permissions
    if (!auth('advanced') or !authlvl($subnet['lvl'])) {
        $self['error'] = "Permission denied!";
        printmsg($self['error'], 0);
        return array(8, $self['error'] . "\n");
    }
    // define the remaining entries
    if (array_key_exists('set_lgrace', $options)) {
        $SET['lease_grace_period'] = $options['set_lgrace'];
    }
    if (array_key_exists('set_llength', $options)) {
        $SET['lease_length'] = $options['set_llength'];
    }
    if (array_key_exists('set_lrenewal', $options)) {
        $SET['lease_renewal_time'] = $options['set_lrenewal'];
    }
    if (array_key_exists('set_lrebind', $options)) {
        $SET['lease_rebind_time'] = $options['set_lrebind'];
    }
    // Set the IPs if you got this far
    $SET['ip_addr_start'] = $start_dec;
    $SET['ip_addr_end'] = $end_dec;
    // Get the DHCP pool record before updating (logging)
    list($status, $rows, $original_pool) = ona_get_dhcp_pool_record(array('id' => $SET['id']));
    // Update the record
    list($status, $rows) = db_update_record($onadb, 'dhcp_pools', array('id' => $SET['id']), $SET);
    if ($status or !$rows) {
        $self['error'] = "ERROR => dhcp_pool_modify() SQL Query failed: " . $self['error'];
        printmsg($self['error'], 0);
        return array(6, $add_to_error . $self['error'] . "\n");
    }
    $success_start = ip_mangle($SET['ip_addr_start'], 'dotted');
    $success_end = ip_mangle($SET['ip_addr_end'], 'dotted');
    // Get the DHCP pool record after updating (logging)
    list($status, $rows, $new_pool) = ona_get_dhcp_pool_record(array('id' => $SET['id']));
    // Return the success notice
    $self['error'] = "INFO => DHCP pool UPDATED:{$original_pool['id']}: {$success_start}-{$success_end} on {$subnet['name']}.";
    $log_msg = "INFO => DHCP pool UPDATED:{$original_pool['id']}: ";
    $more = "";
    foreach (array_keys($original_pool) as $key) {
        if ($original_pool[$key] != $new_pool[$key]) {
            $log_msg .= $more . $key . "[" . $original_pool[$key] . "=>" . $new_pool[$key] . "]";
            $more = ";";
        }
    }
    // only print to logfile if a change has been made to the record
    if ($more != '') {
        printmsg($self['error'], 0);
        printmsg($log_msg, 0);
    }
    return array(0, $add_to_error . $self['error'] . "\n");
}
示例#7
0
文件: subnet.inc.php 项目: edt82/ona
function subnet_del($options = "")
{
    global $conf, $self, $onadb;
    // Version - UPDATE on every edit!
    $version = '1.06';
    printmsg('DEBUG => subnet_del(' . $options . ') called', 3);
    // Parse incoming options string to an array
    $options = parse_options($options);
    // Sanitize options[commit] (default is no)
    $options['commit'] = sanitize_YN($options['commit'], 'N');
    // Return the usage summary if we need to
    if ($options['help'] or !$options['subnet']) {
        // NOTE: Help message lines should not exceed 80 characters for proper display on a console
        $self['error'] = 'ERROR => Insufficient parameters';
        return array(1, <<<EOM

subnet_del-v{$version}
Deletes a subnet (subnet) from the database

  Synopsis: subnet_del [KEY=VALUE] ...

  Required:
    subnet=IP or ID              select subnet by search string

  Optional:
    commit=[yes|no]               commit db transaction (no)


EOM
);
    }
    // Find the subnet record we're deleting
    list($status, $rows, $subnet) = ona_find_subnet($options['subnet']);
    if ($status or !$rows) {
        $self['error'] = "ERROR => Subnet not found";
        return array(2, $self['error'] . "\n");
    }
    // Check permissions
    if (!auth('subnet_del') or !authlvl($subnet['lvl'])) {
        $self['error'] = "Permission denied!";
        printmsg($self['error'], 0);
        return array(3, $self['error'] . "\n");
    }
    // If "commit" is yes, delete the subnet
    if ($options['commit'] == 'Y') {
        $text = "";
        // FIXME: (add all this) ...
        // SUMMARY:
        //   Delete assignments to any DHCP servers
        //   Delete any DHCP pools on the current subnet
        //   Delete any DHCP options associated with this subnet
        //   Delete any interfaces belonging to hosts with more than one interface
        //   Delete any hosts (and all their associated info) that have only one interface
        //   Delete subnet Record
        //   Delete custom attributes
        //
        //   FIXME: display a warning if there are no more subnets that a dhcp server is serving dhcp for?
        // Delete DHCP server assignments
        list($status, $rows) = db_delete_records($onadb, 'dhcp_server_subnets', array('subnet_id' => $subnet['id']));
        if ($status) {
            $self['error'] = "ERROR => DHCP server assignment delete failed: {$self['error']}";
            return array(5, $self['error'] . "\n");
        }
        // Delete DHCP pools
        list($status, $rows) = db_delete_records($onadb, 'dhcp_pools', array('subnet_id' => $subnet['id']));
        if ($status) {
            $self['error'] = "ERROR => DHCP pool delete failed: {$self['error']}";
            return array(5, $self['error'] . "\n");
        }
        // Delete DHCP options
        list($status, $rows) = db_delete_records($onadb, 'dhcp_option_entries', array('subnet_id' => $subnet['id']));
        if ($status) {
            $self['error'] = "ERROR => DHCP parameter delete failed: {$self['error']}";
            return array(5, $self['error'] . "\n");
        }
        // Delete tag entries
        list($status, $rows, $records) = db_get_records($onadb, 'tags', array('type' => 'subnet', 'reference' => $subnet['id']));
        $log = array();
        $i = 0;
        foreach ($records as $record) {
            $log[$i] = "INFO => Tag DELETED: {$record['name']} from {$subnet['name']}";
            $i++;
        }
        //do the delete
        list($status, $rows) = db_delete_records($onadb, 'tags', array('type' => 'subnet', 'reference' => $subnet['id']));
        if ($status) {
            $self['error'] = "ERROR => subnet_del() Tag delete SQL Query failed: {$self['error']}";
            printmsg($self['error'], 0);
            return array(5, $add_to_error . $self['error'] . "\n");
        }
        //log deletions
        foreach ($log as $log_msg) {
            printmsg($log_msg, 0);
            $add_to_error .= $log_msg . "\n";
        }
        // Delete custom attribute entries
        // get list for logging
        list($status, $rows, $records) = db_get_records($onadb, 'custom_attributes', array('table_name_ref' => 'subnets', 'table_id_ref' => $subnet['id']));
        $log = array();
        $i = 0;
        foreach ($records as $record) {
            list($status, $rows, $ca) = ona_get_custom_attribute_record(array('id' => $record['id']));
            $log[$i] = "INFO => Custom Attribute DELETED: {$ca['name']} ({$ca['value']}) from {$subnet['name']}";
            $i++;
        }
        //do the delete
        list($status, $rows) = db_delete_records($onadb, 'custom_attributes', array('table_name_ref' => 'subnets', 'table_id_ref' => $subnet['id']));
        if ($status) {
            $self['error'] = "ERROR => subnet_del() Custom attribute delete SQL Query failed: {$self['error']}";
            printmsg($self['error'], 0);
            return array(5, $self['error'] . "\n");
        }
        //log deletions
        foreach ($log as $log_msg) {
            printmsg($log_msg, 0);
            //$add_to_error .= $log_msg . "\n";
        }
        // Delete associated host / interface records that need to be deleted
        // BUSINESS RULE: We delete hosts that have only one interface (and it's on this subnet)
        // BUSINESS RULE: We delete interfaces from hosts that have multiple interfaces
        list($status, $rows, $interfaces) = db_get_records($onadb, 'interfaces', array('subnet_id' => $subnet['id']));
        $hosts_to_delete = array();
        $interfaces_to_delete = array();
        foreach ($interfaces as $interface) {
            // Select all  interfaces for the associated host where the subnet ID is not our subnet ID
            $where = "host_id = {$interface['host_id']} AND subnet_id != {$subnet['id']}";
            list($status, $rows, $tmp) = db_get_records($onadb, 'interfaces', $where, '', 0);
            // We'll delete hosts that have only one interface (i.e. no interfaces on any other subnets)
            if ($rows == 0) {
                array_push($hosts_to_delete, $interface['host_id']);
            } else {
                array_push($interfaces_to_delete, $interface['id']);
            }
        }
        unset($interfaces);
        // make sure we only have one reference for each host and interface
        $interfaces_to_delete = array_unique($interfaces_to_delete);
        $hosts_to_delete = array_unique($hosts_to_delete);
        // Delete interfaces we have selected
        foreach ($interfaces_to_delete as $interface_id) {
            list($status, $output) = run_module('interface_del', array('interface' => $interface_id, 'commit' => 'Y'));
            if ($status) {
                return array(5, $output);
            }
        }
        // Delete hosts we have selected
        foreach ($hosts_to_delete as $host_id) {
            list($status, $output) = run_module('host_del', array('host' => $host_id, 'commit' => 'Y'));
            if ($status) {
                return array(5, $output);
            }
        }
        // Delete the subnet
        list($status, $rows) = db_delete_records($onadb, 'subnets', array('id' => $subnet['id']));
        if ($status or !$rows) {
            $self['error'] = "ERROR => Subnet delete failed: {$self['error']}";
            return array(5, $self['error'] . "\n");
        }
        // Return the success notice
        $ip = ip_mangle($subnet['ip_addr'], 'dotted');
        $cidr = ip_mangle($subnet['ip_mask'], 'cidr');
        $self['error'] = "INFO => Subnet DELETED: {$subnet['name']} IP: {$ip}/{$cidr}";
        printmsg($self['error'], 0);
        return array(0, $self['error'] . "\n");
    }
    //
    // We are just displaying records that would have been deleted
    //
    // SUMMARY:
    //   Display assignments to any DHCP servers
    //   Display any DHCP pools on the current subnet
    //   Display any DHCP parameters associated with this subnet
    //   Display subnet Record
    //   Display Host records (and all their sub-records)
    //   Display custom attributes
    // Otherwise just display the host record for the host we would have deleted
    $text = "Record(s) NOT DELETED (see \"commit\" option)\n" . "Displaying record(s) that would have been deleted:\n";
    // Display the Subnet's complete record
    list($status, $tmp) = subnet_display("subnet={$subnet['id']}&verbose=N");
    $text .= "\n" . $tmp;
    // Display assignments to any DHCP servers
    list($status, $rows, $records) = db_get_records($onadb, 'dhcp_server_subnets', array('subnet_id' => $subnet['id']));
    if ($rows) {
        $text .= "\nASSOCIATED DHCP SERVER ASSIGNMENT RECORDS ({$rows}):\n";
    }
    foreach ($records as $record) {
        $text .= format_array($record);
    }
    // Display any DHCP pools on the current subnet
    list($status, $rows, $records) = db_get_records($onadb, 'dhcp_pools', array('subnet_id' => $subnet['id']));
    if ($rows) {
        $text .= "\nASSOCIATED DHCP POOL RECORDS ({$rows}):\n";
    }
    foreach ($records as $record) {
        $text .= format_array($record);
    }
    // Display associated DHCP entries
    list($status, $rows, $records) = db_get_records($onadb, 'dhcp_option_entries', array('subnet_id' => $subnet['id']));
    if ($rows) {
        $text .= "\nASSOCIATED DHCP ENTRY RECORDS ({$rows}):\n";
    }
    foreach ($records as $record) {
        list($status, $rows, $dhcp) = ona_get_dhcp_option_entry_record(array('id' => $record['id']));
        $text .= "  {$dhcp['display_name']} => {$dhcp['value']}\n";
    }
    // Display associated tags
    list($status, $rows, $records) = db_get_records($onadb, 'tags', array('type' => 'subnet', 'reference' => $subnet['id']));
    if ($rows) {
        $text .= "\nASSOCIATED TAG RECORDS ({$rows}):\n";
    }
    foreach ($records as $record) {
        $text .= "  {$record['name']}\n";
    }
    // Display associated custom attributes
    list($status, $rows, $records) = db_get_records($onadb, 'custom_attributes', array('table_name_ref' => 'subnets', 'table_id_ref' => $subnet['id']));
    if ($rows) {
        $text .= "\nASSOCIATED CUSTOM ATTRIBUTE RECORDS ({$rows}):\n";
    }
    foreach ($records as $record) {
        list($status, $rows, $ca) = ona_get_custom_attribute_record(array('id' => $record['id']));
        $text .= "  {$ca['name']} => {$ca['value']}\n";
    }
    // Display associated host  / interface records that would be deleted
    // BUSINESS RULE: We delete hosts that have only one interface (and it's on this subnet)
    // BUSINESS RULE: We delete interfaces from hosts that have multiple interfaces (including at least one on a different subnet)
    list($status, $rows, $interfaces) = db_get_records($onadb, 'interfaces', array('subnet_id' => $subnet['id']));
    $hosts_to_delete = array();
    $interfaces_to_delete = array();
    foreach ($interfaces as $interface) {
        // Select all  interfaces for the associated host where the subnet ID is not our subnet ID
        $where = "host_id = {$interface['host_id']} AND subnet_id != {$subnet['id']}";
        list($status, $rows, $tmp) = db_get_records($onadb, 'interfaces', $where, '', 0);
        // We'll delete hosts that have only one interface (i.e. no interfaces on any other subnets)
        if ($rows == 0) {
            array_push($hosts_to_delete, $interface['host_id']);
        } else {
            array_push($interfaces_to_delete, $interface['id']);
        }
    }
    unset($interfaces);
    // make sure we only have one reference for each host and interface
    $interfaces_to_delete = array_unique($interfaces_to_delete);
    $hosts_to_delete = array_unique($hosts_to_delete);
    // Display interfaces we would have deleted
    $rows = count($interfaces_to_delete);
    if ($rows) {
        $text .= "\n----- ASSOCIATED HOST INTERFACE RECORDS ({$rows}) -----\n";
    }
    foreach ($interfaces_to_delete as $interface_id) {
        list($status, $output) = run_module('interface_del', array('interface' => $interface_id), false);
        $output = preg_replace('/^(.*)?\\n(.*)?\\n/', '', $output);
        $text .= $output;
    }
    // Display hosts we would have deleted
    $rows = count($hosts_to_delete);
    if ($rows) {
        $text .= "\n-----ASSOCIATED HOSTS ({$rows}) -----\n";
    }
    foreach ($hosts_to_delete as $host_id) {
        list($status, $output) = run_module('host_del', array('host' => $host_id), false);
        $output = preg_replace('/^(.*)?\\n(.*)?\\n/', '', $output);
        $text .= $output;
    }
    return array(7, $text);
}
示例#8
0
function dhcp_entry_modify($options = "")
{
    // The important globals
    global $conf, $self, $onadb;
    // Version - UPDATE on every edit!
    $version = '1.04';
    printmsg("DEBUG => dhcp_entry_modify({$options}) called", 3);
    // Parse incoming options string to an array
    $options = parse_options($options);
    // Return the usage summary if we need to
    if ($options['help'] or !($options['id'] and ($options['set_option'] and array_key_exists('set_value', $options) or array_key_exists('set_value', $options)))) {
        // NOTE: Help message lines should not exceed 80 characters for proper display on a console
        $self['error'] = 'ERROR => Insufficient parameters';
        return array(1, <<<EOM

dhcp_entry_modify-v{$version}
Modifies a DHCP entry in the database

  Synopsis: dhcp_entry_modify [KEY=VALUE] ...

  Where:
    id=ID                                       DHCP entry ID

  Options:
    set_option=DHCP type                        DHCP parameter type
    set_value=STRING                            string value for the DHCP type

  Notes:
    If you specify a type, you must specify a value.


EOM
);
    }
    // Determine the entry itself exists
    list($status, $rows, $entry) = ona_get_dhcp_option_entry_record(array('id' => $options['id']));
    if ($status or !$rows) {
        printmsg("DEBUG => Invalid DHCP entry record ID ({$options['id']})!", 3);
        $self['error'] = "ERROR => Invalid DHCP entry record ID ({$options['id']})!";
        return array(2, $self['error'] . "\n");
    }
    printmsg("DEBUG => dhcp_entry_modify(): Found entry, {$entry['display_name']} => {$entry['value']}", 3);
    $desc = '';
    // Load associated host, subnet or server record
    $host = $subnet = $server = array();
    if ($entry['host_id']) {
        list($status, $rows, $host) = ona_find_host($entry['host_id']);
        $desc = $host['fqdn'];
    }
    if ($entry['subnet_id']) {
        list($status, $rows, $subnet) = ona_find_subnet($entry['subnet_id']);
        $desc = "{$subnet['name']} (" . ip_mangle($subnet['ip_addr']) . ")";
    }
    if ($entry['server_id']) {
        list($status, $rows, $server) = ona_find_host($entry['server_id']);
        $desc = $server['fqdn'];
    }
    // Check permissions on source identifier
    $lvl = 100;
    if ($host['id']) {
        $lvl = $host['lvl'];
    }
    if ($subnet['id']) {
        $lvl = $subnet['lvl'];
    }
    if (!auth('advanced') or !authlvl($lvl)) {
        $self['error'] = "Permission denied!";
        printmsg($self['error'], 0);
        return array(10, $self['error'] . "\n");
    }
    // unset $host if $server is defined .. we don't need it anymore
    if ($server['id']) {
        $host = array();
    }
    // This variable will contain the updated info we'll insert into the DB
    $SET = array();
    if (array_key_exists('set_value', $options)) {
        // trim leading and trailing whitespace from 'value'
        $SET['value'] = trim($options['set_value']);
        // trim leading and trailing whitespace from 'value' and check that a value exists
        $SET['value'] = trim($options['set_value']);
        if (strlen($SET['value']) == 0) {
            printmsg("DEBUG => The DHCP value was blank", 3);
            $self['error'] = "ERROR => DHCP value was blank";
            return array(2, $self['error'] . "\n");
        }
    }
    if ($options['set_option']) {
        // Make sure they specified a value
        if (!array_key_exists('set_value', $options)) {
            printmsg("DEBUG => No value specified for given DHCP parameter type ({$options['set_option']})!", 3);
            $self['error'] = "ERROR => No value specified for given DHCP parameter type ({$options['set_option']})!";
            return array(8, $self['error'] . "\n");
        }
        // Determine the type is valid
        list($status, $rows, $type) = ona_find_dhcp_option(trim($options['set_option']));
        if ($status or !$rows) {
            printmsg("DEBUG => Invalid DHCP parameter type specified ({$options['set_option']})!", 3);
            $self['error'] = "ERROR => Invalid DHCP parameter type specified ({$options['set_option']})!";
            return array(8, $self['error'] . "\n");
        }
        printmsg("DEBUG => dhcp_entry_modify(): Found parameter type {$type['display_name']}", 3);
        $SET['dhcp_option_id'] = $type['id'];
        // Make sure this isn't a duplicate
        // TODO: this code seems a bit suspect of being nasty.. possibly fix it up
        $search = array('dhcp_option_id' => $type['id'], 'host_id' => 0, 'subnet_id' => 0);
        if ($host['id']) {
            $search['host_id'] = $host['id'];
        }
        if ($subnet['id']) {
            $search['subnet_id'] = $subnet['id'];
        }
        if ($server['id']) {
            $search['server_id'] = $server['id'];
        }
        list($status, $rows, $record) = ona_get_dhcp_option_entry_record($search);
        if ($status or $rows > 1 or $rows == 1 and $record['id'] != $entry['id']) {
            printmsg("DEBUG => That DHCP parameter type is already defined ({$search})!", 3);
            $self['error'] = "ERROR => That DHCP parameter type is already defined ({$search})!";
            return array(11, $self['error'] . "\n");
        }
    }
    // Get the dhcp entry record before updating (logging)
    list($status, $rows, $original_entry) = ona_get_dhcp_option_entry_record(array('id' => $entry['id']));
    // Update the record
    list($status, $rows) = db_update_record($onadb, 'dhcp_option_entries', array('id' => $entry['id']), $SET);
    if ($status or !$rows) {
        $self['error'] = "ERROR => dhcp_entry_modify() SQL Query failed: " . $self['error'];
        printmsg($self['error'], 0);
        return array(6, $self['error'] . "\n");
    }
    // Get the entry again to display details
    list($status, $tmp_rows, $entry) = ona_get_dhcp_option_entry_record(array('id' => $entry['id']));
    // Return the success notice
    $self['error'] = "INFO => DHCP entry UPDATED:{$entry['id']}: \"{$entry['display_name']}\"={$entry['value']} on {$desc} ";
    $log_msg = "INFO => DHCP entry UPDATED:{$entry['id']}: ";
    $more = "";
    foreach (array_keys($original_entry) as $key) {
        if ($original_entry[$key] != $entry[$key]) {
            $log_msg .= $more . $key . "[" . $original_entry[$key] . "=>" . $entry[$key] . "]";
            $more = ";";
        }
    }
    // only print to logfile if a change has been made to the record
    if ($more != '') {
        printmsg($self['error'], 0);
        printmsg($log_msg, 0);
    }
    return array(0, $self['error'] . "\n");
}
示例#9
0
function interface_move($options = "")
{
    global $conf, $self, $onadb;
    printmsg("DEBUG => interface_move({$options}) called", 3);
    // Version - UPDATE on every edit!
    $version = '1.04';
    // Parse incoming options string to an array
    $options = parse_options($options);
    // Return the usage summary if we need to
    if ($options['help'] or !$options['start'] or !$options['new_start']) {
        // NOTE: Help message lines should not exceed 80 characters for proper display on a console
        $self['error'] = 'ERROR => Insufficient parameters';
        return array(1, <<<EOM

interface_move-v{$version}
  Moves all interface addresses from one subnet to another.
  The initial range of IPs does not have to be consecutive.
  The new range of IPs will be used sequentially.

  Synopsis: interface_move [KEY=VALUE] ...

  IP block to move: (source)
    start=IP                      first IP to move
    [end=IP]                      last IP to move

  New IP block: (destination)
    new_start=IP                  first new IP address
    [new_end=IP]                  last new IP address

  Optional:
    commit=[yes|no]               commit db transaction (no)


EOM
);
    }
    // Set options[force] and options[create_a] to N if it's not set
    $options['commit'] = sanitize_YN($options['commit'], 'N');
    // Find the "start" subnet record by IP address
    list($status, $rows, $old_subnet) = ona_find_subnet($options['start']);
    if (!$old_subnet or !$old_subnet['id']) {
        printmsg("DEBUG => Source start address ({$options['start']}) isn't valid!", 3);
        $self['error'] = "ERROR => Source (start) address specified isn't valid!";
        return array(2, $self['error'] . "\n");
    }
    // If they specified an "END" address, make sure it's valid and on the same subnet
    if ($options['end']) {
        // Find an interface record by something in that interface's record
        list($status, $rows, $old_subnet_end) = ona_find_subnet($options['end']);
        // If we didn't get a record then exit
        if (!$old_subnet_end or !$old_subnet_end['id']) {
            printmsg("DEBUG => Source end address ({$options['end']}) isn't valid!", 3);
            $self['error'] = "ERROR => Source (end) address specified isn't valid!";
            return array(3, $self['error'] . "\n");
        }
        if ($old_subnet_end['id'] != $old_subnet['id']) {
            printmsg("DEBUG => Both source addresses ({$options['start']} and {$options['end']}) must be on the same subnet!", 3);
            $self['error'] = "ERROR => Both the source addresses (start and end) must be on the same subnet!";
            return array(4, $self['error'] . "\n");
        }
    } else {
        printmsg("DEBUG => Only moving one host source={$options['start']}!", 3);
        $options['end'] = $options['start'];
    }
    // Find the "end" subnet record by IP address
    list($status, $rows, $new_subnet) = ona_find_subnet($options['new_start']);
    // If we didn't get a record then exit
    if (!$new_subnet or !$new_subnet['id']) {
        printmsg("DEBUG => Destination start address ({$options['new_start']}) isn't valid!", 3);
        $self['error'] = "ERROR => Destination (new_start) address specified isn't valid!";
        return array(2, $self['error'] . "\n");
    }
    // Make sure the "old" and "new" subnets are different subnets
    if ($old_subnet['id'] == $new_subnet['id']) {
        printmsg("DEBUG => Both the source IP range ({$options['start']}+) and the destination IP range ({$options['new_start']}+) are on the same subnet!", 3);
        $self['error'] = "ERROR => Both the source IP range and the destination IP range are on the same subnet!";
        return array(2, $self['error'] . "\n");
    }
    // If they specified a "new_end" address, make sure it's valid and on the same subnet as the new_start subnet
    if ($options['new_end']) {
        // Find an interface record by something in that interface's record
        list($status, $rows, $new_subnet_end) = ona_find_subnet($options['new_end']);
        // If we didn't get a record then exit
        if (!$new_subnet_end or !$new_subnet_end['id']) {
            printmsg("DEBUG => Destination end address ({$options['new_end']}) isn't valid!", 3);
            $self['error'] = "ERROR => Destination (new_end) address specified isn't valid!";
            return array(3, $self['error'] . "\n");
        }
        if ($new_subnet_end['id'] != $new_subnet['id']) {
            printmsg("DEBUG => Both destination addresses ({$options['new_start']} and {$options['new_end']}) must be on the same subnet!", 3);
            $self['error'] = "ERROR => Both the destination addresses (new_start and new_end) must be on the same subnet!";
            return array(4, $self['error'] . "\n");
        }
    } else {
        printmsg("DEBUG => Only moving one host destination={$options['new_start']}!", 3);
        $options['new_end'] = $options['new_start'];
    }
    // Check permissions at the subnet level
    if (!auth('interface_modify')) {
        $self['error'] = "Permission denied!";
        printmsg($self['error'], 0);
        return array(13, $self['error'] . "\n");
    }
    // An array for all the interface records we'll be moving
    $to_move = array();
    // Message to display if we succeed
    $message = "";
    // Load all the interface records we'll be moving
    $i = 0;
    do {
        // FIXME: this should do a more advanced query someday! (like checking that the ipaddress is >= start and <= end
        list($status, $rows, $interface) = ona_get_interface_record(array('subnet_id' => $old_subnet['id']), 'ip_addr');
        if ($rows == 0) {
            break;
        }
        $i++;
        if ($interface['ip_addr'] >= ip_mangle($options['start'], 'numeric')) {
            if ($interface['ip_addr'] <= ip_mangle($options['end'], 'numeric')) {
                $to_move[$i] = $interface;
            }
        }
    } while ($i < $rows);
    $total_to_move = count($to_move);
    $total_assigned = 0;
    // If there's nothing to do, tell them
    if ($total_to_move == 0) {
        printmsg("DEBUG => There are no interfaces in the source address block!", 3);
        $self['error'] = "ERROR => There are no interfaces in the source address block!";
        return array(6, $self['error'] . "\n");
    }
    // Make sure we have a high enough "LVL" to modify the associated hosts
    foreach ($to_move as $interface) {
        // Load the associated host record
        list($status, $rows, $host) = ona_get_host_record(array('id' => $interface['host_id']));
        list($status, $rows, $dns) = ona_get_dns_record(array('id' => $host['primary_dns_id'], 'type' => 'A'));
        // Check permissions at the subnet level
        if (!authlvl($host['LVL'])) {
            $self['error'] = "Permission denied! Can't modify Host: {$host['id']} {$dns['fqdn']}";
            printmsg($self['error'], 0);
            return array(14, $self['error'] . "\n");
        }
        // Check to see if the host has any interfaces in the destination subnet
        // MP: this is now allowed
        //         list($status, $rows, $interface) = ona_get_interface_record(array('host_id' => $interface['host_id'], 'subnet_id' => $new_subnet['id']));
        //         if ($status or $rows) {
        //             printmsg("DEBUG => Source host {$ddns['fqdn']} already has an interface on the destination subnet!",3);
        //             $self['error'] = "ERROR => Source host {$dns['fqdn']} (ID {$host['id']}) already has an interface on the destination subnet!";
        //             return(array(15, $self['error'] . "\n"));
        //         }
    }
    // Get the numeric version of the start/end addresses we are moving interfaces to
    // .. and make sure that the $low_ip and $high_ip are not subnet or broadcast addresses!
    $low_ip = ip_mangle($options['new_start'], 'numeric');
    $high_ip = ip_mangle($options['new_end'], 'numeric');
    if ($low_ip == $new_subnet['ip_addr']) {
        $low_ip++;
    }
    $num_hosts = 0xffffffff - $new_subnet['ip_mask'];
    if ($high_ip == $new_subnet['ip_addr'] + $num_hosts) {
        $high_ip--;
    }
    printmsg("INFO => Asked to move {$total_to_move} interfaces to new range: " . ip_mangle($low_ip, 'dotted') . ' - ' . ip_mangle($high_ip, 'dotted'), 0);
    // Loop through each interface we need to move, and find an available address for it.
    $pool_interfering = 0;
    foreach (array_keys($to_move) as $i) {
        while ($low_ip <= $high_ip) {
            list($status, $rows, $interface) = ona_get_interface_record(array('ip_addr' => $low_ip));
            if ($rows == 0 and $status == 0) {
                // Since the IP seems available, let's double check and make sure it's not in a DHCP address pool
                list($status, $rows, $pool) = ona_get_dhcp_pool_record("ip_addr_start < '{$low_ip}' AND ip_addr_end > '{$low_ip}'");
                if ($rows == 0 and $status == 0) {
                    // The IP is available, lets use it!
                    $to_move[$i]['new_ip_address'] = $low_ip;
                    $total_assigned++;
                    $low_ip++;
                    break;
                }
                $pool_interfering = 1;
                printmsg("DEBUG => Couldn't use the DHCP POOL address: " . ip_mangle($low_ip, 'dotted'), 3);
            }
            $low_ip++;
        }
    }
    // If total_assigned != total_to_move, error - not enough free IP addresses in destination subnet!
    if ($total_assigned != $total_to_move) {
        printmsg("DEBUG => The destination IP range doesn't have enough free IP addresses!", 3);
        $self['error'] = "ERROR => The destination IP range doesn't have enough free IP addresses!\n";
        if ($pool_interfering) {
            $self['error'] .= "INFO => Some IPs in the destination range were part of a DHCP pool range.\n";
        }
        return array(6, $self['error']);
    }
    // Display what we would have done if "commit" isn't "yes"
    if ($options['commit'] != "Y") {
        $self['error'] = "Interface(s) NOT MOVED (see \"commit\" option)";
        $text = $self['error'] . "\n" . "Displaying {$total_to_move} interface(s) that would have been moved:\n\n";
        foreach ($to_move as $interface) {
            // Get display the hostname we would have moved, as well as it's IP address.
            list($status, $rows, $host) = ona_get_host_record(array('id' => $interface['host_id']));
            list($status, $rows, $dns) = ona_get_dns_record(array('id' => $host['primary_dns_id'], 'type' => 'A'));
            $hostname = strtolower("{$dns['fqdn']}");
            $text .= "  " . ip_mangle($interface['ip_addr'], 'dotted') . " -> " . ip_mangle($interface['new_ip_address'], 'dotted') . "\t({$hostname})\n";
        }
        $text .= "\n";
        return array(7, $text);
    }
    // Loop through and update each interface's IP_ADDRESS and SUBNET_ID
    $text = "SUCCESS => {$total_to_move} interface(s) moved\n";
    $text .= "Interface(s) moved:\n\n";
    foreach ($to_move as $interface) {
        list($status, $rows) = ona_update_record("interfaces", array('id' => $interface['id']), array('ip_addr' => $interface['new_ip_address'], 'subnet_id' => $new_subnet['id']));
        if ($status != 0 or $rows != 1) {
            $self['error'] = "ERROR => Database update failed! {$self['error']}";
            return array(8, $self['error'] . "\n");
        }
        // Get display the hostname we would have moved, as well as its IP address.
        list($status, $rows, $host) = ona_get_host_record(array('id' => $interface['host_id']));
        list($status, $rows, $dns) = ona_get_dns_record(array('id' => $host['primary_dns_id'], 'type' => 'A'));
        $hostname = strtolower("{$dns['fqdn']}");
        $text .= "  " . ip_mangle($interface['ip_addr'], 'dotted') . " -> " . ip_mangle($interface['new_ip_address'], 'dotted') . "\t({$hostname})\n";
    }
    // Return the success notice
    return array(0, $text);
}