'noaccess']); } else { include 'general/noaccess.php'; } exit; } $this->ajaxController = $ajax_page; $this->url = $url; } /** * Main program starts here. * * @return void */ public function run() { $operation = get_parameter('op', ''); switch ($operation) { case 'new': case 'update': $this->showClusterEditor($operation); break; case 'view': $this->showCluster(); break; case 'delete': $this->deleteCluster(); break; case 'force': $this->forceCluster(); break; default: $n_clusters = $this->getCount(); if ($n_clusters > 0) { $this->showList(); } else { $this->showWelcome(); } break; } } /** * Prints error message * * @param string $msg Message. * * @return void */ public function error(string $msg) { if (is_ajax()) { echo json_encode( ['error' => $msg] ); } else { ui_print_error_message($msg); } } /** * Loads view 'first tasks' for cluster view. * Old style. * * @return void */ public function showWelcome() { global $config; include_once $config['homedir'].'/general/first_task/cluster_builder.php'; } /** * Prepares available clusters definition for current users and loads view. * * @param string|null $msg Message (if any). * * @return void */ public function showList(?string $msg='') { global $config; // Extract data. $n_clusters = $this->getCount(); if ($n_clusters > 0) { $clusters = $this->getAll(); } else { $clusters = []; } View::render( 'cluster/list', [ 'message' => $msg, 'config' => $config, 'model' => $this, 'n_clusters' => $n_clusters, 'clusters' => $clusters, ] ); } /** * Show cluster information. * * @param string|null $msg Message (if any). * * @return void */ public function showCluster(?string $msg=null) { global $config; $err = ''; $id = get_parameter('id', null); if (empty($id) === true) { $id_agente = get_parameter('id_agente', null); try { $cluster = Cluster::loadFromAgentId($id_agente, true); } catch (\Exception $e) { $err = ui_print_error_message( __('Cluster not found: '.$e->getMessage()), '', true ); } } else { try { $cluster = new Cluster($id); } catch (\Exception $e) { $err = ui_print_error_message( __('Cluster not found: '.$e->getMessage()), '', true ); } } if ($cluster->agent()->id_agente() === null) { // Failed. $err = ui_print_error_message( __('Cluster agent not found: '), '', true ); $critical = true; } $allGroups = agents_get_all_groups_agent( $cluster->agent()->id_agente(), $cluster->agent()->id_grupo() ); $flag = (int) get_parameter('flag', 0); if ($flag === 1 && check_acl_one_of_groups($config['id_user'], $allGroups, 'AW') === true) { $id_agent_module = get_parameter('id_agente_modulo'); db_process_sql_update( 'tagente_modulo', ['flag' => 1], ['id_agente_modulo' => $id_agent_module] ); } $flag_agent = (int) get_parameter('flag_agent', 0); if ($flag_agent === 1 && check_acl_one_of_groups($config['id_user'], $allGroups, 'AW') === true) { db_process_sql_update( 'tagente_modulo', ['flag' => 1], ['id_agente' => $cluster->agent()->id_agente()] ); } $counters = $cluster->getCounters(); $counters_chart = []; $counters_bullet = []; foreach ($counters as $key => $value) { if ($key === 'not_init') { $counters_chart['Not init'] = $value; } else { $counters_chart[ucfirst($key)] = $value; } $counters_bullet[$key.'_count'] = $value; } unset($counters_chart['Total']); $module_involved_ids = $cluster->getIdsModulesInvolved(); View::render( 'cluster/view', [ 'message' => $msg, 'error' => $err, 'config' => $config, 'model' => $this, 'cluster' => $cluster, 'critical' => $critical, 'allGroups' => $allGroups, 'counters_chart' => $counters_chart, 'counters_bullet' => $counters_bullet, 'module_involved_ids' => array_combine($module_involved_ids, $module_involved_ids), ] ); } /** * Removes a cluster from db. * * @return void */ public function deleteCluster() { $msg = ''; $id = get_parameter('id', null); try { $cluster = new Cluster($id); $cluster->delete(); unset($cluster); } catch (\Exception $e) { $msg = ui_print_error_message( __('Error while deleting, reason: %s', $e->getMessage()), '', true ); } if (empty($msg) === true) { $msg = ui_print_success_message( __('Cluster successfully deleted.'), '', true ); } $this->showList($msg); } /** * Force cluster execution. * * @return void */ public function forceCluster() { $msg = ''; $id = get_parameter('id', null); try { $cluster = new Cluster($id); $cluster->force(); unset($cluster); } catch (\Exception $e) { $msg = ui_print_error_message( __('Error while forcing, reason: %s', $e->getMessage()), '', true ); } if (empty($msg) === true) { $msg = ui_print_success_message( __('Cluster successfully forced.'), '', true ); } $this->showCluster($msg); } /** * Shows editor for target cluster (or new one). * * @param string $operation Current operation. * * @return void */ public function showClusterEditor(string $operation) { global $config; if (!check_acl($config['id_user'], 0, 'AW')) { db_pandora_audit( AUDIT_LOG_ACL_VIOLATION, 'Trying to create clusters' ); include 'general/noaccess.php'; } else { $wizard = new ClusterWizard( $this->url, $operation ); $wizard->run(); } } /** * Returns number of clusters registered. * * @return integer */ public function getCount() { return $this->getAll('count'); } /** * Return all cluster definitons matching given filters. * * @param mixed $fields Fields array or 'count' keyword to retrieve * count, null or default to use default ones. * @param array $filter Filters to be applied. * @param integer $offset Offset (pagination). * @param integer $limit Limit (pagination). * @param string $order Sort order. * @param string $sort_field Sort field. * * @return array With all results or false if error. * @throws \Exception On error. */ public static function getAll( $fields=null, array $filter=[], ?int $offset=null, ?int $limit=null, ?string $order=null, ?string $sort_field=null ) { $sql_filters = []; $order_by = ''; $pagination = ''; global $config; if (is_array($filter) === false) { throw new \Exception('[ClusterManager::getAll] Filter must be an array.'); } if (empty($filter['id_group']) === false && (int) $filter['id_group'] !== 0 ) { $sql_filters[] = sprintf( ' AND tc.`group` = %d', $filter['id_group'] ); } if (empty($filter['free_search']) === false) { $topic = io_safe_input($filter['free_search']); $sql_filters[] = sprintf( ' AND (lower(tc.name) like lower("%%%s%%") OR lower(tc.description) like lower("%%%s%%") ) ', $topic, $topic ); } $count = false; if (is_array($fields) === false && $fields === 'count') { $fields = ['tc.*']; $count = true; } else if (is_array($fields) === false) { // Default values. $fields = [ 'tc.*', '(SELECT COUNT(*) FROM `tcluster_agent` WHERE `id_cluster` = tc.`id`) as `nodes`', 'tas.known_status', ]; } if (isset($order) === true) { $dir = 'asc'; if ($order === 'desc') { $dir = 'desc'; }; if ($sort_field === 'type') { $sort_field = 'cluster_type'; } if (in_array( $sort_field, [ 'name', 'description', 'group', 'cluster_type', 'nodes', 'known_status', ] ) === true ) { $order_by = sprintf( 'ORDER BY `%s` %s', $sort_field, $dir ); } } if (isset($limit) === true && $limit > 0 && isset($offset) === true && $offset >= 0 ) { $pagination = sprintf( ' LIMIT %d OFFSET %d ', $limit, $offset ); } $sql = sprintf( 'SELECT %s FROM tcluster tc LEFT JOIN tagente ta ON tc.id_agent = ta.id_agente LEFT JOIN tagente_modulo tam ON tam.id_agente = tc.id_agent AND tam.nombre = "%s" LEFT JOIN tagente_estado tas ON tam.id_agente_modulo=tas.id_agente_modulo WHERE 1=1 %s %s %s', join(',', $fields), io_safe_input('Cluster status'), join(' ', $sql_filters), $order_by, $pagination ); if ($count === true) { $sql = sprintf('SELECT count(*) as n FROM ( %s ) tt', $sql); // Counter.. All data. return db_get_value_sql($sql); } return db_get_all_rows_sql($sql); } /** * Return data for datatables painting. * * @return void * @throws \Exception On Error. */ public function draw() { global $config; // Datatables offset, limit and order. $filter = get_parameter('filter', []); $start = get_parameter('start', 0); $length = get_parameter('length', $config['block_size']); $order = get_datatable_order(true); try { ob_start(); $fields = [ 'tc.*', '(SELECT COUNT(*) FROM `tcluster_agent` WHERE `id_cluster` = tc.`id`) as `nodes`', 'tas.known_status', ]; // Retrieve data. $data = self::getAll( // Fields. $fields, // Filter. $filter, // Offset. $start, // Limit. $length, // Order. $order['direction'], // Sort field. $order['field'] ); // Retrieve counter. $count = self::getAll( 'count', $filter ); if ($data) { $data = array_reduce( $data, function ($carry, $item) { global $config; // Transforms array of arrays $data into an array // of objects, making a post-process of certain fields. $tmp = (object) $item; $manage = check_acl( $config['id_user'], $tmp->group, 'AW', true ); $tmp->name = ''.$tmp->name.''; if (empty($tmp->group) === true) { $tmp->group = __('Not set'); } else { // Html div part for csv export. $tmp->group = ui_print_group_icon( $tmp->group, true ).html_print_div( [ 'content' => groups_get_name($tmp->group), 'class' => 'invisible', ], true ); } // Type. if ($tmp->cluster_type === 'AA') { $tmp->type = __('Active-Active'); } else if ($tmp->cluster_type === 'AP') { $tmp->type = __('Active-Passive'); } else { $tmp->type = __('Unknown'); } // Status. // Html div part for csv export. $tmp->known_status = ui_print_module_status( $tmp->known_status, true ).html_print_div( [ 'content' => $tmp->known_status, 'class' => 'invisible', ], true ); // Options. View. $tmp->options = ''; $tmp->options .= html_print_image( 'images/details.svg', true, [ 'title' => __('View'), 'class' => 'main_menu_icon invert_filter', ] ); $tmp->options .= ''; if ($manage) { // Options. Edit. $tmp->options .= ''; $tmp->options .= html_print_image( 'images/edit.svg', true, [ 'title' => __('Edit'), 'class' => 'main_menu_icon invert_filter', ] ); $tmp->options .= ''; // Options. Delete. $tmp->options .= ''; $tmp->options .= html_print_image( 'images/delete.svg', true, [ 'title' => __('Delete'), 'class' => 'main_menu_icon invert_filter', ] ); $tmp->options .= ''; } $carry[] = $tmp; return $carry; } ); } // Datatables format: RecordsTotal && recordsfiltered. echo json_encode( [ 'data' => $data, 'recordsTotal' => $count, 'recordsFiltered' => $count, ] ); // Capture output. $response = ob_get_clean(); } catch (\Exception $e) { echo json_encode(['error' => $e->getMessage()]); exit; } // If not valid, show error with issue. json_decode($response); if (json_last_error() == JSON_ERROR_NONE) { // If valid dump. echo $response; } else { echo json_encode( ['error' => $response] ); } } /** * Provides data for wizard. Ajax method. * * @return void */ public function getAgentsFromGroup() { $side = get_parameter('side', null); $id = get_parameter('id', null); $group_id = get_parameter('group_id', 0); $group_recursion = (bool) get_parameter('group_recursion', 0); $groups = []; if ($group_recursion === true) { $groups = groups_get_children_ids($group_id, true); } else { $groups = $group_id; } if ($side === 'left') { // Available agents. $agents = agents_get_agents( [ 'id_grupo' => $groups ], [ 'id_agente', 'alias', ] ); $agents = array_reduce( $agents, function ($carry, $item) { $carry[$item['id_agente']] = io_safe_output($item['alias']); return $carry; } ); } else if ($side === 'right') { // Selected agents. $cluster = new Cluster($id); $agents = $cluster->getMembers(); $agents = array_reduce( $agents, function ($carry, $item) use ($groups) { if (in_array($item->id_grupo(), $groups) === true) { $carry[$item->id_agente()] = io_safe_output( $item->alias() ); } return $carry; } ); } if (empty($agents) === true) { echo '[]'; } else { // Dump response. echo json_encode($agents); } } /** * Returns a goBack form structure. * * @return array Form structure. */ public function getGoBackForm() { $form['form']['action'] = $this->url; $form['form']['method'] = 'POST'; $form['form']['id'] = 'go-back-form'; $form['inputs'] = [ [ 'arguments' => [ 'name' => 'submit', 'label' => __('Go back'), 'type' => 'submit', 'attributes' => [ 'icon' => 'back', 'mode' => 'secondary', ], 'return' => true, ], ], ]; return $form; } }