Subversion Repositories ALCASAR

Rev

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

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