1388 lines
63 KiB
PHP
1388 lines
63 KiB
PHP
<?php
|
|
|
|
|
|
namespace App\Controllers;
|
|
|
|
class Provision extends BaseController
|
|
{
|
|
public function testSocket(): void
|
|
{
|
|
// TELL THE SOCKET TO REFRESH PAGE
|
|
// $data["product_uid"] = "bea86662-adb3-4c09-816b-014f450d9713"; // 3cc24fd6-e6c7-4c08-8a64-f06e3f790f38
|
|
$data["product_uid"] = "3cc24fd6-e6c7-4c08-8a64-f06e3f790f38"; //
|
|
$data["provision_action"] = "Auto%20Configuration%20Started";
|
|
$SOCKET_SERVER_LOCATION = $_ENV['SOCKET_SERVER_LOCATION'];
|
|
log_message('critical', "TEST TEST ***** ***** Provision :: Action To :: " . $SOCKET_SERVER_LOCATION . '/broadcast/provisioning');
|
|
$this->APIcall("GET", $SOCKET_SERVER_LOCATION . '/broadcast/provisioning', $data);
|
|
}
|
|
|
|
public function prepareProvision(): string
|
|
{
|
|
|
|
//$this->testSocket();
|
|
$current_database = $_ENV['MAIN_DATABASE_IP'];
|
|
log_message('critical', "***** ***** prepareProvision :: Working Database " . $current_database);
|
|
|
|
log_message('critical', "***** ***** prepareProvision :: Starting Port Allocation ");
|
|
$this->allocatePortNo(); // allocte port for the conyainer use
|
|
|
|
log_message('critical', "***** ***** prepareProvision :: Starting Product Database if Needed ");
|
|
$this->prepareDataBase(); // allocte port for the conyainer use
|
|
|
|
log_message('critical', "***** ***** prepareProvision :: Create needed DockerCompose Files ");
|
|
$this->updateProvision();
|
|
|
|
log_message('critical', "***** ***** prepareProvision :: Populate HAPROXY for URL ");
|
|
$this->configureURL();
|
|
|
|
log_message('critical', "***** ***** scheduleRefreshAction :: Refresh Requested Sites ");
|
|
$this->scheduleRefreshAction();
|
|
|
|
return 0;
|
|
}
|
|
|
|
//PROVISION_MSQL_DATABASE_IP="172.16.4.96"
|
|
//PROVISION_MSQL_DATABASE_USERNAME="root"
|
|
//PROVISION_MSQL_DATABASE_PASSWORD="may12002!"
|
|
//PROVISION_MSQL_DATABASE="wordpress"
|
|
//PROVISION_MSQL_DATABASE_PORT="3307"
|
|
|
|
private function prepareDataBase(): string
|
|
{
|
|
$servername = $_ENV['PROVISION_MSQL_DATABASE_IP'] . ":" . $_ENV['PROVISION_MSQL_DATABASE_PORT']; // "172.16.4.96:3307";
|
|
$database = $_ENV['PROVISION_MSQL_DATABASE']; //"wordpress";
|
|
$username = $_ENV['PROVISION_MSQL_DATABASE_USERNAME']; //"root";
|
|
$password = $_ENV['PROVISION_MSQL_DATABASE_PASSWORD']; //"may12002!";
|
|
// Create connection
|
|
$conn = mysqli_connect($servername, $username, $password, $database);
|
|
if ($conn->connect_error) {
|
|
die("Connection failed: " . $conn->connect_error);
|
|
}
|
|
//echo "Connected successfully";
|
|
log_message('critical', "***** ***** prepareDataBase :: Connected successfully ");
|
|
|
|
$list_limit = 2;
|
|
$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')
|
|
AND provision_status = 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;
|
|
$ContainerName = $this->generatedContainerName($productId, $pr->id); // $productId . str_pad($pr->id, 10, "0", STR_PAD_LEFT);
|
|
|
|
$dbName = $ContainerName;
|
|
// Create database
|
|
$sql = "CREATE DATABASE $dbName";
|
|
if ($conn->query($sql) === TRUE) {
|
|
// echo "Database created successfully";
|
|
log_message('critical', "***** ***** prepareDataBase :: () Database created successfully ");
|
|
|
|
$mysql = "UPDATE members_products SET updated=now() WHERE uid::TEXT = '" . $provisionUID . "'";
|
|
try {
|
|
|
|
$query = $this->db->query($mysql);
|
|
|
|
$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);
|
|
} catch (\Exception $e) {
|
|
// echo 'Message: ' .$e->getMessage();
|
|
log_message('critical', "***** ***** prepareDataBase Error:: () " . $e->getMessage());
|
|
}
|
|
|
|
} else {
|
|
//echo "Error creating database: " . $conn->error;
|
|
log_message('critical', "***** ***** prepareDataBase Error:: (Error creating database:) " . $conn->error);
|
|
}
|
|
}
|
|
mysqli_close($conn);
|
|
return '';
|
|
}
|
|
|
|
private function generatedContainerName($productId, $provID)
|
|
{
|
|
return $productId . "-SVR-" . str_pad($provID, 10, "0", STR_PAD_LEFT);
|
|
}
|
|
|
|
private function generatedBlogDatabaseName($productId, $provID): string
|
|
{
|
|
return strtoupper($productId . str_pad($provID, 10, "0", STR_PAD_LEFT));
|
|
}
|
|
|
|
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/";
|
|
$partMachineLocal = $_ENV['PATH_MACHINE_LOCAL']; // "/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 = $this->generatedContainerName($productId, $pr->id); // $productId . str_pad($pr->id, 10, "0", STR_PAD_LEFT);
|
|
$partFolder = $ansible_folder . "/parts/" . $provisionUID;
|
|
|
|
// // make sure we compose the docker compose to use
|
|
// $this->prepareDockerComposer(
|
|
// $subscriptionId,
|
|
// $provisionPort,
|
|
// $productId,
|
|
// $provisionUID,
|
|
// $memberID,
|
|
// $pr->internal_url
|
|
// );
|
|
|
|
|
|
$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
|
|
$destinationHomeFolder = $_ENV['DESTINATION_HOME_FOLDER'] . $ContainerName;
|
|
$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;
|
|
// $SITE_CONTENTS_GATEWAY = $_ENV['SITE_CONTENTS_GATEWAY'];
|
|
// $SITE_CONTACT_GATEWAY = $_ENV['SITE_CONTACT_GATEWAY'];
|
|
// $MYSQL_PROVISION_DATABASE_PORT = $_ENV['PROVISION_MSQL_DATABASE_IP'] . ":" . $_ENV['PROVISION_MSQL_DATABASE_PORT']; // "172.16.4.96:3307";
|
|
// $destinationHomeFolder = $_ENV['DESTINATION_HOME_FOLDER'] . $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", $MYSQL_PROVISION_DATABASE_PORT, $composer_template_contents);
|
|
// $composer_template_contents = str_replace("PROVISION_UID_REPLACE", $provisionUID, $composer_template_contents);
|
|
// $composer_template_contents = str_replace("PROVISION_IMAGE_NAME_REPLACE", "registry.chiefsoft.com/pweb/pweb-01-merms-pweb0006c:latest", $composer_template_contents);
|
|
// $composer_template_contents = str_replace("SITE_CONTENTS_URL_REPLACE", $SITE_CONTENTS_GATEWAY, $composer_template_contents);
|
|
// $composer_template_contents = str_replace("SITE_CONTACT_URL_REPLACE", $SITE_CONTACT_GATEWAY, $composer_template_contents);
|
|
//
|
|
// $templateRandom = 'P' . rand(1, 6);
|
|
// $composer_template_contents = str_replace("TEMPLATE_NAME_REPLACE", $templateRandom, $composer_template_contents);
|
|
|
|
$composer_template_contents = $this->prepareTemplateFile($composer_template_contents, $ContainerName, $allocatedPort, $provisionUID, $ansible_folder, $productId, $pr->internal_url, $pr->id);
|
|
|
|
//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 0;
|
|
}
|
|
|
|
private function assignProvideImageName($productId, $provisionUID): array
|
|
{
|
|
// $PROVISION_IMAGE_NAME = match ($productId) {
|
|
// "A000001" => "registry.chiefsoft.com/pweb/pweb-01-merms-pweb0006c:latest",
|
|
// "A000002" => "registry.chiefsoft.com/bweb/bweb-01-merms-pweb0006c:latest",
|
|
// default => '',
|
|
// };
|
|
$PROVISION_IMAGE_NAME = '';
|
|
$PROVISION_IMAGE_FLAVOR = 'P' . rand(1, 6); // temporary - should be blank
|
|
|
|
// let us confirm if we have a custom template for this line
|
|
$provisionUID = trim($provisionUID);
|
|
$mysql = "SELECT * FROM members_products WHERE uid::text = '$provisionUID'";
|
|
$query = $this->db->query($mysql);
|
|
$provision_detail = $query->getResult();
|
|
|
|
if (count($provision_detail) > 0) {
|
|
//var_dump($provision_detail[0]);
|
|
$result = $provision_detail[0]; // Get results as an array of objects
|
|
$product_template = $result->product_template;
|
|
$custom_template = $result->custom_template;
|
|
|
|
if ($product_template == '') { // No template assigned
|
|
$imageData = $this->pickLatestImage($productId);
|
|
if (count($imageData)) {
|
|
$this->assignTemplateToProvision($provisionUID, $imageData["provision_uid"]); //stamp image on the provison
|
|
$PROVISION_IMAGE_NAME = $imageData["provision_name"];
|
|
$PROVISION_IMAGE_FLAVOR = $imageData["flavor"];
|
|
}
|
|
}
|
|
|
|
if ($product_template != '') { // We have a template
|
|
//$provision_name = $this->selectTemplateFromUID($product_template);
|
|
$provision_data = $this->selectTemplateDetailsFromUID($product_template);
|
|
if ($provision_data[0] != '') {
|
|
$PROVISION_IMAGE_NAME = $provision_data[0]; // $provision_name;
|
|
$PROVISION_IMAGE_FLAVOR = $provision_data[1];
|
|
}
|
|
}
|
|
|
|
if ($custom_template != '') { // We have a custom template
|
|
$provision_name = $this->selectCustomnTemplateFromName($custom_template);
|
|
if ($provision_name != '') {
|
|
$PROVISION_IMAGE_NAME = $provision_name;
|
|
$PROVISION_IMAGE_FLAVOR = "";
|
|
}
|
|
}
|
|
|
|
log_message('critical', "***** ***** assignProvideImageName ProductTemplate: $PROVISION_IMAGE_NAME CustomTemplate: $custom_template ");
|
|
}
|
|
return [$PROVISION_IMAGE_NAME, $PROVISION_IMAGE_FLAVOR];
|
|
}
|
|
|
|
private function selectCustomnTemplateFromName($custom_id)
|
|
{
|
|
$mysql = "SELECT * FROM custom_templates WHERE custom_id = '$custom_id'";
|
|
$query = $this->db->query($mysql);
|
|
$template_detail = $query->getResult();
|
|
$provision_name = '';
|
|
if (count($template_detail) > 0) {
|
|
//var_dump($provision_detail[0]);
|
|
$result = $template_detail[0]; // Get results as an array of objects
|
|
$provision_name = trim($result->provision_name);
|
|
}
|
|
return $provision_name;
|
|
}
|
|
|
|
private function selectTemplateDetailsFromUID($template_uid): array
|
|
{
|
|
$mysql = "SELECT * FROM products_templates WHERE uid::text = '$template_uid'";
|
|
$query = $this->db->query($mysql);
|
|
$template_detail = $query->getResult();
|
|
$provision_name = '';
|
|
$provision_flavor = '';
|
|
if (count($template_detail) > 0) {
|
|
//var_dump($provision_detail[0]);
|
|
$result = $template_detail[0]; // Get results as an array of objects
|
|
$provision_name = trim($result->provision_name);
|
|
$provision_flavor = trim($result->flavor);
|
|
}
|
|
return [$provision_name, $provision_flavor];
|
|
}
|
|
|
|
private function selectTemplateFromUID($template_uid)
|
|
{
|
|
$mysql = "SELECT * FROM products_templates WHERE uid::text = '$template_uid'";
|
|
$query = $this->db->query($mysql);
|
|
$template_detail = $query->getResult();
|
|
$provision_name = '';
|
|
if (count($template_detail) > 0) {
|
|
//var_dump($provision_detail[0]);
|
|
$result = $template_detail[0]; // Get results as an array of objects
|
|
$provision_name = trim($result->provision_name);
|
|
}
|
|
return $provision_name;
|
|
}
|
|
|
|
private function pickLatestImage($productId)
|
|
{
|
|
$mysql = "SELECT uid::text AS provision_uid,provision_name,flavor FROM products_templates
|
|
WHERE product_id = trim('$productId')
|
|
AND status = 1 ORDER BY id DESC limit 1";
|
|
$query = $this->db->query($mysql);
|
|
$template_detail = $query->getResult();
|
|
$data = [];
|
|
if (count($template_detail) > 0) {
|
|
/// var_dump($template_detail[0]);
|
|
$result = $template_detail[0]; // Get results as an array of objects
|
|
$data["provision_uid"] = $result->provision_uid;
|
|
$data["provision_name"] = $result->provision_name;
|
|
$data["flavor"] = $result->flavor;
|
|
}
|
|
return $data;
|
|
}
|
|
|
|
private function assignTemplateToProvision($provisionUID, $provision_uid)
|
|
{
|
|
$mysql = "UPDATE members_products SET product_template='$provision_uid' WHERE uid::text = '$provisionUID' AND product_template = '' ";
|
|
$this->db->query($mysql);
|
|
return 0;
|
|
}
|
|
|
|
private function prepareTemplateFile($composer_template_contents, $ContainerName, $allocatedPort, $provisionUID, $ansible_folder, $productId, $internalUrl, $provID): string
|
|
{
|
|
|
|
// $PROVISION_IMAGE_NAME = match ($productId) {
|
|
// "A000001" => "registry.chiefsoft.com/pweb/pweb-01-merms-pweb0006c:latest",
|
|
// "A000002" => "registry.chiefsoft.com/bweb/bweb-01-merms-pweb0006c:latest",
|
|
// default => '',
|
|
// };
|
|
//
|
|
$PROVISION_IMAGE_DATA = $this->assignProvideImageName($productId, $provisionUID);
|
|
$PROVISION_IMAGE_NAME = $PROVISION_IMAGE_DATA[0]; // $this->assignProvideImageName($productId, $provisionUID);
|
|
$PROVISION_IMAGE_FLAVOR = $PROVISION_IMAGE_DATA[1];
|
|
|
|
$partMachineLocal = $_ENV['PATH_MACHINE_LOCAL'];
|
|
$SITE_CONTENTS_GATEWAY = $_ENV['SITE_CONTENTS_GATEWAY'];
|
|
$SITE_CONTACT_GATEWAY = $_ENV['SITE_CONTACT_GATEWAY'];
|
|
$MYSQL_PROVISION_DATABASE_PORT = $_ENV['PROVISION_MSQL_DATABASE_IP'] . ":" . $_ENV['PROVISION_MSQL_DATABASE_PORT']; // "172.16.4.96:3307";
|
|
$destinationHomeFolder = $_ENV['DESTINATION_HOME_FOLDER'] . $ContainerName;
|
|
$CNT_DB_NAME = $this->generatedBlogDatabaseName($productId, $provID)
|
|
$CNT_DB_USER_NAME = "bloguser";
|
|
//$templateRandom = 'P' . rand(1, 6);
|
|
$composer_template_contents = str_replace("WHAT_CONTAINER_NAME", $ContainerName, $composer_template_contents);
|
|
$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_NAME", $CNT_DB_NAME, $composer_template_contents);
|
|
$composer_template_contents = str_replace("CNT_DB_USER_NAME", $CNT_DB_USER_NAME, $composer_template_contents);
|
|
$composer_template_contents = str_replace("CNT_DB_PASS", $provisionUID, $composer_template_contents);
|
|
$composer_template_contents = str_replace("CNT_DB_DATA", $MYSQL_PROVISION_DATABASE_PORT, $composer_template_contents);
|
|
$composer_template_contents = str_replace("PROVISION_UID_REPLACE", $provisionUID, $composer_template_contents);
|
|
$composer_template_contents = str_replace("PROVISION_IMAGE_NAME_REPLACE", $PROVISION_IMAGE_NAME, $composer_template_contents);
|
|
$composer_template_contents = str_replace("SITE_CONTENTS_URL_REPLACE", $SITE_CONTENTS_GATEWAY, $composer_template_contents);
|
|
$composer_template_contents = str_replace("SITE_CONTACT_URL_REPLACE", $SITE_CONTACT_GATEWAY, $composer_template_contents);
|
|
$composer_template_contents = str_replace("TEMPLATE_NAME_REPLACE", $PROVISION_IMAGE_FLAVOR, $composer_template_contents);
|
|
|
|
try {
|
|
//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);
|
|
} catch (\Exception $e) {
|
|
log_message('critical', "***** ***** prepareTemplateFile Error:: () " . $e->getMessage());
|
|
}
|
|
|
|
$composer_template_path = $ansible_folder . "/templates/composers/" . $productId . "/docker-compose.yml";
|
|
$composer_template_path_local = $partMachineLocal . $provisionUID;
|
|
$prov_name = str_replace(".", "_", $internalUrl) . ".yml";
|
|
$template_file = $ansible_folder . "/templates/" . $productId . ".yml";
|
|
$partFolder = $ansible_folder . "/parts/" . $provisionUID;
|
|
|
|
if (!is_dir($partFolder)) {
|
|
mkdir($partFolder, 0700);
|
|
}
|
|
|
|
try {
|
|
$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 PROVISIONING FILE
|
|
$myfile = fopen($ansible_folder . "/" . $prov_name, "w") or die("Unable to open file!");
|
|
fwrite($myfile, $template_content_processed);
|
|
fclose($myfile);
|
|
} catch (\Exception $e) {
|
|
log_message('critical', "***** ***** prepareTemplateFile Error:: () " . $e->getMessage());
|
|
}
|
|
// GET THE TEMPLATE FOR THIS PROVISIONING
|
|
|
|
return $composer_template_contents;
|
|
}
|
|
|
|
private function scheduleRefreshAction(): void
|
|
{
|
|
$mysql = "SELECT * FROM member_product_refresh WHERE product_id IN ('A000001','A000002','A000006') AND status =0 LIMIT 1";
|
|
$query = $this->db->query($mysql);
|
|
// $num = $query->num_rows();
|
|
$provision_list = $query->getResult();
|
|
//$provision_list =[];
|
|
foreach ($provision_list as $pr) {
|
|
$this->db->query("UPDATE member_product_refresh SET status = status + 1 WHERE id = " . $pr->id);
|
|
$subscriptionUId = $pr->subscription_uid;
|
|
if ($this->refreshProvision($subscriptionUId) == 100) {
|
|
log_message('critical', "***** ***** scheduleRefreshAction Started:: () ");
|
|
}
|
|
}
|
|
|
|
$mysql = "SELECT * FROM member_product_refresh WHERE product_id IN ('A000003','A000004') AND status =0 LIMIT 1";
|
|
$query = $this->db->query($mysql);
|
|
// $num = $query->num_rows();
|
|
$provision_list = $query->getResult();
|
|
//$provision_list =[];
|
|
foreach ($provision_list as $pr) {
|
|
$this->db->query("UPDATE member_product_refresh SET status = status + 1 WHERE id = " . $pr->id);
|
|
$subscriptionUId = $pr->subscription_uid;
|
|
if ($this->refreshBlogProvision($subscriptionUId) == 100) {
|
|
log_message('critical', "***** ***** scheduleRefresh BLOG Action Started:: () ");
|
|
}
|
|
}
|
|
}
|
|
|
|
private function refreshBlogProvision($subscriptionUId): int
|
|
{
|
|
|
|
return $this->refreshProvision($subscriptionUId);
|
|
}
|
|
|
|
private function refreshProvision($subscriptionUId): int
|
|
{
|
|
log_message('critical', "***** ***** refreshProvision :: Execute Refresh Provisioning() ");
|
|
$rsyncPass = "******noNEDD****";
|
|
// $remote_composer_path = "chiefsoft@10.0.0.32:/home/chiefsoft/MermsProvision/ANSIBLE/parts/";
|
|
// $partMachineLocal = "/home/chiefsoft/MermsProvision/ANSIBLE/parts/";
|
|
$remote_composer_path = $_ENV['REMOTE_COMPOSER_PATH']; // "chiefsoft@10.0.0.32:/home/chiefsoft/MermsProvision/ANSIBLE/parts/";
|
|
$partMachineLocal = $_ENV['PATH_MACHINE_LOCAL']; // "/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 member_product_uid ,
|
|
p.member_id AS member_id ,
|
|
p.internal_url ,
|
|
p.provision_port,
|
|
p.provision_status
|
|
FROM provision_plans pp
|
|
LEFT JOIN members_products p ON p.id =pp.provision_id
|
|
WHERE p.uid = '$subscriptionUId' ";
|
|
|
|
$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;
|
|
$productUid = $pr->member_product_uid;
|
|
$playbook = $pr->product_id . "_repair.yml";
|
|
$provisionUID = $pr->prov_uid;
|
|
$member_id = $pr->member_id;
|
|
$internal_url = $pr->internal_url;
|
|
$provision_port = $pr->provision_port;
|
|
$members_product_id = $pr->mpid;
|
|
|
|
$this->provisionActions($member_id, $provisionUID, "Rebuilding Provision Started ");
|
|
|
|
|
|
log_message('critical', "Members Product ID ***** " . $pr->mpid . " Provision_Status == " . $pr->provision_status);
|
|
$this->updateToNow($productUid); // increase count not to repeat
|
|
|
|
$ansible_host = $productId . "_SERVER";
|
|
$ContainerName = $this->generatedContainerName($productId, $pr->mpid); //$productId ."-SVR-". str_pad($pr->mpid, 10, "0", STR_PAD_LEFT);
|
|
//$destinationHomeFolder = "/home/chiefsoft/SITES/" . $ContainerName;
|
|
$destinationHomeFolder = $_ENV['DESTINATION_HOME_FOLDER'] . $ContainerName;
|
|
// $composer_template_path_local = $partMachineLocal . $provisionUID;
|
|
// $composer_template_path_remote = $remote_composer_path . $provisionUID;
|
|
|
|
$composer_template_path_local = $partMachineLocal . $productUid;
|
|
$composer_template_path_remote = $remote_composer_path . $productUid;
|
|
|
|
// $ansible_transport_path = $pr->provision_uid; // $ContainerName;
|
|
$ansible_transport_path = $productUid; // $ContainerName;
|
|
|
|
// let us make sure all we promise are availale
|
|
//"WHAT_PART_LOCAL
|
|
|
|
|
|
// Remember this is in a CONTAINER so the path follows
|
|
$this_composer_part_location = "/var/www/html/ANSIBLE/parts/" . $productUid;
|
|
if (!is_dir($this_composer_part_location)) {
|
|
mkdir($this_composer_part_location, 0700);
|
|
}
|
|
|
|
// make sure we compose the docker compose to use
|
|
$this->prepareDockerComposer(
|
|
$members_product_id,
|
|
$provision_port,
|
|
$productId,
|
|
$productUid,
|
|
$member_id,
|
|
$internal_url
|
|
);
|
|
|
|
$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" => (int)$_ENV['ANSIBLE_TEMPLATE_ID'],
|
|
"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\",
|
|
\"CONTAINER_NAME\":\"$ContainerName\"
|
|
}"
|
|
];
|
|
log_message('critical', "02- ANSIBLE CALL PARAMETERS ********* " . serialize($params));
|
|
$ansibleReturn = $this->ansibleProvision($ansibleToken, $params);
|
|
|
|
log_message('critical', "ANSIBLE RETURN ***** " . $ansibleReturn);
|
|
if ($ansibleReturn === 200) {
|
|
log_message('critical', "Calling update_To_Completed ***** " . $ansibleReturn);
|
|
$this->update_To_Completed($productUid);
|
|
} else {
|
|
log_message('critical', "Calling WHY PATH update_To_Completed ***** " . $ansibleReturn);
|
|
$this->update_To_Completed($productUid);
|
|
}
|
|
$this->provisionActions($member_id, $provisionUID, "Rebuilding Provision Completed ");
|
|
}
|
|
return 100;
|
|
}
|
|
|
|
private function prepareDockerComposer(
|
|
$members_product_id,
|
|
$members_product_port,
|
|
$product_id,
|
|
$member_product_uid,
|
|
$member_id,
|
|
$internal_url
|
|
): void
|
|
{
|
|
|
|
|
|
$public_path = FCPATH;
|
|
$ansible_folder = str_replace("public/", "ANSIBLE", $public_path);
|
|
$partMachineLocal = $_ENV['PATH_MACHINE_LOCAL'];
|
|
|
|
$subscriptionId = $members_product_id;
|
|
$provisionPort = $members_product_port;
|
|
$productId = $product_id;
|
|
$provisionUID = $member_product_uid;
|
|
$memberID = $member_id;
|
|
$ContainerName = $this->generatedContainerName($productId, $members_product_id); // $productId . str_pad($pr->id, 10, "0", STR_PAD_LEFT);
|
|
$partFolder = $ansible_folder . "/parts/" . $member_product_uid;
|
|
|
|
/*
|
|
* may be if the file is already there , we can turn back
|
|
*
|
|
*/
|
|
$destination_composer_path = $ansible_folder . "/parts/" . $provisionUID . "/docker-compose.yml";
|
|
|
|
|
|
$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(".", "_", $internal_url) . ".yml";
|
|
$template_file = $ansible_folder . "/templates/" . $productId . ".yml";
|
|
//Get the domposer template file
|
|
$destinationHomeFolder = $_ENV['DESTINATION_HOME_FOLDER'] . $ContainerName;
|
|
$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;
|
|
// $SITE_CONTENTS_GATEWAY = $_ENV['SITE_CONTENTS_GATEWAY'];
|
|
// $SITE_CONTACT_GATEWAY = $_ENV['SITE_CONTACT_GATEWAY'];
|
|
// $MYSQL_PROVISION_DATABASE_PORT = $_ENV['PROVISION_MSQL_DATABASE_IP'] . ":" . $_ENV['PROVISION_MSQL_DATABASE_PORT']; // "172.16.4.96:3307";
|
|
// $destinationHomeFolder = $_ENV['DESTINATION_HOME_FOLDER'] . $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", $MYSQL_PROVISION_DATABASE_PORT, $composer_template_contents);
|
|
// $composer_template_contents = str_replace("PROVISION_UID_REPLACE", $provisionUID, $composer_template_contents);
|
|
// $composer_template_contents = str_replace("PROVISION_IMAGE_NAME_REPLACE", "registry.chiefsoft.com/pweb/pweb-01-merms-pweb0006c:latest", $composer_template_contents);
|
|
// $composer_template_contents = str_replace("SITE_CONTENTS_URL_REPLACE", $SITE_CONTENTS_GATEWAY, $composer_template_contents);
|
|
// $composer_template_contents = str_replace("SITE_CONTACT_URL_REPLACE", $SITE_CONTACT_GATEWAY, $composer_template_contents);
|
|
//
|
|
//
|
|
// $templateRandom = 'P' . rand(1, 6);
|
|
// $composer_template_contents = str_replace("TEMPLATE_NAME_REPLACE", $templateRandom, $composer_template_contents);
|
|
//
|
|
$composer_template_contents = $this->prepareTemplateFile($composer_template_contents, $ContainerName, $allocatedPort, $provisionUID, $ansible_folder, $productId, $internal_url, $members_product_id);
|
|
|
|
//Save to the specific path
|
|
// $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);
|
|
*/
|
|
}
|
|
|
|
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");
|
|
}
|
|
|
|
//Now let us try fix hanging stuffs
|
|
$mysql = "SELECT id, member_id, uid, internal_url,product_id,status,provision_port,updated
|
|
FROM members_products
|
|
WHERE provision_port > 0
|
|
AND status = 6
|
|
AND added < now() - INTERVAL '5 minutes'
|
|
ORDER BY updated ASC LIMIT 1";
|
|
|
|
$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;
|
|
$mysql = "UPDATE members_products SET updated=now(), provision_status=0 WHERE uid::TEXT = '" . $provisionUID . "' AND provision_port > 0";
|
|
$query = $this->db->query($mysql);
|
|
}
|
|
//SELECT * FROM members_products WHERE status = 6 AND added < now() - INTERVAL '5 minutes' LIMIT 1
|
|
}
|
|
|
|
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;
|
|
case "A000006":
|
|
$maxItem = 22000;
|
|
break;
|
|
}
|
|
} else {
|
|
$maxItem = $maxItem + 1;
|
|
}
|
|
$portF = $maxItem;
|
|
} catch (\Exception $e) {
|
|
echo 'Caught exception: ', $e->getMessage(), "\n";
|
|
}
|
|
return $portF;
|
|
}
|
|
|
|
private function provisionServer($productId)
|
|
{
|
|
$primaryServer = "";
|
|
switch ($productId) {
|
|
case "A000001":
|
|
case "A000002":
|
|
$primaryServer = $_ENV['DEPLOYMENT_SERVER_1'];
|
|
break;
|
|
case "A000003":
|
|
case "A000004":
|
|
$primaryServer = $_ENV['DEPLOYMENT_SERVER_2'];
|
|
break;
|
|
case "A000005":
|
|
case "A000006":
|
|
$primaryServer = $_ENV['DEPLOYMENT_SERVER_3'];
|
|
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): void
|
|
{
|
|
try {
|
|
$mysql = "UPDATE members_products SET updated=now(),
|
|
provision_status=provision_status+1
|
|
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;
|
|
$data["provision_action"] = $actionText;
|
|
|
|
$SOCKET_SERVER_LOCATION = $_ENV['SOCKET_SERVER_LOCATION'];
|
|
log_message('critical', "***** ***** Provision :: Action To :: " . $SOCKET_SERVER_LOCATION . '/broadcast/provisioning');
|
|
$this->APIcall("GET", $SOCKET_SERVER_LOCATION . '/broadcast/provisioning', $data);
|
|
|
|
} catch (\Exception $e) {
|
|
// echo 'Caught exception: ', $e->getMessage(), "\n";
|
|
log_message('critical', "***** ***** Provision Error:: provisionActions() " . $e->getMessage());
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
// $data["product_uid"] = "bea86662-adb3-4c09-816b-014f450d9713"; // 3cc24fd6-e6c7-4c08-8a64-f06e3f790f38
|
|
$data["product_uid"] = "3cc24fd6-e6c7-4c08-8a64-f06e3f790f38"; //
|
|
$data["provision_action"] = "Auto%20Configuration%20Started";
|
|
$SOCKET_SERVER_LOCATION = $_ENV['SOCKET_SERVER_LOCATION'];
|
|
log_message('critical', "TEST TEST ***** ***** Provision :: Action To :: " . $SOCKET_SERVER_LOCATION . '/broadcast/provisioning');
|
|
$this->APIcall("GET", $SOCKET_SERVER_LOCATION . '/broadcast/provisioning', $data);
|
|
*/
|
|
public function releaseProvision()
|
|
{
|
|
log_message('critical', "***** ***** ReleaseProvision :: Execute Actual Provisioning() ");
|
|
$PROCESS_LIMIT = 2;
|
|
$rsyncPass = "******noNEDD****";
|
|
// $remote_composer_path = "chiefsoft@10.0.0.32:/home/chiefsoft/MermsProvision/ANSIBLE/parts/";
|
|
// $partMachineLocal = "/home/chiefsoft/MermsProvision/ANSIBLE/parts/";
|
|
$remote_composer_path = $_ENV['REMOTE_COMPOSER_PATH']; // "chiefsoft@10.0.0.32:/home/chiefsoft/MermsProvision/ANSIBLE/parts/";
|
|
$partMachineLocal = $_ENV['PATH_MACHINE_LOCAL']; // "/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 member_product_uid ,
|
|
p.member_id AS member_id ,
|
|
p.internal_url ,
|
|
p.provision_port,
|
|
p.provision_status
|
|
FROM provision_plans pp
|
|
LEFT JOIN members_products p ON p.id =pp.provision_id
|
|
WHERE p.provision_status = 1
|
|
ORDER BY pp.updated ASC LIMIT " . $PROCESS_LIMIT;
|
|
$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;
|
|
$productUid = $pr->member_product_uid;
|
|
$playbook = $pr->product_id . ".yml";
|
|
$provisionUID = $pr->prov_uid;
|
|
$member_id = $pr->member_id;
|
|
$internal_url = $pr->internal_url;
|
|
$provision_port = $pr->provision_port;
|
|
$members_product_id = $pr->mpid;
|
|
|
|
log_message('critical', "Members Product ID ***** " . $pr->mpid . " Provision_Status == " . $pr->provision_status);
|
|
$this->updateToNow($productUid); // increase count not to repeat
|
|
|
|
$ansible_host = $productId . "_SERVER";
|
|
$ContainerName = $this->generatedContainerName($productId, $pr->mpid); //$productId ."-SVR-". str_pad($pr->mpid, 10, "0", STR_PAD_LEFT);
|
|
//$destinationHomeFolder = "/home/chiefsoft/SITES/" . $ContainerName;
|
|
$destinationHomeFolder = $_ENV['DESTINATION_HOME_FOLDER'] . $ContainerName;
|
|
// $composer_template_path_local = $partMachineLocal . $provisionUID;
|
|
// $composer_template_path_remote = $remote_composer_path . $provisionUID;
|
|
|
|
$composer_template_path_local = $partMachineLocal . $productUid;
|
|
$composer_template_path_remote = $remote_composer_path . $productUid;
|
|
|
|
// $ansible_transport_path = $pr->provision_uid; // $ContainerName;
|
|
$ansible_transport_path = $productUid; // $ContainerName;
|
|
|
|
// let us make sure all we promise are availale
|
|
//"WHAT_PART_LOCAL
|
|
|
|
|
|
// Remember this is in a CONTAINER so the path follows
|
|
$this_composer_part_location = "/var/www/html/ANSIBLE/parts/" . $productUid;
|
|
if (!is_dir($this_composer_part_location)) {
|
|
mkdir($this_composer_part_location, 0700);
|
|
}
|
|
|
|
// make sure we compose the docker compose to use
|
|
$this->prepareDockerComposer(
|
|
$members_product_id,
|
|
$provision_port,
|
|
$productId,
|
|
$productUid,
|
|
$member_id,
|
|
$internal_url
|
|
);
|
|
|
|
$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" => (int)$_ENV['ANSIBLE_TEMPLATE_ID'],
|
|
"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\",
|
|
\"CONTAINER_NAME\":\"$ContainerName\"
|
|
}"
|
|
];
|
|
log_message('critical', "01- ANSIBLE CALL PARAMETERS ********* " . serialize($params));
|
|
$ansibleReturn = $this->ansibleProvision($ansibleToken, $params);
|
|
|
|
log_message('critical', "ANSIBLE RETURN ***** " . $ansibleReturn);
|
|
if ($ansibleReturn === 200) {
|
|
log_message('critical', "Calling update_To_Completed ***** " . $ansibleReturn);
|
|
$this->update_To_Completed($productUid);
|
|
} else {
|
|
log_message('critical', "Calling WHY PATH update_To_Completed ***** " . $ansibleReturn);
|
|
$this->update_To_Completed($productUid);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
private function update_To_Completed($provisionUID)
|
|
{
|
|
log_message('critical', "update_To_Completed ******** ***** " . $provisionUID);
|
|
try {
|
|
$mysql = "UPDATE members_products SET updated=now(),
|
|
provision_status=provision_status+1 ,
|
|
status = 7
|
|
WHERE status = 6
|
|
AND uid::TEXT = '" . $provisionUID . "'";
|
|
|
|
$query = $this->db->query($mysql);
|
|
} catch (Exception $e) {
|
|
echo 'Caught exception: ', $e->getMessage(), "\n";
|
|
log_message('critical', "***** ***** Provision Error:: updateToCompleted() " . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
// 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 );
|
|
//// $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>";
|
|
|
|
}
|
|
|
|
public function configureURL()
|
|
{
|
|
log_message('critical', "***** ***** Configure URL :: Set up URL access for product ");
|
|
$limit = 1;
|
|
$mysql = "SELECT id, uid, internal_url,primary_server,provision_port,url_status FROM members_products WHERE url_status = 0 LIMIT $limit";
|
|
$query = $this->db->query($mysql);
|
|
$provision_list = $query->getResult();
|
|
foreach ($provision_list as $pr) {
|
|
$mbId = $pr->id;
|
|
$provisionURL = $pr->internal_url;
|
|
$provisionServer = $pr->primary_server;
|
|
$provisionPort = $pr->provision_port;
|
|
$provisionUID = $pr->uid;
|
|
|
|
log_message('critical', "***** ***** Configure URL Start ::: $provisionURL == $provisionServer:$provisionPort ");
|
|
// Here call haproxy actions
|
|
list ($res, $message) = $this->configureHaproxyURL($provisionURL, $provisionServer, $provisionPort);
|
|
// TODO: Check $res for errors
|
|
$mysql_close = "UPDATE members_products SET url_status = url_status + 1 WHERE id = $mbId ";
|
|
$this->db->query($mysql_close);
|
|
log_message('critical', "***** ***** Conclude if all Okay => $mysql_close ");
|
|
}
|
|
|
|
}
|
|
|
|
public function haproxy(): string
|
|
{
|
|
// $limit = 1;
|
|
// $mysql = "SELECT
|
|
// internal_url,
|
|
// provision_port,
|
|
// product_id,
|
|
// url_status
|
|
// FROM members_products
|
|
// WHERE url_status = 0 LIMIT $limit";
|
|
// $query = $this->db->query($mysql);
|
|
// $provision_list = $query->getResult();
|
|
// foreach ($provision_list as $pr) {
|
|
// $provisionURL = $pr->internal_url;
|
|
// $productId = $pr->product_id;
|
|
// $provisionPort = $pr->provision_port;
|
|
// $provisionUID = $pr->uid;
|
|
//
|
|
//
|
|
//
|
|
// log_message('critical', "***** ***** Configure URL $provisionURL to Point to ::: $provisionServer:$provisionPort ");
|
|
//
|
|
// }
|
|
|
|
|
|
list ($res, $message) = $this->configureHaproxyURL("23607.devprov.mermsemr.com", "172.16.4.91", "6603");
|
|
var_dump($message);
|
|
log_message('critical', "Message => '" . $message . "'");
|
|
return "Message:<br/>" . $message;
|
|
}
|
|
|
|
public function QuickFix()
|
|
{
|
|
return $this->configureHaproxyURL('sanyaameye.pers.mermsemr.com', '10.13.1.28', '4400');
|
|
}
|
|
|
|
|
|
public function configureHaproxyURL($provisionURL, $provisionServer, $provisionPort)
|
|
{
|
|
$message = "";
|
|
$base_url = $_ENV['HAPROXY_SERVER_URL']; //'http://172.16.4.99:5555';
|
|
$username = $_ENV['HAPROXY_SERVER_USER']; //'admin';
|
|
$password = $_ENV['HAPROXY_SERVER_PASS']; //'Hapr0xy001';
|
|
|
|
log_message('critical', "provisionURL => $provisionURL");
|
|
log_message('critical', "provisionServer => $provisionServer");
|
|
log_message('critical', "provisionPort => $provisionPort");
|
|
|
|
$status_code = [];
|
|
|
|
// 200
|
|
list($status_code[0], $cfgver) = $this->getHaProxyCfgVer($base_url, $username, $password);
|
|
$cfgver0 = trim($cfgver);
|
|
|
|
// Add backend
|
|
/*
|
|
# Add backend
|
|
# https://www.haproxy.com/documentation/dataplaneapi/community/?v=v3#post-/services/haproxy/configuration/backends
|
|
curl -XPOST --user admin:Hapr0xy001 \
|
|
-H 'Content-Type: application/json' -H 'Accept: application/json' \
|
|
-d '{
|
|
"name": "backend'$CFGVER'",
|
|
"mode": "http",
|
|
"http_connection_mode": "httpclose",
|
|
"forwardfor": {
|
|
"enabled": "enabled"
|
|
},
|
|
"compression": {
|
|
"algorithms": ["gzip"],
|
|
"types": ["text/html", "text/plain", "text/css", "text/javascript"]
|
|
}
|
|
}' \
|
|
"http://172.16.4.99:5555/v3/services/haproxy/configuration/backends?version=$CFGVER" > backend.txt
|
|
*/
|
|
$backend = "backend" . $cfgver0;
|
|
$data = [
|
|
"name" => $backend,
|
|
"mode" => "http",
|
|
"http_connection_mode" => "httpclose",
|
|
"forwardfor" => [
|
|
"enabled" => "enabled"
|
|
],
|
|
"compression" => [
|
|
"algorithms" => ["gzip"],
|
|
"types" => ["text/html", "text/plain", "text/css", "text/javascript"]
|
|
]
|
|
];
|
|
$uri = '/v3/services/haproxy/configuration/backends?version=' . $cfgver0;
|
|
// 202
|
|
list($status_code[1], $result) = $this->getHaProxyPost($base_url, $username, $password, $uri, $data);
|
|
|
|
// TODO: check the status code
|
|
|
|
// 200
|
|
list($status_code[2], $cfgver) = $this->getHaProxyCfgVer($base_url, $username, $password);
|
|
$cfgver = trim($cfgver);
|
|
|
|
// Add Server
|
|
/*
|
|
#https://www.haproxy.com/documentation/dataplaneapi/community/?v=v3#post-/services/haproxy/configuration/backends/-parent_name-/servers
|
|
curl -XPOST --user admin:Hapr0xy001 \
|
|
-H 'Content-Type: application/json' -H 'Accept: application/json' \
|
|
-d '{
|
|
"name": "server'$CFGVER'",
|
|
"address": "172.16.4.92",
|
|
"port": 4401,
|
|
"check": "enabled",
|
|
"health_check_port": 4401
|
|
}' \
|
|
"http://172.16.4.99:5555/v3//services/haproxy/configuration/backends/$BACKEND/servers?version=$CFGVER" > server.txt
|
|
*/
|
|
# test => "server4"
|
|
$server = "server" . $cfgver0;
|
|
$data = [
|
|
"name" => $server,
|
|
"address" => $provisionServer,
|
|
"port" => (int)$provisionPort,
|
|
"check" => "enabled",
|
|
"health_check_port" => (int)$provisionPort
|
|
];
|
|
$uri = '/v3/services/haproxy/configuration/backends/' . $backend . '/servers?version=' . $cfgver;
|
|
// 202
|
|
list($status_code[3], $result) = $this->getHaProxyPost($base_url, $username, $password, $uri, $data);
|
|
|
|
// TODO: check the status code
|
|
|
|
// 200
|
|
list($status_code[4], $cfgver) = $this->getHaProxyCfgVer($base_url, $username, $password);
|
|
$cfgver = trim($cfgver);
|
|
|
|
// Add a new ACL to "http" frontend
|
|
/*
|
|
# https://www.haproxy.com/documentation/dataplaneapi/community/?v=v3#post-/services/haproxy/configuration/frontends/-parent_name-/acls/-index-
|
|
curl -X POST --user admin:Hapr0xy001 \
|
|
-H 'Content-Type: application/json' -H 'Accept: application/json' \
|
|
-d '{
|
|
"acl_name": "acl'$CFGVER'",
|
|
"criterion": "req.hdr(Host)",
|
|
"value": "23233.devprov.mermsemr.com"
|
|
}' \
|
|
"http://172.16.4.99:5555/v3/services/haproxy/configuration/frontends/http/acls/0?version=$CFGVER"
|
|
*/
|
|
$acl = "acl" . $cfgver0;
|
|
$data = [
|
|
"acl_name" => $acl,
|
|
"criterion" => "req.hdr(Host)",
|
|
"value" => $provisionURL
|
|
];
|
|
$uri = '/v3/services/haproxy/configuration/frontends/http/acls/0?version=' . $cfgver;
|
|
// 202
|
|
list($status_code[5], $result) = $this->getHaProxyPost($base_url, $username, $password, $uri, $data);
|
|
|
|
// TODO: check the status code
|
|
|
|
// 200
|
|
list($status_code[6], $cfgver) = $this->getHaProxyCfgVer($base_url, $username, $password);
|
|
$cfgver = trim($cfgver);
|
|
|
|
// Add a new Backend Switching Rule to "http" frontend for "use_backend"
|
|
/*
|
|
# https://www.haproxy.com/documentation/dataplaneapi/community/?v=v3#post-/services/haproxy/configuration/frontends/-parent_name-/backend_switching_rules/-index-
|
|
curl -X POST --user admin:Hapr0xy001 \
|
|
-H 'Content-Type: application/json' -H 'Accept: application/json' \
|
|
-d '{
|
|
"name": "'$BACKEND'",
|
|
"cond": "if",
|
|
"cond_test": "'$ACL'"
|
|
}' \
|
|
"http://172.16.4.99:5555/v3/services/haproxy/configuration/frontends/http/backend_switching_rules/0?version=$CFGVER" > use_backend.txt
|
|
*/
|
|
$data = [
|
|
"name" => $backend,
|
|
"cond" => "if",
|
|
"cond_test" => $acl
|
|
];
|
|
$uri = '/v3/services/haproxy/configuration/frontends/http/backend_switching_rules/0?version=' . $cfgver;
|
|
// 202
|
|
list($status_code[7], $result) = $this->getHaProxyPost($base_url, $username, $password, $uri, $data);
|
|
|
|
// TODO: check the status code
|
|
|
|
// 200
|
|
list($status_code[8], $cfgver) = $this->getHaProxyCfgVer($base_url, $username, $password);
|
|
$cfgver = trim($cfgver);
|
|
|
|
$codes = "";
|
|
foreach ($status_code as $i => $code) {
|
|
$codes .= "\n$i => $code";
|
|
}
|
|
return [$status_code[7], "<pre>FIRST CFGVER=$cfgver0\n\n--- CODES: ----$codes\n\nLAST CFGVER=$cfgver</pre>"];
|
|
}
|
|
|
|
private function getHaproxyPost($base_url, $username, $password, $uri, $data)
|
|
{
|
|
$url = $base_url . $uri;
|
|
$payload = json_encode($data);
|
|
$headers = array(
|
|
'Content-Type:application/json',
|
|
'Authorization: Basic ' . base64_encode("$username:$password") // <---
|
|
);
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 30); //timeout after 30 seconds
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
|
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
|
// Debug
|
|
//curl_setopt($ch, CURLOPT_VERBOSE, true);
|
|
//$streamVerboseHandle = fopen('php://temp', 'w+');
|
|
//curl_setopt($ch, CURLOPT_STDERR, $streamVerboseHandle);
|
|
// End Debug
|
|
$result = curl_exec($ch);
|
|
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); //get status code
|
|
if ($result === FALSE) {
|
|
$result = sprintf("cUrl error (#%d): %s<br>\n", curl_errno($ch), htmlspecialchars(curl_error($ch)));
|
|
}
|
|
// Debug
|
|
//rewind($streamVerboseHandle);
|
|
//$verboseLog = stream_get_contents($streamVerboseHandle);
|
|
//$result .= "\ncUrl verbose information:\n<pre>" . htmlspecialchars($verboseLog) . "</pre>\n";
|
|
//$result .= "<pre>$payload</pre>\n";
|
|
// End Debug
|
|
curl_close($ch);
|
|
return [$status_code, $result];
|
|
}
|
|
|
|
private function getHaproxyGet($base_url, $username, $password, $uri)
|
|
{
|
|
$url = $base_url . $uri;
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 30); //timeout after 30 seconds
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
|
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
|
|
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
|
|
$result = curl_exec($ch);
|
|
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); //get status code
|
|
curl_close($ch);
|
|
return [$status_code, $result];
|
|
}
|
|
|
|
private function getHaproxyCfgVer($base_url, $username, $password)
|
|
{
|
|
return $this->getHaproxyGet($base_url, $username, $password, '/v3/services/haproxy/configuration/version');
|
|
}
|
|
|
|
}
|