newdisk.html 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Add new disk to RAID</title>
  5. <meta charset="UTF-8">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0 user-scalable=no">
  7. <link rel="stylesheet" href="../../../script/semantic/semantic.min.css">
  8. <script type="text/javascript" src="../../../script/jquery.min.js"></script>
  9. <script type="text/javascript" src="../../../script/semantic/semantic.min.js"></script>
  10. <script type="text/javascript" src="../../../script/ao_module.js"></script>
  11. <style>
  12. .installedDisk .checkboxWrapper{
  13. position: absolute;
  14. right: 1em;
  15. top: 1.8em;
  16. }
  17. .installedDisk:not(.disabled){
  18. cursor: pointer;
  19. }
  20. .installedDisk:not(.disabled):hover{
  21. background-color: rgb(243, 243, 243);
  22. }
  23. .backicon {
  24. position: fixed;
  25. bottom: 0;
  26. left: 0;
  27. width: 30%;
  28. height: calc(50vh - 10px);
  29. background-image: url('./img/drive-add.svg');
  30. background-size: contain;
  31. background-repeat: no-repeat;
  32. margin-left: -3%;
  33. margin-bottom: -5%;
  34. opacity: 0.2;
  35. }
  36. .installedDisk.active{
  37. background-color: rgb(232, 246, 253);
  38. }
  39. </style>
  40. </head>
  41. <body>
  42. <br>
  43. <div class="backicon"></div>
  44. <div class="ui container">
  45. <div style="float:right;">
  46. <button class="ui circular icon basic button" onclick="reloadList();"><i class="ui green refresh icon"></i></button>
  47. <button id="confirmButton" onclick="addDisk();" class="ui circular green icon button"><i class="ui check icon"></i></button>
  48. </div>
  49. <p>Select a disk to add to RAID Volume <span id="targetRAIDVol"></span></p>
  50. <br>
  51. <div id="noUsableDisk" class="ui yellow message" style="display:none;">
  52. <i class="yellow exclamation triangle icon"></i> There are no usable / spare disks on your system
  53. </div>
  54. <div id="usablediskSelectionList" style="margin-bottom: 1em;">
  55. </div>
  56. <div id="disableddiskSelectionList">
  57. </div>
  58. </div>
  59. <!-- Disk Format Confirmation -->
  60. <div id="confirmDiskChoice" class="ui mini modal">
  61. <i class="close icon"></i>
  62. <div class="header">
  63. Confirm Disk Choice
  64. </div>
  65. <div class="image content">
  66. <div class="ui small image">
  67. <img src="./img/drive-format.svg">
  68. </div>
  69. <div class="description">
  70. <h3 id="oprconfirm"></h3>
  71. <p><b>Selecting this disk will erase all data permanently.</b> Confirm?</p>
  72. </div>
  73. </div>
  74. <div class="actions">
  75. <div class="ui black deny button">
  76. Cancel
  77. </div>
  78. <div class="ui positive left labeled icon button" onclick="confirmAddDisk();">
  79. <i class="check icon"></i>
  80. Confirm
  81. </div>
  82. </div>
  83. </div>
  84. <br><br>
  85. <script>
  86. let selectedDiskID = "";
  87. let editingMD = {
  88. md: "" //RAID device path, e.g. /dev/md0
  89. };
  90. if (window.location.hash.length > 1){
  91. var tmp = window.location.hash.substr(1);
  92. editingMD = JSON.parse(decodeURIComponent(tmp));
  93. }
  94. if (editingMD.md == ""){
  95. //invalid usage
  96. alert("Invalid usage");
  97. }else{
  98. //load disk info
  99. initDiskList();
  100. $("#targetRAIDVol").text(editingMD.md);
  101. }
  102. function bytesToSize(bytes) {
  103. var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
  104. if (bytes == 0) return 'n/a';
  105. var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
  106. if (i == 0) return bytes + ' ' + sizes[i];
  107. return (bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i];
  108. };
  109. function uuidv4() {
  110. return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c =>
  111. (+c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> +c / 4).toString(16)
  112. );
  113. }
  114. /* Disk Choice Confirmation */
  115. function addDisk(){
  116. selectedDiskID = $("input[type=radio][name=\"disk\"]:checked");
  117. if (selectedDiskID.length == 0){
  118. //No selected disk
  119. return;
  120. }
  121. selectedDiskID = selectedDiskID[0].value;
  122. $("#oprconfirm").text(selectedDiskID);
  123. $("#confirmDiskChoice").modal("show");
  124. }
  125. function confirmAddDisk(){
  126. /*
  127. //Authreq is bypassed as add disk seems don't need that much security
  128. var apiObject = {
  129. api: "../system/disk/raid/addMemeber",
  130. data: {
  131. raidDev: editingMD.md,
  132. memDev: selectedDiskID
  133. },
  134. title: `<i class='yellow add circle icon'></i> Add disk to RAID volume `,
  135. desc: `Confirm formatting and adding ${selectedDiskID} to ${editingMD.md}`,
  136. thisuser: true, //This username as default, set to false for entering other user
  137. method: "POST",
  138. success: undefined
  139. }
  140. apiObject = encodeURIComponent(JSON.stringify(apiObject));
  141. parent.newFloatWindow({
  142. url: "SystemAO/security/authreq.html#" + apiObject,
  143. width: 480,
  144. height: 300,
  145. appicon: "SystemAO/security/img/lock.svg",
  146. title: `Confirm Disk Add`,
  147. parent: ao_module_windowID,
  148. callback: "handleDiskAddCallback"
  149. });
  150. */
  151. $.ajax({
  152. url: "../../../system/disk/raid/addMemeber",
  153. data:{
  154. raidDev: editingMD.md,
  155. memDev: selectedDiskID
  156. },
  157. method: "POST",
  158. success: function(data){
  159. handleDiskAddCallback(data);
  160. }
  161. })
  162. }
  163. window.handleDiskAddCallback = function(data){
  164. if (data.error != undefined){
  165. alert(data.error);
  166. }else{
  167. //Disk added. Handle callback to parent
  168. if (ao_module_hasParentCallback()){
  169. ao_module_parentCallback(data);
  170. }
  171. //Operation completed.
  172. setTimeout(function(){
  173. ao_module_close();
  174. }, 300);
  175. }
  176. }
  177. function reloadList(){
  178. initDiskList();
  179. }
  180. function initDiskList(){
  181. $("#disableddiskSelectionList").html("");
  182. $("#usablediskSelectionList").html("");
  183. $.get("../../../system/disk/devices/list", function(data){
  184. if (data.error != undefined){
  185. console.log(data.error);
  186. }else{
  187. let usableDiskCount = 0;
  188. data.forEach(function(driveInfo){
  189. //Generate the children table
  190. let childrenTable = "";
  191. let notUsable = false;
  192. if (driveInfo.children != undefined){
  193. for (var i = 0; i < driveInfo.children.length; i++){
  194. let thisChild = driveInfo.children[i];
  195. childrenTable = childrenTable + `<tr>
  196. <td>${thisChild.name}</td>
  197. <td>${bytesToSize(thisChild.size)}</td>
  198. <td>${thisChild.type}</td>
  199. <td>${thisChild.mountpoint}</td>
  200. </tr>`;
  201. //Check if this disk is already in other raid object
  202. if (thisChild.name.substr(0, 2) == "md" || thisChild.type.substr(0, 4) == "raid"){
  203. //This is already in some raid array
  204. notUsable = true;
  205. }
  206. if (thisChild.mountpoint == "/"){
  207. //This is the root drive! Don't allow self destruct
  208. notUsable = true;
  209. }
  210. }
  211. }
  212. var domUID = uuidv4();
  213. let diskDOM = (`<div onclick="handleSelect(this);" class="ui segment installedDisk ${domUID} ${notUsable?"disabled":""}">
  214. <h4 class="ui header">
  215. <img src="./img/drive.svg">
  216. <div class="content">
  217. ${bytesToSize(driveInfo.size)} - <span class="diskname ${domUID}">Unknown Disk</span>
  218. <div class="sub header">/dev/${driveInfo.name}</div>
  219. </div>
  220. </h4>
  221. <div class="children">
  222. <table class="ui very basic unstackable table">
  223. <thead>
  224. <tr>
  225. <th>Name</th>
  226. <th>Size</th>
  227. <th>Partition Type</th>
  228. <th>Mount Point</th>
  229. </tr></thead>
  230. <tbody>${childrenTable}</tbody>
  231. </table>
  232. </div>
  233. <div class="checkboxWrapper">
  234. <div class="ui radio checkbox">
  235. <input type="radio" name="disk" value="/dev/${driveInfo.name}">
  236. <label></label>
  237. </div>
  238. </div>
  239. </div>`);
  240. if (!notUsable){
  241. $("#usablediskSelectionList").append(diskDOM);
  242. }else{
  243. $("#disableddiskSelectionList").append(diskDOM);
  244. }
  245. if (driveInfo.children == undefined || driveInfo.children.length == 0){
  246. $(".installedDisk." + domUID).find(".children").hide();
  247. }
  248. //console.log(driveInfo);
  249. if (notUsable){
  250. $(".installedDisk." + domUID).find(".checkboxWrapper").hide();
  251. }
  252. resolveDiskLabelToDOM(`/dev/${driveInfo.name}`, ".diskname." + domUID);
  253. if (!notUsable){
  254. usableDiskCount++;
  255. }
  256. });
  257. if (usableDiskCount == 0){
  258. //No usable disk. Is all disk in use?
  259. $("#noUsableDisk").show();
  260. $("#confirmButton").addClass("disabled");
  261. }else{
  262. $("#noUsableDisk").hide();
  263. $("#confirmButton").removeClass("disabled");
  264. }
  265. }
  266. })
  267. }
  268. //Resolve the disk label name to dom
  269. function resolveDiskLabelToDOM(diskPath, domSelector){
  270. $.get("../../../system/disk/devices/model?devName=" + diskPath, function(data){
  271. let diskLabelName = ""
  272. if (data.error == undefined){
  273. //[0] is disk labeled name
  274. //[1] is disk labeled size
  275. diskLabelName = data[0];
  276. }
  277. $(domSelector).html(diskLabelName);
  278. });
  279. }
  280. //Select the select box in the hdd
  281. function handleSelect(object){
  282. if (!$(object).hasClass("disabled")){
  283. $(object).find("input[type=radio]")[0].checked = true;
  284. $(".installedDisk.active").removeClass(".active");
  285. $(object).addClass('active');
  286. }
  287. }
  288. </script>
  289. </body>
  290. </html>