<?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);

function get_machine_from_serial_or_hostname($con, $conf){
    $json["status"] = "success";
    $json["message"] = "Successfuly queried API.";
    $json["data"] = Array();

    if(isset($_REQUEST["serial"])){
        $safe_machine_serial = safe_serial("serial");
        $safe_machine_hostname = safe_fqdn("serial");
    }elseif(isset($_REQUEST["machine_serial"])){
        $safe_machine_serial = safe_serial("machine_serial");
        $safe_machine_hostname = safe_fqdn("machine_serial");
    }
    if($safe_machine_serial === FALSE && $safe_machine_hostname === FALSE ){
        $json["status"] = "error";
        $json["message"] = "Error: not valid chassis serial number or hostname.";
        return $json;
    }
    if($safe_machine_serial === FALSE){
        $q = "SELECT * FROM machines WHERE hostname='$safe_machine_hostname'";
    }else{
        $q = "SELECT * FROM machines WHERE serial='$safe_machine_serial'";
    }
    $r = mysqli_query($con, $q);
    if($r === FALSE){
        $json["status"] = "error";
        $json["message"] = mysqli_error($con). " doing $q";
        return $json;
    }
    $n = mysqli_num_rows($r);
    if($n != 1){
        if($safe_machine_serial !== FALSE){
            $q = "SELECT * FROM machines WHERE hostname='$safe_machine_hostname'";
            $r = mysqli_query($con, $q);
            if($r === FALSE){
                $json["status"] = "error";
                $json["message"] = mysqli_error($con). " doing $q";
                return $json;
            }
            $n = mysqli_num_rows($r);
            if($n != 1){
                $json["status"] = "error";
                $json["message"] = "Error: machine with serial or hostname $safe_machine_serial doesn't exist.";
                return $json;
            }
        }else{
            $json["status"] = "error";
            $json["message"] = "Error: machine with serial or hostname $safe_machine_serial doesn't exist.";
            return $json;
        }
    }
    $json["data"] = mysqli_fetch_array($r);
    return $json;
}

function api_actions($con,$conf){
    $json["status"] = "success";
    $json["message"] = "Successfuly queried API.";
    if(!isset($_REQUEST["action"])){
        $json["status"] = "error";
        $json["message"] = "Error: no action specified.";
        return $json;
    }

    // If not on a trusted network, then we need authentication
    if(oci_ip_check($con, $conf) === FALSE){
        if((!isset($_REQUEST["oci_login"])) || $_REQUEST["oci_login"] == "" || (!isset($_REQUEST["oci_pass"])) || $_REQUEST["oci_pass"] == ""){
            $json["status"] = "error";
            $json["message"] = "Error: please set oci_login and oci_pass to authenticate.";
            return $json;
        }
        $ret = oci_auth_user($con, $conf, $_REQUEST["oci_login"], $_REQUEST["oci_pass"]);
        if($ret["status"] != "success"){
            return $ret;
        }
    }

    switch($_REQUEST["action"]){
    case "enc":
        # Puppet ENC is now in src/inc/enc.php
        $json = puppet_enc($con,$conf);
        return $json;
        break;
    case "machine_show_from_hostname":
        $safe_hostname = safe_fqdn("hostname");
        $r = mysqli_query($con, "SELECT * FROM machines WHERE hostname='$safe_hostname'");
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "No such hostname in database.";
            return $json;
        }
        $a = mysqli_fetch_array($r);
        $json["data"] = $a;
        return $json;
        break;
    case "cluster_rolecounts_list":
        $safe_cluster_name = safe_fqdn("name");
        if($safe_cluster_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid cluster name.";
            return $json;
        }
        $q = "SELECT * FROM clusters WHERE name='$safe_cluster_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: cluster not found.";
            return $json;
        }
        $cluster = mysqli_fetch_array($r);
        $cluster_id = $cluster["id"];
        $q = "SELECT roles.name AS role, rolecounts.count AS count FROM roles,rolecounts WHERE rolecounts.cluster='$cluster_id' AND rolecounts.role=roles.id ORDER BY roles.name";
        $r = mysqli_query($con, $q);
        $n = mysqli_num_rows($r);
        $json["data"] = Array();
        for($i=0;$i<$n;$i++){
            $json["data"][] = mysqli_fetch_array($r);
        }
        return $json;
        break;
    case "cluster_show":
        $safe_cluster_name = safe_fqdn("name");
        if($safe_cluster_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid cluster name.";
            return $json;
        }
        $q = "SELECT * FROM clusters WHERE name='$safe_cluster_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: cluster not found.";
            return $json;
        }
        $json["data"] = mysqli_fetch_array($r);

        # Get the first master serial.
        if(! is_null($json["data"]["first_master_machine_id"])){
            $machine_id = $json["data"]["first_master_machine_id"];
            $q = "SELECT serial FROM machines WHERE id='$machine_id'";
            $r = mysqli_query($con, $q);
            if($r === FALSE){
                $json["status"] = "error";
                $json["message"] = mysqli_error($con);
                return $json;
            }
            $n = mysqli_num_rows($r);
            if($n != 1){
                $json["status"] = "error";
                $json["message"] = "Error: first master serial not found in file: ".__FILE__." line: ".__LINE__.".";
                return $json;
            }
            $machine = mysqli_fetch_array($r);
            $json["data"]["first_master_machine_serial"] = $machine["serial"];
        }
        return $json;
        break;
    case "cluster_rolecounts_set":
        $safe_cluster_name = safe_fqdn("name");
        if($safe_cluster_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid cluster name.";
            return $json;
        }
        $q = "SELECT * FROM clusters WHERE name='$safe_cluster_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: cluster not found.";
            return $json;
        }
        $cluster = mysqli_fetch_array($r);
        $safe_cluster_id = $cluster["id"];

        $safe_role_name = safe_fqdn("role");
        if($safe_role_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid role name.";
            return $json;
        }
        $q = "SELECT * FROM roles WHERE name='$safe_role_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: role not found.";
            return $json;
        }
        $role = mysqli_fetch_array($r);
        $safe_role_id = $role["id"];

        $safe_role_count = safe_int("count");
        if($safe_role_count === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid role count.";
            return $json;
        }

        $q = "UPDATE rolecounts SET count='$safe_role_count' WHERE role='$safe_role_id' AND cluster='$safe_cluster_id'";
        $r = mysqli_query($con, $q);
        return $json;
        break;
    case "cluster_set":
        $safe_cluster_name = safe_fqdn("name");
        if($safe_cluster_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid cluster name.";
            return $json;
        }
        $q = "SELECT * FROM clusters WHERE name='$safe_cluster_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: cluster not found.";
            return $json;
        }
        $cluster = mysqli_fetch_array($r);
        $update = "";

        // initial_cluster_setup
        if(isset($_REQUEST["initial_cluster_setup"])){
            if($_REQUEST["initial_cluster_setup"] == "yes"){
                $safe_initial_cluster_setup = "yes";
            }else{
                $safe_initial_cluster_setup = "no";
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "initial_cluster_setup='$safe_initial_cluster_setup'";
        }

        // nested virtualization
        if(isset($_REQUEST["nested_virt"])){
            if($_REQUEST["nested_virt"] == "yes"){
                $safe_nested_virt = "yes";
            }else{
                $safe_nested_virt = "no";
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "nested_virt='$safe_nested_virt'";
        }

        // nested virtualization
        if(isset($_REQUEST["use_ovs_ifaces"])){
            if($_REQUEST["use_ovs_ifaces"] == "yes"){
                $safe_use_ovs_ifaces = "yes";
            }else{
                $safe_use_ovs_ifaces = "no";
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "use_ovs_ifaces='$safe_use_ovs_ifaces'";
        }

        // Swift part power
        if(isset($_REQUEST["swift_part_power"])){
            $safe_swift_part_power = safe_int("swift_part_power");
            if($safe_swift_part_power === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not valid swift part power.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "swift_part_power='$safe_swift_part_power'";
        }

        // Swift proxy hostname
        if(isset($_REQUEST["swift_proxy_hostname"])){
            $safe_swift_proxy_hostname = safe_fqdn("swift_proxy_hostname");
            if($safe_swift_proxy_hostname === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid swift proxy hostname.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "swift_proxy_hostname='$safe_swift_proxy_hostname'";
        }

        // Swift encryption key ID
        if(isset($_REQUEST["swift_encryption_key_id"])){
            $safe_swift_encryption_key_id = safe_uuid("swift_encryption_key_id");
            if($safe_swift_encryption_key_id === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: swift_encryption_key_id is not an UUID.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "swift_encryption_key_id='$safe_swift_encryption_key_id'";
        }

        // Swift disable encryption
        if(isset($_REQUEST["swift_disable_encryption"])){
            if($_REQUEST["swift_disable_encryption"] == "yes"){
                $safe_swift_disable_encryption = "yes";
            }else{
                $safe_swift_disable_encryption = "no";
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "swift_disable_encryption='$safe_swift_disable_encryption'";
        }

        if(isset($_REQUEST["swift_object_replicator_concurrency"])){
            $safe_swift_object_replicator_concurrency = safe_int("swift_object_replicator_concurrency");
            if($safe_swift_object_replicator_concurrency === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: swift_object_replicator_concurrency is not an int.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "swift_object_replicator_concurrency='$safe_swift_object_replicator_concurrency'";
        }

        if(isset($_REQUEST["swift_rsync_connection_limit"])){
            $safe_swift_rsync_connection_limit = safe_int("swift_rsync_connection_limit");
            if($safe_rsync_connection_limit === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: swift_rsync_connection_limit is not an int.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "swift_rsync_connection_limit='$safe_swift_rsync_connection_limit'";
        }

        // External swift stuff
        if(isset($_REQUEST["extswift_use_external"])){
            if($_REQUEST["extswift_use_external"] == "yes"){
                $safe_extswift_use_external = "yes";
            }else{
                $safe_extswift_use_external = "no";
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "extswift_use_external='$safe_extswift_use_external'";
        }

        if(isset($_REQUEST["extswift_auth_url"])){
            $safe_extswift_auth_url = safe_url("extswift_auth_url");
            if($safe_extswift_auth_url === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: extswift_auth_url is not a valid URL.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "extswift_auth_url='$safe_extswift_auth_url'";
        }

        if(isset($_REQUEST["extswift_proxy_url"])){
            $safe_extswift_proxy_url = safe_url("extswift_proxy_url");
            if($safe_extswift_proxy_url === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: extswift_proxy_url is not a valid URL.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "extswift_proxy_url='$safe_extswift_proxy_url'";
        }

        if(isset($_REQUEST["extswift_project_name"])){
            $safe_extswift_project_name = safe_fqdn("extswift_project_name");
            if($safe_extswift_project_name === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid extswift_project_name.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "extswift_project_name='$safe_extswift_project_name'";
        }

        if(isset($_REQUEST["extswift_project_domain_name"])){
            $safe_extswift_project_domain_name = safe_fqdn("extswift_project_domain_name");
            if($safe_extswift_project_domain_name === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid extswift_project_domain_name.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "extswift_project_domain_name='$safe_extswift_project_domain_name'";
        }

        if(isset($_REQUEST["extswift_user_name"])){
            $safe_extswift_user_name = safe_fqdn("extswift_user_name");
            if($safe_extswift_user_name === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid extswift_user_name.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "extswift_user_name='$safe_extswift_user_name'";
        }

        if(isset($_REQUEST["extswift_user_domain_name"])){
            $safe_extswift_user_domain_name = safe_fqdn("extswift_user_domain_name");
            if($safe_extswift_user_domain_name === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid extswift_user_domain_name.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "extswift_user_domain_name='$safe_extswift_user_domain_name'";
        }

        if(isset($_REQUEST["extswift_password"])){
            $safe_extswift_password = safe_password("extswift_password");
            if($safe_extswift_password === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid extswift_password.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "extswift_password='$safe_extswift_password'";
        }

        // Time server host
        if(isset($_REQUEST["time_server_host"])){
            $safe_time_server_host = safe_fqdn("time_server_host");
            if($safe_swift_part_power === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not valid time server host.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "time_server_host='$safe_time_server_host'";
        }

        // Time server host
        if(isset($_REQUEST["vip_hostname"])){
            $safe_vip_hostname = safe_fqdn("vip_hostname");
            if($safe_swift_part_power === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not valid time server host.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "vip_hostname='$safe_vip_hostname'";
        }

        if(isset($_REQUEST["amp_secgroup_list"])){
            $safe_amp_secgroup_list = safe_uuid_list("amp_secgroup_list");
            if($safe_amp_secgroup_list === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not valid UUID list for amp_secgroup_list.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "amp_secgroup_list='$safe_amp_secgroup_list'";
        }

        if(isset($_REQUEST["amp_boot_network_list"])){
            $safe_amp_boot_network_list = safe_uuid_list("amp_boot_network_list");
            if($safe_amp_boot_network_list === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not valid UUID list for amp_boot_network_list.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "amp_boot_network_list='$safe_amp_boot_network_list'";
        }

        if(isset($_REQUEST["disable_notifications"])){
            if($_REQUEST["disable_notifications"] == "yes"){
                $safe_disable_notifications = "yes";
            }else{
                $safe_disable_notifications = "no";
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "disable_notifications='$safe_disable_notifications'";
        }

        if(isset($_REQUEST["enable_monitoring_graphs"])){
            if($_REQUEST["enable_monitoring_graphs"] == "yes"){
                $safe_enable_monitoring_graphs = "yes";
            }else{
                $safe_enable_monitoring_graphs = "no";
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "enable_monitoring_graphs='$safe_enable_monitoring_graphs'";
        }
        if(isset($_REQUEST["statsd_hostname"])){
            $safe_statsd_hostname = safe_fqdn("statsd_hostname");
            if($safe_statsd_hostname == FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not valid statsd host.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "statsd_hostname='$safe_statsd_hostname'";
        }

        if(isset($_REQUEST["monitoring_graphite_host"])){
            $safe_monitoring_graphite_host = safe_fqdn("monitoring_graphite_host");
            if($safe_monitoring_graphite_host === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not valid monitoring graphite host.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "monitoring_graphite_host='$safe_monitoring_graphite_host'";
        }

        if(isset($_REQUEST["monitoring_graphite_port"])){
            $safe_monitoring_graphite_port = safe_int("monitoring_graphite_port");
            if($safe_monitoring_graphite_port === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not valid monitoring graphite port.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "monitoring_graphite_port='$safe_monitoring_graphite_port'";
        }
        if(isset($_REQUEST["self_signed_api_cert"])){
            if($_REQUEST["self_signed_api_cert"] == "yes"){
                $safe_self_signed_api_cert = "yes";
            }else{
                $safe_self_signed_api_cert = "no";
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "self_signed_api_cert='$safe_self_signed_api_cert'";
        }

        # Emulated CPU config
        if(isset($_REQUEST["cpu_mode"])){
            $safe_cpu_mode = safe_fqdn("cpu_mode");
            if($safe_cpu_mode === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not valid cpu-mode.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "cpu_mode='$safe_cpu_mode'";
        }

        if(isset($_REQUEST["cpu_model"])){
            $safe_cpu_model = safe_password("cpu_model");
            if($safe_cpu_model === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not valid cpu-model.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "cpu_model='$safe_cpu_model'";
        }

        if(isset($_REQUEST["cpu_model_extra_flags"])){
            $safe_cpu_model_extra_flags = safe_password("cpu_model_extra_flags");
            if($safe_cpu_model_extra_flags === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not valid cpu_model_extra_flags here.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "cpu_model_extra_flags='$safe_cpu_model_extra_flags'";
        }

        if(isset($_REQUEST["first_master"])){
            $safe_first_master_serial = safe_serial("first_master");
            if($safe_first_master_serial === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not valid chassis serial number.";
                return $json;
            }
            $r = mysqli_query($con, "SELECT * FROM machines WHERE serial='$safe_first_master_serial' AND role='controller' AND cluster='".$cluster["id"]."'");
            if($r === FALSE){
                $json["status"] = "error";
                $json["message"] = mysqli_error($con). " doing $q";
                return $json;
            }
            $n = mysqli_num_rows($r);
            if($n != 1){
                $json["status"] = "error";
                $json["message"] = "Error: machine with serial $safe_machine_serial doesn't exist as a controller on cluster $safe_cluster_name.";
                return $json;
            }
            $machine = mysqli_fetch_array($r);
            $machine_id      = $machine["id"];
            if($update != ""){
                $update .= ", ";
            }
            $update .= "first_master_machine_id='$machine_id'";
        }

        # Build the API using the variables.json file
        $json_file = file_get_contents("/usr/share/openstack-cluster-installer/variables.json");
        $dec_json = json_decode($json_file, TRUE);
        $items_json_array = $dec_json["clusters"];
        $a_keys = array_keys($items_json_array);
        $n = sizeof($a_keys);
        for($i=0;$i<$n;$i++){
                $col = $a_keys[$i];
                $attr = $items_json_array[$col];
                if(isset($_REQUEST[$col])){
                    switch($attr["type"]){
                    case "int":
                        $safe_value = safe_int($col);
                        break;
                    case "float":
                        $safe_value = safe_float($col);
                        break;
                    case "boolean":
                        if($_REQUEST[$col] == "yes"){
                            $safe_value = "yes";
                        }else{
                            $safe_value = "no";
                        }
                        break;
                    case "fqdn":
                        $safe_value = safe_fqdn($col);
                        break;
                    case "string":
                        $safe_value = safe_password($col);
                        break;
                    default:
                        $safe_value = FALSE;
                        break;
                    }
                    if($safe_value === FALSE){
                        $json["status"] = "error";
                        $json["message"] = "Error: not valid $col here.";
                        return $json;
                    }
                    if($update != ""){
                        $update .= ", ";
                    }
                    $update .= "$col='$safe_value'";
                }
        }

        $q = "UPDATE clusters SET $update WHERE name='$safe_cluster_name'";
        if($update != ""){
            $r = mysqli_query($con, $q);
        }

        return $json;
        break;
    case "cluster_show_ips":
        $safe_cluster_name = safe_fqdn("name");
        if($safe_cluster_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid cluster name.";
            return $json;
        }
        $q = "SELECT * FROM clusters WHERE name='$safe_cluster_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: cluster not found.";
            return $json;
        }
        $cluster = mysqli_fetch_array($r);
        $cluster_id = $cluster["id"];
        $q = "SELECT machines.hostname AS hostname, INET_NTOA(ips.ip) AS ipaddr FROM machines,ips WHERE machines.cluster='$cluster_id' AND machines.id=ips.machine";
        $r = mysqli_query($con, $q);
        $n = mysqli_num_rows($r);
        for($i=0;$i<$n;$i++){
            $json["data"][] = mysqli_fetch_array($r);
        }
        return $json;
        break;
    case "machine_destroy":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];
        $machine_id = $machine["id"];

        $q = "DELETE FROM blockdevices WHERE machine_id='$machine_id'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con). " doing $q";
            return $json;
        }

        $q = "DELETE FROM physblockdevices WHERE machine_id='$machine_id'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con). " doing $q";
            return $json;
        }

        $q = "DELETE FROM ifnames WHERE machine_id='$machine_id'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con). " doing $q";
            return $json;
        }

        $q = "DELETE FROM ips WHERE machine='$machine_id'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con). " doing $q";
            return $json;
        }

        $q = "DELETE FROM machines WHERE id='$machine_id'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con). " doing $q";
            return $json;
        }
        return $json;
        break;
    case "get_machine_status":
        # Validate IPv4
        $safe_ip = safe_ipv4("ipaddr");
        if($safe_ip === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: wrong ipaddr param.";
            return $json;
        }
        if(check_machine_with_ip_exists($safe_ip) === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: machine with ip $safe_ip doesn't exist.";
            return $json;
        }
        # Fetch machine info and output
        $r = mysqli_query($con, "SELECT * FROM machines WHERE ipaddr='$safe_ip'");
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $install_machine = mysqli_fetch_array($r);
        $json["data"] = $install_machine;
        return $json;
        break;
    case "machine_list":
        $r = mysqli_query($con, "SELECT * FROM machines");
        $n = mysqli_num_rows($r);
        $json["data"] = array();
        for($i=0;$i<$n;$i++){
            $a = mysqli_fetch_array($r);
            $json["data"][$i] = $a;
            $allfld = array("hostname","dell_lifecycle_version","notes","loc_dc","loc_row","loc_rack","loc_u_start","loc_u_end","ladvd_report","ipmi_addr","ipmi_detected_ip","ipmi_port","ipmi_username","ipmi_password");
            foreach ($allfld as &$fld){
                if($json["data"][$i][$fld] == ""){
                    $json["data"][$i][$fld] = "-";
                }
            }
            # For each machines, get the location_name and swiftregion
            if($a["location_id"] == NULL){
                $json["data"][$i]["location_name"] = "-";
                $json["data"][$i]["swiftregion_name"] = "-";
            }else{
                $rl = mysqli_query($con, "SELECT name,swiftregion FROM locations WHERE id='".$a["location_id"]."'");
                $nl = mysqli_num_rows($rl);
                if($nl == 0){
                    $json["data"][$i]["location_name"] = "-";
                    $json["data"][$i]["swiftregion_name"] = "-";
                }else{
                    $al = mysqli_fetch_array($rl);
                    $json["data"][$i]["location_name"] = $al["name"];
                    $json["data"][$i]["swiftregion_name"] = $al["swiftregion"];
                }
            }
            # For each machines, get the block devices
            $bd_r = mysqli_query($con, "SELECT name,size_mb FROM blockdevices WHERE machine_id='".$a["id"]."' ORDER BY name");
            $bd_n = mysqli_num_rows($bd_r);
            if($bd_n == 0){
                $json["data"][$i]["blockdevices"] = "-";
            }else{
                $json["data"][$i]["blockdevices"] = "";
                for($j=0;$j<$bd_n;$j++){
                    $bd_a = mysqli_fetch_array($bd_r);
                    if($json["data"][$i]["blockdevices"] != ""){
                        $json["data"][$i]["blockdevices"] .= "/";
                    }
                    if($bd_a["size_mb"] >= 2097152){
                        $block_size = round($bd_a["size_mb"] / 1048576) . "TB";
                    }elseif($bd_a["size_mb"] >= 2048){
                        $block_size = round($bd_a["size_mb"] / 1024) . "GB";
                    }else{
                        $block_size = $bd_a["size_mb"] . "MB";
                    }
                    $json["data"][$i]["blockdevices"] .= $bd_a["name"] . ":" . $block_size;
                }
            }

            # For each machines, get the network devices
            $nd_r = mysqli_query($con, "SELECT name,macaddr,max_speed,switchport_name,switch_hostname FROM ifnames WHERE machine_id='".$a["id"]."' ORDER BY name");
            $nd_n = mysqli_num_rows($nd_r);
            if($nd_n == 0){
                $json["data"][$i]["nics"] = "-";
                $json["data"][$i]["links"] = "-";
            }else{
                $json["data"][$i]["nics"] = "";
                $json["data"][$i]["links"] = "";
                for($j=0;$j<$nd_n;$j++){
                    $nd_a = mysqli_fetch_array($nd_r);
                    if($json["data"][$i]["nics"] != ""){
                        $json["data"][$i]["nics"] .= "/";
                    }
                    if($json["data"][$i]["links"] != ""){
                        $json["data"][$i]["links"] .= "/";
                    }
                    $speed = $nd_a["max_speed"];
                    if($speed < 1000){
                        $speed = $speed . "MBits";
                    }else{
                        $speed = ($speed / 1000) . "GBits";
                    }
                    $json["data"][$i]["nics"] .= $nd_a["name"] . "_" . $nd_a["macaddr"] . "@" . $speed . "_" . $nd_a["switch_hostname"] . "_" . $nd_a["switchport_name"];
                    $json["data"][$i]["links"] .= $nd_a["name"] . "_" . $nd_a["switch_hostname"] . "_" . $nd_a["switchport_name"];
                }
            }

            # For each machines, get the cluster name
            if($a["cluster"] == NULL){
                $json["data"][$i]["cluster_name"] = "-";
            }else{
                $rc = mysqli_query($con, "SELECT name FROM clusters WHERE id='".$a["cluster"]."'");
                $nc = mysqli_num_rows($rc);
                if($nc == 0){
                    $json["data"][$i]["cluster_name"] = "-";
                }else{
                    $ac = mysqli_fetch_array($rc);
                    $json["data"][$i]["cluster_name"] = $ac["name"];
                }
            }
            # For each machines, get the provisionned IPs
            if($a["cluster"] == NULL){
                $json["data"][$i]["mgmt_ip"] = "-";
            }else{
                $json["data"][$i]["mgmt_ip"] = "";
                $rnet = mysqli_query($con, "SELECT INET_NTOA(ips.ip) AS ipaddr, networks.name AS networkname FROM ips,networks WHERE ips.network=networks.id AND machine='".$a["id"]."' AND usefor='machine' AND networks.role NOT LIKE 'ipmi' AND networks.role NOT LIKE 'vm-net' AND networks.role NOT LIKE 'ceph-cluster' AND networks.role NOT LIKE 'ovs-bridge'");
                $nnet = mysqli_num_rows($rnet);
                for($j=0;$j<$nnet;$j++){
                    $anet = mysqli_fetch_array($rnet);
                    if($json["data"][$i]["mgmt_ip"] != ""){
                        $json["data"][$i]["mgmt_ip"] .= "/";
                    }
                    $json["data"][$i]["mgmt_ip"] .= $anet["ipaddr"] . "@" . $anet["networkname"];
                }
            }
        }
        return $json;
        break;
    case "machine_guessed_profile":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];

        if(isset($_REQUEST["debug"]) && $_REQUEST["debug"] = "yes"){
            $debug="yes";
        }else{
            $debug="no";
        }

        $json = hardware_profile_guess_profile($con, $conf, $machine["id"],$debug);

        return $json;
        break;
    case "machine_check_megacli_applied":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];

        if(isset($_REQUEST["profile_name"]) && $_REQUEST["profile_name"] != ""){
            $safe_profile_name = safe_fqdn("profile_name");
            if($safe_profile_name === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not valid profile name.";
                return $json;
            }
        }

        $json = hardware_profile_check_megacli_applied($con, $conf, $machine["id"], $safe_profile_name);

        return $json;
        break;
    case "profile_list":
        $json = hardware_profile_list($con, $conf);
        return $json;
        break;
    case "machine_megacli_apply":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];

        if(isset($_REQUEST["profile_name"]) && $_REQUEST["profile_name"] != ""){
            $safe_profile_name = safe_fqdn("profile_name");
            if($safe_profile_name === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not valid profile name.";
                return $json;
            }
        }else{
            $safe_profile_name = "";
        }

        $json = hardware_profile_apply_megacli_raid($con, $conf, $machine["id"], $safe_profile_name);

        return $json;
        break;
    case "machine_megacli_reset_raid":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];

        $json = hardware_profile_apply_megacli_reset_raid($con, $conf, $machine["id"]);

        return $json;
        break;
    case "machine_guess_racking":
        $ret = get_machine_from_serial_or_hostname($con, $conf);
        if($ret["status"] != "success"){ return $ret; }
        $machine = $ret["data"];

        $ret = auto_racking_guess_location($con, $conf, $machine["id"]);
        if($ret["status"] != "success"){
            return $ret;
        }

        if(sizeof($ret["data"]) == 0){
            $json["data"] = "No racking info could be guessed.";
        }else{
            $json["data"] = "Machine is in datacenter ".$ret["data"]["dc"]." row ".$ret["data"]["row"]." rack ".$ret["data"]["rack"]." ustart ".$ret["data"]["u_start"]." uend ".$ret["data"]["u_end"].".";
        }

        return $json;
        break;
    case "machine_auto_rack":
        $ret = get_machine_from_serial_or_hostname($con, $conf);
        if($ret["status"] != "success"){ return $ret; }
        $machine = $ret["data"];

        $ret = auto_racking_auto_assign_location($con, $conf, $machine["id"]);
        if($ret["status"] != "success"){
            return $ret;
        }

        return $json;
        break;
    case "machine_auto_add":
        $ret = get_machine_from_serial_or_hostname($con, $conf);
        if($ret["status"] != "success"){ return $ret; }
        $machine = $ret["data"];

        $json = auto_provision_add_machine($con, $conf, $machine["id"]);

        return $json;
        break;
    case "machine_to_dns":
        $ret = get_machine_from_serial_or_hostname($con, $conf);
        if($ret["status"] != "success"){ return $ret; }
        $machine = $ret["data"];

        machine_create_host_dns($con, $conf, $machine, 'yes');

        return $json;
        break;
    case "machine_out_of_dns":
        $ret = get_machine_from_serial_or_hostname($con, $conf);
        if($ret["status"] != "success"){ return $ret; }
        $machine = $ret["data"];

        machine_delete_host_dns($con, $conf, $machine, 'yes');

        return $json;
        break;
    case "machine_to_monitoring":
        $ret = get_machine_from_serial_or_hostname($con, $conf);
        if($ret["status"] != "success"){ return $ret; }
        $machine = $ret["data"];

        machine_add_to_monitoring($con, $conf, $machine, 'yes');

        return $json;
        break;
    case "machine_out_of_monitoring":
        $ret = get_machine_from_serial_or_hostname($con, $conf);
        if($ret["status"] != "success"){ return $ret; }
        $machine = $ret["data"];

        machine_delete_from_monitoring($con, $conf, $machine);

        return $json;
        break;
    case "machine_gen_root_pass":
        $ret = get_machine_from_serial_or_hostname($con, $conf);
        if($ret["status"] != "success"){ return $ret; }
        $machine = $ret["data"];

        machine_gen_root_pass($con, $conf, $machine, 'yes');

        return $json;
        break;
    case "machine_forget_root_pass":
        $ret = get_machine_from_serial_or_hostname($con, $conf);
        if($ret["status"] != "success"){ return $ret; }
        $machine = $ret["data"];

        machine_forget_root_pass($con, $conf, $machine, 'yes');

        return $json;
        break;
    case "machine_report_counter_reset":
        $ret = get_machine_from_serial_or_hostname($con, $conf);
        if($ret["status"] != "success"){ return $ret; }
        $machine = $ret["data"];

        $q = "UPDATE machines SET report_counter='0' WHERE id='".$machine["id"]."'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }

        return $json;
        break;
    case "machine_show":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];

        $r = mysqli_query($con, "SELECT * FROM clusters WHERE id='".$machine["cluster"]."'");
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $cluster = mysqli_fetch_array($r);
        $json["data"]["machine_cluster"] = $cluster;

        $r = mysqli_query($con, "SELECT * FROM blockdevices WHERE machine_id='".$machine["id"]."' ORDER BY name");
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        $blockdevs = [];
        for($i=0;$i<$n;$i++){
            $blockdevs[] = mysqli_fetch_array($r);
        }
        $json["data"]["machine_blockdevices"] = $blockdevs;

        $r = mysqli_query($con, "SELECT INET_NTOA(ips.ip) as ipaddr,networks.name AS networkname FROM ips,networks WHERE machine='".$machine["id"]."' AND ips.network=networks.id");
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        $ips = [];
        for($i=0;$i<$n;$i++){
            $ips[] = mysqli_fetch_array($r);
        }
        $json["data"]["machine_ips"] = $ips;

        # All ifaces
        $r = mysqli_query($con, "SELECT * FROM ifnames WHERE machine_id='".$machine["id"]."' ORDER BY name");
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        $ifs = [];
        for($i=0;$i<$n;$i++){
            $ifs[] = mysqli_fetch_array($r);
        }
        $json["data"]["machine_ifs"] = $ifs;

        # All megacli devices
        $r = mysqli_query($con, "SELECT * FROM physblockdevices WHERE machine_id='".$machine["id"]."' ORDER BY slot");
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
            if($n >= 1){
            $physbd = [];
            for($i=0;$i<$n;$i++){
                $physbd[] = mysqli_fetch_array($r);
            }
            $json["data"]["machine_phys_blockdevices"] = $physbd;
        }

        return $json;
        break;
    case "machine_set":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];
        $safe_machine_serial = $machine["serial"];

        $Q_ADDON = "";

        if(isset($_REQUEST["use_ceph"])){
            if($_REQUEST["use_ceph"] == "yes"){
                $Q_ADDON .= "use_ceph_if_available='yes'";
            }else{
                $Q_ADDON .= "use_ceph_if_available='no'";
            }
        }

        if(isset($_REQUEST["install_on_raid"])){
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            if($_REQUEST["install_on_raid"] == "yes"){
                $Q_ADDON .= "install_on_raid='yes'";
            }else{
                $Q_ADDON .= "install_on_raid='no'";
            }
        }

        if(isset($_REQUEST["ceph_osd_initial_setup"])){
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            if($_REQUEST["ceph_osd_initial_setup"] == "yes"){
                $Q_ADDON .= "ceph_osd_initial_setup='yes'";
            }else{
                $Q_ADDON .= "ceph_osd_initial_setup='no'";
            }
        }

        if(isset($_REQUEST["force_no_bgp2host"])){
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            if($_REQUEST["force_no_bgp2host"] == "yes"){
                $Q_ADDON .= "force_no_bgp2host='yes'";
            }else{
                $Q_ADDON .= "force_no_bgp2host='no'";
            }
        }

        if(isset($_REQUEST["raid_type"])){
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            switch($_REQUEST["raid_type"]){
            case "0":
                $Q_ADDON .= "raid_type='0'";
                break;
            default:
            case "1":
                $Q_ADDON .= "raid_type='1'";
                break;
            case "5":
                $Q_ADDON .= "raid_type='5'";
                break;
            case "10":
                $Q_ADDON .= "raid_type='10'";
                break;
            }
        }

        if(isset($_REQUEST["raid_dev0"])){
            $raid_dev0 = safe_blockdev_name("raid_dev0");
            if($raid_dev0 === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not valid raid device name.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "raid_dev0='$raid_dev0'";
        }

        if(isset($_REQUEST["raid_dev1"])){
            $raid_dev1 = safe_blockdev_name("raid_dev1");
            if($raid_dev1 === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not valid raid device name.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "raid_dev1='$raid_dev1'";
        }

        if(isset($_REQUEST["raid_dev2"])){
            $raid_dev2 = safe_blockdev_name("raid_dev2");
            if($raid_dev2 === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not valid raid device name.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "raid_dev2='$raid_dev2'";
        }

        if(isset($_REQUEST["raid_dev3"])){
            $raid_dev3 = safe_blockdev_name("raid_dev3");
            if($raid_dev3 === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not valid raid device name.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "raid_dev3='$raid_dev3'";
        }

        if(isset($_REQUEST["serial_console_device"])){
            $serial_console_device = safe_blockdev_name("serial_console_device");
            if($serial_console_device === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not valid serial device name.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "serial_console_dev='$serial_console_device'";
        }

        $location_param_list = [ "loc_dc", "loc_row", "loc_rack", "loc_u_start", "loc_u_end" ];
        foreach ($location_param_list as &$one_param){
            if(isset($_REQUEST[$one_param])){
                $safe_param_value = safe_fqdn($one_param);
                if($safe_param_value === FALSE){
                    $json["status"] = "error";
                    $json["message"] = "Error: not valid $one_param parameter.";
                    return $json;
                }
                if($Q_ADDON != ""){
                    $Q_ADDON .= ", ";
                }
                $Q_ADDON .= "$one_param='$safe_param_value'";
            }
        }

        if(isset($_REQUEST["use_gpu"])){
            if($_REQUEST["use_gpu"] == "yes"){
                $safe_use_gpu = "yes";
            }else{
                $safe_use_gpu = "no";
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "use_gpu='$safe_use_gpu'";
        }

        if(isset($_REQUEST["nested_virt"])){
            if($_REQUEST["nested_virt"] == "yes"){
                $safe_nested_virt = "yes";
            }elseif($_REQUEST["nested_virt"] == "cluster_value"){
                $safe_nested_virt = "cluster_value";
            }else{
                $safe_nested_virt = "no";
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "nested_virt='$safe_nested_virt'";
        }

        if(isset($_REQUEST["gpu_name"])){
            $safe_gpu_name = safe_fqdn('gpu_name');
            if($safe_gpu_name === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid GPU name.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "gpu_name='$safe_gpu_name'";
        }

        if(isset($_REQUEST["gpu_vendor_id"])){
            $safe_gpu_vendor_id = safe_fqdn('gpu_vendor_id');
            if($safe_gpu_vendor_id === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid GPU vendor id.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "gpu_vendor_id='$safe_gpu_vendor_id'";
        }

        if(isset($_REQUEST["gpu_product_id"])){
            $safe_gpu_product_id = safe_fqdn('gpu_product_id');
            if($safe_gpu_product_id === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid GPU product id.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "gpu_product_id='$safe_gpu_product_id'";
        }

        if(isset($_REQUEST["gpu_device_type"])){
            if($_REQUEST["gpu_device_type"] != "type-PCI" AND $_REQUEST["gpu_device_type"] != "type-PF" AND $_REQUEST["gpu_device_type"] != "type-VF"){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid GPU product id.";
                return $json;
            }else{
                $safe_gpu_device_type = $_REQUEST["gpu_device_type"];
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "gpu_device_type='$safe_gpu_device_type'";
        }

        if(isset($_REQUEST["vfio_ids"])){
            $safe_vfio_ids = safe_password('vfio_ids');
            if($safe_vfio_ids === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid GPU product id.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "vfio_ids='$safe_vfio_ids'";
        }

        if(isset($_REQUEST["cpu_mode"])){
            if($_REQUEST["cpu_mode"] == "host-model" || $_REQUEST["cpu_mode"] == "host-passthrough" || $_REQUEST["cpu_mode"] == "custom" || $_REQUEST["cpu_mode"] == "cluster_value"){
                $safe_cpu_mode = $_REQUEST["cpu_mode"];
            }else{
                $json["status"] = "error";
                $json["message"] = "Error: not a valid cpu-mode.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "cpu_mode='$safe_cpu_mode'";
        }

        if(isset($_REQUEST["cpu_model"])){
            $safe_cpu_model = safe_password('cpu_model');
            if($safe_cpu_model === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid cpu-model.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "cpu_model='$safe_cpu_model'";
        }

        if(isset($_REQUEST["cpu_model_extra_flags"])){
            $safe_cpu_model_extra_flags = safe_password('cpu_model_extra_flags');
            if($safe_cpu_model_extra_flags === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid cpu_model_extra_flags.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "cpu_model_extra_flags='$safe_cpu_model_extra_flags'";
        }

        if(isset($_REQUEST["force_dhcp_agent"])){
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            if($_REQUEST["force_dhcp_agent"] == "yes"){
                $Q_ADDON .= "force_dhcp_agent='yes'";
            }else{
                $Q_ADDON .= "force_dhcp_agent='no'";
            }
        }

        if(isset($_REQUEST["swift_store_account"])){
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            if($_REQUEST["swift_store_account"] == "yes"){
                $Q_ADDON .= "swift_store_account='yes'";
            }else{
                $Q_ADDON .= "swift_store_account='no'";
            }
        }
        if(isset($_REQUEST["swift_store_container"])){
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            if($_REQUEST["swift_store_container"] == "yes"){
                $Q_ADDON .= "swift_store_container='yes'";
            }else{
                $Q_ADDON .= "swift_store_container='no'";
            }
        }

        if(isset($_REQUEST["swift_store_object"])){
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            if($_REQUEST["swift_store_object"] == "yes"){
                $Q_ADDON .= "swift_store_object='yes'";
            }else{
                $Q_ADDON .= "swift_store_object='no'";
            }
        }

        if(isset($_REQUEST["hostname"])){
            $safe_hostname = safe_fqdn('hostname');
            if($safe_hostname === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid hostname.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "hostname='$safe_hostname'";
        }

        if(isset($_REQUEST["notes"])){
            $safe_notes = safe_password('notes');
            if($safe_notes === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid note.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "notes='$safe_notes'";
        }

        if(isset($_REQUEST["use_ipmi"])){
            if($_REQUEST["use_ipmi"] == "yes"){
                $safe_use_ipmi = "yes";
            }else{
                $safe_use_ipmi = "no";
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "use_ipmi='$safe_use_ipmi'";
        }

        if(isset($_REQUEST["ipmi_call_chassis_bootdev"])){
            if($_REQUEST["ipmi_call_chassis_bootdev"] == "yes"){
                $safe_ipmi_call_chassis_bootdev = "yes";
            }else{
                $safe_ipmi_call_chassis_bootdev = "no";
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "ipmi_call_chassis_bootdev='$safe_ipmi_call_chassis_bootdev'";
        }

        if(isset($_REQUEST["ipmi_username"])){
            $safe_ipmi_username = safe_fqdn('ipmi_username');
            if($safe_ipmi_username === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid ipmi_username.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "ipmi_username='$safe_ipmi_username'";
        }

        if(isset($_REQUEST["ipmi_password"])){
            $safe_ipmi_password = safe_password('ipmi_password');
            if($safe_ipmi_password === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid ipmi_password.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "ipmi_password='$safe_ipmi_password'";
        }

        if(isset($_REQUEST["ipmi_addr"])){
            $safe_ipmi_addr = safe_ipv4('ipmi_addr');
            if($safe_ipmi_addr === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid ipmi_addr.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "ipmi_addr='$safe_ipmi_addr'";
        }

        if(isset($_REQUEST["ipmi_port"])){
            $safe_ipmi_port = safe_int('ipmi_port');
            if($safe_ipmi_port === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid ipmi_port.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "ipmi_port='$safe_ipmi_port'";
        }

        if(isset($_REQUEST["ipmi_netmask"])){
            $safe_ipmi_netmask = safe_ipv4('ipmi_netmask');
            if($safe_ipmi_netmask === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid ipmi_netmask.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "ipmi_netmask='$safe_ipmi_netmask'";
        }

        if(isset($_REQUEST["ipmi_default_gw"])){
            $safe_ipmi_default_gw = safe_ipv4('ipmi_default_gw');
            if($safe_ipmi_default_gw === FALSE){
                $json["status"] = "error";
                $json["message"] = "Error: not a valid ipmi_default_gw.";
                return $json;
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "ipmi_default_gw='$safe_ipmi_default_gw'";
        }

        if(isset($_REQUEST["ipmi_vlan"])){
            if($_REQUEST["ipmi_vlan"] == "off"){
                $safe_ipmi_vlan = "off";
            }else{
                $safe_ipmi_vlan = safe_int('ipmi_vlan');
                if($safe_ipmi_vlan === FALSE){
                    $json["status"] = "error";
                    $json["message"] = "Error: not a valid ipmi_vlan.";
                    return $json;
                }
            }
            if($Q_ADDON != ""){
                $Q_ADDON .= ", ";
            }
            $Q_ADDON .= "ipmi_vlan='$safe_ipmi_vlan'";
        }

        # Build the API using the variables.json file
        $json_file = file_get_contents("/usr/share/openstack-cluster-installer/variables.json");
        $dec_json = json_decode($json_file, TRUE);
        $items_json_array = $dec_json["machines"];
        $a_keys = array_keys($items_json_array);
        $n = sizeof($a_keys);
        for($i=0;$i<$n;$i++){
                $col = $a_keys[$i];
                $attr = $items_json_array[$col];
                if(isset($_REQUEST[$col])){
                    switch($attr["type"]){
                    case "int":
                        $safe_value = safe_int($col);
                        break;
                    case "float":
                        $safe_value = safe_float($col);
                        break;
                    case "boolean":
                        if($_REQUEST[$col] == "yes"){
                            $safe_value = "yes";
                        }else{
                            $safe_value = "no";
                        }
                        break;
                    case "fqdn":
                        $safe_value = safe_fqdn($col);
                        break;
                    case "string":
                        $safe_value = safe_password($col);
                        break;
                    default:
                        $safe_value = FALSE;
                        break;
                    }
                    if($safe_value === FALSE){
                        $json["status"] = "error";
                        $json["message"] = "Error: not valid $col here.";
                        return $json;
                    }
                    if($Q_ADDON != ""){
                        $Q_ADDON .= ", ";
                    }
                    $Q_ADDON .= "$col='$safe_value'";
                }
        }


        $q = "UPDATE machines SET $Q_ADDON WHERE serial='$safe_machine_serial'";
        $r = mysqli_query($con, $q);

        return $json;
        break;
    # Remove a machine from a cluster
    case "machine_remove":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];
        $safe_machine_serial = $machine["serial"];

        $machine_status  = $machine["status"];
        $machine_id      = $machine["id"];
        $machine_cluster = $machine["cluster"];
        $machine_role    = $machine["role"];

        $q = "UPDATE machines SET cluster=NULL, hostname='' WHERE id='$machine_id'";
        $r = mysqli_query($con, $q);

        // If role is controller, check if there's another controller left. If there's at least one, then
        // we must set any of these controllers as first master
        if($machine_role == "controller"){
            $q = "SELECT first_master_machine_id FROM clusters WHERE id='$machine_cluster'";
            $r = mysqli_query($con, $q);
            $cluster = mysqli_fetch_array($r);
            $fm_id = $cluster["first_master_machine_id"];;
            if($fm_id == $machine_id){
                $q = "SELECT * FROM machines WHERE cluster='$machine_cluster' AND role='controller' LIMIT 1;";
                $r = mysqli_query($con, $q);
                $n = mysqli_num_rows($r);
                // No controler left: we set the first_master as NULL
                if($n == 0){
                    $q = "UPDATE clusters SET first_master_machine_id=NULL WHERE id='$machine_cluster'";
                    $r = mysqli_query($con, $q);
                // We just set the first controler we find left as first_master
                }else{
                    $first_master = mysqli_fetch_array($r);
                    $new_fm_id = $first_master["id"];
                    $q = "UPDATE clusters SET first_master_machine_id='$new_fm_id' WHERE id='$machine_cluster'";
                    $r = mysqli_query($con, $q);
                }
            }
        }

        // If role is sql, check if there's another sql node left. If there's at least one, then
        // we must set a sql node as first master
        if($machine_role == "sql"){
            $q = "SELECT first_sql_machine_id FROM clusters WHERE id='$machine_cluster'";
            $r = mysqli_query($con, $q);
            $cluster = mysqli_fetch_array($r);
            $fsql_id = $cluster["first_master_machine_id"];;
            if($fsql_id == $machine_id){
                $q = "SELECT * FROM machines WHERE cluster='$machine_cluster' AND role='sql' LIMIT 1;";
                $r = mysqli_query($con, $q);
                $n = mysqli_num_rows($r);
                // No sql node left: we set the first_master as NULL
                if($n == 0){
                    $q = "UPDATE clusters SET first_sql_machine_id=NULL WHERE id='$machine_cluster'";
                    $r = mysqli_query($con, $q);
                // We just set the first sql node we find left as first_sql
                }else{
                    $first_master = mysqli_fetch_array($r);
                    $new_fsql_id = $first_master["id"];
                    $q = "UPDATE clusters SET first_sql_machine_id='$new_fsql_id' WHERE id='$machine_cluster'";
                    $r = mysqli_query($con, $q);
                }
            }
        }

        // Delete all IPs of the machine in the DB
        $q = "DELETE FROM ips WHERE machine='$machine_id' AND usefor NOT LIKE 'ipmi'";
        $r = mysqli_query($con, $q);
        return $json;
        break;
    # Add a machine to a cluster
    case "machine_add":
        // Check the serial
        $safe_machine_serial = safe_serial("machine_serial");
        if($safe_machine_serial === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid chassis serial number.";
            return $json;
        }
        $r = mysqli_query($con, "SELECT * FROM machines WHERE serial='$safe_machine_serial'");
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: machine with serial $safe_machine_serial doesn't exist.";
            return $json;
        }
        $machine = mysqli_fetch_array($r);
        $machine_status  = $machine["status"];
        $machine_id      = $machine["id"];
        $machine_cluster = $machine["cluster"];

        // Check status of that machine
        if($machine_status != "live"){
            $json["status"] = "error";
            $json["message"] = "Error: machine isn't running live image.";
            return $json;
        }
        if(!is_null($machine["cluster"])){
            $json["status"] = "error";
            $json["message"] = "Error: machine already enrolled in a cluster.";
            return $json;
        }

        if($machine["cluster"] !== NULL){
            $json["status"] = "error";
            $json["message"] = "Error: machine with serial $safe_machine_serial is already enrolled.";
            return $json;
        }

        // Check cluster name and fetch its id
        $safe_cluster_name = safe_fqdn("cluster_name");
        if($safe_cluster_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid cluster name.";
            return $json;
        }
        $r = mysqli_query($con, "SELECT * FROM clusters WHERE name='$safe_cluster_name'");
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: cluster name $safe_cluster_name doesn't exist.";
            return $json;
        }
        $cluster = mysqli_fetch_array($r);
        $safe_cluster_id     = $cluster["id"];

        // Check role name
        $safe_role_name = safe_fqdn("role_name");
        if($safe_role_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid role name.";
            return $json;
        }
        $r = mysqli_query($con, "SELECT id FROM roles WHERE name='$safe_role_name'");
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: role name $safe_role_name doesn't exist.";
            return $json;
        }
        $role = mysqli_fetch_array($r);
        $safe_role_id = $role["id"];

        // Check location name
        $safe_location_name = safe_fqdn("location_name");
        if($safe_location_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid location name.";
            return $json;
        }
        $r = mysqli_query($con, "SELECT id FROM locations WHERE name='$safe_location_name'");
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: location name $safe_location_name doesn't exist.";
            return $json;
        }
        $location = mysqli_fetch_array($r);
        $safe_location_id = $location["id"];

        $json = add_node_to_cluster($con, $conf, $machine_id, $safe_cluster_id, $safe_role_name, $safe_location_id);
        return $json;
        break;
    case "location_list":
        $r = mysqli_query($con, "SELECT * FROM locations ORDER BY id");
        $n = mysqli_num_rows($r);
        $json["data"] = [];
        for($i=0;$i<$n;$i++){
            $a = mysqli_fetch_array($r);
            $json["data"][$i] = $a;
        }
        return $json;
        break;
    case "location_create":
        # Validate location name
        $safe_location_name = safe_fqdn("name");
        if($safe_location_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: location name format.";
            return $json;
        }
        $q = "SELECT * FROM locations WHERE name='$safe_location_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 0){
            $json["status"] = "error";
            $json["message"] = "Error: location name already exists.";
            return $json;
        }
        # Validate swiftregion
        $safe_swiftregion_name = safe_fqdn("swiftregion");
        if($safe_swiftregion_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: swiftregion name format.";
            return $json;
        }
        $q = "SELECT * FROM swiftregions WHERE name='$safe_swiftregion_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: swiftregion name not found.";
            return $json;
        }

        $r = mysqli_query($con, "INSERT INTO locations (name, swiftregion) VALUES ('$safe_location_name', '$safe_swiftregion_name')");
        return $json;
        break;
    case "location_delete":
        # Validate location name
        $safe_location_name = safe_fqdn("name");
        if($safe_location_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: location name format.";
            return $json;
        }
        $q = "SELECT * FROM locations WHERE name='$safe_location_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: location name not found.";
            return $json;
        }
        $a = mysqli_fetch_array($r);

        $q = "SELECT * FROM networks WHERE location_id='".$a["id"]."'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n >= 1){
            $json["status"] = "error";
            $json["message"] = "Error: cannot delete location, sone networks are using it.";
            return $json;
        }

        $r = mysqli_query($con, "DELETE FROM locations WHERE name='$safe_location_name'");
        return $json;
        break;
    case "swiftregion_list":
        $r = mysqli_query($con, "SELECT * FROM swiftregions ORDER BY id");
        $n = mysqli_num_rows($r);
        $json["data"] = [];
        for($i=0;$i<$n;$i++){
            $a = mysqli_fetch_array($r);
            $json["data"][$i] = $a;
        }
        return $json;
        break;
    case "swiftregion_create":
        # Validate swiftregion name
        $safe_swiftregion_name = safe_fqdn("name");
        if($safe_swiftregion_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: swiftregion name format.";
            return $json;
        }
        $q = "SELECT * FROM swiftregions WHERE name='$safe_swiftregion_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 0){
            $json["status"] = "error";
            $json["message"] = "Error: swiftregion name already exists.";
            return $json;
        }
        $q = "INSERT INTO swiftregions (name) VALUES ('$safe_swiftregion_name')";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con) . " with query $q";
            return $json;
        }
        return $json;
        break;
    case "swiftregion_delete":
        # Validate swiftregion name
        $safe_swiftregion_name = safe_fqdn("name");
        if($safe_swiftregion_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: swiftregion name format.";
            return $json;
        }
        $q = "SELECT * FROM swiftregions WHERE name='$safe_swiftregion_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: swiftregion name not found.";
            return $json;
        }
        $q = "SELECT * FROM locations WHERE swiftregion='$safe_swiftregion_name'";
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n >= 1){
            $json["status"] = "error";
            $json["message"] = "Error: cannot delete swift region: some location (aka: swift zones) are using it.";
            return $json;
        }
        $r = mysqli_query($con, "DELETE FROM swiftregions WHERE name='$safe_swiftregion_name'");
        return $json;
        break;
    case "machine_reboot_on_hdd":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];
        $safe_machine_serial = $machine["serial"];

        if($machine["status"] == "firstboot" || $machine["status"] == "installed"){
            $json["message"] = "Warning: machine already started on HDD.";
            return $json;
        }

        ipmi_set_boot_device($con, $conf, $machine["id"], "disk");

        # Fix status in db
        $r = mysqli_query($con, "UPDATE machines SET status='firstboot' WHERE serial='$safe_machine_serial'");
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        # Perform reboot
        $ret = send_ssh_cmd($conf, $con, $machine["ipaddr"], "shutdown -r now");
        return $json;
        break;
    case "machine_reboot_on_live":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];
        $safe_machine_serial = $machine["serial"];

        if($machine["status"] == "live"){
            $json["message"] = "Warning: machine already started on Live image.";
            return $json;
        }

        ipmi_set_boot_device($con, $conf, $machine["id"], "pxe");

        # Fix status in db
        $q = "UPDATE machines SET status='bootinglive' WHERE serial='$safe_machine_serial'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $ret = send_ssh_cmd($conf, $con, $machine["ipaddr"], "shutdown -r now");
        return $json;
        break;
    case "machine_wipe":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];
        $safe_machine_serial = $machine["serial"];

        $machine_status  = $machine["status"];
        $machine_id      = $machine["id"];
        $machine_cluster = $machine["cluster"];

        // Check status of that machine
        if($machine_status != "live"){
            $json["status"] = "error";
            $json["message"] = "Error: machine isn't running live image.";
            return $json;
        }
        // Stop any running MD
        $cmd = "if [ -e /dev/md0 ] ; then mdadm --stop /dev/md0 ; mdadm --remove /dev/md0 ; fi";
        $ret = send_ssh_cmd($conf, $con, $machine["ipaddr"], $cmd);
        $json["message"] .= "\n$cmd";

        $cmd = "if [ -e /dev/md127 ] ; then mdadm --stop /dev/md127 ; mdadm --remove /dev/md127 ; fi";
        $ret = send_ssh_cmd($conf, $con, $machine["ipaddr"], $cmd);
        $json["message"] .= "\n$cmd";

        // Whipe the first chunks of the HDDs
        $q = "SELECT * FROM blockdevices WHERE machine_id='$machine_id'";
        $r = mysqli_query($con, $q);
        $n = mysqli_num_rows($r);
        for($i=0;$i<$n;$i++){
            $hdd = mysqli_fetch_array($r);
            $name = $hdd["name"];
            $cmd = "dd if=/dev/urandom of=/dev/$name bs=102400 count=1000";
            $ret = send_ssh_cmd($conf, $con, $machine["ipaddr"], $cmd);
            $json["message"] .= "\n$cmd";
        }
        $cmd = "partprobe";
        $ret = send_ssh_cmd($conf, $con, $machine["ipaddr"], $cmd);
        $json["message"] .= "\n$cmd";
        return $json;
        break;
    case "machine_display_install_cmd":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];
        $safe_machine_serial = $machine["serial"];

        $machine_id = $machine["id"];

        $slave_install_return = slave_install_server_os_command($con, $conf, $machine_id);
        if($slave_install_return["status"] != "success"){
            $json["status"] = "error";
            $json["message"] = "Error while calculating installation command line for host $safe_machine_serial: ".$slave_install_return["message"];
            return $json;
        }
        $json["data"] .= "Running: ". $slave_install_return["cmd"];
        return $json;
        break;

    case "machine_install_os":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];

        $json = oci_install_machine($con, $conf, $machine["id"]);

        return $json;
        break;

    case "machine_install_log":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];
        $safe_machine_serial = $machine["serial"];

        $machine_id = $machine["id"];
        $machine_ip = $machine["ipaddr"];
        $machine_status = $machine["status"];
        if($machine_status == "live"){
            $json["data"] = "Machine is on live, not installing...";
        }elseif($machine_status == "installing"){
            $json["data"] = send_ssh_cmd($conf, $con, $machine_ip, "tail -n 80 /var/log/oci.log");
        }elseif($machine_status == "installed"){
            $json["data"] = send_ssh_cmd($conf, $con, $machine_ip, "oci-tail-last-puppet-log");
        }else{
            $json["data"] = "Machine is booting...";
        }
        return $json;
        break;
    case "machine_ip_list":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];
        $safe_machine_serial = $machine["serial"];

        $json["data"] = Array();

        $q = "SELECT networks.name AS networkname, INET_NTOA(ips.ip) AS ipaddr, ips.usefor AS usefor FROM ips,machines,networks WHERE ips.machine=machines.id AND machines.serial='$safe_machine_serial' AND networks.id=ips.network";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        for($i=0;$i<$n;$i++){
            $a = mysqli_fetch_array($r);
            $json["data"][$i] = $a;
        }
        return $json;
        break;
    case "machine_ip_add":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];
        $safe_machine_serial = $machine["serial"];

        # Validate IP address
        $safe_machine_ip = safe_ipv4("ip_addr");
        if($safe_machine_ip === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not a valid IP address.";
            return $json;
        }
        $safe_ip_long = ip2long($safe_machine_ip);
        $q = "SELECT * FROM ips WHERE ip='$safe_ip_long'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n > 0){
            $json["status"] = "error";
            $json["message"] = "Error: IP address already in used.";
            return $json;
        }

        # Validate network name
        $safe_network_name = safe_fqdn("network_name");
        if($safe_network_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: network name format.";
            return $json;
        }
        $q = "SELECT * FROM networks WHERE name='$safe_network_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: network name not found.";
            return $json;
        }
        $network = mysqli_fetch_array($r);
        
        # Validate that the IP is within the network range
        $network_ip_min = $network["ip"];
        $network_ip_min_long = ip2long($network_ip_min);
        $inv_cidr = 32 - $network["cidr"];
        $netowrk_ip_max_long = $network_ip_min_long + pow(2, $inv_cidr) - 2;
        $network_ip_min_long += 1;
        $netowrk_ip_max_long -= 1;
        if($safe_ip_long < $network_ip_min_long || $safe_ip_long > $netowrk_ip_max_long){
            $json["status"] = "error";
            $json["message"] = "Error: IP not in range of network.";
            return $json;
        }
        $q = "INSERT INTO ips (network,ip,type,machine,usefor) VALUES ('".$network["id"]."', '".$safe_ip_long."','4','".$machine["id"]."','machine')";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        return $json;
        break;
    case "machine_ip_remove":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];
        $safe_machine_serial = $machine["serial"];

        # Validate IP address
        $safe_machine_ip = safe_ipv4("ip_addr");
        if($safe_machine_ip === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not a valid IP address.";
            return $json;
        }
        $safe_ip_long = ip2long($safe_machine_ip);
        $q = "SELECT * FROM ips WHERE ip='$safe_ip_long'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: machine with serial $safe_machine_serial doesn't own $safe_machine_ip.";
            return $json;
        }
        $ip = mysqli_fetch_array($r);
        $ip_id = $ip["id"];
        $q = "DELETE FROM ips WHERE id='$ip_id'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        return $json;
        break;
    case "ipmi_assign_check":
        $json = check_if_machines_on_ipmi_network($con, $conf);
        return $json;
        break;
    case "cluster_list":
        $q = "SELECT * FROM clusters";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $json["data"] = Array();
        $n = mysqli_num_rows($r);
        for($i=0;$i<$n;$i++){
            $a = mysqli_fetch_array($r);
            $json["data"][$i] = $a;
        }
        return $json;
        break;
    case "cluster_create":
        // Validate name
        $safe_cluster_name = safe_fqdn("name");
        if($safe_cluster_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid cluster name.";
            return $json;
        }
        $q = "SELECT * FROM clusters WHERE name='$safe_cluster_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 0){
            $json["status"] = "error";
            $json["message"] = "Error: cluster name already exists.";
            return $json;
        }

        // Validate domain
        $safe_domain_name = safe_fqdn("domain");
        if($safe_domain_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid domain name.";
            return $json;
        }
        $json = new_cluster($con, $conf, $safe_cluster_name, $safe_domain_name);
        return $json;
        break;

    case "cluster_delete":
        // Validate name
        $safe_cluster_name = safe_fqdn("name");
        if($safe_cluster_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid cluster name.";
            return $json;
        }
        $q = "SELECT * FROM clusters WHERE name='$safe_cluster_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: cluster name doesn't exist.";
            return $json;
        }
        $cluster = mysqli_fetch_array($r);

        # Check if some machines are in the cluster
        $q = "SELECT cluster FROM machines WHERE cluster='".$cluster["id"]."'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n >= 1){
            $json["status"] = "error";
            $json["message"] = "Error: cannot delete cluster: some machines are using it. Remove these machines first.";
            return $json;
        }

        # Check if some networks are in the cluster
        $q = "SELECT cluster FROM networks WHERE cluster='".$cluster["id"]."'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n >= 1){
            $json["status"] = "error";
            $json["message"] = "Error: cannot delete cluster: some networks are using it. Remove these networks first.";
            return $json;
        }

        return cluster_delete($con, $conf, $safe_cluster_name);
        break;

    case "cluster_show_networks":
        // Validate name
        $safe_cluster_name = safe_fqdn("cluster_name");
        if($safe_cluster_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid cluster name.";
            return $json;
        }
        $q = "SELECT * FROM clusters WHERE name='$safe_cluster_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: cluster name doesn't exist.";
            return $json;
        }
        $cluster = mysqli_fetch_array($r);
        $cluster_id = $cluster["id"];

        $q = "SELECT * FROM networks WHERE cluster='$cluster_id'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        for($i=0;$i<$n;$i++){
            $a = mysqli_fetch_array($r);
            $json["data"][$i] = $a;
        }
        return $json;
        break;

    case "cluster_show_machines":
        // Validate name
        $safe_cluster_name = safe_fqdn("cluster_name");
        if($safe_cluster_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid cluster name.";
            return $json;
        }
        $q = "SELECT * FROM clusters WHERE name='$safe_cluster_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: cluster name doesn't exist.";
            return $json;
        }
        $cluster = mysqli_fetch_array($r);
        $cluster_id = $cluster["id"];

        $q = "SELECT * FROM machines WHERE cluster='$cluster_id'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        for($i=0;$i<$n;$i++){
            $a = mysqli_fetch_array($r);
            $json["data"][$i] = $a;
        }
        return $json;
        break;

    case "network_list":
        $q = "SELECT networks.id AS id,networks.name AS name,networks.ip AS ip,networks.cidr AS cidr,networks.is_public AS is_public,networks.cluster AS cluster,networks.role AS role,networks.iface1 AS iface1,networks.iface2 AS iface2,networks.bridgename AS bridgename,networks.vlan AS vlan,networks.mtu AS mtu,locations.name AS location, networks.ipmi_match_addr AS ipmi_match_addr, networks.ipmi_match_cidr AS ipmi_match_cidr, networks.first_ip AS first_ip, networks.last_ip AS last_ip FROM networks,locations WHERE locations.id=networks.location_id";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        for($i=0;$i<$n;$i++){
            $a = mysqli_fetch_array($r);
            $a["first_ip"] = long2ip($a["first_ip"]);
            $a["last_ip"]  = long2ip($a["last_ip"]);
            if(is_null($a["cluster"])){
                $a["cluster_name"] = "-";
            }else{
                $qc = "SELECT name FROM clusters WHERE id='". $a["cluster"] ."'";
                $rc = mysqli_query($con, $qc);
                $nc = mysqli_num_rows($rc);
                if($nc == 0){
                    $a["cluster_name"] = "-";
                }else{
                    $ac = mysqli_fetch_array($rc);
                    $a["cluster_name"] = $ac["name"];
                }
            }
            $json["data"][$i] = $a;
        }
        return $json;
        break;

    case "network_delete":
        # Validate network name
        $safe_network_name = safe_fqdn("name");
        if($safe_network_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: network name format.";
            return $json;
        }
        $q = "SELECT * FROM networks WHERE name='$safe_network_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: network name not found.";
            return $json;
        }
        $network = mysqli_fetch_array($r);
        $r = mysqli_query($con, "DELETE FROM ips WHERE network='".$network["id"]."'");
        $r = mysqli_query($con, "DELETE FROM networks WHERE name='$safe_network_name'");
        return $json;
        break;

    case "new_network":
        // Check cluster name
        $safe_network_name = safe_fqdn("name");
        if($safe_network_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid network name.";
            return $json;
        }
        $q = "SELECT * FROM networks WHERE name='$safe_network_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 0){
            $json["status"] = "error";
            $json["message"] = "Error: network name already exists.";
            return $json;
        }

        // Check location
        $safe_location_name = safe_fqdn("location");
        if($safe_location_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid location name.";
        }
        $q = "SELECT * FROM locations WHERE name='$safe_location_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: location name doesn't exist. $q";
            return $json;
        }
        $location = mysqli_fetch_array($r);
        $safe_location_id = $location["id"];

        // Check IP
        $safe_network_ip = safe_ipv4("ipaddr");
        if($safe_network_ip === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: wrong ipaddr param.";
            return $json;
        }

        // Check mask
        $safe_cidr_mask = safe_int("cidr_mask");
        if($safe_cidr_mask === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: wrong cidr param.";
            return $json;
        }
        if($safe_cidr_mask > 32 || $safe_cidr_mask < 8){
            $json["status"] = "error";
            $json["message"] = "Error: CIDR mask must be between 8 and 32.";
            return $json;
        }

        // Check is_public
        if(!isset($_REQUEST["is_public"])){
            $json["status"] = "error";
            $json["message"] = "Error: is_public not set.";
            return $json;
        }
        if($_REQUEST["is_public"] == "yes"){
            $safe_is_public = "yes";
        }else{
            $safe_is_public = "no";
        }

        if($safe_cidr_mask == 32){
            $first_ip = ip2long($safe_network_ip);
            $last_ip = ip2long($safe_network_ip);
        }elseif($safe_cidr_mask == 31){
            $first_ip = ip2long($safe_network_ip);
            $last_ip = ip2long($safe_network_ip) + 1;
        }elseif($safe_cidr_mask == 30){
            $first_ip = ip2long($safe_network_ip) +1;
            $last_ip = ip2long($safe_network_ip) + 2;
        }else{
            $number_of_ip = 2 ** (32 - $safe_cidr_mask);
            $first_ip = ip2long($safe_network_ip) + 2;
            $last_ip = ip2long($safe_network_ip) + $number_of_ip - 2;
        }

        $q = "INSERT INTO networks (name, location_id, ip, cidr, is_public, first_ip, last_ip) VALUES ('$safe_network_name', '$safe_location_id', '$safe_network_ip', '$safe_cidr_mask', '$safe_is_public', '$first_ip', '$last_ip')";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = "Query: $q error: ".mysqli_error($con);
            return $json;
        }
        return $json;
        break;

    case "network_set":
        // Check network name is valid and exists
        $safe_network_name = safe_fqdn("network_name");
        if($safe_network_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid network name.";
            return $json;
        }
        $q = "SELECT * FROM networks WHERE name='$safe_network_name'";
        $r = mysqli_query($con, $q);
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Cannot find network by that name.";
            return $json;
        }
        $network = mysqli_fetch_array($r);

        $update = "";

        if(isset($_REQUEST["role"])){
            switch($_REQUEST["role"]){
            case "all":
                $safe_role_name = "all";
                break;
            case "vm-net":
                $safe_role_name = "vm-net";
                break;
            case "ovs-bridge":
                $safe_role_name = "ovs-bridge";
                break;
            case "ceph-cluster":
                $safe_role_name = "ceph-cluster";
                break;
            case "ipmi":
                $safe_role_name = "ipmi";
                break;
            default:
                $safe_role_name = safe_fqdn("role");
                if($safe_role_name === FALSE){
                    $json["status"] = "error";
                    $json["message"] = "Wrong role name format.";
                    return $json;
                }
                $q = "SELECT * FROM roles WHERE name='$safe_role_name'";
                $r = mysqli_query($con, $q);
                if($r === FALSE){
                    $json["status"] = "error";
                    $json["message"] = mysqli_error($con);
                    return $json;
                }
                $n = mysqli_num_rows($r);
                if($n != 1){
                    $json["status"] = "error";
                    $json["message"] = "Error: no role by that name.";
                    return $json;
                }
                break;
            }
            $update .= "role='$safe_role_name'";
        }
        if(isset($_REQUEST["iface1_name"])){
            $safe_eth1_name = safe_ethname("iface1_name");
            if($safe_eth1_name === FALSE){
                    $json["status"] = "error";
                    $json["message"] = "Wrong eth1 name format here.";
                    return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "iface1='$safe_eth1_name'";
        }

        if(isset($_REQUEST["iface2_name"])){
            $safe_eth2_name = safe_ethname("iface2_name");
            if($safe_eth2_name === FALSE){
                    $json["status"] = "error";
                    $json["message"] = "Wrong eth2 name format.";
                    return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "iface2='$safe_eth2_name'";
        }

        if(isset($_REQUEST["ip"])){
            $safe_ip = safe_ipv4("ip");
            if($safe_ip === FALSE){
                    $json["status"] = "error";
                    $json["message"] = "Wrong ip address format.";
                    return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "ip='$safe_ip'";
        }else{
            $safe_ip = $network["ip"];
        }

        if(isset($_REQUEST["cidr"])){
            $safe_cidr = safe_int("cidr");
            if($safe_cidr === FALSE || $safe_cidr < 0 || $safe_cidr > 32){
                    $json["status"] = "error";
                    $json["message"] = "Wrong cidr format.";
                    return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "cidr='$safe_cidr'";
        }else{
            $safe_cidr = $network["cidr"];
        }

        if(isset($_REQUEST["is_public"])){
            if($_REQUEST["is_public"] == "yes"){
                $ispublic = "yes";
            }else{
                $ispublic = "no";
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "is_public='$ispublic'";
        }

        if(isset($_REQUEST["vlan"])){
            if($_REQUEST["vlan"] == "null" || $_REQUEST["vlan"] == "0"){
                if($update != ""){
                    $update .= ", ";
                }
                $update .= "vlan=null";
            }else{
                $safe_vlan = safe_int("vlan");
                if($safe_vlan === FALSE || $safe_vlan < 1 || $safe_vlan > 70000){
                        $json["status"] = "error";
                        $json["message"] = "Wrong vlan format.";
                        return $json;
                }
                if($update != ""){
                    $update .= ", ";
                }
                $update .= "vlan='$safe_vlan'";
            }
        }

        if(isset($_REQUEST["mtu"])){
            $safe_mtu = safe_int("mtu");
            if($safe_mtu === FALSE || $safe_mtu < 0 || $safe_mtu > 9999){
                $json["status"] = "error";
                $json["message"] = "Wrong mtu format.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "mtu='$safe_mtu'";
        }

        if(isset($_REQUEST["location"])){
            $safe_location = safe_fqdn("location");
            if($safe_location === FALSE){
                $json["status"] = "error";
                $json["message"] = "Wrong location format.";
                return $json;
            }
            $q = "SELECT * FROM locations WHERE name='$safe_location'";
            $r = mysqli_query($con, $q);
            if($r === FALSE){
                $json["status"] = "error";
                $json["message"] = mysqli_error($con);
                return $json;
            }
            $n = mysqli_num_rows($r);
            if($n != 1){
                $json["status"] = "error";
                $json["message"] = "Error: location name not found.";
                return $json;
            }
            $location = mysqli_fetch_array($r);
            $location_id = $location["id"];
            if($update != ""){
                $update .= ", ";
            }
            $update .= "location_id='$location_id'";
        }
        if(isset($_REQUEST["bridgename"])){
            $safe_bridgename = safe_fqdn("bridgename");
            if($safe_bridgename === FALSE){
                $json["status"] = "error";
                $json["message"] = "Wrong bridge name format.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "bridgename='$safe_bridgename'";
        }

        # IPMI dhcp network matching params
        if(isset($_REQUEST["ipmi_match_addr"])){
            $safe_ipmi_match_addr = safe_ipv4("ipmi_match_addr");
            if($safe_ipmi_match_addr === FALSE){
                $json["status"] = "error";
                $json["message"] = "Wrong ipmi_match_addr format.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "ipmi_match_addr='$safe_ipmi_match_addr'";
        }
        if(isset($_REQUEST["ipmi_match_cidr"])){
            $safe_ipmi_match_cidr = safe_int("ipmi_match_cidr");
            if($safe_ipmi_match_cidr === FALSE){
                $json["status"] = "error";
                $json["message"] = "Wrong ipmi_match_cidr format.";
                return $json;
            }
            if($update != ""){
                $update .= ", ";
            }
            $update .= "ipmi_match_cidr='$safe_ipmi_match_cidr'";
        }

        if(!isset($safe_ip)){
            $safe_ip = $network["ip"];
        }
        if(!isset($safe_cidr)){
            $safe_cidr = $network["cidr"];
        }

        $number_of_ip = 2 ** (32 - $safe_cidr);
        if($safe_cidr == 32){
            $net_first_ip = ip2long($safe_ip);
            $net_last_ip = ip2long($safe_ip);
        }else{
            $net_first_ip = ip2long($safe_ip) + 2;
            $net_last_ip = ip2long($safe_ip) + $number_of_ip - 2;
        }

        if( isset($_REQUEST["last_ip"]) && !isset($_REQUEST["first_ip"]) || !isset($_REQUEST["last_ip"]) && isset($_REQUEST["first_ip"]) ){
            $json["status"] = "error";
            $json["message"] = "You cannot set first IP without last IP, or last IP without first IP.";
            return $json;
        }

        if((isset($_REQUEST["ip"]) || isset($_REQUEST["cidr"])) && !isset($_REQUEST["first_ip"])){
            # If we're setting up network IP or CIDR without supplying first and last IP,
            # then we must use the automatically calculated values.
            $update .= ", first_ip='$net_first_ip', last_ip='$net_last_ip'";
        }else{
            if(isset($_REQUEST["first_ip"])){
                $safe_first_ip = safe_ipv4("first_ip");
                if($safe_first_ip === FALSE){
                    $json["status"] = "error";
                    $json["message"] = "Wrong first_ip format.";
                    return $json;
                }
                if($update != ""){
                    $update .= ", ";
                }
                $safe_first_ip_long = ip2long($safe_first_ip);
                # Check if the IP is in the range
                if($safe_first_ip_long < $net_first_ip || $safe_first_ip_long > $net_last_ip){
                    $json["status"] = "error";
                    $json["message"] = "Specified network first IP address is out of the network range line ".__LINE__." file ".__FILE__.".";
                }
                $update .= "first_ip='$safe_first_ip_long'";
            }

            if(isset($_REQUEST["last_ip"])){
                $safe_last_ip = safe_ipv4("last_ip");
                if($safe_last_ip === FALSE){
                    $json["status"] = "error";
                    $json["message"] = "Wrong last_ip format.";
                    return $json;
                }
                if($update != ""){
                    $update .= ", ";
                }
                $safe_last_ip_long = ip2long($safe_last_ip);
                # Check if the IP is in the range
                if($safe_last_ip_long < $net_first_ip || $safe_last_ip_long > $net_last_ip){
                    $json["status"] = "error";
                    $json["message"] = "Specified network first IP address is out of the network range line ".__LINE__." file ".__FILE__.".";
                    return $json;
                }
                $update .= "last_ip='$safe_last_ip_long'";
            }
            if($safe_first_ip_long > $safe_last_ip_long){
                $json["status"] = "error";
                $json["message"] = "Specified first IP is greater than last IP.";
                return $json;
            }
        }
        $q = "UPDATE networks SET $update WHERE name='$safe_network_name'";
        if($update != ""){
            $r = mysqli_query($con, $q);
        }
        return $json;
        break;

    case "network_add":
        // Check network name is valid and exists
        $safe_network_name = safe_fqdn("network_name");
        if($safe_network_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid network name.";
            return $json;
        }
        $q = "SELECT * FROM networks WHERE name='$safe_network_name'";
        $r = mysqli_query($con, $q);
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Cannot find network by that name.";
            return $json;
        }

        // Validate cluster name and fetch its id
        $safe_cluster_name = safe_fqdn("cluster_name");
        if($safe_cluster_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid cluster name.";
            return $json;
        }
        $q = "SELECT * FROM clusters WHERE name='$safe_cluster_name'";
        $r = mysqli_query($con, $q);
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Cannot find cluster by that name.";
            return $json;
        }
        $cluster = mysqli_fetch_array($r);
        $safe_cluster_id = $cluster["id"];

        // Check role name
        $safe_role_name = safe_fqdn("role_name");
        if($safe_role_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid role name.";
            return $json;
        }
        if($safe_role_name == "all" || $safe_role_name == "vm-net" || $safe_role_name == 'ovs-bridge' || $safe_role_name == 'ceph-cluster' || $safe_role_name == 'ipmi'){
            $sql_role = "'$safe_role_name'";
        }else{
            $r = mysqli_query($con, "SELECT id FROM roles WHERE name='$safe_role_name'");
            if($r === FALSE){
                $json["status"] = "error";
                $json["message"] = mysqli_error($con);
                return $json;
            }
            $n = mysqli_num_rows($r);
            if($n != 1){
                $json["status"] = "error";
                $json["message"] = "Error: role name $safe_role_name doesn't exist.";
                return $json;
            }
            $sql_role = "'$safe_role_name'";
        }


        // Check network card 1 param
        $safe_iface1 = safe_fqdn("iface1");
        if($safe_iface1 === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid iface 1 name.";
            return $json;
        }
        switch($safe_iface1){
        case "eth0":
        case "eth1":
        case "eth2":
        case "eth3":
        case "eth4":
        case "eth5":
        case "10m1":
        case "10m2":
        case "10m3":
        case "10m4":
        case "100m1":
        case "100m2":
        case "100m3":
        case "100m4":
        case "1g1":
        case "1g2":
        case "1g3":
        case "1g4":
        case "10g1":
        case "10g2":
        case "10g3":
        case "10g4":
            break;
        default:
            $json["status"] = "error";
            $json["message"] = "Error: not valid iface 1 name.";
            return $json;
        }

        // Check network card 2 param
        $safe_iface2 = safe_fqdn("iface2");
        if($safe_iface2 === FALSE){
            $json["status"] = "error";
            $json["message"] = "Error: not valid iface 2 name.";
            return $json;
        }
        switch($safe_iface2){
        case "none":
        case "eth0":
        case "eth1":
        case "eth2":
        case "eth3":
        case "eth4":
        case "eth5":
        case "10m1":
        case "10m2":
        case "10m3":
        case "10m4":
        case "100m1":
        case "100m2":
        case "100m3":
        case "100m4":
        case "1g1":
        case "1g2":
        case "1g3":
        case "1g4":
        case "10g1":
        case "10g2":
        case "10g3":
        case "10g4":
            break;
        default:
            $json["status"] = "error";
            $json["message"] = "Error: not valid iface 2 name.";
            return $json;
        }
        $q = "UPDATE networks SET cluster='$safe_cluster_id', role=$sql_role, iface1='$safe_iface1', iface2='$safe_iface2' WHERE name='$safe_network_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $q = "SELECT * FROM networks WHERE name='$safe_network_name'";
        $r = mysqli_query($con, $q);
        $network = mysqli_fetch_array($r);
        // If role is controller or all, then assign a VIP
        if(($network["role"] == "controller" || $network["role"] == "all") && ($network["is_public"] == "yes") ){
            $ret = reserve_ip_address($con, $conf, $network["id"], 0, "vip");
            if($ret["status"] != "success"){
                $json["status"] = "error";
                $json["message"] = $ret["message"];
                return $json;
            }
        }
        if($network["is_public"] == "no" && $network["role"] != "ovs-bridge"){
            $ret = reserve_ip_to_all_slaves_of_network($con, $conf, $safe_cluster_id, $network["id"], $safe_role_name);
            if($ret["status"] != "success"){
                $json["status"] = "error";
                $json["message"] = $ret["message"];
                return $json;
            }
        }
        return $json;
        break;

    case "network_remove":
        $safe_network_name = safe_fqdn("network_name");
        if($safe_network_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Network name in wrong format.";
            return $json;
        }
        $q = "SELECT * FROM networks WHERE name='$safe_network_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Cannot find network by that ID.";
            return $json;
        }
        $network = mysqli_fetch_array($r);
        $safe_network_id = $network["id"];

        $q = "UPDATE networks SET cluster=NULL, role=NULL WHERE id='$safe_network_id'";
        $r = mysqli_query($con, $q);
        $q = "DELETE FROM ips WHERE network='$safe_network_id'";
        $r = mysqli_query($con, $q);
        return $json;
        break;

    case "machine_apply_ipmi":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];
        $safe_machine_serial = $machine["serial"];

        $safe_machine_id = $machine["id"];

        $ipmi_username   = $machine["ipmi_username"];
        $ipmi_password   = $machine["ipmi_password"];
        $ipmi_addr       = $machine["ipmi_addr"];
        $ipmi_netmask    = $machine["ipmi_netmask"];
        $ipmi_default_gw = $machine["ipmi_default_gw"];
        if($ipmi_netmask == ''){
            $ipmi_netmask = "255.255.255.0";
        }
        if($ipmi_default_gw == ''){
            $cmd = "ipcalc " . $ipmi_addr . "/" . $ipmi_netmask ." | grep HostMin: | awk '{print \$2}'";
            $output = "";
            $return_var = 0;
            exec($cmd, $output, $return_var);
            $ipmi_default_gw = $output[0];
        }

        $ret = perform_ipmitool_cmd($con, $conf, $safe_machine_id, $ipmi_username, $ipmi_password, $ipmi_addr, $ipmi_default_gw, $ipmi_netmask);
        $json["message"] = $ret["message"];
        return $json;
        break;

    case "machine_set_ipmi":
        $safe_machine_serial = safe_serial("serial");
        if($safe_machine_serial === FALSE){
            $json["status"] = "error";
            $json["message"] = "Wrong machine serial number format.";
            return $json;
        }
        $q = "SELECT * FROM machines WHERE serial='$safe_machine_serial'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "No machine with serial $safe_machine_serial in database.";
            return $json;
        }
        $machine = mysqli_fetch_array($r);
        $safe_machine_id = $machine["id"];
        
        if(!isset($_REQUEST["ipmi_use"])){
            $json["status"] = "error";
            $json["message"] = "ipmi_use param not set.";
            return $json;
        }
        if($_REQUEST["ipmi_use"] != 'yes'){
            $q = "UPDATE machines SET ipmi_use='no' WHERE id='$safe_machine_id'";
            $r = mysqli_query($con, $q);
            return $json;
        }

        $safe_ipmi_addr = safe_fqdn("ipmi_addr");
        if($safe_ipmi_addr === FALSE){
            $safe_ipmi_addr = safe_ipv4("ipmi_addr");
            if($safe_ipmi_addr === FALSE){
                $json["status"] = "error";
                $json["message"] = "IPMI address in wrong format.";
                return $json;
            }
        }
        if(isset($_REQUEST["ipmi_default_gw"])){
            $safe_ipmi_default_gw = safe_ipv4("ipmi_default_gw");
            if($safe_ipmi_default_gw === FALSE){
                $json["status"] = "error";
                $json["message"] = "IPMI default gw in wrong format.";
                return $json;
            }
        }
        if(isset($_REQUEST["ipmi_netmask"])){
            $safe_ipmi_netmask = safe_ipv4("ipmi_netmask");
            if($safe_ipmi_netmask === FALSE){
                $json["status"] = "error";
                $json["message"] = "IPMI netmask in wrong format.";
                return $json;
            }
        }
        if(isset($_REQUEST["ipmi_call_chassis_bootdev"])){
            if($_REQUEST["ipmi_call_chassis_bootdev"] == "yes"){
                $safe_ipmi_call_chassis_bootdev = "yes";
            }else{
                $safe_ipmi_call_chassis_bootdev = "no";
            }
            $q = "UPDATE machines SET ipmi_call_chassis_bootdev='$safe_ipmi_call_chassis_bootdev' WHERE id='$safe_machine_id'";
            $r = mysqli_query($con, $q);
        }
        $safe_ipmi_port = safe_int("ipmi_port");
        if($safe_ipmi_port === FALSE){
            $out .= "IPMI port in wrong format.";
            return $out;
        }
        $safe_ipmi_username = safe_fqdn("ipmi_username");
        if($safe_ipmi_username === FALSE){
            $json["status"] = "error";
            $json["message"] = "IPMI username in wrong format.";
            return $json;
        }
        $safe_ipmi_password = safe_password("ipmi_password");
        if($safe_ipmi_password === FALSE){
            $json["status"] = "error";
            $json["message"] = "IPMI password in wrong format.";
            return $json;
        }
        if(isset($_REQUEST["perform_ipmitool_cmd"]) && $_REQUEST["perform_ipmitool_cmd"] == "yes"){
            $machine_id = $machine["id"];
            perform_ipmitool_cmd($con, $conf, $machine_id, $safe_ipmi_username, $safe_ipmi_password, $safe_ipmi_addr, $safe_ipmi_default_gw, $safe_ipmi_netmask);
        }

        $q = "UPDATE machines SET ipmi_use='yes', ipmi_addr='$safe_ipmi_addr', ipmi_port='$safe_ipmi_port', ipmi_username='$safe_ipmi_username', ipmi_password='$safe_ipmi_password' WHERE id='$safe_machine_id'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        return $json;
        break;

    case "ipmi_show_cmd_console":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];
        $safe_machine_serial = $machine["serial"];

        $cmd = "ipmitool -I lanplus -H " . $machine["ipmi_addr"] . " -p " . $machine["ipmi_port"] . " -U " . escapeshellarg($machine["ipmi_username"]) ." -P " . escapeshellarg($machine["ipmi_password"]) . " sol activate\n";
        $cmd .= "Or login with the web UI: https://" . $machine["ipmi_addr"];
        $json["message"] .= "\n$cmd";
        return $json;
        break;
    case "ipmi_reboot_on_hdd":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];
        $safe_machine_serial = $machine["serial"];

        $machine_id    = $machine["id"];
        $ipmi_addr     = $machine["ipmi_addr"];
        $ipmi_port     = $machine["ipmi_port"];
        $ipmi_username = $machine["ipmi_username"];
        $ipmi_password = $machine["ipmi_password"];

        ipmi_set_boot_device($con, $conf, $machine_id, "disk");

        $r = mysqli_query($con, "UPDATE machines SET status='firstboot' WHERE serial='$safe_machine_serial'");

        $cmd = "ipmitool -I lanplus -H $ipmi_addr -p $ipmi_port -U " . escapeshellarg($ipmi_username) . " -P " . escapeshellarg($ipmi_password) . " power cycle";
        $output = "";
        $return_var = 0;
        exec($cmd, $output, $return_var);
        return $json;
        break;
    case "ipmi_reboot_on_live":
        $json = get_machine_from_serial_or_hostname($con, $conf);
        if($json["status"] != "success"){ return $json; }
        $machine = $json["data"];
        $safe_machine_serial = $machine["serial"];

        $machine_id    = $machine["id"];
        $ipmi_addr     = $machine["ipmi_addr"];
        $ipmi_port     = $machine["ipmi_port"];
        $ipmi_username = $machine["ipmi_username"];
        $ipmi_password = $machine["ipmi_password"];

        ipmi_set_boot_device($con, $conf, $machine_id, "pxe");

        $r = mysqli_query($con, "UPDATE machines SET status='bootinglive' WHERE serial='$safe_machine_serial'");

        $cmd = "ipmitool -I lanplus -H $ipmi_addr -p $ipmi_port -U " . escapeshellarg($ipmi_username) . " -P " . escapeshellarg($ipmi_password) . " power cycle";
        $output = "";
        $return_var = 0;
        exec($cmd, $output, $return_var);
        return $json;
        break;
    case "swift_caculate_ring":
        $safe_cluster_name = safe_fqdn("cluster_name");
        if($safe_cluster_name === FALSE){
            $out .= "Wrong cluster_name format.";
            print($out);
            die();
        }
        $q = "SELECT * FROM clusters WHERE name='$safe_cluster_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "No cluster with name $safe_cluster_name in database.";
            return $json;
        }
        $cluster = mysqli_fetch_array($r);

        if(isset($_REQUEST["initial_account_weight"])){
            $safe_initial_account_weight = safe_int("initial_account_weight");
            if($safe_initial_account_weight === FALSE){
                $json["status"] = "error";
                $json["message"] = "Wrong initial account weight format.";
                return $json;                
            }
        }else{
            $safe_initial_account_weight = 1000;
        }

        if(isset($_REQUEST["initial_container_weight"])){
            $safe_initial_container_weight = safe_int("initial_container_weight");
            if($safe_initial_container_weight === FALSE){
                $json["status"] = "error";
                $json["message"] = "Wrong initial container weight format.";
                return $json;
            }
        }else{
            $safe_initial_container_weight = 1000;
        }

        if(isset($_REQUEST["initial_object_weight"])){
            $safe_initial_object_weight = safe_int("initial_object_weight");
            if($safe_initial_object_weight === FALSE){
                $json["status"] = "error";
                $json["message"] = "Wrong initial object weight format.";
                return $json;
            }
        }else{
            $safe_initial_object_weight = 1000;
        }

        $json["data"] = build_swift_ring($con, $conf, $cluster["id"], "no", $safe_initial_account_weight, $safe_initial_container_weight, $safe_initial_object_weight);

        return $json;
        break;
    case "role_list":
        $r = mysqli_query($con, "SELECT * FROM roles");
        $n = mysqli_num_rows($r);
        $json["data"] = array();
        for($i=0;$i<$n;$i++){
            $a = mysqli_fetch_array($r);
            $json["data"][$i] = $a;
        }
        return $json;
        break;
    case "role_create":
        $safe_role_name = safe_fqdn("name");
        if($safe_role_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Wrong role name format.";
            return $json;
        }
        $q = "SELECT * FROM roles WHERE name='$safe_role_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 0){
            $json["status"] = "error";
            $json["message"] = "Error: role name already exists.";
            return $json;
        }
        if($safe_role_name == "all" || $safe_role_name == "vm-net" || $safe_role_name == "ovs-bridge" || $safe_role_name == "ceph-cluster" || $safe_role_name == "ipmi"){
            $json["status"] = "error";
            $json["message"] = "Error: this role is reserved for special networking purposes.";
            return $json;
        }
        $r = mysqli_query($con, "INSERT INTO roles (name) VALUES ('$safe_role_name')");
        return $json;
        break;
    case "role_delete":
        $safe_role_name = safe_fqdn("name");
        if($safe_role_name === FALSE){
            $json["status"] = "error";
            $json["message"] = "Wrong role name format.";
            return $json;
        }
        $q = "SELECT * FROM roles WHERE name='$safe_role_name'";
        $r = mysqli_query($con, $q);
        if($r === FALSE){
            $json["status"] = "error";
            $json["message"] = mysqli_error($con);
            return $json;
        }
        $n = mysqli_num_rows($r);
        if($n != 1){
            $json["status"] = "error";
            $json["message"] = "Error: no role by that name.";
            return $json;
        }
        $r = mysqli_query($con, "DELETE FROM roles WHERE name='$safe_role_name'");
        return $json;
        break;
    default:
        $json["status"] = "error";
        $json["message"] = "Error: no action by that name.";
        return $json;
        break;
    }
    
}

$out_json = api_actions($con,$conf);
print(json_encode($out_json) . "\n");
?>
