|
@@ -11,8 +11,8 @@
|
|
|
<script src="../disk/quota/script/Chart.min.js"></script>
|
|
|
<style>
|
|
|
.mdevice{
|
|
|
- color: rgb(59, 59, 59);
|
|
|
- font-size: 0.8em;
|
|
|
+ color: rgb(136, 136, 136);
|
|
|
+ font-weight: lighter;
|
|
|
}
|
|
|
.mdevuuid{
|
|
|
font-size: 0.6em !important;
|
|
@@ -66,6 +66,17 @@
|
|
|
margin-right: 0 !important;
|
|
|
}
|
|
|
|
|
|
+ /* Statistics of Device Status */
|
|
|
+ .deviceOverview{
|
|
|
+ background-color: #f3f3f3 !important;
|
|
|
+ border-radius: 0.4em !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .deviceOverview .ui.statistics .statistic .label{
|
|
|
+ text-transform: none !important;
|
|
|
+ font-weight: 300;
|
|
|
+ }
|
|
|
+
|
|
|
/* Danger zone css */
|
|
|
.dangerzone{
|
|
|
border: 1px solid #dedede;
|
|
@@ -86,102 +97,20 @@
|
|
|
user-select: none;
|
|
|
}
|
|
|
|
|
|
- /* Emulate the NAS disk interface */
|
|
|
- .nasFrontPanel{
|
|
|
- display: block;
|
|
|
- border-radius: 0.4em;
|
|
|
- background-color: white;
|
|
|
- border: 1px solid rgb(214, 214, 214);
|
|
|
- min-height: 150px;
|
|
|
- padding: 1em;
|
|
|
- }
|
|
|
-
|
|
|
- .nasDisk{
|
|
|
- width: 30px;
|
|
|
- height: 120px;
|
|
|
- background-color: white;
|
|
|
- border-radius: 0.4em;
|
|
|
- position: relative;
|
|
|
- display: inline-block;
|
|
|
- margin-right: 0.4em;
|
|
|
- cursor: pointer;
|
|
|
- }
|
|
|
-
|
|
|
- .nasDisk:hover{
|
|
|
- opacity: 0.7;
|
|
|
- }
|
|
|
-
|
|
|
- .nasDisk.inactive{
|
|
|
- background: rgb(98,98,98);
|
|
|
- background: linear-gradient(217deg, rgba(98,98,98,1) 12%, rgba(59,59,59,1) 77%);
|
|
|
- }
|
|
|
-
|
|
|
- .nasDisk.active{
|
|
|
- background: rgb(96,133,215);
|
|
|
- background: linear-gradient(217deg, rgba(96,133,215,1) 12%, rgba(31,122,196,1) 77%);
|
|
|
- }
|
|
|
-
|
|
|
- .nasDisk.faulty{
|
|
|
- background: rgb(215,96,96);
|
|
|
- background: linear-gradient(217deg, rgba(215,96,96,1) 12%, rgba(168,51,43,1) 77%);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- .nasDisk .nasDiskLabel{
|
|
|
- position: absolute;
|
|
|
- transform-origin: 0 0;
|
|
|
- color: white;
|
|
|
- transform: rotate(-90deg);
|
|
|
- width: 150px;
|
|
|
- height: 40px;
|
|
|
- margin-top: 120px;
|
|
|
- padding: 0.6em;
|
|
|
- padding-top: 0.6em;
|
|
|
- }
|
|
|
-
|
|
|
- .nasDisk .nasDiskNumberTag{
|
|
|
- position: absolute;
|
|
|
- top: 0em;
|
|
|
- right: 0em;
|
|
|
- height: 22px;
|
|
|
- width: 100%;
|
|
|
- background-color: rgb(44, 44, 44);
|
|
|
- color: rgb(233, 233, 233);
|
|
|
- text-align: center;
|
|
|
- border-top-left-radius: 0.4em;
|
|
|
- border-top-right-radius: 0.4em;
|
|
|
- }
|
|
|
-
|
|
|
</style>
|
|
|
</head>
|
|
|
<body>
|
|
|
- <br>
|
|
|
<div class="ui container">
|
|
|
+ <div class="ui basic segment">
|
|
|
+ <h3 class="ui header">
|
|
|
+ <span id="RAIDhealthyState"></span>
|
|
|
+ <div class="sub header"><span id="RAIDvolCount">0</span> RAID Storage Volume Detected</div>
|
|
|
+ </h3>
|
|
|
+ </div>
|
|
|
<div class="ui stackable grid">
|
|
|
<div class="six wide column" style="border-right: 1px solid #e0e0e0;">
|
|
|
- <p>List of RAID Volumes</p>
|
|
|
<div id="raidVolList">
|
|
|
- <div class="ui segment raidVol">
|
|
|
- <h4 class="ui header">
|
|
|
- <img src="../../img/system/raid.svg">
|
|
|
- <div class="healthIcon"><i class="ui green check circle icon"></i></div>
|
|
|
- <div class="content">
|
|
|
- <span>Volume 1</span> <span class="mdevice">(/dev/md0)</span>
|
|
|
- <div class="sub header mdevuuid" style="margin-top: 0.4em;">
|
|
|
- cbc11a2b:fbd42653:99c1340b:9c4962fb
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <br><br>
|
|
|
- <div class="ui small fluid usedvol progress">
|
|
|
- <div class="bar"></div>
|
|
|
- <div class="label volinfo">
|
|
|
- <div class="numeric">100 / 100PB</div>
|
|
|
- <div class="percentage">1%</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </h4>
|
|
|
- </div>
|
|
|
- <div><i class="ui green check circle icon"></i> No RAID Volumes</div>
|
|
|
+ <p style="text-align: center;"><i class="ui loading spinner icon"></i></p>
|
|
|
</div>
|
|
|
<div class="ui divider"></div>
|
|
|
<div style="width: 100%;" align="center">
|
|
@@ -191,26 +120,57 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="ten wide column">
|
|
|
- <div id="volumeOverviews">
|
|
|
- <div class="ui basic segment">
|
|
|
- <h1 class="ui header">
|
|
|
- <span id="healthy"><i class="ui loading circle notch icon"></i> Loading</span>
|
|
|
- <div class="sub header"><span id="totalVolume">0</span> RAID volumes Loaded</div>
|
|
|
- </h1>
|
|
|
- </div>
|
|
|
- <div class="ui divider"></div>
|
|
|
- <div class="ui basic segment">
|
|
|
- <div id="diskEmu" class="nasFrontPanel">
|
|
|
- <div class="nasDisk">
|
|
|
- <div class="nasDiskLabel">/dev/sda</div>
|
|
|
- <div class="nasDiskNumberTag">0</div>
|
|
|
+ <div id="volumeDetail">
|
|
|
+ <div id="raidDiskOverview">
|
|
|
+ <h3 class="ui header">
|
|
|
+ <i class="ui green check circle icon"></i>
|
|
|
+ <div class="content">
|
|
|
+ <span>/dev/md0</span>
|
|
|
+ <div class="sub header">10c0a9d9:763e326a:7d825b41:e1dc0536 | clean</div>
|
|
|
+ </div>
|
|
|
+ </h3>
|
|
|
+ <div class="ui divider"></div>
|
|
|
+ <div class="ui basic segment deviceOverview">
|
|
|
+ <div class="ui tiny four statistics">
|
|
|
+ <div class="statistic">
|
|
|
+ <div class="value">
|
|
|
+ <img src="../disk/raid/img/drive.svg" class="ui inline image">
|
|
|
+ <span id="RAIDActiveDevices">0</span>
|
|
|
+ </div>
|
|
|
+ <div class="label">
|
|
|
+ Active Devices
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="statistic">
|
|
|
+ <div class="value">
|
|
|
+ <img src="../disk/raid/img/drive-working.svg" class="ui inline image">
|
|
|
+ <span id="RAIDWorkingDevices">0</span>
|
|
|
+ </div>
|
|
|
+ <div class="label">
|
|
|
+ Working Devices
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="statistic">
|
|
|
+ <div class="value">
|
|
|
+ <img src="../disk/raid/img/drive-failed.svg" class="ui inline image">
|
|
|
+ <span id="RAIDFailedDevices">0</span>
|
|
|
+ </div>
|
|
|
+ <div class="label">
|
|
|
+ Failed Devices
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="statistic">
|
|
|
+ <div class="value">
|
|
|
+ <img src="../disk/raid/img/drive-spare.svg" class="ui inline image">
|
|
|
+ <span id="RAIDSpareDevices">0</span>
|
|
|
+ </div>
|
|
|
+ <div class="label">
|
|
|
+ Spare Devices
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- <div id="volumeDetail">
|
|
|
-
|
|
|
-
|
|
|
<div id="raidDiskList">
|
|
|
|
|
|
</div>
|
|
@@ -252,61 +212,129 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
<script>
|
|
|
- var diskData = [{
|
|
|
- "DevicePath" : "/dev/sda",
|
|
|
- "State": ["active", "sync"]
|
|
|
- },
|
|
|
- {
|
|
|
- "DevicePath" : "/dev/sdb",
|
|
|
- "State": ["active", "sync"]
|
|
|
- },
|
|
|
- {
|
|
|
- "DevicePath" : "/dev/sdc",
|
|
|
- "State": ["faulty", "spare"]
|
|
|
- },
|
|
|
- {
|
|
|
- "DevicePath" : "/dev/sdd",
|
|
|
- "State": []
|
|
|
- }];
|
|
|
|
|
|
- $("#volumeDetail").hide();
|
|
|
+ //Quick function to check if the disk is healthy
|
|
|
+ function isHealthy(stateText) {
|
|
|
+ // Check if the stateText contains any unhealthy states
|
|
|
+ if (stateText.includes('faulty') || stateText.includes('resyncing') ||
|
|
|
+ stateText.includes('recovering') || stateText.includes('degraded') ||
|
|
|
+ stateText.includes('inactive')) {
|
|
|
+ return false; // Array is not healthy
|
|
|
+ } else {
|
|
|
+ return true; // Array is healthy
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- function GenerateEmulatedDisk(){
|
|
|
- $("#diskEmu").html("");
|
|
|
+ //Get the RAID health state icon from state Text
|
|
|
+ function getStateIconFromStateText(stateText) {
|
|
|
+ if (stateText.includes('faulty')) {
|
|
|
+ return 'ui red times circle icon';
|
|
|
+ } else if (stateText.includes('resyncing')) {
|
|
|
+ return 'ui green loading sync icon';
|
|
|
+ } else if (stateText.includes('recovering')) {
|
|
|
+ return 'ui yellow loading sync icon';
|
|
|
+ } else if (stateText.includes('degraded')) {
|
|
|
+ return 'ui yellow exclamation triangle';
|
|
|
+ } else if (stateText.includes('inactive')) {
|
|
|
+ return 'ui grey check sync icon';
|
|
|
+ } else if (stateText.includes('active')) {
|
|
|
+ return 'ui green check circle icon';
|
|
|
+ } else if (stateText.includes('clean')) {
|
|
|
+ return 'ui green check circle icon';
|
|
|
+ } else if (stateText.includes('spare')) {
|
|
|
+ return 'ui blue check circle icon';
|
|
|
+ } else if (stateText.includes('reshape')) {
|
|
|
+ return 'ui blue loading sync icon';
|
|
|
+ } else if (stateText.includes('frozen')) {
|
|
|
+ return 'ui blue snowflake icon';
|
|
|
+ } else {
|
|
|
+ return 'ui blue question circle icon';
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- //Generate the list of disk base on diskData
|
|
|
- let diskCounter = 0;
|
|
|
- diskData.forEach(function(diskInfo){
|
|
|
- let diskStateClass = "inactive";
|
|
|
- if (diskInfo.State.length > 0){
|
|
|
- for (var i = 0; i < diskInfo.State.length; i++){
|
|
|
- let thisState = diskInfo.State[i];
|
|
|
- if (thisState == "sync" || thisState == "active"){
|
|
|
- diskStateClass = "active";
|
|
|
- }else if (thisState == "faulty"){
|
|
|
- diskStateClass = "faulty"
|
|
|
- }
|
|
|
+ function loadRAIDVolDetail(deviceName){
|
|
|
+ function capitalize(string) {
|
|
|
+ return string.charAt(0).toUpperCase() + string.slice(1);
|
|
|
+ }
|
|
|
|
|
|
- //Add more state here if required
|
|
|
- }
|
|
|
+ //Get the information of the device
|
|
|
+ $("#raidDiskList").html("");
|
|
|
+ $.get("../../system/disk/raid/detail?devName=" + deviceName, function(data){
|
|
|
+ if (data.error != undefined){
|
|
|
+ $("#raidDiskList").html(`<h3 class="ui header">
|
|
|
+ <i class="ui red circle times icon"></i>
|
|
|
+ <div class="content" style="font-weight: 300;">
|
|
|
+ Unable to load RAID volume information
|
|
|
+ <div class="sub header">${capitalize(data.error)}</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </h3>`);
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
- console.log(diskStateClass);
|
|
|
- $("#diskEmu").append(`
|
|
|
- <div class="nasDisk ${diskStateClass}">
|
|
|
- <div class="nasDiskLabel">${diskInfo.DevicePath}</div>
|
|
|
- <div class="nasDiskNumberTag">${diskCounter}</div>
|
|
|
- </div>
|
|
|
- `);
|
|
|
-
|
|
|
+ //Render the disk list
|
|
|
+ $("#raidDiskList").html("");
|
|
|
+
|
|
|
+ //Update the active disks info
|
|
|
+ $("#RAIDActiveDevices").text(data.ActiveDevices);
|
|
|
+ $("#RAIDWorkingDevices").text(data.WorkingDevices);
|
|
|
+ $("#RAIDFailedDevices").text(data.FailedDevices);
|
|
|
+ $("#RAIDSpareDevices").text(data.SpareDevices);
|
|
|
|
|
|
|
|
|
- diskCounter++;
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- GenerateEmulatedDisk();
|
|
|
+ //Initialize the RAID volume list on this system
|
|
|
+ function initRAIDVolList(){
|
|
|
+ $("#raidVolList").html(`<p style="text-align: center;"><i class="ui loading spinner icon"></i></p>`);
|
|
|
+ $.get("../../system/disk/raid/list", function(data){
|
|
|
+ if (data.error != undefined){
|
|
|
+ $("#raidVolList").html(`<p style="text-align: center;"><i class="ui red circle remove icon"></i> ${data.error}</p>`);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ $("#raidVolList").html("");
|
|
|
+ let containUnhealthyDisk = false;
|
|
|
+ for (var i = 0; i < data.length; i++){
|
|
|
+ let thisDiskInfo = data[i];
|
|
|
+ $("#raidVolList").append(`<div class="ui segment raidVol">
|
|
|
+ <h4 class="ui header">
|
|
|
+ <img src="../../img/system/raid.svg">
|
|
|
+ <div class="healthIcon"><i class="${getStateIconFromStateText(thisDiskInfo.State)}"></i></div>
|
|
|
+ <div class="content" style="margin-left: 0.6em;">
|
|
|
+ <span>${thisDiskInfo.DevicePath}</span> <span class="mdevice">(${thisDiskInfo.RaidLevel})</span>
|
|
|
+ <div class="sub header mdevuuid" style="margin-top: 0.4em;">
|
|
|
+ ${thisDiskInfo.UUID}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </h4>
|
|
|
+ </div>`);
|
|
|
+ if (!isHealthy(thisDiskInfo.State)){
|
|
|
+ containUnhealthyDisk = true;
|
|
|
+ }
|
|
|
+ console.log(thisDiskInfo);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data.length == 0){
|
|
|
+ $("#raidVolList").html(`<div><i class="ui green check circle icon"></i> No RAID Volumes</div>`);
|
|
|
+ }else{
|
|
|
+ //Load the first RAID vol info
|
|
|
+ loadRAIDVolDetail(data[0].DevicePath);
|
|
|
+ }
|
|
|
+ $("#RAIDvolCount").text(data.length);
|
|
|
+
|
|
|
+ //Update the overall health text
|
|
|
+ if (containUnhealthyDisk){
|
|
|
+ $("#RAIDhealthyState").html("<i class='ui yellow exclamation triangle icon'></i> Attention Needed!");
|
|
|
+ }else{
|
|
|
+ $("#RAIDhealthyState").html("<i class='ui green circle check icon'></i> Healthy");
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+ }
|
|
|
+ initRAIDVolList();
|
|
|
+
|
|
|
</script>
|
|
|
-
|
|
|
</body>
|
|
|
</html>
|