forked from unraid/webgui
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathArrayOperation.page
More file actions
618 lines (612 loc) · 35.8 KB
/
ArrayOperation.page
File metadata and controls
618 lines (612 loc) · 35.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
Menu="Main:5"
Title="Array Operation"
Tag="snowflake-o"
---
<?PHP
/* Copyright 2005-2018, Lime Technology
* Copyright 2012-2018, Bergware International.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
?>
<?
$keyfile = file_exists($var['luksKeyfile']);
$encrypt = false;
/* only one of $forced, $missing, or $wrong will be true, or all will be false */
$forced = $missing = $wrong = false;
foreach ($disks as $disk) {
if (strpos($disk['fsType'],'luks:')!==false || ($disk['fsType']=='auto' && (strpos($var['defaultFsType'],'luks:')!==false || $disk['luksState']==2 || $disk['luksState']==3))) {
$encrypt = true;
if (!$keyfile) {
if ($disk['luksState']==0) $forced = true; else $missing = true;
} else {
if ($disk['luksState']==3) $wrong = true;
}
}
}
if ($forced && $missing) $forced = false;
function check_encryption() {
global $forced, $missing, $wrong;
if ($forced) $status = "Enter new key";
elseif ($missing) $status = "Missing key";
elseif ($wrong) $status = "Wrong key";
else return;
echo "<tr><td></td><td class='gap'>Encryption status:</td><td><span class='red-text'>$status</span><span id='pass'><input name='luksReformat' type='checkbox' onchange='selectInput(this.form)'>permit reformat</span></td></tr>";
echo "<tr><td></td><td class='gap'>Encryption input:</td><td>";
echo "<select name='input' size='1' onchange='selectInput(this.form)'>";
echo mk_option(1,'text','Passphrase');
echo mk_option(1,'file','Keyfile');
echo "</select></td></tr>";
echo "<tr id='text'><td></td><td class='gap'>Passphrase:</td><td><input type='password' name='text' maxlength='512' value='' onkeyup='selectInput(this.form)'><input name='showPass' type='checkbox' onchange='selectInput(this.form)'>show passphrase</td></tr>";
echo "<tr id='copy'><td></td><td class='gap'>Retype passphrase:</td><td><input type='password' name='copy' maxlength='512' value='' onkeyup='selectInput(this.form)'></td></tr>";
echo "<tr id='file'><td></td><td class='gap'>Keyfile:</td><td><input type='file' name='local' onchange='getFileContent(event,this.form)'></td></tr>";
}
function maintenance_mode() {
echo "<tr>";
echo "<td></td>";
echo "<td><input type='checkbox' name='startMode' value='Maintenance'>Maintenance mode</td>";
echo "<td><strong>Maintenance mode</strong> - if checked, Start array but do not mount disks.</td>";
echo "</tr>";
}
function status_indicator() {
global $var;
switch ($var['mdColor']) {
case 'green-on': $orb = 'circle'; $color = 'green'; $help = 'Started, array protected'; break;
case 'green-blink': $orb = 'circle'; $color = 'grey'; $help = 'Stopped'; break;
case 'yellow-on': $orb = 'warning'; $color = 'yellow'; $help = 'Started, array unprotected'; break;
case 'yellow-blink': $orb = 'warning'; $color = 'grey'; $help = 'Stopped'; break;
}
echo "<a class='info nohand' onclick='return false'><i class='fa fa-$orb orb $color-orb'></i><span>$help</span></a>";
}
function missing_cache() {
global $disks;
$missing = false;
foreach ($disks as $disk) if ($disk['type']=='Cache') $missing |= (strpos($disk['status'],'_MISSING')!==false);
return $missing;
}
?>
<style>
tr#copy,tr#file{display:none}
td.gap{padding-left:26px!important}
span#pass{display:none;margin-left:20px}
</style>
<script>
var ctrl = "<span class='status <?=$tabbed?'':'vhshift'?>'><a style='cursor:pointer' class='tooltip_diskio' title='Toggle reads/writes display' onclick='toggle_diskio();return false'><i class='toggle fa'></i></a></span>";
function selectInput(form) {
if (form.input.value == 'text') {
form.file.value = '';
form.local.value = '';
<?if ($forced):?>
$('#text').show();
$('#copy').show();
$('#pass').hide();
<?elseif ($missing):?>
$('#text').show();
$('#copy').hide();
$('#pass').hide();
<?elseif ($wrong):?>
$('#text').show();
if ($('input[name="luksReformat"]').prop('checked')) $('#copy').show(); else $('#copy').hide();
$('#pass').show();
<?endif;?>
$('#file').hide();
$('input[name="text"],input[name="copy"]').attr('type',$('input[name="showPass"]').prop('checked')?'text':'password');
$('#cmdStart').prop('disabled',$('#copy').is(':visible') ? (form.text.value!=form.copy.value || form.text.value=='') : form.text.value=='');
} else {
form.text.value = '';
form.copy.value = '';
$('#text').hide();
$('#copy').hide();
$('#file').show();
<?if ($wrong):?>
$('#pass').show();
<?else:?>
$('#pass').hide();
<?endif;?>
$('#cmdStart').prop('disabled',!form.file.value);
}
}
function getFileContent(event,form) {
var input = event.target;
var reader = new FileReader();
reader.onload = function(){form.file.value=reader.result;selectInput(form);};
reader.readAsDataURL(input.files[0]);
}
function prepareInput(form) {
$(form).append('<input type="hidden" name="cmdStart" value="Start">');
if (form.input === undefined) {
form.submit();
} else {
var data = {};
data['#file'] = 'unused';
data['#include'] = 'webGui/include/KeyUpload.php';
data['text'] = form.text.value;
data['file'] = form.file.value;
form.input.disabled = true;
form.local.disabled = true;
form.file.disabled = true;
form.text.disabled = true;
form.copy.disabled = true;
$.post('/update.php',data,function(){form.submit();});
}
}
function parityWarning(form) {
if (form.md_invalidslot.checked) {
<?if (strpos($disks['parity2']['status'],'_NP')===false):?>
var text = '<i>Dual parity valid</i> requires <b>ALL</b> disks in their original slots';
<?else:?>
var text = '<i>Parity valid</i> requires <b>ALL</b> disks to have their original content';
<?endif;?>
} else {
var text = '<i>Parity</i> disk(s) content will be overwritten';
}
swal({title:'Proceed to start',text:text,html:true,type:'warning',confirmButtonText:'Proceed',showCancelButton:true},function(){prepareInput(form);});
}
function tab0() {
$.removeCookie('one',{path:'/'});
$.cookie('tab','tab0',{path:'/'});
}
function parityStatus() {
$.post('/webGui/include/DeviceList.php',{path:'<?=$path?>',device:'parity'},function(data) {
if (data) {$.each(data.split(';'),function(k,v) {if ($('#line'+k).length>0) $('#line'+k).html(v);});}
timers.parityStatus = setTimeout(parityStatus,3000);
if (!data && $('#cancelButton').length>0 && $('#cancelButton').val()=='Cancel') {
$('#cancelButton').val('Done').prop('onclick',null).off('click').click(function(){refresh();});
$('#cancelText').html('');
$('#line4').html('completed');
}
});
}
function stopArray(form) {
$(form).append('<input type="hidden" name="cmdStop" value="Stop">');
<?if ($confirm['stop']):?>
swal({title:'Proceed?',text:'This will stop the array',type:'warning',showCancelButton:true},function(p){if (p) form.submit(); else $('input[name="cmdStop"]').remove();});
<?else:?>
form.submit();
<?endif;?>
}
function stopParity(form,text) {
$(form).append('<input type="hidden" name="cmdNoCheck" value="Cancel">');
<?if ($confirm['stop']):?>
swal({title:'Proceed?',text:'This will stop the running '+text+' operation',type:'warning',showCancelButton:true},function(p){if (p) form.submit(); else $('input[name="cmdNoCheck"]').remove();});
<?else:?>
form.submit();
<?endif;?>
}
function pauseParity(form) {
$(form).append('<input type="hidden" name="cmdNoCheck" value="Pause">');
$('#pauseButton').val('Resume').prop('onclick',null).off('click').click(function(){resumeParity(form);});
form.submit();
}
function resumeParity(form) {
$(form).append('<input type="hidden" name="cmdCheck" value="Resume">');
$('#pauseButton').val('Pause').prop('onclick',null).off('click').click(function(){pauseParity(form);});
form.submit();
}
function shutdown_now(form,cmd) {
$(form).append('<input type="hidden" name="cmd" value="'+cmd+'">');
<?if ($confirm['down']):?>
swal({title:'Proceed?',text:'This will '+cmd+' the system',type:'warning',showCancelButton:true},function(p){if (p) form.submit(); else $('input[name="cmd"]').remove();});
<?else:?>
form.submit();
<?endif;?>
}
function toggleApply(checked) {
$('input[name="#apply"]').prop('disabled',!checked);
}
parityStatus();
<?if ($tabbed):?>
$('.tabs').append(ctrl);
if ($.cookie('tab')=='tab0') $('i.toggle').hide();
$('#tab'+$('input[name$="tabs"]').length).click(function(){tab0(); $('i.toggle').hide('slow');});
<?else:?>
$('div[id=title]:not(":last, .disable_diskio")').each(function(){$(this).append(ctrl);});
<?endif;?>
<?if (substr($var['fsState'],-3)=='ing'):?>
function reload_page() {
$.get('/webGui/include/ReloadPage.php',function(data) {
switch (data) {
case 'wait':
setTimeout(reload_page,10000);
break;
case 'stop':
setTimeout(refresh,0);
break;
default:
if (data) $('#fsState').html(data);
setTimeout(reload_page,3000);
break;
}
});
}
reload_page();
<?endif;?>
$('.tooltip_diskio').tooltipster({delay:100,trigger:'custom',triggerOpen:{mouseenter:true},triggerClose:{click:false,scroll:true,mouseleave:true}});
toggle_diskio(true);
$(function(){
var form = document.arrayOps;
if (form.input !== undefined) selectInput(form);
});
</script>
<form name="arrayOps" method="POST" action="/update.htm" target="progressFrame">
<input type="hidden" name="startState" value="<?=htmlspecialchars($var['mdState'])?>">
<input type="hidden" name="file" value="">
<table class="array_status">
<?$parity = $var['mdResync'] ? '<br><small>Disabled -- Parity operation is running</small>' : '';
$mover = file_exists('/var/run/mover.pid') ? '<br><small>Disabled -- Mover is running</small>' : '';
$btrfs = exec('pgrep -cf /sbin/btrfs') ? '<br><small>Disabled -- BTRFS operation is running</small>' : '';
switch ($var['fsState']):
case "Started":?>
<tr><td><?status_indicator()?><span class="strong">Started<?=(($var['startMode']=='Maintenance')?' - Maintenance Mode':'')?></span></td>
<td><input type="button" value="Stop" onclick="stopArray(this.form)"<?if ($parity||$mover||$btrfs):?> disabled<?endif;?>></td>
<td id="stop"><strong>Stop</strong> will take the array off-line.<?=$parity?:$mover?:$btrfs?:''?></td></tr>
<? if ($var['fsNumUnmountable']>0):?>
<tr><td><strong>Unmountable disk<?=$var['fsNumUnmountable']==1?'':'s'?> present:</strong><br>
<? foreach ($disks as $disk) if (strpos($disk['fsStatus'],'Unmountable')!==false)
echo "<span class='blue-text'>".my_disk($disk['name'])."</span> • ".my_id($disk['id'])." (".$disk['device'].")<br>";?>
</td><td><input type="submit" id="btnFormat" name="cmdFormat" value="Format" disabled><input type="hidden" name="unmountable_mask" value="<?=$var['fsUnmountableMask']?>"></td>
<td><strong>Format</strong> will create a file system in all <strong>Unmountable</strong> disks, discarding all data currently on those disks.<br>
<a class="info none img nohand"><input type="checkbox" name="confirmFormat" value="OFF" onclick="$('#btnFormat').prop('disabled',!arrayOps.confirmFormat.checked)">
<small>Yes I want to do this <i class="fa fa-asterisk red-text" ></i></small><span><b>All data is permanently lost !!!<br>This is not used to recover data</b><br><i>Format is never part of a rebuild</i></span></a>
</td></tr>
<? endif;
if (!$var['mdResyncPos']):
if (strstr($var['mdResyncAction'],"recon")):?>
<tr><td></td><td><input type="submit" name="cmdCheck" value="Sync"></td><td><strong>Sync</strong> will start <strong>Parity-Sync</strong> and/or <strong>Data-Rebuild</strong>.</td></tr>
<? elseif (strstr($var['mdResyncAction'],"clear")):?>
<tr><td></td><td><input type="submit" name="cmdCheck" value="Clear"></td><td><strong>Clear</strong> will start <strong>Clearing</strong> new data disk(s).</td></tr>
<? else:
if ($var['mdResyncAction']=="check"):?>
<tr><td></td><td><input type="submit" name="cmdCheck" value="Check"></td><td><strong>Check</strong> will start <strong>Read-Check</strong> of all array disks.</td></tr>
<? elseif (strstr($var['mdResyncAction'],"check")):?>
<tr><td>Parity is valid.</td><td><input type="submit" name="cmdCheck" value="Check"></td><td><strong>Check</strong> will start <strong>Parity-Check</strong>. <a href="/Main/Scheduler"<?if ($tabbed):?> onclick="$.cookie('one','tab1',{path:'/'})"<?endif;?>>(Schedule)</a>
<br><input type="checkbox" name="optionCorrect" value="correct" checked><small>Write corrections to parity</small></td></tr>
<? endif;?>
<tr><td></td><td><input type="button" value="History" onclick="openBox('/webGui/include/ParityHistory.php','Parity/Read-Check History',600,900,false)"></td>
<? if ($var['sbSyncExit']!=0):?>
<td>Last check incomplete on <strong><?=my_time($var['sbSynced2']).day_count($var['sbSynced2'])?></strong><?if ($var['sbSynced2']):?>, finding <strong><?=$var['sbSyncErrs']?></strong> error<?=$var['sbSyncErrs']==1?'':'s'?>.<?endif;?>
<br><i class="fa fa-dot-circle-o icon"></i><small>Error code: <?=my_error($var['sbSyncExit'])?></small></td></tr>
<? elseif ($var['sbSynced']==0):
list($date,$duration,$speed,$status,$error) = last_parity_log();?>
<? if ($status==0):?>
<td>Last checked on <strong><?=my_time($date).day_count($date)?></strong>, finding <strong><?=$error?></strong> error<?=$error==1?'':'s'?>.
<br><i class="fa fa-clock-o icon"></i><small>Duration: <?=my_check($duration,$speed)?></small></td></tr>
<? else:?>
<td>Last check incomplete on <strong><?=my_time($date).day_count($date)?></strong>, finding <strong><?=$error?></strong> error<?=$error==1?'':'s'?>.
<br><i class="fa fa-dot-circle-o icon"></i><small>Error code: <?=my_error($status)?></small></td></tr>
<? endif;
elseif ($var['sbSynced2']==0):
list($date,$duration,$speed,$status,$error) = explode('|', read_parity_log($var['sbSynced']));
if ($status==0):?>
<td>Last checked on <strong><?=my_time($var['sbSynced']).day_count($var['sbSynced'])?></strong>, finding <strong><?=$error?></strong> error<?=$error==1?'':'s'?>.
<br><i class="fa fa-clock-o icon"></i><small>Duration: <?=my_check($duration,$speed)?></small></td></tr>
<? else:?>
<td>Last check incomplete on <strong><?=my_time($var['sbSynced']).day_count($var['sbSynced'])?></strong>, finding <strong><?=$error?></strong> error<?=$error==1?'':'s'?>.
<br><i class="fa fa-dot-circle-o icon"></i><small>Error code: <?=my_error($status)?></small></td></tr>
<? endif;
else:
$duration = $var['sbSynced2']-$var['sbSynced'];
$speed = $duration?my_scale($var['mdResyncSize']*1024/$duration,$unit,1)." $unit/sec":'';?>
<td>Last check completed on <strong><?=my_time($var['sbSynced2']).day_count($var['sbSynced2'])?></strong>, finding <strong><?=$var['sbSyncErrs']?></strong> error<?=$var['sbSyncErrs']==1?'':'s'?>.
<br><i class="fa fa-clock-o icon"></i><small>Duration: <?=my_check($duration,$speed)?></small></td></tr>
<? endif;
endif;
else:
if ($var['mdResyncAction']=="check"):?>
<tr><td>Read-Check in progress.</td><td>
<input type="button" id="pauseButton"<?if ($var['mdResync']):?> value="Pause" onclick="pauseParity(this.form)"<?else:?> value="Resume" onclick="resumeParity(this.form)"<?endif;?>>
<input type="button" id="cancelButton" value="Cancel" onclick="stopParity(this.form,'Read-Check')"></td>
<td id="cancelText"><strong>Cancel</strong> will stop the Read-Check.</td></tr>
<? elseif (strstr($var['mdResyncAction'],"check")):?>
<tr><td>Parity-Check in progress.</td><td>
<input type="button" id="pauseButton"<?if ($var['mdResync']):?> value="Pause" onclick="pauseParity(this.form)"<?else:?> value="Resume" onclick="resumeParity(this.form)"<?endif;?>>
<input type="button" id="cancelButton" value="Cancel" onclick="stopParity(this.form,'Parity-Check')"></td>
<td id="cancelText"><strong>Cancel</strong> will stop the Parity-Check.</td></tr>
<? elseif (strstr($var['mdResyncAction'],"recon")):?>
<tr><td>Parity-Sync/Data-Rebuild in progress.</td><td>
<input type="button" id="pauseButton"<?if ($var['mdResync']):?> value="Pause" onclick="pauseParity(this.form)"<?else:?> value="Resume" onclick="resumeParity(this.form)"<?endif;?>>
<input type="button" id="cancelButton" value="Cancel" onclick="stopParity(this.form,'Parity-Sync/Data-Rebuild')"></td>
<td id="cancelText"><strong>Cancel</strong> will stop Parity-Sync/Data-Rebuild.
<br>WARNING: canceling may leave the array unprotected!</td></tr>
<? elseif (strstr($var['mdResyncAction'],"clear")):?>
<tr><td>Clearing in progress.</td><td>
<input type="button" id="pauseButton"<?if ($var['mdResync']):?> value="Pause" onclick="pauseParity(this.form)"<?else:?> value="Resume" onclick="resumeParity(this.form)"<?endif;?>>
<input type="button" id="cancelButton" value="Cancel" onclick="stopParity(this.form,'Clearing')"></td>
<td id="cancelText"><strong>Cancel</strong> will stop Clearing.</td></tr>
<? endif;?>
<tr><td></td><td><input type="button" value="History" onclick="openBox('/webGui/include/ParityHistory.php','Parity/Read-Check History',600,900,false)"></td><td>Current operation started on <strong><?=my_time($var['sbUpdated'])?></strong></td></tr>
<tr><td>Total size:</td><td id="line0"></td><td></td></tr>
<tr><td>Elapsed time:</td><td id="line1"></td><td></td></tr>
<tr><td>Current position:</td><td id="line2"></td><td></td></tr>
<tr><td>Estimated speed:</td><td id="line3"></td><td></td></tr>
<tr><td>Estimated finish:</td><td id="line4"></td><td></td></tr>
<? if (strstr($var['mdResyncAction'],"check ")):?>
<tr><td>Sync errors <?if ($var['mdResyncCorr']==0):?>detected:<?else:?>corrected:<?endif;?></td><td id="line5"></td><td></td></tr>
<? endif;
endif;
break;
case "Starting":?>
<tr><td><?status_indicator()?><span class="strong big">Starting...</span></td><td><input type="submit" name="cmdStart" value="Start" disabled></td><td></td></tr>
<? break;
case "Formatting":?>
<tr><td><?status_indicator()?><span class="strong big">Started, formatting...</span></td><td><input type="submit" name="cmdStop" value="Stop" disabled></td><td></td></tr>
<? break;
case "Copying":?>
<tr><td><?status_indicator()?><span id="fsState" class="strong big">Copying, <?=$var['fsCopyPrcnt']?>% complete...</span></td><td><input type="submit" name="cmdNoCopy" value="Cancel"></td><td></td></tr>
<? break;
case "Clearing":?>
<tr><td><?status_indicator()?><span id="fsState" class="strong big">Clearing, <?=$var['fsClearPrcnt']?>% complete...</span></td><td><input type="submit" name="cmdNoClear" value="Cancel"></td><td></td></tr>
<? break;
case "Stopping":?>
<tr><td><?status_indicator()?><span class="strong big">Stopping...</span></td><td><input type="submit" name="cmdStop" value="Stop" disabled></td><td></td></tr>
<? break;
case "Stopped":
if ($var['configValid']=="error"):?>
<tr><td><?status_indicator()?><span class="strong big">Stopped.</span></td><td><input type="submit" name="cmdStart" value="Start" disabled></td>
<td>Invalid, missing or expired <a href="/Tools/Registration">registration key</a>.</td></tr>
<? elseif ($var['configValid']=="invalid"):?>
<tr><td><?status_indicator()?><span class="strong big">Stopped.</span></td><td><input type="submit" name="cmdStart" value="Start" disabled></td>
<td>Too many attached devices. Please consider upgrading your <a href="/Tools/Registration">registration key</a>.</td></tr>
<? elseif ($var['configValid']=="nokeyserver"):?>
<tr><td><?status_indicator()?><span class="strong big">Stopped.</span></td><td><input type="submit" name="cmdStart" value="Start" disabled></td>
<td>Cannot contact key-server. Please check your <a href="/Settings/NetworkSettings">network settings</a>.</td></tr>
<? elseif ($var['configValid']=="withdrawn"):?>
<tr><td><?status_indicator()?><span class="strong big">Stopped.</span></td><td><input type="submit" name="cmdStart" value="Start" disabled></td>
<td>This Unraid OS release has been withdrawn and may no longer be used. Please <a href="/Plugins">update</a> your server.</td></tr>
<? else:
switch ($var['mdState']):
case "STOPPED":
if (strstr($var['mdResyncAction'],"recon")):?>
<tr><td><?status_indicator()?><span class="strong big">Stopped</span>. Configuration valid.</td><td><input type="button" id="cmdStart" value="Start" onclick="prepareInput(this.form)"></td>
<td><strong>Start</strong> will bring the array on-line and start <strong>Parity-Sync</strong> and/or <strong>Data-Rebuild</strong>.</td></tr>
<? elseif ($var['mdResyncAction']=="clear"):?>
<tr><td><?status_indicator()?><span class="strong big">Stopped</span>. New data disk(s) detected.</td><td><input type="button" id="cmdStart" value="Start" onclick="prepareInput(this.form)"></td>
<td><strong>Start</strong> will bring the array on-line and start <strong>Clearing</strong> new data disk(s).</td></tr>
<? elseif ($var['sbClean']!="yes" && $var['mdResyncAction']=="check"):?>
<tr><td><?status_indicator()?><span class="strong big">Stopped</span>. Unclean shutdown detected.</td><td><input type="button" id="cmdStart" value="Start" onclick="prepareInput(this.form)"></td>
<td><strong>Start</strong> will bring the array on-line.</td></tr>
<? elseif ($var['sbClean']!="yes" && strstr($var['mdResyncAction'],"check")):?>
<tr><td><?status_indicator()?><span class="strong big">Stopped</span>. Unclean shutdown detected.</td><td><input type="button" id="cmdStart" value="Start" onclick="prepareInput(this.form)"></td>
<td><strong>Start</strong> will bring the array on-line and start <strong>Parity-Check</strong>.
<br><input type="checkbox" name="optionCorrect" value="correct" checked><small>Write corrections to parity</small></td></tr>
<? elseif (missing_cache()):?>
<tr><td><?status_indicator()?><span class="strong big">Stopped</span>. Missing Cache disk.</td><td><input type="button" id="cmdStart" value="Start" onclick="prepareInput(this.form)" disabled></td>
<td><strong>Start</strong> will remove the missing cache disk and then bring the array on-line.
<br><input type="checkbox" name="confirmStart" value="OFF" onclick="$('#cmdStart').prop('disabled',!arrayOps.confirmStart.checked)"><small>Yes I want to do this</small></td></tr>
<? else:?>
<tr><td><?status_indicator()?><span class="strong big">Stopped</span>. Configuration valid.</td><td><input type="button" id="cmdStart" value="Start" onclick="prepareInput(this.form)"></td>
<td><strong>Start</strong> will bring the array on-line.</td></tr>
<? endif;
maintenance_mode();
check_encryption();
break;
case "NEW_ARRAY":
if (strpos($disks['parity']['status'],"DISK_NP")===0 && strpos($disks['parity2']['status'],"DISK_NP")===0):?>
<tr><td><?status_indicator()?><span class="strong big">Stopped</span>. Configuration valid.</td><td><input type="button" id="cmdStart" value="Start" onclick="prepareInput(this.form)"></td>
<td><strong>Start</strong> will record all disk information and bring the array on-line.
<br>The array will be immediately available, but <strong>unprotected</strong> since <em>parity</em> has not been assigned.</td></tr>
<? else:?>
<tr><td><?status_indicator()?><span class="strong big">Stopped</span>. Configuration valid.</td><td><input type="button" id="cmdStart" value="Start" onclick="parityWarning(this.form)"></td>
<td><strong>Start</strong> will record all disk information, bring the array on-line, and start Parity-Sync.
<br>The array will be immediately available, but <strong>unprotected</strong> until Parity-Sync completes.
<br><input type="checkbox" name="md_invalidslot" value="99">Parity is already valid.</td></tr>
<? endif;
maintenance_mode();
check_encryption();
break;
case "DISABLE_DISK":?>
<tr><td><?status_indicator()?><span class="strong big">Stopped</span>. Missing disk.</td><td><input type="button" id="cmdStart" value="Start" onclick="prepareInput(this.form)" disabled></td>
<td><strong>Start</strong> will disable the missing disk and then bring the array on-line. Install a replacement disk as soon as possible.
<br><input type="checkbox" name="confirmStart" value="OFF" onclick="$('#cmdStart').prop('disabled',!arrayOps.confirmStart.checked)"><small>Yes I want to do this</small></td></tr>
<? maintenance_mode();
check_encryption();
break;
case "RECON_DISK":?>
<tr><td><?status_indicator()?><span class="strong big">Stopped</span>. Replacement disk installed.</td><td><input type="button" id="cmdStart" value="Start" onclick="prepareInput(this.form)"></td>
<td><strong>Start</strong> will start <strong>Parity-Sync</strong> and/or <strong>Data-Rebuild</strong>.</td></tr>
<? maintenance_mode();
check_encryption();
break;
case "SWAP_DSBL":
if ($var['fsCopyPrcnt']=="100"):?>
<tr><td><?status_indicator()?><span class="strong big">Stopped</span>. Upgrading disk/swapping parity.</td><td><input type="button" id="cmdStart" value="Start" onclick="prepareInput(this.form)"></td>
<td><strong>Start</strong> will expand the file system of the data disk (if possible); then bring the array on-line and start Data-Rebuild.</td></tr>
<? maintenance_mode();
check_encryption();
else:?>
<tr><td><?status_indicator()?><span class="strong big">Stopped</span>. Upgrading disk/swapping parity.</td><td><input type="submit" name="cmdCopy" value="Copy" disabled></td>
<td><strong>Copy</strong> will copy the parity information to the new <em>parity</em> disk.
<br>Once copy completes, the array may be Started, to initiate Data-Rebuild of the disabled disk.
<br><input type="checkbox" name="confirmStart" value="OFF" onclick="arrayOps.cmdCopy.disabled=!arrayOps.confirmStart.checked"><small>Yes I want to do this</small></td></tr>
<? endif;
break;
case "ERROR:INVALID_EXPANSION":?>
<tr><td><?status_indicator()?><span class="strong big">Stopped</span>. Invalid expansion.</td><td><input type="submit" name="cmdStart" value="Start" disabled></td>
<td>You may not add new disk(s) and also remove existing disk(s).</td></tr>
<? break;
case "ERROR:NEW_DISK_TOO_SMALL":?>
<tr><td><?status_indicator()?><span class="strong big">Stopped</span>. Replacement disk is too small.</td><td><input type="submit" name="cmdStart" value="Start" disabled></td>
<td>The replacement disk must be as big or bigger than the original.</td></tr>
<? break;
case "ERROR:PARITY_NOT_BIGGEST":?>
<tr><td><?status_indicator()?><span class="strong big">Stopped</span>. Disk in parity slot is not biggest.</td><td><input type="submit" name="cmdStart" value="Start" disabled></td>
<td>If this is a new array, move the largest disk into the <em>parity</em> slot.
<br>If you are adding a new disk or replacing a disabled disk, try Parity-Swap.</td></tr>
<? break;
case "ERROR:TOO_MANY_MISSING_DISKS":?>
<tr><td><?status_indicator()?><span class="strong big">Stopped</span>. Invalid configuration.</td><td><input type="submit" name="cmdStart" value="Start" disabled></td>
<td>Too many wrong and/or missing disks!</td></tr>
<? break;
case "ERROR:NO_DATA_DISKS":?>
<tr><td><?status_indicator()?><span class="strong big">Stopped</span>. No data disks.</td><td><input type="submit" name="cmdStart" value="Start" disabled></td>
<td>No array data disks have been assigned!</td></tr>
<? break;
endswitch;
endif;
endswitch;?>
<tr><td></td><td class="line" colspan="2"></td></tr>
</table>
</form>
<?if ($var['fsState']=="Started"):?>
<table class="array_status noshift">
<tr><td></td><td><input type="button" id="button-down" onclick="$('[id^=button-]').prop('disabled',true);toggle_state('down')" value="Spin Down"<?=$parity?' disabled':''?>><input type="button" id="button-up" onclick="$('[id^=button-]').prop('disabled',true);toggle_state('up')" value="Spin Up"<?=$parity?' disabled':''?>></td>
<td><strong>Spin Down</strong> will immediately spin down all disks.<br><strong>Spin Up</strong> will immediately spin up all disks.</td></tr>
<tr><td></td><td><input type="button" value="Clear Statistics" onclick="toggle_state('Clear')"></td><td><strong>Clear Statistics</strong> will immediately clear all disk statistics.</td></tr>
<tr><td></td><td class="line" colspan="2"></td></tr>
</table>
<?if ($var['shareCacheEnabled']=="yes" && is_dir("/mnt/cache")):?>
<form name="mover_schedule" method="POST" action="/update.htm" target="progressFrame">
<table class="array_status noshift">
<tr><td></td>
<?if ($mover):?>
<td><input type="submit" name="cmdStartMover" value="Move now" disabled></td><td>Disabled - Mover is running.</td>
<?else:?>
<td><input type="submit" name="cmdStartMover" value="Move now"></td><td><strong>Move now</strong> will immediately invoke the Mover. <a href="/Main/Scheduler"<?if ($tabbed):?> onclick="$.cookie('one','tab2',{path:'/'})"<?endif;?>>(Schedule)</a></td>
<?endif;?>
</tr>
</table>
</form>
<?endif;?>
<?endif;?>
<form name="shutdownOps" method="POST" action="/webGui/include/Boot.php">
<table class="array_status noshift">
<tr><td></td><td><input type="button" name="reboot" value="Reboot" onclick="shutdown_now(this.form,'reboot')"><input type="button" name="shutdown" value="Power down" onclick="shutdown_now(this.form,'shutdown')"></td>
<td><strong>Reboot</strong> will activate a <em>clean</em> system reset.<br><strong>Power down</strong> will activate a <em>clean</em> power down.</td></tr>
<tr><td></td><td class="line" colspan="2"></td></tr>
</table>
</form>
<?if ($keyfile):?>
<form name="delete_keyfile" method="POST" action="/update.php" target="progressFrame">
<input type="hidden" name="#file" value="unused">
<input type="hidden" name="#include" value="webGui/include/KeyUpload.php">
<table class="array_status noshift">
<tr><td></td><td><input type="submit" name="#apply" value="Delete" disabled></td><td><strong>Delete</strong> will delete the encryption keyfile.
<br><input type="checkbox" onchange="toggleApply(this.checked)"><small>Yes I want to do this</small></td></tr>
</table>
</form>
<?endif;?>
<?
if (isset($display['sleep'])) @include $display['sleep'];
?>
<?if ($btrfs):?>
<script>
function enable_stop() {
$.get('/webGui/include/ReloadPage.php',{btrfs:'btrfs'},function(data) {
switch (data) {
case 'disable':
setTimeout(enable_stop,5000);
break;
case 'enable':
var stop = $('td#stop');
stop.html(stop.html().replace("<?=$btrfs?>",""));
$('input[value="Stop"]').prop('disabled',false);
break;}
});
}
enable_stop();
</script>
<?endif;?>
> **Colored Status Indicator** the significance of the color indicator of the *Array* is as follows:
>
> <i class='fa fa-circle orb green-orb'></i>Array is Started and Parity is valid.
>
> <i class='fa fa-circle orb grey-orb'></i>Array is Stopped, Parity is valid.
>
> <i class='fa fa-warning orb yellow-orb'></i>Array is Started, but Parity is invalid.
>
> <i class='fa fa-warning orb grey-orb'></i>Array is Stopped, Parity is invalid.
>
<?if ($var['fsState'] == "Stopped"):?>
> #### Assigning Devices
>
> An Unraid disk array consists of a single parity disk and a number of data disks. The data
> disks are exclusively used to store user data, and the parity disk provides the redundancy necessary
> to recover from any singe disk failure.
>
> Note that we are careful to use the term *disk* when referring to an array storage device. We
> use the term *hard drive* (or sometimes just *drive*) when referring to an actual hard disk drive (HDD)
> device. This is because in a RAID system it is possible to read/write an array disk whose corresponding
> hard drive is disabled or even missing! In addition, it is useful to be able to ask, "which device is
> assigned to be the parity disk?"; or, "which device corresponds to disk2?".
>
> We therefore need a way to assign hard drives to array disks. This is accomplished here on the
> Main page when the array is stopped. There is a drop-down box for each array disk which lists all the
> unassigned devices. To assign a device simply select it from the list. Each time a device
> assignment is made, the system updates a configuration file to record the assignment.
>
> #### Requirements
>
> Unlike traditional RAID systems which stripe data across all the array devices, an Unraid server
> stores files on individual hard drives. Consequently, all file write operations will involve both the
> data disk the file is being written to, and the parity disk. For these reasons,
>
> * the parity disk size must be as large or larger than any of the data disks,
>
> and
>
> * given a choice, the parity disk should be the fastest disk in your collection.
>
> #### Guidelines
>
> Here are the steps you should follow when designing your Unraid disk array:
>
> 1. Decide which hard drive you will use for parity, and which hard drives you will use for
> data disk1, disk2, etc., and label them in some fashion. Also, find the serial number of each hard
> drive and jot it down somewhere; you will need this information later.
>
> 2. Install your hard drive devices, boot Unraid OS and bring up the webGui. If this is a fresh system
> build, then the Main page will show no disks installed. This doesn't mean the system can't detect your
> hard drives; it just means that none have been assigned yet.
>
> 3. Remember the serial numbers you recored back in step 1? For parity and each data disk, select the
> proper hard drive based on its serial number from the drop down list.
>
> #### Hot Plug
>
> You may also *hot plug* hard drives into your server if your hardware supports it. For example,
> if you are using hard drive cages, you may simply plug them into your server while powered on and
> with array Stopped. Refresh the Main page to have new unassigned devices appear in the assignment
> dropdown lists.
>
> #### Next Steps
>
> Once you have assigned all of your hard drives, refer to the Array Status section below
> and Start the array.
<?if ($encrypt):?>
<div></div>
> #### Encryption input
>
> Passphrase or file is stored in /root/keyfile.<br>
> This keyfile is read during array Start and is used to encrypt/decrypt content of encrypted devices.
>
> With array Stopped, the user can specify a new encryption key. Note that once a device
> is formatted with a particular key it may only be opened using that same key. Changing the encryption key requires
> encrypted devices to be reformatted **resulting in permanent loss of all existing data on those devices.**
>
> With array Started, the keyfile may be deleted to ensure there is no encryption key present on the server when
> the array is online. Note that plugins are installed and may execute before and during the array Start process.
>
> #### Passphrase
>
> Enter a passphrase of up to 512 characters. It is highly advisable to only use the 95 printable characters from the
> first 128 characters of the [ASCII table](https://en.wikipedia.org/wiki/ASCII), as they will always have the same binary
> representation. Other characters may have different encoding depending on system configuration and your passphrase will
> not work with a different encoding. If you want a longer passphrase or to include binary data, upload a keyfile instead.
>
> Please refer to the [cryptsetup FAQ](https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions#5-security-aspects)
> for what constitutes a *secure* passphrase.
>
> **Memorize** this passphrase. **IF LOST, ENCRYPTED CONTENT CANNOT BE RECOVERED!**
>
> #### Keyfile
>
> Select a local keyfile with a stored encryption key or a binary file. The maximum size of the keyfile is 8M (8388608 byte).
>
> **Backup** your local keyfile. **IF LOST, ENCRYPTED CONTENT CANNOT BE RECOVERED!**
<?endif;?>
<?endif;?>