Subversion Repositories ALCASAR

Rev

Rev 3309 | Rev 3314 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log

Rev Author Line No. Line
3294 rexy 1
<?php
2
 
3
// written by Alexandre BOUIJOUX
4
 
5
/*******************
6
 * READ CONF FILES *
7
 ******************/
8
define('CONF_FILE', '/usr/local/etc/alcasar.conf');
9
 
10
$conf_files = [CONF_FILE];
11
 
12
// Files reading test
13
foreach ($conf_files as $file) {
14
	if (!file_exists($file)) {
15
		exit("Requested file $file isn't present");
16
	}
17
 
18
	if (!is_readable($file)) {
19
		exit("Can't read the file $file");
20
	}
21
}
22
 
23
// Read ALCASAR CONF_FILE
24
$file_conf = fopen(CONF_FILE, 'r');
25
if (!$file_conf) {
26
	exit('Error opening the file '.CONF_FILE);
27
}
28
while (!feof($file_conf)) {
29
	$buffer = fgets($file_conf, 4096);
30
	if ((strpos($buffer, '=') !== false) && (substr($buffer, 0, 1) !== '#')) {
31
		$tmp = explode('=', $buffer, 2);
32
		$conf[trim($tmp[0])] = trim($tmp[1]);
33
	}
34
}
35
 
36
// Handle error messages
37
// Move errors messages from cookies to array.
38
$errors_msg = [];
39
$cookies_keys = [ "add_replica_error", "change_replicas_state_error", "add_ssh_key_error", "delete_ssh_key_error" ];
40
foreach ($cookies_keys as $key) {
41
	// Ignore if error didn't happened
42
	if (!array_key_exists($key, $_COOKIE)) {
43
		continue;
44
	}
45
 
46
	// Store message in errors messages array
47
	$errors_msg[$key] = $_COOKIE[$key];
48
 
49
	// Delete the cookie
50
	unset($_COOKIE[$key]);
51
	setcookie($key, false, 1);
52
}
53
 
54
// Choice of language
55
$Language = 'en';
56
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
57
	$Langue	  = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
58
	$Language = strtolower(substr(chop($Langue[0]), 0, 2));
59
}
60
if ($Language === 'fr') {
61
	$l_action		= "Action";
62
	$l_add_to_list		= "Ajouter";
63
	$l_algorithm		= "Algorithme";
64
	$l_apply		= "Appliquer les changements";
65
	$l_bind_port		= "Port de liaison";
66
	$l_cant_read_pubkey	= "Impossible de lire la clé publique de 'root'.";
67
	$l_confirm_uninstall	= "Êtes-vous certain de vouloir désinstaller la fédération ?";
3309 rexy 68
	$l_db_pwd		= "Mot de passe d'accès à la base de données";
69
	$l_db_user		= "Utilisateur de la base de données";
3294 rexy 70
	$l_delete		= "Supprimer";
71
	$l_error_details	= "Détails des erreurs";
72
	$l_field		= "Champ";
73
	$l_go_network_conf_page	= "Allez sur la page de configuration réseau.";
74
	$l_host_name		= "Nom d'hôte";
75
	$l_hosts_settings	= "Paramètres de réplication des hôtes";
3306 rexy 76
	$l_import_ssh_key	= "Si cet ALCASAR est primaire, importez ici les clés publiques des secondaires";
3294 rexy 77
	$l_install_repl		= "Installer la fédération";
78
	$l_ip_address		= "Adresse IP";
79
	$l_no_primary_connected = "Aucun primaire connecté";
3308 rexy 80
	$l_no_ssh_key		= "Aucune clé SSH importée.";
3294 rexy 81
	$l_not_connected	= "Non connecté";
3306 rexy 82
	$l_pubkey_to_deploy	= "Si cet ALCASAR est secondaire, copiez la clé publique ci-dessous pour l'importez dans le primaire.";
3294 rexy 83
	$l_remote_access_mgmt	= "Gestion des accès distants";
84
	$l_remote_role		= "Rôle de l'hôte distant";
85
	$l_repl_io_running	= "État";
3313 rexy 86
	$l_started			= "Démarré";
87
	$l_stopped			= "Arrêté";
88
	$l_in_progress		= "En cours ...";
3294 rexy 89
	$l_replication_install	= "Installer la Fédération";
90
	$l_replication_title	= "Fédération";
91
	$l_role_primary		= "Primaire";
92
	$l_role_secondary	= "Secondaire";
3306 rexy 93
	$l_ssh_keys_for_primary	= "Liste des secondaires autorisées à se connecter";
3294 rexy 94
	$l_ssh_port		= "Port SSH";
95
	$l_ssh_user		= "Utilisateur SSH";
3309 rexy 96
	$l_ssh_wan_enabled	= "Le service SSH sur le WAN est activé.";
97
	$l_ssh_wan_must_be_on	= "Le service SSH sur le WAN doit être activé.";
3294 rexy 98
	$l_start		= "Démarrer";
99
	$l_stop			= "Arrêter";
100
	$l_uninstall_repl	= "Désinstaller la fédération";
101
	$l_value		= "Valeur";
102
	$l_want_server_as_prim	= "Vous voulez que le serveur soit primaire ?";
103
} else if ($Language === 'es') {
3309 rexy 104
	$l_action		= "Acción";
105
	$l_add_to_list		= "Añadir";
106
	$l_algorithm		= "Algoritmo";
107
	$l_apply		= "Aplicar los cambios";
108
	$l_bind_port		= "Puerto de conexión";
109
	$l_cant_read_pubkey	= "No se puede leer la clave pública de «root».";
3294 rexy 110
	$l_confirm_uninstall	= "¿Estás seguro de que quieres desinstalar la federación?";
3309 rexy 111
	$l_db_pwd		= "Contraseña de acceso a la base de datos";
112
	$l_db_user		= "Usuario de la base de datos";
113
	$l_delete		= "Eliminar";
114
	$l_error_details	= "Detalles de los errores";
115
	$l_field		= "campo";
116
	$l_go_network_conf_page	= "Vaya a la página de configuración de red";
117
	$l_host_name		= "Nombre de host";
118
	$l_hosts_settings	= "Parámetros de replicación de los hosts";
119
	$l_import_ssh_key	= "Importar una clave SSH";
3294 rexy 120
	$l_install_repl		= "Creación de la federación";
3309 rexy 121
	$l_ip_address		= "dirección IP";
122
	$l_no_primary_connected = "No hay ningún servidor primario conectado.";
123
	$l_no_ssh_key		= "No se ha importado ninguna clave SSH.";
124
	$l_not_connected	= "No conectado";
125
	$l_pubkey_to_deploy	= "La clave debe implementarse en los servidores primarios.";
126
	$l_remote_access_mgmt	= "Gestión de accesos remotos";
127
	$l_remote_role		= "Función del host remoto";
128
	$l_repl_io_running	= "Estado";
3313 rexy 129
	$l_started			= "Iniciado";
130
	$l_stopped			= "Decreto";
131
	$l_in_progress		= "En curso ...";
3294 rexy 132
	$l_replication_install	= "Creación de la federación";
133
	$l_replication_title	= "Federación";
3309 rexy 134
	$l_role_primary		= "Primaria";
135
	$l_role_secondary	= "Secundaria";
136
	$l_ssh_keys_for_primary	= "Lista de claves autorizadas para conectarse al usuario local «replication».";
137
	$l_ssh_port		= "Puerto SSH";
138
	$l_ssh_user		= "Usuario SSH";
139
	$l_ssh_wan_enabled	= "El servicio SSH en la WAN está activado.";
140
	$l_ssh_wan_must_be_on	= "El servicio SSH en la WAN debe estar activado.";
141
	$l_start		= "Iniciar";
142
	$l_stop			= "Detener";
3294 rexy 143
	$l_uninstall_repl	= "Desinstalar la federación";
3309 rexy 144
	$l_value		= "Valor";
145
	$l_want_server_as_prim	= "¿Quiere que el servidor sea primario?";
3294 rexy 146
} else {
147
	$l_action		= "Action";
148
	$l_add_to_list		= "Add";
149
	$l_algorithm		= "Algorithm";
150
	$l_apply		= "Apply changes";
151
	$l_bind_port		= "Bind port";
152
	$l_cant_read_pubkey	= "Can't read root's public key.";
153
	$l_confirm_uninstall	= "Are you sure you want to uninstall the federation?";
3309 rexy 154
	$l_db_pwd		= "Database access password";
3294 rexy 155
	$l_db_user		= "Database user";
156
	$l_delete		= "Delete";
157
	$l_error_details	= "Error details";
158
	$l_field		= "Field";
159
	$l_go_network_conf_page	= "Go to network config page.";
160
	$l_host_name		= "Host name";
161
	$l_hosts_settings	= "Replicated hosts settings";
162
	$l_import_ssh_key	= "Import a SSH key";
163
	$l_install_repl		= "Setting up the federation";
164
	$l_ip_address		= "IP address";
3309 rexy 165
	$l_no_primary_connected = "No primary server connected";
3308 rexy 166
	$l_no_ssh_key		= "No SSH key imported.";
3294 rexy 167
	$l_not_connected	= "Not connected";
168
	$l_pubkey_to_deploy	= "The following public key has to be deployed on remote primary servers.";
169
	$l_remote_access_mgmt	= "Remote access management";
170
	$l_remote_role		= "Remote role";
171
	$l_repl_io_running	= "State";
3313 rexy 172
	$l_started			= "Started";
173
	$l_stopped			= "Stopped";
174
	$l_in_progress		= "In progress...";
3294 rexy 175
	$l_replication_install	= "Setting up the federation";
176
	$l_replication_title	= "Federation";
177
	$l_role_primary		= "Primary";
178
	$l_role_secondary	= "Secondary";
179
	$l_ssh_keys_for_primary	= "List of keys allowed to connect to local 'replication' user.";
180
	$l_ssh_port		= "SSH port";
181
	$l_ssh_user		= "SSH user";
3309 rexy 182
	$l_ssh_wan_enabled	= "SSH service on WAN is enabled.";
183
	$l_ssh_wan_must_be_on	= "SSH service on WAN must be enabled.";
3294 rexy 184
	$l_start		= "Start";
185
	$l_stop			= "Stop";
186
	$l_uninstall_repl	= "Uninstall the federation";
187
	$l_value		= "Value";
188
	$l_want_server_as_prim	= "Want server to be a primary?";
189
}
190
 
191
$reg_ip      = '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$';
192
$reg_ip_port = '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\:([1-9]|[1-9][0-9]|[1-9][0-9]{2}|[1-9][0-9]{3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))$';
193
$reg_host    = '^[a-zA-Z0-9-_]+$';
194
$reg_ssh_key = "^(ssh-dss AAAAB3NzaC1kc3|ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNT|sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb2|ssh-ed25519 AAAAC3NzaC1lZDI1NTE5|sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29t|ssh-rsa AAAAB3NzaC1yc2)[0-9A-Za-z+/]+[=]{0,3}(\s.*)?$";
195
$reg_linux_user = "[a-z_][a-z0-9_-]*[$]?";
196
$reg_mariadb_user = "^[a-z]{1,32}$";
197
 
198
// Allow new SSH file size of 128kB;
199
$max_ssh_file_size = 131072;
200
 
201
$choice = $_POST['choice'] ?? "";
202
switch ($choice) {
203
	case 'install_replication':
204
		if (isset($conf['REPLICATION']) && $conf['REPLICATION'] == "on") {
205
			exit("Replication already installed.");}
206
		$stdout = [];
207
		exec('sudo /usr/local/bin/alcasar-replication-install.sh 2>&1', $stdout);
208
		header('Location: '.$_SERVER['PHP_SELF']);
209
		break;
210
	case 'uninstall_replication':
211
		if (!isset($conf['REPLICATION']) || $conf['REPLICATION'] == "off") {
212
			exit("Replication not installed.");}
213
		$stdout = [];
214
		exec('sudo /usr/local/bin/alcasar-replication-uninstall.sh 2>&1', $stdout);
215
		header('Location: '.$_SERVER['PHP_SELF']);
216
		break;
217
	case 'add_replica':
218
		$role = trim($_POST['role'] ?? "");
219
		$name = trim($_POST['name'] ?? "");
220
		$ip = trim($_POST['ip'] ?? "");
221
		$port = trim($_POST['port'] ?? "");
3308 rexy 222
		// we fix ssh user name to simplify ACC
223
		// $user = trim($_POST['user'] ?? "");
224
		$user = "replication" ;
225
		// we fix db user name to simplify ACC
226
		// $db_user = trim($_POST['db_user'] ?? "");
227
		$db_user = "db_replication";
3294 rexy 228
		$db_pwd = trim($_POST['db_pwd'] ?? "");
229
		$bind_port = trim($_POST['bind_port'] ?? "");
230
		$stdout = [];
231
		$return = 0;
232
		switch ($role) {
233
			case 'primary':
234
				exec("sudo /usr/local/bin/alcasar-replication-add.sh --to-primary"." --name=".escapeshellarg($name)." --address=".escapeshellarg($ip)." --port=".escapeshellarg($port)." --user=". escapeshellarg($user)." --db-user=".escapeshellarg($db_user)." --db-password=".escapeshellarg($db_pwd)." 2>&1", $stdout, $return);
235
				break;
236
			case 'secondary':
237
				exec("sudo /usr/local/bin/alcasar-replication-add.sh --to-secondary"." --name=".escapeshellarg($name)." --bind-port=".escapeshellarg($bind_port)." --db-user=".escapeshellarg($db_user)." --db-password=".escapeshellarg($db_pwd)." 2>&1", $stdout, $return);
238
				break;
239
			default:
240
				// Error
241
				exit();}
242
		// If script went wrong
243
		if ($return) {
244
			$key = $choice . "_error";
245
			// Concatenate stdout lines
246
			$value = implode(PHP_EOL, $stdout);
247
			// Save error message in cookies
248
			setcookie($key, $value);
249
		}
250
		header('Location: '.$_SERVER['PHP_SELF']);
251
		break;
252
	case 'change_replicas_state':
253
		$stdout = [];
254
		$return = 0;
255
		$key_prefix = "action_primary_";
256
 
257
		// Search for action_primary_<hostname> key
258
		foreach ($_POST as $key => $value) {
259
			if (!str_starts_with($key, $key_prefix)) {
260
				continue;}
261
			// Get the remote name
262
			$name = explode($key_prefix, $key)[1];
263
			switch ($value) {
264
				case 'start':
265
					exec("sudo /usr/local/bin/alcasar-replication-start.sh --name=".escapeshellarg($name)." 2>&1", $stdout, $return);
266
					break;
267
				case 'stop':
268
					exec("sudo /usr/local/bin/alcasar-replication-stop.sh --name=".escapeshellarg($name)." 2>&1", $stdout, $return);
269
					break;
270
				case 'delete':
271
					exec("sudo /usr/local/bin/alcasar-replication-delete.sh --name=".escapeshellarg($name)." 2>&1", $stdout, $return);
272
					break;
273
				default:
274
					break;
275
			}
276
		}
277
		// If script went wrong
278
		if ($return) {
279
			$key = $choice . "_error";
280
			// Concatenate stdout lines
281
			$value = implode(PHP_EOL, $stdout);
282
			// Save error message in cookies
283
			setcookie($key, $value);
284
		}
285
		header('Location: '.$_SERVER['PHP_SELF']);
286
		break;
287
	case 'add_ssh_key':
288
		$file = $_FILES['new_ssh_key_input'] ?? "";
289
		$stdout = [];
290
		$return = 0;
291
		// Stop if file doesn't exist
292
		if (empty($file)) {
293
			break;}
294
		// Check file size
295
		if ($file['size'] > $max_ssh_file_size) {
296
			break;}
297
		// Add new key(s) to authorized keys list
298
		$tmp_file = $file['tmp_name'];
299
		exec("sudo /usr/local/bin/alcasar-replication-ssh-keys-management.sh --add --file=$tmp_file 2>&1", $stdout, $return);
300
		// If script went wrong
301
		if ($return) {
302
			$key = $choice . "_error";
303
			// Concatenate stdout lines
304
			$value = implode(PHP_EOL, $stdout);
305
			// Save error message in cookies
306
			setcookie($key, $value);
307
		}
308
		header('Location: '.$_SERVER['PHP_SELF']);
309
		break;
310
	case 'delete_ssh_key':
311
		$stdout = [];
312
		$return = 0;
313
		$key_prefix = "action_ssh_key_";
314
		foreach ($_POST as $key => $value) {
315
			if (!str_starts_with($key, $key_prefix)) {
316
				continue;}
317
			$decoded_value = htmlspecialchars_decode($value);
318
			// Delete key
319
			exec("sudo /usr/local/bin/alcasar-replication-ssh-keys-management.sh --delete --regex=$decoded_value 2>&1", $stdout, $return);
320
			// If script went wrong
321
			if ($return) {
322
				$key = $choice . "_error";
323
				// Concatenate stdout lines
324
				$value = implode(PHP_EOL, $stdout);
325
				// Save error message in cookies
326
				setcookie($key, $value);
327
			}
328
		}
329
		header('Location: '.$_SERVER['PHP_SELF']);
330
		break;
331
	default:
332
		break;
333
}
334
 
335
?>
336
<!DOCTYPE HTML>
337
<html>
338
<head>
339
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
340
	<title><?= $l_replication_title ?></title>
341
	<link rel="stylesheet" href="/css/acc.css" type="text/css">
342
	<script src="/js/jquery.min.js"></script>
343
	<script src="/js/jquery.connections.js"></script>
344
	<script type="text/javascript">
345
		window.onload = main;
346
		function main() {
347
			show_fields_for_new_primary();
348
			set_required_on_common_fields();
349
			enable_apply_btn_if_selected_primary_action();
350
			enable_apply_btn_if_selected_ssh_key_action();
351
		}
352
		// Set 'required' attribute on fields needed by both primary and secondary
353
		function set_required_on_common_fields() {
354
			document.querySelectorAll(".role_primary.role_secondary").forEach((input) => {
355
				input.setAttribute("required", "");
356
			});
357
		}
358
		// Only enable fields needed for new primary remote
359
		function show_fields_for_new_primary() {
360
			// Toggle 'disabled' and 'required' attributes
361
			document.querySelectorAll("input[class='role_primary']").forEach((input) => {
362
				input.removeAttribute("disabled");
363
				input.setAttribute("required", "");
364
			});
365
			document.querySelectorAll("input[class='role_secondary']").forEach((input) => {
366
				input.setAttribute("disabled", "");
367
				input.removeAttribute("required");
368
			});
369
		}
370
		function show_fields_for_new_secondary() {
371
			// Toggle 'disabled' and 'required' attributes
372
			document.querySelectorAll("input[class='role_primary']").forEach((input) => {
373
				input.removeAttribute("required");
374
				input.setAttribute("disabled", "");
375
			});
376
			document.querySelectorAll("input[class='role_secondary']").forEach((input) => {
377
				input.setAttribute("required", "");
378
				input.removeAttribute("disabled");
379
			});
380
		}
381
		// Enable the remote's list Apply button if there are any pending actions
382
		function enable_apply_btn_if_selected_primary_action() {
383
			let btn = document.querySelector("#apply_changes_primary_btn");
384
			if (!btn) {
385
				return;}
386
			let change_to_apply = false;
387
			// Check for any pending change
388
			document.querySelectorAll(".primary_action_select").forEach((element) => {
389
				if (element.value != "") {
390
					btn.removeAttribute("disabled");
391
					change_to_apply = true;
392
				}
393
			});
394
			// Disable button if there are no pending changes
395
			if (!change_to_apply) {
396
				btn.setAttribute("disabled", "");
397
			}
398
		}
399
		// Enable the SSH keys's list Apply button if there are any pending actions
400
		function enable_apply_btn_if_selected_ssh_key_action() {
401
			let btn = document.querySelector("#apply_changes_ssh_key_btn");
402
			if (!btn) {
403
				return;
404
			}
405
			let change_to_apply = false;
406
			// Check for any pending change
407
			document.querySelectorAll(".ssh_key_action_input").forEach((element) => {
408
				if (element.checked) {
409
					btn.removeAttribute("disabled");
410
					change_to_apply = true;
411
				}
412
			});
413
			// Disable button if there are no pending changes
414
			if (!change_to_apply) {
415
				btn.setAttribute("disabled", "");
416
			}
417
		}
418
	</script>
419
</head>
420
<body>
421
<div id="ldoverlay" class="overlay">
422
	<div class="lds-spinner" id="spinner"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>
423
</div>
424
<?php if ($conf['REPLICATION'] == "on") { ?>
425
<div class="panel">
426
	<div class="panel-header"><?= $l_hosts_settings ?></div>
427
</div>
428
<div>
429
<table width="100%" cellspacing="0" cellpadding="5" border="1">
430
	<tr>
431
		<td width="50%" align="center">
432
			<?php $section = "change_replicas_state" ?>
433
			<form action="<?= htmlspecialchars($_SERVER['PHP_SELF']) ?>" method="POST">
434
			<input type="hidden" name="choice" value="<?= $section ?>">
435
			<table cellspacing="2" cellpadding="3" border="1" style="table-layout: auto; min-width: 10em;">
436
				<tr>
437
					<th><?= $l_ip_address ?></th>
438
					<th><?= $l_host_name ?></th>
439
					<th><?= $l_repl_io_running ?></th>
440
					<th><?= $l_bind_port ?></th>
441
					<th><?= $l_action ?></th>
442
				</tr>
443
				<?php
444
				$stdout = [];
445
				$return = 0;
446
				exec("sudo /usr/local/bin/alcasar-replication-list.sh --all 2>&1", $stdout, $return);
447
				// If script went wrong
448
				if ($return) {
449
					// Print error message
450
					$errors_msg[$section."_error"] = implode(PHP_EOL, $stdout);
451
				// Successfully fetched remotes stats
452
				} else {
453
					$connected_prims = [];
454
					$current_prim = "";
455
					// Parse stdout in keys-array
456
					foreach ($stdout as $row) {
457
						// Skip useless delimiter
458
						if (str_starts_with($row, '*')) {
459
							continue;
460
						}
461
						// Split key: value
462
						$exploded = explode(": ", $row);
463
						$key = $exploded[0];
464
						$value = $exploded[1] ?? "";
465
						// Create subarray when starting to display a new remote
466
						if (!strcmp($key, "Connection_name")) {
467
							$current_prim = $value;
468
							$connected_prims[$current_prim] = [];
469
						}
470
						// Put value in prim's subarray
471
						($connected_prims[$current_prim])[$key] = $value;
472
					}
473
					// Skip resetted replicas,
474
					// they will stay displayed still the next database restart.
475
					foreach ($connected_prims as $prim) {
476
						if (empty($prim["Relay_Log_File"])) {
477
							unset($connected_prims[$prim["Connection_name"]]);
478
						}
479
					}
480
					// List each connection
481
					foreach ($connected_prims as $prim) {
482
						?>
483
						<tr>
484
							<td><?php
485
								$master_host = $prim["Master_Host"];
486
								if ($master_host != "127.0.0.1") {
487
									echo "$master_host";
488
								} else {
489
									echo "$l_not_connected";
490
								}
491
							?></td>
492
							<td><?= $prim["Connection_name"] ?></td>
3313 rexy 493
							<td>
494
							<? if ($prim["Slave_IO_Running"] == "Yes") { echo "Démarré"; }
495
							   if ($prim["Slave_IO_Running"] == "No") { echo "Arreté"; }
496
							   if ($prim["Slave_IO_Running"] == "Connecting") { echo "Connexion en cours"; }
497
							?>
498
							</td>
3294 rexy 499
							<td><?= $prim["Master_Port"] ?></td>
500
							<td>
501
								<select name="action_primary_<?= $prim["Connection_name"] ?>" class="primary_action_select" onchange="enable_apply_btn_if_selected_primary_action()">
502
									<option value=""></option>
503
									<?php
504
										// Actions available on all remotes
505
										$options = array(
506
											"start" => "$l_start",
507
											"stop" => "$l_stop",
508
											"delete" => "$l_delete"
509
										);
510
										// Remove some options depending on the current remote state
511
										switch ($prim["Slave_IO_Running"]) {
512
										case 'Yes':
513
										case 'Connecting':
514
											unset($options["start"]);
515
											unset($options["delete"]);
516
											break;
517
										case 'No':
518
											unset($options["stop"]);
519
											break;
520
										default:
521
											break;
522
										}
523
										// Print options
524
										foreach ($options as $key => $value) { ?>
525
											<option value="<?= $key ?>"><?= $value ?></option>
526
										<?php }
527
									 ?>
528
								</select>
529
							</td>
530
						</tr>
531
					<?php }
532
					// Show submit button if there are primary servers connected
533
					echo "<tr><td colspan=5 valign='middle' align='center'>";
534
					if (sizeof($connected_prims)) { ?>
535
						<input type="submit" id="apply_changes_primary_btn" value="<?= $l_apply ?>" onClick="document.getElementById('ldoverlay').style.display='block';">
536
					<?php } else { ?>
537
						<p><?= $l_no_primary_connected ?></p>
538
					<?php }
539
					echo "</td></tr>";
540
				} ?>
541
			</table>
542
			</form>
543
			<?php if (isset($errors_msg[$section."_error"])) { ?>
544
				<details open>
545
					<summary><?= $l_error_details ?></summary>
546
					<textarea readonly cols=50 rows=10><?= $errors_msg[$section."_error"] ?></textarea>
547
				</details>
548
			<?php } ?>
549
		</td>
550
		<td width="50%" valign="middle" align="center">
551
			<?php $section = "add_replica" ?>
552
			<form action="<?= htmlspecialchars($_SERVER['PHP_SELF']) ?>" method="POST">
553
			<input type="hidden" name="choice" value="<?= $section ?>">
554
				<table cellspacing="2" cellpadding="3" border="1">
555
					<tr>
556
						<th><?= $l_field ?></th>
557
						<th><?= $l_value ?></th>
558
					</tr>
559
					<tr>
560
						<td><?= $l_remote_role ?></td>
561
						<td>
562
							<fieldset>
563
								<div>
564
									<input type="radio" id="role_primary" name="role" value="primary" checked onClick="show_fields_for_new_primary()"/>
565
									<label for="role_primary"><?= $l_role_primary ?></label>
566
 
567
									<input type="radio" id="role_secondary" name="role" value="secondary" onClick="show_fields_for_new_secondary()"/>
568
									<label for="role_secondary"><?= $l_role_secondary ?></label>
569
								</div>
570
							</fieldset>
571
						</td>
572
					</tr>
573
					<tr>
574
						<td><label for="input_name"><?= $l_host_name ?></label></td>
575
						<td><input type="text" id="input_name" name="name" class="role_primary role_secondary" pattern="<?= $reg_host ?>"></td>
576
					</tr>
577
					<tr>
578
						<td><label for="input_ip"><?= $l_ip_address ?></label></td>
579
						<td><input type="text" id="input_ip" name="ip" class="role_primary" pattern="<?= $reg_ip ?>"></td>
580
					</tr>
581
					<tr>
582
						<td><label for="input_bind_port"><?= $l_bind_port ?></label></td>
583
						<td><input type="number" id="input_bind_port" name="bind_port" min="0" max="65535" class="role_secondary" pattern="<?= $reg_ip_port ?>"></td>
584
					</tr>
585
					<tr>
586
						<td><label for="input_port"><?= $l_ssh_port ?></label></td>
3313 rexy 587
						<td><input type="number" id="input_port" name="port" min="0" max="65535" class="role_primary" pattern="<?= $reg_ip_port ?>"></td>
3294 rexy 588
					</tr>
589
					<tr>
3308 rexy 590
					<td><label for="input_db_pwd"><?= $l_db_pwd ?></label></td>
3294 rexy 591
						<td><input type="password" id="input_db_pwd" name="db_pwd" class="role_primary role_secondary"></td>
592
					</tr>
593
					<tr>
594
						<td colspan=2 valign="middle" align="center">
3313 rexy 595
							<input type="submit" class="button" value="<?= $l_add_to_list ?>">
3294 rexy 596
						</td>
597
					</tr>
598
				</table>
599
			</form>
600
			<?php if (isset($errors_msg[$section."_error"])) { ?>
601
				<details open>
602
					<summary><?= $l_error_details ?></summary>
603
					<textarea readonly cols=50 rows=10><?= htmlspecialchars($errors_msg[$section."_error"]) ?></textarea>
604
				</details>
605
			<?php } ?>
606
		</td>
607
	</tr>
608
</table>
609
</div>
610
<br>
611
<div class="panel">
612
	<div class="panel-header"><?= $l_remote_access_mgmt ?></div>
613
</div>
614
<div>
615
<table width="100%" cellspacing="0" cellpadding="5" border="1">
616
	<tr>
617
		<td width="50%" align="center">
618
			<p><?= $l_ssh_keys_for_primary ?></p>
619
			<?php $section = "delete_ssh_key" ?>
620
			<form action="<?= htmlspecialchars($_SERVER['PHP_SELF']) ?>" method="POST">
621
			<input type="hidden" name="choice" value="<?= $section ?>">
622
			<table cellspacing="2" cellpadding="3" border="1" style="table-layout: auto; min-width: 10em;">
623
				<tr>
624
					<th><?= $l_host_name ?></th>
625
					<th><?= $l_algorithm ?></th>
626
					<th><?= $l_delete ?></th>
627
				</tr>
628
				<?php
629
				$stdout = [];
630
				$return = 0;
631
				exec("sudo /usr/local/bin/alcasar-replication-ssh-keys-management.sh --list 2>&1", $stdout, $return);
632
				// If script went wrong
633
				if ($return) {
634
					// Print error message
635
					$errors_msg[$section."_error"] = implode(PHP_EOL, $stdout);
636
				// Successfully fetched remotes stats
637
				} else {
638
					// List each key
639
					foreach ($stdout as $line) {
640
						// Skip empty lines
641
						if (str_starts_with($line, ' ')) {
642
							continue;
643
						}
644
						// Split args
645
						$exploded = explode(' ', $line);
646
						$algo = $exploded[0] ?? "";
647
						$hostname = $exploded[2] ?? "";
648
						?>
649
						<tr>
650
							<td><?= $hostname ?></td>
651
							<td><?= $algo ?></td>
652
							<td>
653
								<input type="checkbox" name="action_ssh_key_<?= htmlspecialchars($hostname) ?>" value="<?= htmlspecialchars($hostname) ?>" class="ssh_key_action_input" onchange="enable_apply_btn_if_selected_ssh_key_action()">
654
							</td>
655
						</tr>
656
					<?php }
657
					// Show submit button if there are primary servers connected
3308 rexy 658
					echo "<tr><td colspan=3 valign='middle' align='center'>";
3294 rexy 659
					if (sizeof($stdout)) { ?>
660
						<input type="submit" id="apply_changes_ssh_key_btn" value="<?= $l_apply ?>" onClick="document.getElementById('ldoverlay').style.display='block';">
661
					<?php } else { ?>
662
						<p><?= $l_no_ssh_key ?></p>
663
					<?php }
3308 rexy 664
					echo "</td></tr>";
3294 rexy 665
				} ?>
666
			</table>
667
			</form>
668
			<?php if (isset($errors_msg[$section."_error"])) { ?>
669
				<details open>
670
					<summary><?= $l_error_details ?></summary>
671
					<textarea readonly cols=50 rows=10><?= $errors_msg[$section."_error"] ?></textarea>
672
				</details>
673
			<?php } ?>
674
		</td>
675
		<td width="25%" valign="middle" align="center">
676
			<?php $section = "add_ssh_key" ?>
677
			<form action="<?= htmlspecialchars($_SERVER['PHP_SELF']) ?>" method="POST" enctype="multipart/form-data">
678
			<input type="hidden" name="choice" value="<?= $section ?>">
679
				<input type="hidden" name="MAX_FILE_SIZE" value="<?= $max_ssh_file_size ?>" />
3306 rexy 680
				<label for="new_ssh_key_input"><?= $l_import_ssh_key ?><br></label>
3294 rexy 681
				<br>
682
				<input type="file" name="new_ssh_key_input" id="new_ssh_key_input" accept=".pub">
683
				<br>
684
				<input type="submit" class="button" value="<?= $l_add_to_list ?>" onClick="document.getElementById('ldoverlay').style.display='block';">
685
			</form>
686
			<?php if (isset($errors_msg[$section."_error"])) { ?>
687
				<details open>
688
					<summary><?= $l_error_details ?></summary>
689
					<textarea readonly cols=50 rows=10><?= $errors_msg[$section."_error"] ?></textarea>
690
				</details>
691
			<?php } ?>
692
		</td>
693
		<td width="25%" valign="middle" align="center">
3306 rexy 694
				<label for="pubkey_stdout"><?= $l_pubkey_to_deploy ?><br></label>
3294 rexy 695
				<br>
696
				<?php
697
				$stdout = [];
698
				$return = 0;
699
				exec("sudo /usr/local/bin/alcasar-replication-ssh-keys-management.sh --show-pubkey 2>&1", $stdout, $return);
700
				// If script went wrong
701
				if ($return != 0) {
702
					echo "<p>$l_cant_read_pubkey</p>";
703
				} else { ?>
704
					<input type="text" id="pubkey_stdout" readonly value="<?= implode(PHP_EOL, $stdout) ?>">
705
				<?php } ?>
706
		</td>
707
	</tr>
708
</table>
709
</div>
710
<br>
711
<?php } ?>
712
<div class="panel">
713
	<div class="panel-header"><?= $l_replication_title ?></div>
714
</div>
715
<table width="100%" cellspacing="0" cellpadding="5" border="1">
716
	<tr>
717
		<td width="50%" valign="middle" align="center">
718
			<?php if ($conf['REPLICATION'] == "on") { ?>
719
				<form action="<?= htmlspecialchars($_SERVER['PHP_SELF']) ?>" method="POST" onsubmit="return confirm('<?= $l_confirm_uninstall ?>');">
720
					<input type="hidden" name="choice" value="uninstall_replication">
721
					<input type="submit" value="<?= $l_uninstall_repl ?>" onClick="document.getElementById('ldoverlay').style.display='block';">
722
				</form>
723
			<?php } else { ?>
724
				<form action="<?= htmlspecialchars($_SERVER['PHP_SELF']) ?>" method="POST">
725
					<input type="hidden" name="choice" value="install_replication">
726
					<input type="submit" value="<?= $l_install_repl ?>" onClick="document.getElementById('ldoverlay').style.display='block';">
727
				</form>
728
			<?php } ?>
729
		</td>
730
		<?php if ($conf['REPLICATION'] == "on") { ?>
731
			<td width="50%" valign="middle" align="center">
732
				<?php if ($conf['SSH_WAN'] !== '0') { ?>
733
					<input type="checkbox" id="togglessh" checked disabled>
734
					<label for="togglessh"><?= $l_ssh_wan_enabled ?></label>
735
				<?php } else { ?>
736
				<p><?= $l_want_server_as_prim ?></p>
737
					<input type="checkbox" id="togglessh" disabled>
738
					<label for="togglessh"><b><?= $l_ssh_wan_must_be_on ?></b> <a href="/acc/admin/network.php"><?= $l_go_network_conf_page ?></a></label>
739
				<?php } ?>
740
			</td>
741
		<?php } ?>
742
	</tr>
743
</table>
744
</body>
745
</html>