<?php

require_once("inc/read_conf.php");
require_once("inc/db.php");
require_once("inc/ssh.php");
require_once("inc/idna_convert.class.php");
require_once("inc/validate_param.php");
require_once("inc/slave_actions.php");
require_once("inc/auth.php");
require_once("inc/enc.php");
require_once("inc/ipmi_cmds.php");
require_once("inc/hardware_profile.php");
require_once("inc/auto_racking.php");
require_once("inc/plugin_dns.php");
require_once("inc/plugin_monitoring.php");
require_once("inc/plugin_root_pass.php");
require_once("inc/auto_provision.php");

$conf = readmyconf();
$con = connectme($conf);

if(oci_ip_check($con, $conf) === FALSE){
    die("Source IP not in openstack-cluster-installer.conf.");
}

$data = json_decode(file_get_contents('php://input'), true);

$remote_addr = $_SERVER['REMOTE_ADDR'];

// Validate memory size
if(!isset($data["memory"][0]["size"]))	die("No memory size reported.");
$memory_size = $data["memory"][0]["size"];
$reg = '/^[0-9]{1,11}$/';
if(!preg_match($reg,$memory_size))	die("Memory size not an int of size max 11 chars.");
$safe_memory_size = $memory_size;

// These aren't interesting for the moment
//$memory_type = $data["memory"][0]["type"];
//$memory_speed = $data["memory"][0]["speed"];
//$memory_manufacturer = $data["memory"][0]["manufacturer"];

// Validate serial number
if (!isset($data["machine"][0]["serial"]))	die("No serial number reported.");
$serial_number = $data["machine"][0]["serial"];
$reg = '/^[ _0-9a-zA-Z-]{1,64}$/';
if(!preg_match($reg,$serial_number))	die("Chassis serial number not in acceptable format.");
$safe_serial_number = $serial_number;

if (!isset($data["machine"][0]["productname"])){
    $prod_name = "No product name reported.";
}else{
    $reg = '/^[ ;_.0-9a-zA-Z-(),+]{1,120}$/';
    if(!preg_match($reg, $data["machine"][0]["productname"])){
        $prod_name = "Product name not in acceptable format.";
    }else{
        $prod_name = $data["machine"][0]["productname"];
    }
}

if (!isset($data["machine"][0]["ladvd_report"])){
    $ladvd_report = "No ladvd report";
}else{
    $reg = '/^[ ;_.0-9a-zA-Z-(),+]{1,120}$/';
    if(!preg_match($reg, $data["machine"][0]["ladvd_report"])){
        $ladvd_report = "Detect failed";
    }else{
        $ladvd_report = $data["machine"][0]["ladvd_report"];
    }
}

if (!isset($data["machine"][0]["bios_version"])){
    $bios_version = "Not reported";
}else{
    $reg = '/^[ ;_.0-9a-zA-Z-(),+\\>]{1,120}$/';
    if(!preg_match($reg, $data["machine"][0]["bios_version"])){
        $bios_version = "BIOS version is weird.";
    }else{
        $bios_version = $data["machine"][0]["bios_version"];
    }
}

if (!isset($data["machine"][0]["dell_lifecycle_version"])){
    $dell_lifecycle_version = "0.0.0";
}else{
    $reg = '/^[ ;_.0-9a-zA-Z-(),+\\>]{1,120}$/';
    if(!preg_match($reg, $data["machine"][0]["dell_lifecycle_version"])){
        $dell_lifecycle_version = "Lifecycle version is weird.";
    }else{
        $dell_lifecycle_version = $data["machine"][0]["dell_lifecycle_version"];
    }
}

if (!isset($data["machine"][0]["ipmi_firmware_version"])){
    $ipmi_version = "Not reported";
}else{
    $reg = '/^[ ;_.0-9a-zA-Z-(),+\\>]{1,120}$/';
    if(!preg_match($reg, $data["machine"][0]["ipmi_firmware_version"])){
        $ipmi_version = "Detect failed";
    }else{
        $ipmi_version = $data["machine"][0]["ipmi_firmware_version"];
    }
}

if (!isset($data["machine"][0]["ipmi_detected_ip"])){
    $ipmi_detected_ip = "Not reported";
}else{
    $reg = '/^[ :.0-9a-fA-F]{1,120}$/';
    if(!preg_match($reg, $data["machine"][0]["ipmi_detected_ip"])){
        $ipmi_detected_ip = "Detect failed";
    }else{
        $ipmi_detected_ip = $data["machine"][0]["ipmi_detected_ip"];
    }
}

$r = mysqli_query($con, "SELECT * FROM machines WHERE serial='" . $safe_serial_number . "'");
$n = mysqli_num_rows($r);
if($n == 0){
    $r = mysqli_query($con, "INSERT INTO machines (ipaddr, dhcp_ip, serial, product_name, ladvd_report, bios_version, dell_lifecycle_version, ipmi_firmware_version, ipmi_detected_ip, memory, status) VALUES ('" . $remote_addr. "', '" . $remote_addr. "', '$safe_serial_number' , '$prod_name', '$ladvd_report', '$bios_version', '$dell_lifecycle_version', '$ipmi_version', '$ipmi_detected_ip', '$safe_memory_size', 'live')");
    if($r === FALSE){
        $error = mysqli_error($con);
        printf("Error inserting: %s\n",  mysqli_error($con));
    }
    $machine_id = mysqli_insert_id($con);
    $report_counter = 0;

    if (isset($data["blockdevices"])){
        foreach($data["blockdevices"] as &$blockdevice){
            if(isset($blockdevice['name']) && isset($blockdevice['size'])){
                $blk_name = $blockdevice['name'];
                $reg = '/^[0-9a-zA-Z-]{1,64}$/';
                if(!preg_match($reg,$blk_name))	die("Block device name suspicious");
                $safe_blk_name = $blk_name;
                $blk_size = $blockdevice['size'];
                $reg = '/^[0-9]{6,16}$/';
                if(!preg_match($reg,$blk_size))	die("Block device size not an int of size min 6 max 16 chars.");
                $safe_blk_size = $blk_size / (1024*1024);
                $r = mysqli_query($con, "INSERT INTO blockdevices (machine_id, name, size_mb) VALUES ('".$machine_id."', '".$safe_blk_name."', '".$safe_blk_size."')");
            }
        }
    }

    if (isset($data["phys-blockdevices"])){
        foreach($data["phys-blockdevices"] as &$blockdevice){
            $blk_slot   = $blockdevice['slot'];
            $blk_model  = $blockdevice['model'];
            $blk_serial = $blockdevice['serial'];
            $blk_size   = $blockdevice['size'];
            $blk_state  = $blockdevice['state'];

            $reg_alpha = '/^[.0-9a-zA-Z- \(\)]{1,64}$/';
            $reg_int = '/^[.0-9]{1,64}$/';
            if(!preg_match($reg_int,   $blk_slot))   die("Block device slot suspicious");
            if(!preg_match($reg_alpha, $blk_model))  die("Block device model suspicious");
            if(!preg_match($reg_alpha, $blk_serial)) die("Block device serial suspicious");
            if(!preg_match($reg_int,   $blk_size))   die("Block device size suspicious");
            if(!preg_match($reg_alpha, $blk_state))  die("Block device state suspicious");
            $safe_blk_size = $blk_size / (1024*1024);
            $r = mysqli_query($con, "INSERT INTO physblockdevices (machine_id, slot, model, serial, size, state) VALUES ('".$machine_id."', '".$blk_slot."', '".$blk_model."', '".$blk_serial."', '".$blk_size."', '".$blk_state."')");
        }
    }

    if(isset($data["interfaces"])){
        foreach($data["interfaces"] as &$iface){
            if(isset($iface["name"]) && isset($iface["macaddr"]) && isset($iface["max_speed"])){
                $if_name = $iface["name"];
                $reg = '/^[0-9a-zA-Z-]{1,64}$/';
                if(!preg_match($reg,$blk_name)) die("Network interface device name suspicious");
                $safe_if_name = $if_name;

                $if_macaddr = $iface["macaddr"];
                $reg = '/^[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}$/';
                if(!preg_match($reg,$if_macaddr)) die("Network interface MAC address suspicious");
                $safe_if_macaddr = $if_macaddr;

                $if_max_speed = $iface["max_speed"];
                $reg = '/^[0-9]{1,10}$/';
                if(!preg_match($reg,$if_max_speed)) die("Network interface max_speed suspicious");
                $safe_if_max_speed = $if_max_speed;

                $if_switch_hostname = $iface["switch_hostname"];
                $reg = '/^((?!-))(xn--)?[a-z0-9][.a-z0-9-]{0,61}[a-z0-9]{0,1}$/';
                if(!preg_match($reg,$if_switch_hostname)) die("Switch hostname suspicious");
                $safe_if_switch_hostname = $if_switch_hostname;

                $if_switchport_name = $iface["switchport_name"];
                $reg = '/^[.:0-9a-zA-Z-]{1,64}$/';
                if(!preg_match($reg,$if_switchport_name)) die("Switchport name suspicious");
                $safe_if_switchport_name = $if_switchport_name;

                $r = mysqli_query($con, "INSERT INTO ifnames (machine_id, name, macaddr, max_speed, switchport_name, switch_hostname) VALUES ('$machine_id', '$safe_if_name', '$safe_if_macaddr', '$safe_if_max_speed', '$safe_if_switchport_name', '$safe_if_switch_hostname')");
            }
        }
    }
}else{
    $a = mysqli_fetch_array($r);
    $machine_id = $a["id"];
    // Check if we should update the DHCP address.
    // We do that only if the machine in in Live, as
    // it is possible to manually launch the agent
    // when the machine is installed.
    if($a["status"] == "live"){
        $dhcp_update = ", dhcp_ip='".$remote_addr."'";
    }else{
        $dhcp_update = "";
    }

    $report_counter = $a["report_counter"] + 1;

    // We keep the machine id...
    $req = "UPDATE machines SET report_counter='$report_counter', ipaddr='$remote_addr', memory='".$safe_memory_size."', serial='$safe_serial_number', product_name='$prod_name', ladvd_report='$ladvd_report', bios_version='$bios_version', dell_lifecycle_version='$dell_lifecycle_version', ipmi_firmware_version='$ipmi_version', ipmi_detected_ip='$ipmi_detected_ip', lastseen=NOW() $dhcp_update WHERE serial='$safe_serial_number'";
    $r = mysqli_query($con, $req);
    if (isset($data["blockdevices"])){
        $blkdev_array = array();
        foreach($data["blockdevices"] as &$blockdevice){
            if(isset($blockdevice['name']) && isset($blockdevice['size'])){
                $blk_name = $blockdevice['name'];
                $reg = '/^[0-9a-zA-Z-]{1,64}$/';
                if(!preg_match($reg,$blk_name)) die("Block device name suspicious");
                $safe_blk_name = $blk_name;
                $blk_size = $blockdevice['size'];
                $reg = '/^[0-9]{6,16}$/';
                if(!preg_match($reg,$blk_size)) die("Block device size not an int of size min 6 max 16 chars.");
                $safe_blk_size = $blk_size / (1024*1024);
                $blkdev_array[] = array(
                    "name" => $safe_blk_name,
                    "size_mb" => $safe_blk_size,
                    );
            }
        }

        // Check if there's a difference between the report and the db
        $all_if_in_sql = "yes";
        for($i=0;$i<sizeof($blkdev_array);$i++){
            $myblkdev = $blkdev_array[$i];
            $safe_blk_name = $myblkdev["name"];
            $safe_blk_size = $myblkdev["size_mb"];
            $q = "SELECT id FROM blockdevices WHERE machine_id='$machine_id' AND name='$safe_blk_name' AND size_mb='$safe_blk_size'";
            $r = mysqli_query($con, $q);
            $n = mysqli_num_rows($r);
            if($n != 1){
                $all_if_in_sql = "no";
            }
        }

        // Check if the number of dev don't match
        $q = "SELECT id FROM blockdevices WHERE machine_id='$machine_id'";
        $r = mysqli_query($con, $q);
        $n = mysqli_num_rows($r);
        if($n != sizeof($blkdev_array)){
            $all_if_in_sql = "no";
        }

        // If there is, delete all block devices from db, and record them again
        if($all_if_in_sql == "no"){
            $r = mysqli_query($con, "DELETE FROM blockdevices WHERE machine_id='".$machine_id."'");
            for($i=0;$i<sizeof($blkdev_array);$i++){
                $myblkdev = $blkdev_array[$i];
                $safe_blk_name = $myblkdev["name"];
                $safe_blk_size = $myblkdev["size_mb"];
                $r = mysqli_query($con, "INSERT INTO blockdevices (machine_id, name, size_mb) VALUES ('".$machine_id."', '".$safe_blk_name."', '".$safe_blk_size."')");
            }
        }
    }

    if (isset($data["phys-blockdevices"])){
        $blkdev_array = array();
        foreach($data["phys-blockdevices"] as &$blockdevice){
            $blk_slot   = $blockdevice['slot'];
            $blk_model  = $blockdevice['model'];
            $blk_serial = $blockdevice['serial'];
            $blk_size   = $blockdevice['size'];
            $blk_state  = $blockdevice['state'];

            $reg_alpha = '/^[.0-9a-zA-Z- \(\)]{1,64}$/';
            $reg_int = '/^[.0-9]{1,64}$/';
            if(!preg_match($reg_int,   $blk_slot))   die("Block device slot suspicious");
            if(!preg_match($reg_alpha, $blk_model))  die("Block device model suspicious");
            if(!preg_match($reg_alpha, $blk_serial)) die("Block device serial suspicious");
            if(!preg_match($reg_int,   $blk_size))   die("Block device size suspicious");
            if(!preg_match($reg_alpha, $blk_state))  die("Block device state suspicious");
            $safe_blk_size = $blk_size / (1024*1024);

            $blkdev_array[] = array(
                "slot"   => $blk_slot,
                "model"  => $blk_model,
                "serial" => $blk_serial,
                "size"   => $blk_size,
                "state"  => $blk_state,
                );
        }

        // Check if there's a difference between the report and the db
        $all_if_in_sql = "yes";
        for($i=0;$i<sizeof($blkdev_array);$i++){
            $myblkdev = $blkdev_array[$i];
            $safe_blk_slot   = $myblkdev["slot"];
            $safe_blk_model  = $myblkdev["model"];
            $safe_blk_serial = $myblkdev["serial"];
            $safe_blk_size   = $myblkdev["size"];
            $safe_blk_state  = $myblkdev["state"];
            $q = "SELECT id FROM physblockdevices WHERE machine_id='$machine_id' AND slot='$safe_blk_slot' AND model='$safe_blk_model' AND serial='$safe_blk_serial' AND size='$safe_blk_size' AND state='$safe_blk_state'";
            $r = mysqli_query($con, $q);
            $n = mysqli_num_rows($r);
            if($n != 1){
                $all_if_in_sql = "no";
            }
        }

        // Check if the number of dev don't match
        $q = "SELECT id FROM physblockdevices WHERE machine_id='$machine_id'";
        $r = mysqli_query($con, $q);
        $n = mysqli_num_rows($r);
        if($n != sizeof($blkdev_array)){
            $all_if_in_sql = "no";
        }

        // If there is, delete all block devices from db, and record them again
        if($all_if_in_sql == "no"){
            $r = mysqli_query($con, "DELETE FROM physblockdevices WHERE machine_id='".$machine_id."'");
            for($i=0;$i<sizeof($blkdev_array);$i++){
                $myblkdev = $blkdev_array[$i];
                $safe_blk_slot   = $myblkdev["slot"];
                $safe_blk_model  = $myblkdev["model"];
                $safe_blk_serial = $myblkdev["serial"];
                $safe_blk_size   = $myblkdev["size"];
                $safe_blk_state  = $myblkdev["state"];
                $r = mysqli_query($con, "INSERT INTO physblockdevices (machine_id, slot, model, serial, size, state) VALUES ('".$machine_id."', '".$safe_blk_slot."', '".$safe_blk_model."', '".$safe_blk_serial."', '".$safe_blk_size."', '".$safe_blk_state."')");
            }
        }
    }

    if(isset($data["interfaces"])){
        $iface_array = [];
        foreach($data["interfaces"] as &$iface){
            if(isset($iface["name"]) && isset($iface["macaddr"]) && isset($iface["max_speed"])){
                $if_name = $iface["name"];
                $reg = '/^[0-9a-zA-Z-]{1,64}$/';
                if(!preg_match($reg,$if_name)) die("Network interface device name suspicious");
                $safe_if_name = $if_name;

                $if_macaddr = $iface["macaddr"];
                $reg = '/^[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}$/';
                if(!preg_match($reg,$if_macaddr)) die("Network interface MAC address suspicious");
                $safe_if_macaddr = $if_macaddr;

                $if_max_speed = $iface["max_speed"];
                $reg = '/^[0-9]{1,10}$/';
                if(!preg_match($reg,$if_max_speed)) die("Network interface max_speed suspicious");
                $safe_if_max_speed = $if_max_speed;

                $if_switch_hostname = $iface["switch_hostname"];
                $reg = '/^((?!-))(xn--)?[a-z0-9][.a-z0-9-]{0,61}[a-z0-9]{0,1}$/';
                if(!preg_match($reg,$if_switch_hostname)) die("Switch hostname suspicious");
                $safe_if_switch_hostname = $if_switch_hostname;

                $if_switchport_name = $iface["switchport_name"];
                $reg = '/^[.:0-9a-zA-Z-]{1,64}$/';
                if(!preg_match($reg,$if_switchport_name)) die("Switchport name suspicious");
                $safe_if_switchport_name = $if_switchport_name;

                $iface_array[] = array(
                        "name" => $safe_if_name,
                        "macaddr" => $safe_if_macaddr,
                        "max_speed" => $safe_if_max_speed,
                        "switch_hostname" => $safe_if_switch_hostname,
                        "switchport_name" => $safe_if_switchport_name,
                    );
            }
        }

        // Check if there's a difference between the report and the db
        $all_if_in_sql = "yes";

        // First check if the number of ifaces is matching.
        $q = "SELECT id FROM ifnames WHERE machine_id='$machine_id'";
        $r = mysqli_query($con, $q);
        $n = mysqli_num_rows($r);
        if($n != sizeof($iface_array)){
            $all_if_in_sql = "no";
        }

        // Then check if the details are the same.
        for($i=0;$i<sizeof($iface_array);$i++){
            $myiface = $iface_array[$i];
            $safe_if_name      = $myiface["name"];
            $safe_if_macaddr   = $myiface["macaddr"];
            $safe_if_max_speed = $myiface["max_speed"];
            $safe_if_switch_hostname = $myiface["switch_hostname"];
            $safe_if_switchport_name = $myiface["switchport_name"];
            $q = "SELECT id FROM ifnames WHERE machine_id='$machine_id' AND name='$safe_if_name' AND macaddr='$safe_if_macaddr' AND max_speed='$safe_if_max_speed' AND switchport_name='$safe_if_switchport_name' AND switch_hostname='$safe_if_switch_hostname'";
            $r = mysqli_query($con, $q);
            $n = mysqli_num_rows($r);
            if($n != 1){
                $all_if_in_sql = "no";
            }
        }

        // If there is, delete all ifaces from db, and record them again
        if($all_if_in_sql == "no"){
            $r = mysqli_query($con, "DELETE FROM ifnames WHERE machine_id='".$machine_id."'");
            for($i=0;$i<sizeof($iface_array);$i++){
                $myiface = $iface_array[$i];
                $safe_if_name      = $myiface["name"];
                $safe_if_macaddr   = $myiface["macaddr"];
                $safe_if_max_speed = $myiface["max_speed"];
                $safe_if_switch_hostname = $myiface["switch_hostname"];
                $safe_if_switchport_name = $myiface["switchport_name"];
                $q = "INSERT INTO ifnames (machine_id, name, macaddr, max_speed, switchport_name, switch_hostname) VALUES ('$machine_id', '$safe_if_name', '$safe_if_macaddr', '$safe_if_max_speed', '$safe_if_switchport_name', '$safe_if_switch_hostname')";
                $r = mysqli_query($con, $q);
            }
        }
    }
}
if(isset($conf["ipmi"]["automatic_ipmi_numbering"]) && $conf["ipmi"]["automatic_ipmi_numbering"]){
    automatic_ipmi_assign($con, $conf, $machine_id);
}

if(isset($conf["auto_racking"]["auto_rack_machines_info"]) && $conf["auto_racking"]["auto_rack_machines_info"]){
    if($conf["auto_racking"]["auto_rack_machines_num_of_discovery"] == $report_counter){
        auto_racking_auto_assign_location($con, $conf, $machine_id);
    }
}

if(isset($conf["megacli"]["megacli_auto_clear"]) && $conf["megacli"]["megacli_auto_clear"]){
    if($conf["megacli"]["megacli_auto_clear_num_of_discovery"] == $report_counter){
        hardware_profile_apply_megacli_reset_raid($con, $conf, $machine_id);
    }
}

if(isset($conf["megacli"]["megacli_auto_apply"]) && $conf["megacli"]["megacli_auto_apply"]){
    if($conf["megacli"]["megacli_auto_apply_num_of_discovery"] == $report_counter){
        hardware_profile_apply_megacli_raid($con, $conf, $machine_id, "");
    }
}

if(isset($conf["auto_provision"]["auto_add_machines_to_cluster"]) && $conf["auto_provision"]["auto_add_machines_to_cluster"]){
    if($conf["auto_provision"]["auto_add_machines_num_of_discovery"] == $report_counter){
        $json = auto_provision_add_machine($con, $conf, $machine_id);
    }
}

if(isset($conf["auto_install_os"]["auto_install_machines_os"]) && $conf["auto_install_os"]["auto_install_machines_os"]){
    if($conf["auto_install_os"]["auto_install_machines_num_of_discovery"] == $report_counter){
        oci_install_machine($con, $conf, $machine_id);
    }
}

print("Ok\n");
?>
