494 lines
20 KiB
PHP
494 lines
20 KiB
PHP
<?php
|
|
|
|
|
|
namespace App\Controllers;
|
|
|
|
class Provision extends BaseController
|
|
{
|
|
|
|
|
|
public function prepareProvision(): string
|
|
{
|
|
$this->allocatePortNo(); // allocte port for the conyainer use
|
|
|
|
$this->prepareDataBase(); // allocte port for the conyainer use
|
|
|
|
$this->updateProvision();
|
|
|
|
return 0;
|
|
}
|
|
|
|
private function prepareDataBase():string
|
|
{
|
|
$servername = "172.16.4.96:3307";
|
|
$database = "wordpress";
|
|
$username = "root";
|
|
$password = "may12002!";
|
|
// Create connection
|
|
$conn = mysqli_connect($servername, $username, $password, $database);
|
|
if ($conn->connect_error) {
|
|
die("Connection failed: " . $conn->connect_error);
|
|
}
|
|
echo "Connected successfully";
|
|
|
|
$list_limit = 12;
|
|
$mysql = "SELECT id, member_id, uid, internal_url,product_id,status,provision_port,updated
|
|
FROM members_products
|
|
WHERE db_status = 0 AND product_id IN ('A000004','A000003')
|
|
ORDER BY updated ASC LIMIT ".$list_limit;
|
|
|
|
$query = $this->db->query($mysql);
|
|
$provision_list = $query->getResult();
|
|
foreach ($provision_list as $pr) {
|
|
$memberID = $pr->member_id;
|
|
$productId = $pr->product_id;
|
|
$provisionUID = $pr->uid;
|
|
$ContainerName = $productId . str_pad($pr->id, 10, "0", STR_PAD_LEFT);
|
|
|
|
// $allocated_port = $this->allocatePortNumber( $productId );
|
|
// $primary_server = $this->provisionServer( $productId );
|
|
// $mysql = "UPDATE members_products SET updated=now(), provision_port=".$allocated_port.", primary_server='".$primary_server."' WHERE uid::TEXT = '".$provisionUID."' AND provision_port = 0";
|
|
// $query = $this->db->query($mysql);
|
|
$dbName = $ContainerName;
|
|
// Create database
|
|
$sql = "CREATE DATABASE $dbName";
|
|
if ($conn->query($sql) === TRUE) {
|
|
echo "Database created successfully";
|
|
|
|
$sql = "CREATE USER '" . $dbName . "'@'localhost' IDENTIFIED BY '" . $provisionUID . "'";
|
|
$result = mysqli_query($conn, $sql);
|
|
$sql = "GRANT SELECT , INSERT , UPDATE , DELETE ON " . $dbName . " . * TO '" . $dbName . "'@'localhost' IDENTIFIED BY '" . $provisionUID . "'";
|
|
$result = mysqli_query($conn, $sql);
|
|
|
|
$mysql = "UPDATE members_products SET updated=now(), db_status = db_status + 1 WHERE uid::TEXT = '".$provisionUID."'";
|
|
$query = $this->db->query($mysql);
|
|
|
|
} else {
|
|
echo "Error creating database: " . $conn->error;
|
|
}
|
|
}
|
|
|
|
|
|
// Check connection
|
|
|
|
|
|
|
|
|
|
mysqli_close($conn);
|
|
|
|
return '';
|
|
}
|
|
public function updateProvision(): string
|
|
{
|
|
$list_limit = 1; // for noow
|
|
$public_path = FCPATH;
|
|
$ansible_folder = str_replace("public/", "ANSIBLE", $public_path);
|
|
$partMachineLocal = "/home/chiefsoft/MermsProvision/ANSIBLE/parts/";
|
|
if (!is_dir($ansible_folder . "/parts")) {
|
|
mkdir($ansible_folder . "/parts", 0700);
|
|
}
|
|
|
|
$mysql = "SELECT id, uid, internal_url,product_id,status,provision_port,updated, member_id,
|
|
id AS subscription_id
|
|
FROM members_products
|
|
WHERE provision_port > 0
|
|
AND provision_status = 0 AND p_file = 0
|
|
ORDER BY updated ASC LIMIT ".$list_limit;
|
|
|
|
$query = $this->db->query($mysql);
|
|
// $num = $query->num_rows();
|
|
$provision_list = $query->getResult();
|
|
//$provision_list =[];
|
|
foreach ($provision_list as $pr) {
|
|
$subscriptionId = $pr->subscription_id;
|
|
$provisionPort = $pr->provision_port;
|
|
$productId = $pr->product_id;
|
|
$provisionUID = $pr->uid;
|
|
$memberID = $pr->member_id;
|
|
$ContainerName = $productId . str_pad($pr->id, 10, "0", STR_PAD_LEFT);
|
|
$partFolder = $ansible_folder . "/parts/" . $provisionUID;
|
|
|
|
$allocatedPort = $provisionPort;
|
|
$this->updateToNow($provisionUID);
|
|
|
|
if (!is_dir($partFolder)) {
|
|
mkdir($partFolder, 0700);
|
|
}
|
|
|
|
// THIS PROVISONING COMPOSERS
|
|
$composer_template_path = $ansible_folder . "/templates/composers/" . $productId . "/docker-compose.yml";
|
|
$composer_template_path_local = $partMachineLocal . $provisionUID;
|
|
|
|
$prov_name = str_replace(".", "_", $pr->internal_url) . ".yml";
|
|
$template_file = $ansible_folder . "/templates/" . $pr->product_id . ".yml";
|
|
//Get the domposer template file
|
|
$composer_template_contents = file_get_contents($composer_template_path);
|
|
// Do the processing
|
|
$composer_template_contents = str_replace("WHAT_CONTAINER_NAME", $ContainerName, $composer_template_contents);
|
|
$destinationHomeFolder = "/home/chiefsoft/SITES/" . $ContainerName;
|
|
$composer_template_contents = str_replace("DESTINATION_FOLDER", $destinationHomeFolder, $composer_template_contents);
|
|
$composer_template_contents = str_replace("ALLOCATED_PORT", $allocatedPort, $composer_template_contents);
|
|
$composer_template_contents = str_replace("CNT_DB_NAME", $ContainerName, $composer_template_contents);
|
|
$composer_template_contents = str_replace("CNT_DB_PASS", $provisionUID, $composer_template_contents);
|
|
$composer_template_contents = str_replace("CNT_DB_DATA", '172.16.4.96:3307', $composer_template_contents);
|
|
|
|
//Save to the specific path
|
|
$destination_composer_path = $ansible_folder . "/parts/" . $provisionUID . "/docker-compose.yml";
|
|
$composerFile = fopen($destination_composer_path, "w") or die("Unable to open file!");
|
|
fwrite($composerFile, $composer_template_contents);
|
|
fclose($composerFile);
|
|
|
|
// GET THE TEMPLATE FOR THIS PROVISIONING
|
|
$template_content = file_get_contents($template_file);
|
|
$template_content_processed = str_replace("WHAT_HOST_IN_USE", $productId . "_SERVER", $template_content);
|
|
$template_content_processed = str_replace("WHAT_PART_FOLDER", $partFolder, $template_content_processed);
|
|
$template_content_processed = str_replace("DESTINATION_FOLDER", $destinationHomeFolder, $template_content_processed);
|
|
$template_content_processed = str_replace("WHAT_PART_LOCAL", $composer_template_path_local, $template_content_processed); // depends on the local machine
|
|
// CREATE PROVISOINING FILE
|
|
$myfile = fopen($ansible_folder . "/" . $prov_name, "w") or die("Unable to open file!");
|
|
fwrite($myfile, $template_content_processed);
|
|
fclose($myfile);
|
|
$this->registerProvision($subscriptionId,$prov_name);
|
|
$this->provisionActions($memberID, $provisionUID, "Auto Configuration Started");
|
|
}
|
|
|
|
return view('welcome_message');
|
|
}
|
|
|
|
private function registerProvision($subscriptionId,$prov_name){
|
|
|
|
/*
|
|
CREATE TABLE provision_plans (
|
|
id SERIAL,
|
|
uid uuid DEFAULT uuid_generate_v4(),
|
|
provision_id INT REFERENCES members_products(id),
|
|
play_file VARCHAR(100)UNIQUE NOT NULL,
|
|
msg VARCHAR(100) ,
|
|
added timestamp without time zone DEFAULT now(),
|
|
updated timestamp without time zone DEFAULT now()
|
|
);
|
|
ALTER TABLE ONLY provision_plans
|
|
ADD CONSTRAINT provision_plans_id_key UNIQUE (id);
|
|
|
|
*/
|
|
try{
|
|
$mysql = "INSERT INTO provision_plans (provision_id,play_file) VALUES($subscriptionId,'$prov_name')";
|
|
$query = $this->db->query($mysql);
|
|
} catch ( \Exception $e){
|
|
log_message('critical', "***** ***** registerProvision Error:: registerProvision() ".$e->getMessage());
|
|
}
|
|
return 0;
|
|
}
|
|
private function allocatePortNo(){
|
|
$list_limit = 2;
|
|
$mysql = "SELECT id, member_id, uid, internal_url,product_id,status,provision_port,updated
|
|
FROM members_products
|
|
WHERE provision_port = 0
|
|
ORDER BY updated ASC LIMIT ".$list_limit;
|
|
|
|
$query = $this->db->query($mysql);
|
|
$provision_list = $query->getResult();
|
|
foreach ($provision_list as $pr) {
|
|
$memberID = $pr->member_id;
|
|
$productId = $pr->product_id;
|
|
$provisionUID = $pr->uid;
|
|
|
|
$allocated_port = $this->allocatePortNumber( $productId );
|
|
$primary_server = $this->provisionServer( $productId );
|
|
$mysql = "UPDATE members_products SET updated=now(), provision_port=".$allocated_port.", primary_server='".$primary_server."' WHERE uid::TEXT = '".$provisionUID."' AND provision_port = 0";
|
|
$query = $this->db->query($mysql);
|
|
|
|
$this->provisionActions($memberID, $provisionUID, "Allocating Provisioning Ports");
|
|
}
|
|
}
|
|
|
|
private function allocatePortNumber($productId){
|
|
$portF = 0;
|
|
try {
|
|
$mysql = "SELECT max(provision_port) AS max_port FROM members_products WHERE product_id = '".$productId."'";
|
|
$query = $this->db->query($mysql);
|
|
$maxItem = $query->getResult()[0]->max_port;
|
|
//var_dump($maxItem);
|
|
if ($maxItem == 0 ){
|
|
switch ($productId) {
|
|
case "A000002":
|
|
$maxItem = 5500;
|
|
break;
|
|
case "A000004":
|
|
$maxItem = 8800;
|
|
break;
|
|
case "A000005":
|
|
$maxItem = 7700;
|
|
break;
|
|
case "A000001":
|
|
$maxItem = 4400;
|
|
break;
|
|
case "A000003":
|
|
$maxItem = 6600;
|
|
break;
|
|
}
|
|
}
|
|
else{
|
|
$maxItem = $maxItem+1;
|
|
}
|
|
$portF = $maxItem;
|
|
} catch (Exception $e) {
|
|
echo 'Caught exception: ', $e->getMessage(), "\n";
|
|
}
|
|
return $portF;
|
|
}
|
|
|
|
private function provisionServer($productId){
|
|
switch ($productId) {
|
|
case "A000001":
|
|
case "A000002":
|
|
$primaryServer = "172.16.4.92";
|
|
break;
|
|
case "A000003":
|
|
case "A000004":
|
|
$primaryServer = "172.16.4.91";
|
|
break;
|
|
case "A000005":
|
|
$primaryServer = "172.16.4.95";
|
|
break;
|
|
}
|
|
return $primaryServer;
|
|
}
|
|
|
|
/*
|
|
[A000001_SERVER]
|
|
172.16.4.92
|
|
|
|
[A000002_SERVER]
|
|
172.16.4.92
|
|
|
|
[A000003_SERVER]
|
|
172.16.4.91
|
|
|
|
[A000004_SERVER]
|
|
172.16.4.91
|
|
|
|
[A000005_SERVER]
|
|
172.16.4.95
|
|
*/
|
|
private function updateToNow($provisionUID){
|
|
try {
|
|
$mysql = "UPDATE members_products SET updated=now() WHERE uid::TEXT = '".$provisionUID."'";
|
|
$query = $this->db->query($mysql);
|
|
} catch (Exception $e) {
|
|
echo 'Caught exception: ', $e->getMessage(), "\n";
|
|
log_message('critical', "***** ***** Provision Error:: updateToNow() ".$e->getMessage());
|
|
}
|
|
}
|
|
|
|
private function provisionActions($memberID, $provisionUID,$actionText){
|
|
log_message('critical', "***** ***** Provision :: provisionActions($memberID, $provisionUID,$actionText) ");
|
|
try {
|
|
$mysql = "INSERT INTO provision_actions (member_id,product_uid,action) VALUES ($memberID,'$provisionUID', '$actionText')";
|
|
log_message('critical', "***** ***** Provision :: provisionActions(QUERY) :: ".$mysql);
|
|
$query = $this->db->query($mysql);
|
|
|
|
// TELL THE SOCKET TO REFRESH PAGE
|
|
$data["product_uid"] = $provisionUID;
|
|
$this->APIcall("GET", 'http://10.0.0.32:5006/broadcast/provisionings', $data);
|
|
|
|
} catch ( \Exception $e) {
|
|
// echo 'Caught exception: ', $e->getMessage(), "\n";
|
|
log_message('critical', "***** ***** Provision Error:: provisionActions() ".$e->getMessage());
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
public function releaseProvision(){
|
|
$rsyncPass = "May12002!x";
|
|
$remote_composer_path = "chiefsoft@10.0.0.32:/home/chiefsoft/MermsProvision/ANSIBLE/parts/";
|
|
$partMachineLocal = "/home/chiefsoft/MermsProvision/ANSIBLE/parts/";
|
|
$ansibleToken = $this->ansibleLogin();
|
|
$mysql ="SELECT pp.uid AS prov_uid, p.id AS mpid, p.product_id, pp.id AS plan_id, pp.uid , pp.provision_id, pp.play_file, p.uid AS provision_uid
|
|
FROM provision_plans pp
|
|
LEFT JOIN members_products p ON p.id =pp.provision_id
|
|
ORDER BY pp.updated ASC LIMIT 1 ";
|
|
$query = $this->db->query($mysql);
|
|
$provision_list = $query->getResult();
|
|
foreach ($provision_list as $pr) {
|
|
$playFile = $pr->play_file;
|
|
$planId = $pr->plan_id;
|
|
$provisionId = $pr->provision_id;
|
|
$productId = $pr->product_id;
|
|
$playbook = $pr->product_id.".yml";
|
|
$provisionUID = $pr->prov_uid;
|
|
|
|
$ansible_host = $productId . "_SERVER";
|
|
$ContainerName = $productId . str_pad($pr->mpid, 10, "0", STR_PAD_LEFT);
|
|
$destinationHomeFolder = "/home/chiefsoft/SITES/" . $ContainerName;
|
|
$composer_template_path_local = $partMachineLocal . $provisionUID;
|
|
$composer_template_path_remote = $remote_composer_path . $provisionUID;
|
|
$ansible_transport_path = $pr->provision_uid; // $ContainerName;
|
|
|
|
$this->db->query("UPDATE provision_plans SET updated = now() WHERE id = $planId");
|
|
$this->db->query("UPDATE members_products SET p_file = p_file + 1 WHERE id = $provisionId");
|
|
$params = [
|
|
"template_id"=> 2,
|
|
"debug"=> false,
|
|
"dry_run"=> false,
|
|
"playbook"=> $playbook,
|
|
"environment"=> "{
|
|
\"WHAT_HOST_IN_USE\":\"$ansible_host\",
|
|
\"DESTINATION_FOLDER\":\"$destinationHomeFolder\",
|
|
\"WHAT_PART_LOCAL\":\"$composer_template_path_local\",
|
|
\"WHAT_PART_REMOTE\":\"$composer_template_path_remote\",
|
|
\"ANSIBLE_TRANSPORT_PATH\":\"$ansible_transport_path\",
|
|
\"RSYNC_PASSWORD\":\"$rsyncPass\"
|
|
}"
|
|
];
|
|
$this->ansibleProvision($ansibleToken, $params);
|
|
}
|
|
return 0;
|
|
}
|
|
public function runAnsibleShell($provisionFile){
|
|
try{
|
|
log_message('critical', "***** ***** Provision :: runAnsibleShell($provisionFile) ");
|
|
$shellCommand ="/var/www/html/ANSIBLE/auto_play.sh A000001.yml OLU AMEYE "; ///var/www/html/ANSIBLE/$provisionFile";
|
|
log_message('critical', $shellCommand);
|
|
$output = shell_exec($shellCommand );
|
|
log_message('critical', "***** ***** Provision :: runAnsibleShell(output) AFTER SHELL RUN ".serialize($output));
|
|
|
|
// $shellCommand ="ansible-playbook --vault-password-file /var/www/html/ANSIBLE/secrets.pass --key-file ~/.ssh/ansible_worker -i /var/www/html/ANSIBLE/inventory $provisionFile";
|
|
// log_message('critical', $shellCommand);
|
|
//
|
|
// $output = shell_exec($shellCommand );
|
|
// log_message('critical', "***** ***** Provision :: runAnsibleShell(output) AFTER SHELL RUN ".$output);
|
|
} catch ( \Exception $e){
|
|
log_message('critical', "***** ***** Provision Error:: runAnsibleShell() ".$e->getMessage());
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
public function directProvision(){
|
|
|
|
$mysql = "SELECT id AS plan_id, uid, provision_id, play_file from provision_plans ORDER BY updated ASC LIMIT 1 ";
|
|
$query = $this->db->query($mysql);
|
|
$provision_list = $query->getResult();
|
|
foreach ($provision_list as $pr) {
|
|
$playFile = $pr->play_file;
|
|
$planId = $pr->plan_id;
|
|
$provisionId = $pr->provision_id;
|
|
|
|
$this->db->query("UPDATE provision_plans SET updated = now() WHERE id = $planId");
|
|
$this->db->query("UPDATE members_products SET p_file = p_file + 1 WHERE id = $provisionId");
|
|
//$this->runAnsibleShell($playFile);
|
|
|
|
try{
|
|
log_message('critical', "***** ***** Provision :: runAnsibleShell($playFile) ");
|
|
$shellCommand ="ansible-playbook --vault-password-file /var/www/html/ANSIBLE/secrets.pass --key-file ~/.ssh/ansible_worker -i /var/www/html/ANSIBLE/inventory /var/www/html/ANSIBLE/$playFile";
|
|
log_message('critical', $shellCommand);
|
|
$output = shell_exec($shellCommand );
|
|
log_message('critical', "***** ***** Provision :: runAnsibleShell(output) AFTER SHELL RUN ".$output);
|
|
} catch ( \Exception $e){
|
|
log_message('critical', "***** ***** Provision Error:: runAnsibleShell() ".$e->getMessage());
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
public function demo():string {
|
|
|
|
$PROJECT_ID = 8;
|
|
$result = "Unhandled exception";
|
|
$base_url = "http://172.16.4.90:3000";
|
|
$cookies = tempnam('/tmp','cookie.txt');
|
|
|
|
# 1. Login
|
|
$url = $base_url . "/api/auth/login";
|
|
$ch = curl_init( $url );
|
|
# Setup request to send json via POST.
|
|
$payload = json_encode( array( "auth"=> "admin", "password" => "may12002" ) );
|
|
curl_setopt( $ch, CURLOPT_POSTFIELDS, $payload );
|
|
curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
|
|
# Return response instead of printing.
|
|
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
|
|
# Fetch the headers, not the body content:
|
|
//curl_setopt($ch, CURLOPT_HEADER, true); // we want headers
|
|
//curl_setopt($ch, CURLOPT_NOBODY, true); // we don't need body
|
|
# Cookie jar
|
|
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookies);
|
|
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookies);
|
|
|
|
# Send request.
|
|
$result = curl_exec($ch);
|
|
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
$result = 'HTTP code: ' . $httpcode;
|
|
|
|
curl_close($ch);
|
|
|
|
if ($httpcode != "204") {
|
|
return "Login failed! $result";
|
|
}
|
|
|
|
# 2. Get token
|
|
$url = $base_url . "/api/user/tokens";
|
|
$ch = curl_init( $url );
|
|
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
|
|
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookies);
|
|
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookies);
|
|
$res = curl_exec($ch);
|
|
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
$token = null;
|
|
$arr = json_decode($res, true);
|
|
foreach ($arr as $item) {
|
|
if ($item["expired"]===false) {
|
|
$token = $item["id"];
|
|
break;
|
|
}
|
|
|
|
}
|
|
$result = "Found token: $token";
|
|
|
|
# 3. Lauch task
|
|
$PROJECT_ID = 7;
|
|
$url = $base_url . "/api/project/$PROJECT_ID/tasks";
|
|
$headers = [
|
|
'Content-Type:application/json',
|
|
'Accept: application/json',
|
|
'Authorization: Bearer ' . $token
|
|
];
|
|
$ch = curl_init( $url );
|
|
$payload = json_encode( array( "template_id"=> 1, "debug" => false, "dry_run" => false, "playbook" => "first-playbook.yml", "environment" => "{}" ) );
|
|
curl_setopt( $ch, CURLOPT_POSTFIELDS, $payload );
|
|
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
|
|
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
|
|
$res = curl_exec($ch);
|
|
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
$result .= "\n" . 'Launch task HTTP code: ' . $httpcode;
|
|
|
|
curl_close($ch);
|
|
|
|
# 4. Get tasks
|
|
$url = $base_url . "/api/project/$PROJECT_ID/tasks";
|
|
$ch = curl_init( $url );
|
|
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
|
|
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
|
|
$res = curl_exec($ch);
|
|
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
$result .= "\n" . 'Get tasks HTTP code: ' . $httpcode;
|
|
|
|
curl_close($ch);
|
|
|
|
ob_start();
|
|
var_dump($headers);
|
|
var_dump($res);
|
|
$result .= "\n" . ob_get_clean();
|
|
|
|
# Print response.
|
|
return "<pre>$result</pre>";
|
|
|
|
}
|
|
|
|
}
|