blob: c01146eaf6052c9c5334413953ecd2b599aa7254 [file] [log] [blame]
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
include_once "../orchestrator/State.php";
include_once "../orchestrator/Service.php";
include_once "../orchestrator/ServiceComponent.php";
include_once "../orchestrator/Cluster.php";
include_once '../util/Logger.php';
include_once '../conf/Config.inc';
include_once "../util/lock.php";
include_once '../db/HMCDBAccessor.php';
include_once "Transaction.php";
class OrchestratorDB {
// Cluster name
public $clusterName;
private $db;
private $logger;
private $puppet;
private $exploreMode;
private $servicesCache;
private $serviceComponentsCache;
private $serviceMetaInfo;
private $serviceComponentMetaInfo;
/**
* Initialize ODB
* @param string $dbPath
* @param string $clusterName
* @param object $puppet PuppetInvoker
*/
function __construct($dbPath, $clusterName, $puppet) {
$this->clusterName = $clusterName;
$this->db = new HMCDBAccessor($dbPath);
$this->puppet = $puppet;
$this->exploreMode = false;
$this->servicesCache = array();
$this->serviceComponentsCache = array();
$this->serviceMetaInfo = NULL;
$this->serviceComponentMetaInfo = NULL;
$this->logger = new HMCLogger("OrchestratorDB");
}
function getServiceDisplayName($serviceName) {
if (!isset($serviceMetaInfo)
|| $serviceMetaInfo == NULL) {
$result = $this->db->getAllServicesList();
if ($result["result"] != 0 || !isset($result["services"])) {
$this->logger->log_error("Failed to retrieve service meta info from DB"
. ", error=" . $result["error"]);
return $serviceName;
}
$serviceMetaInfo = $result["services"];
}
if (isset($serviceMetaInfo[$serviceName]["displayName"])
&& $serviceMetaInfo[$serviceName]["displayName"] != "") {
return $serviceMetaInfo[$serviceName]["displayName"];
}
return $serviceName;
}
function getServiceComponentDisplayName($serviceName, $componentName) {
if (!isset($serviceComponentMetaInfo)
|| $serviceComponentMetaInfo == NULL) {
$result = $this->db->getAllServiceComponentsList();
if ($result["result"] != 0 || !isset($result["services"])) {
$this->logger->log_error("Failed to retrieve service component meta info from DB"
. ", error=" . $result["error"]);
return $componentName;
}
$serviceComponentMetaInfo = $result["services"];
}
if (isset($serviceComponentMetaInfo[$serviceName]["components"][$componentName]["displayName"])
&& $serviceComponentMetaInfo[$serviceName]["components"][$componentName]["displayName"] != "") {
return $serviceComponentMetaInfo[$serviceName]["components"][$componentName]["displayName"];
}
return $componentName;
}
/**
* Get all the services in the cluster.
* @return array of Service objects
* @return FALSE on error
*/
public function getClusterServices() {
$services = $this->db->getAllServicesInfo($this->clusterName);
if ($services === FALSE || $services["result"] != 0) {
$this->logger->log_error("Failed to get service list from DB");
return FALSE;
}
$svcObjs = array();
foreach ($services["services"] as $svc) {
if (!$svc["isEnabled"]) {
continue;
}
$state = STATE::getStateFromString($svc["state"]);
if ($state === FALSE) {
$this->logger->log_error("Found service with invalid state"
. ", service=" . $svc["serviceName"]
. ", state=" . $svc["state"]);
$state = 0; // unknown
}
$svcObj =
$this->getServiceObj($svc["serviceName"], $state, $this, $this->puppet);
array_push($svcObjs, $svcObj);
}
return $svcObjs;
}
/**
* Get the Service object corresponding to the serviceName.
* @param serviceName service name
* @return Service
* @return FALSE on error
*/
public function getService($serviceName) {
$serviceInfo = $this->db->getServiceInfo($this->clusterName, $serviceName);
if ($serviceInfo["result"] != 0) {
$this->logger->log_error("Failed to get serviceInfo for $serviceName with "
. $serviceInfo["error"]);
return FALSE;
}
if ($serviceInfo["isEnabled"] != TRUE) {
$this->logger->log_error("Could not find ServiceInfo for legal $serviceName");
return FALSE;
}
$state = STATE::getStateFromString($serviceInfo["state"]);
return $this->getServiceObj($serviceName, $state, $this, $this->puppet);
}
public function getServices($serviceNames) {
$svcObjs = array();
foreach ($serviceNames as $serviceName) {
$svcObj = $this->getService($serviceName);
if ($svcObj === FALSE) {
return FALSE;
}
$svcObjs[$serviceName] = $svcObj;
}
return $svcObjs;
}
/**
* Get service dependencies for the given service.
* @param serviceName service name
* @return array of Service objects
*/
public function getServiceDependencies($serviceName) {
$svcDeps = $this->db->getServiceDependencies($serviceName);
if ($svcDeps === FALSE || $svcDeps["result"] != 0) {
$this->logger->log_error("Failed to get service deps from DB");
return FALSE;
}
$services = $this->db->getAllServicesInfo($this->clusterName);
if ($services === FALSE || $services["result"] != 0) {
$this->logger->log_error("Failed to get service list from DB");
return FALSE;
}
$svcObjs = array();
foreach ($svcDeps["serviceDependencies"] as $svcDep) {
if (!isset($services["services"][$svcDep])) {
$this->logger->log_error("Found a service dependency that does not "
. " exist in DB");
return FALSE;
}
$svc = $services["services"][$svcDep];
$state = STATE::getStateFromString($svc["state"]);
if ($state === FALSE) {
$this->logger->log_error("Found service with invalid state"
. ", service=" . $svc["serviceName"]
. ", state=" . $svc["state"]);
$state = 0; // unknown
}
$svcObj =
$this->getServiceObj($svc["serviceName"], $state, $this, $this->puppet);
array_push($svcObjs, $svcObj);
}
return $svcObjs;
}
/**
* Get services which depend on the given service.
* @param serviceName service name
* @return array of Service objects
*/
public function getServiceDependents($serviceName) {
$svcDeps = $this->db->getServiceDependents($serviceName);
if ($svcDeps === FALSE || $svcDeps["result"] != 0) {
$this->logger->log_error("Failed to get service deps from DB");
return FALSE;
}
$services = $this->db->getAllServicesInfo($this->clusterName);
if ($services === FALSE || $services["result"] != 0) {
$this->logger->log_error("Failed to get service list from DB");
return FALSE;
}
$svcObjs = array();
foreach ($svcDeps["serviceDependents"] as $svcDep) {
if (!isset($services["services"][$svcDep])) {
$this->logger->log_debug("Found a service dependent that does not "
. " exist in DB");
continue;
}
$svc = $services["services"][$svcDep];
if (!$svc["isEnabled"]) {
continue;
}
$state = STATE::getStateFromString($svc["state"]);
if ($state === FALSE) {
$this->logger->log_warn("Found service with invalid state"
. ", service=" . $svc["serviceName"]
. ", state=" . $svc["state"]);
$state = 0; // unknown
}
$svcObj =
$this->getServiceObj($svc["serviceName"], $state, $this, $this->puppet);
array_push($svcObjs, $svcObj);
}
return $svcObjs;
}
/**
* Get components of a service.
* @param serviceName service name
* @return array of ServiceComponent objects
*/
public function getServiceComponents($serviceName) {
$result = $this->db->getAllServiceComponents($serviceName);
if ($result === FALSE || $result["result"] != 0
|| !isset($result["components"])
|| !is_array($result["components"])) {
$this->logger->log_error("Failed to get component list from DB");
return FALSE;
}
$fullCompList = $result["components"];
$result = $this->db->getAllServiceComponentsInfo($this->clusterName);
if ($result === FALSE || $result["result"] != 0) {
$this->logger->log_error("Failed to get component list from DB");
return FALSE;
}
$compObjs = array();
if (!isset($result["services"][$serviceName])
|| !is_array($result["services"][$serviceName])
|| !is_array($result["services"][$serviceName]["components"])) {
return array();
}
$comps = $result["services"][$serviceName]["components"];
foreach ($comps as $comp) {
$state = STATE::getStateFromString($comp["state"]);
if ($state === FALSE) {
$this->logger->log_warn("Found component with invalid state"
. ", component=" . $comp["componentName"]
. ", state=" . $comp["state"]);
$state = 0;
}
$isClient = FALSE;
if (isset($fullCompList[$comp["componentName"]])) {
if (isset($fullCompList[$comp["componentName"]]["isClient"])) {
$isClient = $fullCompList[$comp["componentName"]]["isClient"];
}
} else {
$this->logger->log_warn("Found component which doesn't exist in meta list"
. ", component=" . $comp["componentName"]);
}
$compObj =
$this->getServiceComponentObj($comp["componentName"], $serviceName,
$state, $this, $this->puppet, $isClient);
array_push($compObjs, $compObj);
}
return $compObjs;
}
public function getNagiosServerComponent() {
$svc = $this->getService("NAGIOS2");
if ($svc === FALSE) {
return $svc;
}
$compObjs = $this->getServiceComponents("NAGIOS2");
foreach ($compObjs as $compObj) {
if ($compObj->name == "NAGIOS_SERVER2") {
return $compObj;
}
}
return FALSE;
}
public function getDashboardServerComponent() {
$svc = $this->getService("DASHBOARD");
if ($svc === FALSE) {
return $svc;
}
$compObjs = $this->getServiceComponents("DASHBOARD");
foreach ($compObjs as $compObj) {
if ($compObj->name == "DASHBOARD") {
return $compObj;
}
}
return FALSE;
}
/**
* Get component dependencies for a given component of a given
* service.
* @param serviceName service name
* @param componentName component name
* @return array of ServiceComponent objects
*/
public function getComponentDependencies($serviceName, $componentName) {
$result = $this->db->getAllServiceComponentsList();
if ($result === FALSE || $result["result"] != 0) {
$this->logger->log_error("Failed to get component list from DB");
return FALSE;
}
$fullCompList = array();
if (isset($result["services"])) {
foreach ($result["services"] as $svc => $svcInfo) {
if (isset($svcInfo["components"])) {
foreach ($svcInfo["components"] as $comp => $compInfo) {
$fullCompList[$comp] = $compInfo["isClient"];
}
}
}
}
$result = $this->db->getAllServiceComponentsInfo($this->clusterName);
if ($result === FALSE || $result["result"] != 0
|| !isset($result["services"][$serviceName])
|| !is_array($result["services"][$serviceName])
|| !is_array($result["services"][$serviceName]["components"])) {
$this->logger->log_error("Failed to get component list from DB");
return FALSE;
}
$compDeps = $this->db->getServiceComponentDependencies($componentName);
if ($result === FALSE || $result["result"] != 0) {
$this->logger->log_error("Failed to get component deps list from DB");
return FALSE;
}
$compObjs = array();
$comps = $result["services"][$serviceName]["components"];
foreach ($comps as $comp) {
if (FALSE === array_search($comp["componentName"], $compDeps["componentDependencies"])) {
$this->logger->log_debug("Skipping component as not in dep list, comp="
. $comp["componentName"]);
continue;
}
$state = STATE::getStateFromString($comp["state"]);
if ($state === FALSE) {
$this->logger->log_error("Found component with invalid state"
. ", component=" . $comp["componentName"]
. ", state=" . $comp["state"]);
$state = 0;
}
$isClient = FALSE;
if (isset($fullCompList[$comp["componentName"]])) {
$isClient = $fullCompList[$comp["componentName"]];
} else {
$this->logger->log_warn("Found component which doesn't exist in meta list"
. ", component=" . $comp["componentName"]);
}
$compObj =
$this->getServiceComponentObj($comp["componentName"], $serviceName,
$state, $this, $this->puppet, $isClient);
array_push($compObjs, $compObj);
}
return $compObjs;
}
/**
* Get component dependents for a given component of a given
* service.
* @param serviceName service name
* @param componentName component name
* @return array of ServiceComponent objects
*/
public function getComponentDependents($serviceName, $componentName) {
$result = $this->db->getAllServiceComponentsList();
if ($result === FALSE || $result["result"] != 0) {
$this->logger->log_error("Failed to get component list from DB");
return FALSE;
}
$fullCompList = array();
if (isset($result["services"])) {
foreach ($result["services"] as $svc => $svcInfo) {
if (isset($svcInfo["components"])) {
foreach ($svcInfo["components"] as $comp => $compInfo) {
$fullCompList[$comp] = $compInfo["isClient"];
}
}
}
}
$result = $this->db->getAllServiceComponentsInfo($this->clusterName);
if ($result === FALSE || $result["result"] != 0
|| !isset($result["services"][$serviceName])
|| !is_array($result["services"][$serviceName])
|| !is_array($result["services"][$serviceName]["components"])) {
$this->logger->log_error("Failed to get component list from DB");
return FALSE;
}
$compDeps = $this->db->getServiceComponentDependents($componentName);
if ($result === FALSE || $result["result"] != 0) {
$this->logger->log_error("Failed to get component deps list from DB");
return FALSE;
}
$compObjs = array();
$comps = $result["services"][$serviceName]["components"];
foreach ($comps as $comp) {
if (FALSE === array_search($comp["componentName"], $compDeps["componentDependents"])) {
$this->logger->log_debug("Skipping component as not in dep list, comp="
. $comp["componentName"]);
continue;
}
$state = STATE::getStateFromString($comp["state"]);
if ($state === FALSE) {
$this->logger->log_error("Found component with invalid state"
. ", component=" . $comp["componentName"]
. ", state=" . $comp["state"]);
$state = 0;
}
$isClient = FALSE;
if (isset($fullCompList[$comp["componentName"]])) {
$isClient = $fullCompList[$comp["componentName"]];
} else {
$this->logger->log_warn("Found component which doesn't exist in meta list"
. ", component=" . $comp["componentName"]);
}
$compObj =
$this->getServiceComponentObj($comp["componentName"], $serviceName,
$state, $this, $this->puppet, $isClient);
array_push($compObjs, $compObj);
}
return $compObjs;
}
/**
* Get all nodes in the cluster.
* @return mixed
* array( "result" => 0, "error" => msg, "nodes" => array())
*/
public function getAllNodes() {
$result = $this->db->getAllHostsInfo($this->clusterName,
array("=" => array ( "discoveryStatus" => "SUCCESS")), array());
if ($result === FALSE || $result["result"] != 0
|| !isset($result["hosts"]) || !is_array($result["hosts"])) {
$this->logger->log_error("Failed to get host list from DB");
return array ("result" => 1,
"error" => "Failed to get host list from DB");
}
$nodes = array();
foreach ($result["hosts"] as $host) {
array_push($nodes, $host["hostName"]);
}
$result = $this->db->getAllHostsByComponent($this->clusterName);
if ($result === FALSE || $result["result"] != 0) {
$this->logger->log_error("Failed to get host component mapping from DB");
return array ("result" => 1,
"error" => "Failed to get host component mapping from DB");
}
$compMapping = array ();
if (isset($result["components"])
&& is_array($result["components"])) {
foreach ($result["components"] as $compName => $hostsList) {
if (isset($hostsList["hosts"])
&& !empty($hostsList["hosts"])) {
$compMapping[$compName] = array_keys($hostsList["hosts"]);
}
}
}
return array ("result" => 0, "error" => "", "nodes" => $nodes,
"componentMapping" => $compMapping);
}
/**
* Get nodes for the given service-component.
* @param serviceComponent service component
* @return mixed
* array( "result" => 0, "error" => msg, "nodes" => array())
*/
public function getComponentNodes($serviceComponent) {
$result = $this->db->getHostsForComponent($this->clusterName,
$serviceComponent->name);
if ($result === FALSE || $result["result"] != 0
|| !isset($result["hosts"]) || !is_array($result["hosts"])) {
$this->logger->log_error("Failed to get host list from DB");
return array ("result" => 1,
"error" => "Failed to get host list from DB");
}
$nodes = array_keys($result["hosts"]);
return array ("result" => 0, "error" => "", "nodes" => $nodes);
}
/**
* Set service state.
* @param service service whose state needs to be set
* @param state service state
* @return mixed
* array( "result" => 0, "error" => msg)
*/
public function setServiceState($service, $state) {
$this->logger->log_info($service->name . " - ". State::$STATE[$state]);
if (isset(State::$DESIRED_STATE[$state])) {
$result = $this->db->setServiceDesiredState($this->clusterName,
$service->name, State::$DESIRED_STATE[$state]);
}
$result = $this->db->setServiceState($this->clusterName,
$service->name, State::$STATE[$state]);
return $result;
}
/**
* Set service component state.
* @param serviceComponent service-component whose state needs to be set
* @param state service-component state
* @return mixed
* array( "result" => 0, "error" => msg)
*/
public function setServiceComponentState($serviceName, $componentName, $state) {
$this->logger->log_info("Update ServiceComponentState " . $serviceName . " - "
. $componentName . " - " . State::$STATE[$state]);
if (isset(State::$DESIRED_STATE[$state])) {
$result = $this->db->setServiceComponentDesiredState($this->clusterName,
$componentName, State::$DESIRED_STATE[$state], TRUE);
}
$result = $this->db->setServiceComponentState($this->clusterName,
$componentName, State::$STATE[$state], TRUE);
return $result;
}
/**
* Persist a single transaction.
* @param transaction transaction to be persisted
* @param state state of the transaction
* @param description description of the transaction
* @param dryRun is this a dry-run?
* @param txnType Type identifier of txn
* @return mixed
* array( "result" => 0, "error" => msg)
*/
public function persistTransaction($transaction, $state, $description,
$progress, $txnType, $dryRun) {
if ($transaction == NULL) {
return array ( "result" => 0, "error" => "" );
}
if ($dryRun == TRUE) {
$state = "PENDING";
$progress = "PENDING";
}
$this->logger->log_info("persist: " . $transaction->toString()
. ":" . $state . ":" . $description . ":" . $progress);
$result = $this->db->insertOrUpdateSubTransaction($this->clusterName,
$transaction->txId, $transaction->subTxId, $transaction->parentSubTxId,
$state, $description, $progress, $txnType);
return $result;
}
public function persistTransactionOpStatus($transaction, $opStatus) {
if ($transaction == NULL) {
return array ( "result" => 0, "error" => "" );
}
$result = $this->db->updateSubTransactionOpStatus($this->clusterName,
$transaction->txId, $transaction->subTxId, $opStatus);
return $result;
}
private function getServiceObj($serviceName, $serviceState, $db, $puppet) {
$service = NULL;
if (array_key_exists($serviceName, $this->servicesCache)) {
$service = $this->servicesCache[$serviceName];
$this->logger->log_debug("Got cached service for $serviceName");
} else {
$displayName = $this->getServiceDisplayName($serviceName);
$service = new Service($this->clusterName, $serviceName, $serviceState,
$db, $puppet, $displayName);
$this->servicesCache[$serviceName] = $service;
$this->logger->log_debug("Did not get cached service for $serviceName");
}
return $service;
}
private function getServiceComponentObj($componentName, $serviceName, $componentState,
$db, $puppet, $isClient) {
$serviceComponent = NULL;
if (array_key_exists($componentName, $this->serviceComponentsCache)) {
$serviceComponent = $this->serviceComponentsCache[$componentName];
$this->logger->log_debug("Got cached serviceComponent for $componentName");
} else {
$displayName = $this->getServiceComponentDisplayName($serviceName,
$componentName);
$serviceComponent =
new ServiceComponent($this->clusterName, $componentName, $serviceName,
$componentState, $db, $puppet, $isClient, $displayName);
$this->logger->log_debug("Did not get cached serviceComponent for $componentName");
$this->serviceComponentsCache[$componentName] = $serviceComponent;
}
return $serviceComponent;
}
public function reset() {
$this->servicesCache = array();
$this->serviceComponentsCache = array();
$this->logger->log_debug("Reset caches.");
}
public function getServiceClientNode($serviceName) {
$this->logger->log_debug("getServiceClientNode called");
$componentName = $serviceName."_CLIENT";
$clients = $this->db->getHostsForComponent($this->clusterName,
$componentName);
if ($clients === FALSE || $clients["result"] != 0) {
return $clients;
}
$nodes = array_keys($clients["hosts"]);
return array("result" => 0, "error" => "", "nodes" => $nodes);
}
public function getNodeServices($node) {
$roles = $this->db->getRolesForHosts($this->clusterName, array($node));
if ($roles === FALSE || $roles["result"] != 0) {
return $roles;
}
$serviceNames = array();
if (isset($roles["hosts"][$node]["services"])) {
$serviceNames = array_keys($roles["hosts"][$node]["services"]);
}
$services = array();
foreach ($serviceNames as $serviceName) {
$service = $this->getService($serviceName);
if (!$service) {
$this->logger->log_warn("Failed to get service object for $serviceName");
return array('result' => -1, 'error' => "Failed to get service object for $serviceName");
}
array_push($services, $service);
}
return array('result' => 0, 'error' => "", 'services' => $services);
}
public function getNodeRolesAndState($nodes) {
$roles = $this->db->getRolesForHosts($this->clusterName, $nodes);
return $roles;
}
public function setHostsState($hostsToUpdate, $state) {
$this->logger->log_debug("Update HostRoleState - " . State::$STATE[$state]
. print_r($hostsToUpdate, true));
if (isset(State::$DESIRED_STATE[$state])) {
$result = $this->db->setHostsDesiredState($this->clusterName,
$hostsToUpdate, State::$DESIRED_STATE[$state]);
}
$result = $this->db->setHostsState($this->clusterName,
$hostsToUpdate, State::$STATE[$state]);
return $result;
}
public function matchHostStateToComponent($hosts) {
$this->db->matchHostDesiredStateToComponent($this->clusterName, $hosts);
$result = $this->db->matchHostStateToComponent($this->clusterName, $hosts);
return $result;
}
public function getRecursiveServiceDependents($serviceName) {
$deps = $this->db->getAllServiceDependencies();
if ($deps["result"] != 0) {
return FALSE;
}
return $this->db->getRecursiveServiceDependents($deps["serviceDependencies"],
$serviceName);
}
};
?>