<?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]["system_manufacturer"])){
    $system_manufacturer = "Unknown";
}else{
    $reg = '/^[ ;_.0-9a-zA-Z-(),+]{1,120}$/';
    if(!preg_match($reg, $data["machine"][0]["system_manufacturer"])){
        $system_manufacturer = "Invalid.";
    }else{
        $system_manufacturer = $data["machine"][0]["system_manufacturer"];
    }
}

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"];
    }
}

if (!isset($data["machine"][0]["use_oci_sort_dev"])){
    $use_oci_sort_dev="no";
}else{
    if($data["machine"][0]["use_oci_sort_dev"] == "yes"){
        $use_oci_sort_dev="yes";
    }else{
        $use_oci_sort_dev="no";
    }
}

if (!isset($data["machine"][0]["cpu_vendor"])){
    $cpu_vendor = "none";
}else{
    $reg = '/^[ @:.0-9a-zA-Z\(\)]{1,120}$/';
    if(!preg_match($reg, $data["machine"][0]["cpu_vendor"])){
        $cpu_vendor = "none";
    }else{
        $cpu_vendor = $data["machine"][0]["cpu_vendor"];
    }
}

if (!isset($data["machine"][0]["cpu_model_name"])){
    $cpu_model_name = "none";
}else{
    $reg = '/^[ @:.0-9a-zA-Z\(\)]*/';
    if(!preg_match($reg, $data["machine"][0]["cpu_model_name"])){
        $cpu_model_name = "none";
    }else{
        $cpu_model_name = $data["machine"][0]["cpu_model_name"];
    }
}

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

if (!isset($data["machine"][0]["cpu_threads"])){
    $cpu_threads = 0;
}else{
    $reg = '/^[0-9]{1,9}$/';
    if(!preg_match($reg, $data["machine"][0]["cpu_threads"])){
        $cpu_threads = 0;
    }else{
        $cpu_threads = $data["machine"][0]["cpu_threads"];
    }
}

if (!isset($data["machine"][0]["cpu_core_per_socket"])){
    $cpu_core_per_socket = 0;
}else{
    $reg = '/^[0-9]{1,6}$/';
    if(!preg_match($reg, $data["machine"][0]["cpu_core_per_socket"])){
        $cpu_core_per_socket = 0;
    }else{
        $cpu_core_per_socket = $data["machine"][0]["cpu_core_per_socket"];
    }
}

if (!isset($data["machine"][0]["cpu_sockets"])){
    $cpu_sockets = 0;
}else{
    $reg = '/^[0-9]{1,6}$/';
    if(!preg_match($reg, $data["machine"][0]["cpu_sockets"])){
        $cpu_sockets = 0;
    }else{
        $cpu_sockets = $data["machine"][0]["cpu_sockets"];
    }
}

if (!isset($data["machine"][0]["boot_uefi"]) || $data["machine"][0]["boot_uefi"] != "yes"){
    $boot_uefi = "no";
}else{
    $boot_uefi = "yes";
}

if (!isset($data["machine"][0]["secure_boot"]) || $data["machine"][0]["secure_boot"] != "yes"){
    $secure_boot = "no";
}else{
    $secure_boot = "yes";
}

$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, system_manufacturer, product_name, ladvd_report, bios_version, dell_lifecycle_version, ipmi_firmware_version, ipmi_detected_ip, memory, use_oci_sort_dev, cpu_vendor, cpu_model_name, cpu_mhz, cpu_threads, cpu_core_per_socket, cpu_sockets, boot_uefi, secure_boot, status) VALUES ('" . $remote_addr. "', '" . $remote_addr. "', '$safe_serial_number' ,'$system_manufacturer' ,'$prod_name', '$ladvd_report', '$bios_version', '$dell_lifecycle_version', '$ipmi_version', '$ipmi_detected_ip', '$safe_memory_size', '$use_oci_sort_dev', '$cpu_vendor', '$cpu_model_name', '$cpu_mhz', '$cpu_threads', '$cpu_core_per_socket', '$cpu_sockets', '$boot_uefi', '$secure_boot', '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 line ".__LINE__." file ".__FILE__);
                $safe_blk_name = $blk_name;

                if(isset($blockdevice['realdev'])){
                    $blk_realdev = $blockdevice['realdev'];
                    $reg = '/^[0-9a-zA-Z-]{1,64}$/';
                    if(!preg_match($reg,$blk_realdev))	die("Block real device name suspicious line ".__LINE__." file ".__FILE__);
                    $safe_blk_realdev = $blk_realdev;
                }else{
                    $safe_blk_realdev = '';
                }

                $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 line ".__LINE__." file ".__FILE__);
                $safe_blk_size = $blk_size / (1024*1024);

                $r = mysqli_query($con, "INSERT INTO blockdevices (machine_id, name, realdev, size_mb) VALUES ('".$machine_id."', '".$safe_blk_name."', '".$safe_blk_realdev."', '".$safe_blk_size."')");
            }
        }
    }

    if (isset($data["phys-blockdevices"])){
        foreach($data["phys-blockdevices"] as &$blockdevice){
            $blk_ctrl   = $blockdevice['controller'];
            $blk_enc    = $blockdevice['enclosure'];
            $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_ctrl))   die("Block device controller suspicious line ".__LINE__." file ".__FILE__);
            if(!preg_match($reg_int,   $blk_enc))    die("Block device enclosure suspicious line ".__LINE__." file ".__FILE__);
            if(!preg_match($reg_int,   $blk_slot))   die("Block device slot suspicious line ".__LINE__." file ".__FILE__);
            if(!preg_match($reg_alpha, $blk_model))  die("Block device model suspicious line ".__LINE__." file ".__FILE__);
            if(!preg_match($reg_alpha, $blk_serial)) die("Block device serial suspicious line ".__LINE__." file ".__FILE__);
            if(!preg_match($reg_int,   $blk_size))   die("Block device size suspicious line".__LINE__." file ".__FILE__);
            if(!preg_match($reg_alpha, $blk_state))  die("Block device state suspicious line ".__LINE__." file ".__FILE__);
            $safe_blk_size = $blk_size / (1024*1024);
            $r = mysqli_query($con, "INSERT INTO physblockdevices (machine_id, controller, enclosure, slot, model, serial, size, state) VALUES ('".$machine_id."', '".$blk_ctrl."', '".$blk_enc."', '".$blk_slot."', '".$blk_model."', '".$blk_serial."', '".$blk_size."', '".$blk_state."')");
        }
    }

    if(isset($data["blkdev_ctrl"])){
        foreach($data["blkdev_ctrl"] as &$ctrl){
            if(isset($ctrl["hwid"]) && isset($ctrl["vendor"]) && isset($ctrl["product"]) && isset($ctrl["ctrl_type"]) && isset($ctrl["firmware_version"])){
                $blkdev_ctrl_hwid             = $ctrl["hwid"];
                $blkdev_ctrl_vendor           = $ctrl["vendor"];
                $blkdev_ctrl_product          = $ctrl["product"];
                $blkdev_ctrl_ctrl_type        = $ctrl["ctrl_type"];
                $blkdev_ctrl_firmware_version = $ctrl["firmware_version"];

                $reg_alpha = '/^[.0-9a-zA-Z-_ \(\)\[\]:\/]{1,64}$/';
                $reg_int = '/^[.0-9a-zA-Z-]{1,64}$/';
                if(!preg_match($reg_alpha, $blkdev_ctrl_hwid))             die("Block device controller hwid suspicious line ".__LINE__." file ".__FILE__);
                if(!preg_match($reg_alpha, $blkdev_ctrl_vendor))           die("Block device controller vendor suspicious line ".__LINE__." file ".__FILE__);
                if(!preg_match($reg_alpha, $blkdev_ctrl_product))          die("Block device controller product suspicious line ".__LINE__." file ".__FILE__);
                if(!preg_match($reg_alpha, $blkdev_ctrl_ctrl_type))        die("Block device controller ctrl type suspicious line ".__LINE__." file ".__FILE__);
                if(!preg_match($reg_int,   $blkdev_ctrl_firmware_version)) die("Block device controller fw version suspicious line ".__LINE__." file ".__FILE__);
                $r = mysqli_query($con, "INSERT INTO blkdev_ctrl (machine_id, hwid, vendor, product, ctrl_type, firmware_version) VALUES ('".$machine_id."', '".$blkdev_ctrl_hwid."', '".$blkdev_ctrl_vendor."', '".$blkdev_ctrl_product."', '".$blkdev_ctrl_ctrl_type."', '".$blkdev_ctrl_firmware_version."')");
            }
        }
    }

    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,$if_name)) die("Network interface device name suspicious line ".__LINE__." file ".__FILE__);
                $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 line ".__LINE__." file ".__FILE__);
                $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 line ".__LINE__." file ".__FILE__);
                $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 line ".__LINE__." file ".__FILE__);
                $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 line ".__LINE__." file ".__FILE__);
                $safe_if_switchport_name = $if_switchport_name;

                if(isset($iface["firmware_version"]) && $iface["firmware_version"] != ""){
                    $if_firmware_version = $iface["firmware_version"];
                    $reg = '/^[.:0-9a-zA-Z-+]{1,64}$/';
                    if(!preg_match($reg,$if_firmware_version)) die("Iface firmware version suspicious line ".__LINE__." file ".__FILE__);
                    $safe_if_firmware_version = $if_firmware_version;
                }else{
                    $safe_if_firmware_version = "";
                }

                if(isset($iface["driver"]) && $iface["driver"] != ""){
                    $if_driver = $iface["driver"];
                    $reg = '/^[_.:0-9a-zA-Z-]{1,64}$/';
                    if(!preg_match($reg,$if_driver)) die("Iface driver name suspicious line ".__LINE__." file ".__FILE__);
                    $safe_if_driver = $if_driver;
                }else{
                    $safe_if_driver = "";
                }
                $r = mysqli_query($con, "INSERT INTO ifnames (machine_id, name, macaddr, max_speed, switchport_name, switch_hostname, firmware_version, driver) VALUES ('$machine_id', '$safe_if_name', '$safe_if_macaddr', '$safe_if_max_speed', '$safe_if_switchport_name', '$safe_if_switch_hostname', '$safe_if_firmware_version', '$safe_if_driver')");
            }
        }
    }
}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', system_manufacturer='$system_manufacturer', 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', use_oci_sort_dev='$use_oci_sort_dev', cpu_vendor='$cpu_vendor', cpu_model_name='$cpu_model_name', cpu_mhz='$cpu_mhz', cpu_threads='$cpu_threads', cpu_core_per_socket='$cpu_core_per_socket', cpu_sockets='$cpu_sockets', boot_uefi='$boot_uefi', secure_boot='$secure_boot', 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 line ".__LINE__." file ".__FILE__);
                $safe_blk_name = $blk_name;

                if(isset($blockdevice['realdev'])){
                    $blk_realdev = $blockdevice['realdev'];
                    $reg = '/^[0-9a-zA-Z-]{1,64}$/';
                    if(!preg_match($reg,$blk_realdev))	die("Block real device name suspicious $blk_realdev line ".__LINE__." file ".__FILE__);
                    $safe_blk_realdev = $blk_realdev;
                }else{
                    $safe_blk_realdev = '';
                }

                $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 line ".__LINE__." file ".__FILE__);
                $safe_blk_size = $blk_size / (1024*1024);

                $blkdev_array[] = array(
                    "name" => $safe_blk_name,
                    "realdev" => $safe_blk_realdev,
                    "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_realdev = $myblkdev["realdev"];
            $safe_blk_size = $myblkdev["size_mb"];
            $q = "SELECT id FROM blockdevices WHERE machine_id='$machine_id' AND name='$safe_blk_name' AND realdev='$safe_blk_realdev' 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_realdev = $myblkdev["realdev"];
                $safe_blk_size = $myblkdev["size_mb"];
                $r = mysqli_query($con, "INSERT INTO blockdevices (machine_id, name, realdev, size_mb) VALUES ('".$machine_id."', '".$safe_blk_name."', '".$safe_blk_realdev."', '".$safe_blk_size."')");
            }
        }
    }

    if (isset($data["phys-blockdevices"])){
        $blkdev_array = array();
        foreach($data["phys-blockdevices"] as &$blockdevice){
            $blk_ctrl   = $blockdevice['controller'];
            $blk_enc    = $blockdevice['enclosure'];
            $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($blk_ctrl != ""){
                if(!preg_match($reg_alpha, $blk_ctrl))   die("Block device controller suspicious line ".__LINE__." file ".__FILE__);
            }
            if($blk_enc != ""){
                if(!preg_match($reg_int,   $blk_enc))    die("Block device enclosure suspicious line ".__LINE__." file ".__FILE__);
            }
            if(!preg_match($reg_int,   $blk_slot))   die("Block device slot suspicious line ".__LINE__." file ".__FILE__);
            if(!preg_match($reg_alpha, $blk_model))  die("Block device model suspicious line ".__LINE__." file ".__FILE__);
            if(!preg_match($reg_alpha, $blk_serial)) die("Block device serial suspicious line ".__LINE__." file ".__FILE__);
            if(!preg_match($reg_int,   $blk_size))   die("Block device size suspicious line ".__LINE__." file ".__FILE__);
            if(!preg_match($reg_alpha, $blk_state))  die("Block device state suspicious line ".__LINE__." file ".__FILE__);
            $safe_blk_size = $blk_size / (1024*1024);

            $blkdev_array[] = array(
                "controller" => $blk_ctrl,
                "enclosure"  => $blk_enc,
                "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_controller = $myblkdev["controller"];
            $safe_blk_enclosure  = $myblkdev["enclosure"];
            $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 controller='$safe_blk_controller' AND enclosure='$safe_blk_enclosure' 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_controller = $myblkdev["controller"];
                $safe_blk_enclosure  = $myblkdev["enclosure"];
                $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, controller, enclosure, slot, model, serial, size, state) VALUES ('".$machine_id."', '".$safe_blk_controller."', '".$safe_blk_enclosure."', '".$safe_blk_slot."', '".$safe_blk_model."', '".$safe_blk_serial."', '".$safe_blk_size."', '".$safe_blk_state."')");
            }
        }
    }

    if(isset($data["blkdev_ctrl"])){
        $blkdev_ctrl_array = array();
        foreach($data["blkdev_ctrl"] as &$ctrl){
            if(isset($ctrl["hwid"]) && isset($ctrl["vendor"]) && isset($ctrl["product"]) && isset($ctrl["ctrl_type"]) && isset($ctrl["firmware_version"])){
                $blkdev_ctrl_hwid             = $ctrl["hwid"];
                $blkdev_ctrl_vendor           = $ctrl["vendor"];
                $blkdev_ctrl_product          = $ctrl["product"];
                $blkdev_ctrl_ctrl_type        = $ctrl["ctrl_type"];
                $blkdev_ctrl_firmware_version = $ctrl["firmware_version"];

                $reg_alpha = '/^[.0-9a-zA-Z-_ \(\)\[\]:\\/\\\\]{1,64}$/';
                $reg_int = '/^[.0-9a-zA-Z-]{1,64}$/';
                if(!preg_match($reg_alpha, $blkdev_ctrl_hwid))             die("Block device controller hwid suspicious: $blkdev_ctrl_hwid line ".__LINE__." file ".__FILE__);
                if(!preg_match($reg_alpha, $blkdev_ctrl_vendor))           die("Block device controller vendor suspicious line ".__LINE__." file ".__FILE__);
                if(!preg_match($reg_alpha, $blkdev_ctrl_product))          die("Block device controller product suspicious: $blkdev_ctrl_product line ".__LINE__." file ".__FILE__);
                if(!preg_match($reg_alpha, $blkdev_ctrl_ctrl_type))        die("Block device controller ctrl type suspicious line ".__LINE__." file ".__FILE__);
                if($blkdev_ctrl_firmware_version != ""){
                    if(!preg_match($reg_int,   $blkdev_ctrl_firmware_version)) die("Block device controller fw version suspicious line ".__LINE__." file ".__FILE__);
                }

                $blkdev_ctrl_array[] = array(
                    "hwid" => $blkdev_ctrl_hwid,
                    "vendor" => $blkdev_ctrl_vendor,
                    "product" => $blkdev_ctrl_product,
                    "ctrl_type" => $blkdev_ctrl_ctrl_type,
                    "firmware_version" =>$blkdev_ctrl_firmware_version,
                    );
            }
        }

        // Check if there's a difference between the report and the db
        $all_if_in_sql = "yes";
        for($i=0;$i<sizeof($blkdev_ctrl_array);$i++){
            $myblkdev_ctrl = $blkdev_ctrl_array[$i];
            $safe_blkdev_ctrl_hwid             = $myblkdev_ctrl["hwid"];
            $safe_blkdev_ctrl_vendor           = $myblkdev_ctrl["vendor"];
            $safe_blkdev_ctrl_product          = $myblkdev_ctrl["product"];
            $safe_blkdev_ctrl_ctrl_type        = $myblkdev_ctrl["ctrl_type"];
            $safe_blkdev_ctrl_firmware_version = $myblkdev_ctrl["firmware_version"];
            $q = "SELECT id FROM blkdev_ctrl WHERE machine_id='$machine_id' AND hwid='$safe_blkdev_ctrl_hwid' AND vendor='$safe_blkdev_ctrl_vendor' AND product='$safe_blkdev_ctrl_product' AND ctrl_type='$safe_blkdev_ctrl_ctrl_type' AND firmware_version='$safe_blkdev_ctrl_firmware_version'";
            $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 blkdev_ctrl WHERE machine_id='$machine_id'";
        $r = mysqli_query($con, $q);
        $n = mysqli_num_rows($r);
        if($n != sizeof($blkdev_ctrl_array)){
            $all_if_in_sql = "no";
        }

        // If there is, delete all block devices ctrl from db, and record them again
        if($all_if_in_sql == "no"){
            $r = mysqli_query($con, "DELETE FROM blkdev_ctrl WHERE machine_id='".$machine_id."'");
            for($i=0;$i<sizeof($blkdev_ctrl_array);$i++){
                $myblkdev_ctrl = $blkdev_ctrl_array[$i];
                $safe_blkdev_ctrl_hwid             = $myblkdev_ctrl["hwid"];
                $safe_blkdev_ctrl_vendor           = $myblkdev_ctrl["vendor"];
                $safe_blkdev_ctrl_product          = $myblkdev_ctrl["product"];
                $safe_blkdev_ctrl_ctrl_type        = $myblkdev_ctrl["ctrl_type"];
                $safe_blkdev_ctrl_firmware_version = $myblkdev_ctrl["firmware_version"];
                $r = mysqli_query($con, "INSERT INTO blkdev_ctrl (machine_id, hwid, vendor, product, ctrl_type, firmware_version) VALUES ('$machine_id','$safe_blkdev_ctrl_hwid','$safe_blkdev_ctrl_vendor','$safe_blkdev_ctrl_product','$safe_blkdev_ctrl_ctrl_type','$safe_blkdev_ctrl_firmware_version')");
            }
        }
    }

    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 '$if_name' suspicious line ".__LINE__." file ".__FILE__);
                $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 '$if_macaddr' suspicious line ".__LINE__." file ".__FILE__);
                $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 '$if_max_speed' suspicious line ".__LINE__." file ".__FILE__);
                $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 '$if_switch_hostname' suspicious line ".__LINE__." file ".__FILE__);
                $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 '$if_switchport_name' suspicious line ".__LINE__." file ".__FILE__);
                $safe_if_switchport_name = $if_switchport_name;

                if(isset($iface["firmware_version"]) && $iface["firmware_version"] != ""){
                    $if_firmware_version = $iface["firmware_version"];
                    $reg = '/^[\/.:0-9a-zA-Z-+]{1,64}$/';
                    if(!preg_match($reg,$if_firmware_version)) die("Iface firmware version '$if_firmware_version' suspicious line ".__LINE__." file ".__FILE__);
                    $safe_if_firmware_version = $if_firmware_version;
                }else{
                    $safe_if_firmware_version = "";
                }

                if(isset($iface["driver"]) && $iface["driver"] != ""){
                    $if_driver = $iface["driver"];
                    $reg = '/^[_.:0-9a-zA-Z-]{1,64}$/';
                    if(!preg_match($reg,$if_driver)) die("Iface driver name '$if_driver' suspicious line ".__LINE__." file ".__FILE__);
                    $safe_if_driver = $if_driver;
                }else{
                    $safe_if_driver = "";
                }

                $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,
                        "firmware_version" => $safe_if_firmware_version,
                        "driver" => $safe_if_driver,
                    );
            }
        }

        // 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.
        // Useless if $all_if_in_sql is already == "no",
        // so we skip it in that case.
        if($all_if_in_sql != "no"){
            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"];
                $safe_if_firmware_version = $myiface["firmware_version"];
                $safe_if_driver = $myiface["driver"];
                $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' AND firmware_version='$safe_if_firmware_version' AND driver='$safe_if_driver'";
                $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"];
                $safe_if_firmware_version = $myiface["firmware_version"];
                $safe_if_driver = $myiface["driver"];
                $q = "INSERT INTO ifnames (machine_id, name, macaddr, max_speed, switchport_name, switch_hostname, firmware_version, driver) VALUES ('$machine_id', '$safe_if_name', '$safe_if_macaddr', '$safe_if_max_speed', '$safe_if_switchport_name', '$safe_if_switch_hostname', '$safe_if_firmware_version', '$safe_if_driver')";
                $r = mysqli_query($con, $q);
            }
        }
    }
}

# Refretch the $machine, as it may have changed above.
$q = "SELECT * FROM machines WHERE id='$machine_id'";
$r = mysqli_query($con, $q);
$n = mysqli_num_rows($r);
if($n != 1){
    die("Cannot fetch machine $machine_id to perform automations: ".__FILE__." line ".__LINE__);
}
$machine = mysqli_fetch_array($r);

# Apply the automations
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){
        if($machine["status"] == "live"){
            hardware_profile_apply_megacli_reset_raid($con, $conf, $machine_id);
        }else{
            print("Skipping RAID reset as server is not in status==live\n");
        }
    }
}

if(isset($conf["megacli"]["megacli_auto_apply"]) && $conf["megacli"]["megacli_auto_apply"]){
    if($conf["megacli"]["megacli_auto_apply_num_of_discovery"] == $report_counter){
        if($machine["status"] == "live"){
            hardware_profile_apply_megacli_raid($con, $conf, $machine_id, "");
        }else{
            print("Skipping RAID config as server is not in status==live\n");
        }
    }
}

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){
        if($machine["status"] == "live"){
            $json = auto_provision_add_machine($con, $conf, $machine_id);
        }else{
            print("Skipping auto-add, as server is not in status==live\n");
        }
    }
}

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){
        if($machine["status"] == "live"){
            oci_install_machine($con, $conf, $machine_id);
        }else{
            print("Skipping auto-install, as server is not in status==live\n");
        }
    }
}

print("Ok\n");
?>
