index.html 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. <!DOCTYPE html>
  2. <html ng-app="App">
  3. <head>
  4. <title>System Update</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. </head>
  12. <body>
  13. <div class="ui container">
  14. <div class="ui basic segment">
  15. <h3 class="ui header">
  16. <i class="sync icon"></i>
  17. <div class="content">
  18. System Update
  19. <div class="sub header">Update the ArozOS System to the latest version</div>
  20. </div>
  21. </h3>
  22. <div class="ui divider"></div>
  23. <!-- Status Messages-->
  24. <div id="warning" class="ui negative visible icon message">
  25. <i class="red exclamation circle icon"></i>
  26. <div class="content">
  27. <div class="header">
  28. WARNING
  29. </div>
  30. <p>Backup all the important files before performing system update</p>
  31. </div>
  32. </div>
  33. <div id="checking" class="ui icon blue message" style="display:none;">
  34. <i class="notched circle loading icon"></i>
  35. <div class="content">
  36. <div class="header">
  37. Connecting to Download Server
  38. </div>
  39. <p>We're fetching that content for you.</p>
  40. </div>
  41. </div>
  42. <div id="confirmDownload" class="ui icon yellow message" style="display:none;">
  43. <i class="yellow exclamation icon"></i>
  44. <div class="content">
  45. <div class="header">
  46. Confirm Update?
  47. </div>
  48. <p><span>This updates will take up </span><span id="spaceEst" style="font-weight: bold;"></span> <span>of space.</span></p>
  49. <p><b>Please make sure you have back up all important files and config files before you proceeds.</b></p>
  50. <div class="ui buttons">
  51. <button class="ui yellow button" onclick="confirmURLUpdate();">Confirm Update</button>
  52. <button class="ui button" onclick="cancelUpdateStatus();"><i class="ui remove icon"></i> Cancel Update</button>
  53. </div>
  54. </div>
  55. </div>
  56. <div id="downloading" class="ui icon blue message" style="display:none;">
  57. <i class="notched circle loading icon"></i>
  58. <div class="content">
  59. <div class="header" id="downloadStatusText">
  60. Starting Download Session
  61. </div>
  62. <br>
  63. <p id="fallbackmodeExp" style="display:none;">You are seeing this message is because the websocket connection to your host failed to establish. No worry, updates can still be done using AJAX fallback mode, just without the real time progress updates. <br>Please wait until the
  64. download complete before closing this page.</br>
  65. </p>
  66. <div class="ui blue active progress">
  67. <div id="downloadProgressBar" class="bar">
  68. <div class="progress">0.00%</div>
  69. </div>
  70. </div>
  71. </div>
  72. </div>
  73. <div id="success" class="ui icon green message" style="display:none;">
  74. <i class="green checkmark icon"></i>
  75. <div class="content">
  76. <div class="header" id="downloadStatusText">
  77. Update Download Succeed
  78. </div>
  79. <p>Restart ArozOS using the launcher or apply manual update files overwrite to finish the update process.</p>
  80. </div>
  81. </div>
  82. <div id="pending" class="ui icon green message" style="display:none;">
  83. <i class="green clock icon"></i>
  84. <div class="content">
  85. <div class="header" id="downloadStatusText">
  86. Update Pending
  87. </div>
  88. <p>Restart ArozOS using the launcher or apply manual update files overwrite to finish the update process.</p>
  89. </div>
  90. </div>
  91. <div id="failed" class="ui icon red message" style="display:none;">
  92. <i class="red remove icon"></i>
  93. <div class="content">
  94. <div class="header" id="downloadStatusText">
  95. Update Download Failed
  96. </div>
  97. <p id="failedErrorMessage">Unknown Error Occured</p>
  98. </div>
  99. </div>
  100. <div id="restartPanel" class="ui message" style="display:none;">
  101. <div class="header">
  102. Launcher Detected: <span id="launcherName">N/A</span>
  103. </div>
  104. <p>You will need to restart ArozOS in order to apply the updates.</p>
  105. <p>Warning! Make sure you have physical access to this ArozOS Host before pressing the restart button.<br> Update failure might require a manual restart of the ArozOS system host and its launcher.</p>
  106. <button class="ui red button" onclick="restartArozOS();">RESTART NOW</button>
  107. <button class="ui button" onclick="restartLater();">Restart Later</button>
  108. </div>
  109. <!-- End of Status Messages -->
  110. <div class="vendorupdate">
  111. <h4>Update from <span class="vendorName">Vendor</span> (<i class="yellow star icon"></i> Recommended)</h4>
  112. <p>Update from <span class="vendorName">your vendor</span> based on the system update configuration that ship with this machine</p>
  113. <button class="ui blue button updateBtn" onclick="updateViaVendor();"><i class="cloud upload icon"></i> Update from Vendor</button>
  114. <div class="ui divider"></div>
  115. </div>
  116. <h4>Update via Download</h4>
  117. <p>Binary Executable Download URL</p>
  118. <div class="ui fluid input">
  119. <input id="burl" type="text" placeholder="Binary Download URL">
  120. </div>
  121. <small>Usually with pattern like: arozos_{platform}_{cpu_arch}</small>
  122. <br><br>
  123. <p>Webpack Download URL</p>
  124. <div class="ui fluid input">
  125. <input id="wurl" type="text" placeholder="Webpack Download URL">
  126. </div>
  127. <small>Usually with named as: webpack.tar.gz</small>
  128. <br><br>
  129. <button class="ui red button updateBtn" onclick="updateViaURL();"><i class="cloud upload icon"></i> Execute Update</button>
  130. <div class="ui divider"></div>
  131. <div class="ui message">
  132. <h4><i class="info circle icon"></i>Update Instruction</h4>
  133. <p>To update your ArozOS system, you will need two files: A compiled binary of the newer version of ArozOS and the webpack compress file in .tar.gz format. You can get the two files on Github, private distribution servers or from cluster
  134. nodes. Please choose one of the update method below and press "Update" to start the update process.</p>
  135. <p>Notes that updates only work if ArozOS is started by the launcher. If not, you might need to manually update the system using system commands.</p>
  136. <div class="ui accordion">
  137. <div class="title">
  138. <i class="dropdown icon"></i> How to update manually?
  139. </div>
  140. <div class="content">
  141. <p>If your system is not started by any launcher (versions before v1.120), you might want to manually update the ArozOS following the steps below.</p>
  142. <h5><i class="linux icon"></i> Linux (Debian)</h5>
  143. <div class="ui ordered list">
  144. <div class="item">Download the update of the latest ArozOS using one of the above methods</div>
  145. <div class="item">SSH into your host, cd into the ArozOS root (Usually located at ~/arozos/src/)</div>
  146. <div class="item">Check if the "updates" folder exists. If yes, check if the new ArozOS binary and "system" and "web" folder exists</div>
  147. <div class="item">Backup any important files or config if needed</div>
  148. <div class="item">Stop the arozos service using <code>sudo systemctl stop arozos</code></code>
  149. </div>
  150. <div class="item">Copy the updates to the arozos root using <code>cp -r ./updates/* ./</code></div>
  151. <div class="item">Restore the files or config</div>
  152. <div class="item">Start the arozos service using <code>sydo systemctl start arozos</code></div>
  153. <div class="item">The new ArozOS should be updated and ready.</div>
  154. </div>
  155. <h5><i class="windows icon"></i> Windows</h5>
  156. <div class="ui ordered list">
  157. <div class="item">Download the update of the latest ArozOS using one of the above methods</div>
  158. <div class="item">Locate the cmd / powershell window that is running ArozOS</div>
  159. <div class="item">Press <code>Ctrl + C</code> to gracefully stop ArozOS</div>
  160. <div class="item">Open ArozOS root and check if "updates" folder exists. If yes, check if the new ArozOS binary and "system" and "web" folder exists</div>
  161. <div class="item">Backup any important files or config if needed</div>
  162. <div class="item">Copy all the file from the "updates" folder and overwrite the one in ArozOS root (.\arozos\src\)</div>
  163. <div class="item">Restore the files or config</div>
  164. <div class="item">Start the new ArozOS binary (exe) by double clicking it OR starting the start.bat file</div>
  165. </div>
  166. </div>
  167. </div>
  168. </div>
  169. </div>
  170. </div>
  171. <script>
  172. var useVendorUpdate = false;
  173. var vendorUpdateBinaryURL = "";
  174. var vendorUpdateWebpackURL = "";
  175. var vendorUpdateCheckSumURL = "";
  176. $(".accordion").accordion();
  177. initVendorUpdateInfo();
  178. checkPendingUpdates();
  179. function checkPendingUpdates() {
  180. $.get("../../system/update/checkpending", function(data) {
  181. if (data == true) {
  182. //There is a pending update.
  183. hideAllStatus();
  184. $("#pending").slideDown('fast');
  185. $.get("/system/update/restart", function(data) {
  186. if (data.error !== undefined) {
  187. //No launcher
  188. } else {
  189. $("#launcherName").text(data);
  190. $("#restartPanel").show();
  191. }
  192. console.log("Launcher check: ", data);
  193. })
  194. }
  195. })
  196. }
  197. function initVendorUpdateInfo() {
  198. $.get("../../system/update/platform", function(data) {
  199. console.log(data);
  200. if (data.error !== undefined) {
  201. //No vendor update modes
  202. $(".vendorupdate").hide();
  203. } else {
  204. if (data.Config.binary[data.OS] && data.Config.binary[data.OS][data.ARCH]) {
  205. //This update target exists
  206. vendorUpdateBinaryURL = data.Config.binary[data.OS][data.ARCH];
  207. }
  208. vendorUpdateWebpackURL = data.Config.webpack;
  209. vendorUpdateCheckSumURL = data.Config.checksum;
  210. $(".vendorName").text(data.Config.vendor);
  211. }
  212. })
  213. }
  214. function updateViaVendor() {
  215. let binaryDownloadURL = vendorUpdateBinaryURL;
  216. let webpackDownloadURL = vendorUpdateWebpackURL;
  217. if (binaryDownloadURL == "" || webpackDownloadURL == "") {
  218. return
  219. }
  220. //Check space need
  221. $("#checking").slideDown("fast");
  222. $("#warning").slideUp("fast");
  223. useVendorUpdate = true;
  224. $.get(`/system/update/checksize?webpack=${webpackDownloadURL}&binary=${binaryDownloadURL}`, function(data) {
  225. if (data.error != undefined) {
  226. cancelUpdateStatus();
  227. alert("Update failed: " + data.error)
  228. } else {
  229. let totalDownloadBytes = data[0] + data[1];
  230. $("#spaceEst").text(ao_module_utils.formatBytes(totalDownloadBytes, 2));
  231. $("#confirmDownload").slideDown("fast");
  232. $("#checking").slideUp("fast");
  233. console.log(data);
  234. }
  235. })
  236. }
  237. function updateViaURL() {
  238. let binaryDownloadURL = $("#burl").val().trim();
  239. let webpackDownloadURL = $("#wurl").val().trim();
  240. if (binaryDownloadURL == "" || webpackDownloadURL == "") {
  241. alert("Invalid or Empty URL given");
  242. return
  243. }
  244. //Check space need
  245. $("#checking").slideDown("fast");
  246. $("#warning").slideUp("fast");
  247. $.get(`/system/update/checksize?webpack=${webpackDownloadURL}&binary=${binaryDownloadURL}`, function(data) {
  248. if (data.error != undefined) {
  249. cancelUpdateStatus();
  250. alert("Update failed: " + data.error)
  251. } else {
  252. let totalDownloadBytes = data[0] + data[1];
  253. $("#spaceEst").text(ao_module_utils.formatBytes(totalDownloadBytes, 2));
  254. $("#confirmDownload").slideDown("fast");
  255. $("#checking").slideUp("fast");
  256. console.log(data);
  257. }
  258. })
  259. }
  260. function confirmURLUpdate() {
  261. let binaryDownloadURL = $("#burl").val().trim();
  262. let webpackDownloadURL = $("#wurl").val().trim();
  263. let checksumDownloadURL = "";
  264. if (useVendorUpdate) {
  265. //Use vendor link for update. Replace the download target with vendor update links
  266. useVendorUpdate = false;
  267. binaryDownloadURL = vendorUpdateBinaryURL;
  268. webpackDownloadURL = vendorUpdateWebpackURL;
  269. checksumDownloadURL = vendorUpdateCheckSumURL;
  270. }
  271. if (binaryDownloadURL == "" || webpackDownloadURL == "") {
  272. alert("Invalid or Empty URL given");
  273. return
  274. }
  275. var wsroot = ao_module_utils.getWebSocketEndpoint();
  276. var requestEndpoint = wsroot + `/system/update/download?webpack=${webpackDownloadURL}&binary=${binaryDownloadURL}&checksum=${checksumDownloadURL}&ws=true`
  277. console.log("Connecting to: ", requestEndpoint);
  278. var isFailed = false;
  279. hideAllStatus();
  280. $("#downloading").slideDown("fast");
  281. let socket = new WebSocket(requestEndpoint);
  282. socket.onopen = function(e) {
  283. $("#downloadStatusText").text("Download Started");
  284. $(".updateBtn").addClass("disabled");
  285. };
  286. socket.onmessage = function(event) {
  287. let status = JSON.parse(event.data);
  288. if (status.error !== undefined) {
  289. hideAllStatus();
  290. $("#failed").slideDown();
  291. $("#failedErrorMessage").text(status.error);
  292. $(".updateBtn").removeClass("disabled");
  293. isFailed = true
  294. } else {
  295. //Progressing
  296. let progressText = status.Progress.toFixed(2) + "%";
  297. $("#downloadProgressBar").find(".progress").text(progressText);
  298. $("#downloadProgressBar").css("width", status.Progress + "%");
  299. $("#downloadStatusText").text(`[${status.Stage}] ${status.StatusText}`);
  300. }
  301. console.log(event.data);
  302. };
  303. socket.onclose = function(event) {
  304. if(!isFailed){
  305. hideAllStatus();
  306. $("#success").slideDown();
  307. checkLauncher();
  308. }
  309. };
  310. socket.onerror = function(error) {
  311. console.log("Websocket Connection Error: ", error, " Running in fallback mode")
  312. downloadUpdateFallbackMode(binaryDownloadURL, webpackDownloadURL);
  313. };
  314. }
  315. function downloadUpdateFallbackMode(binaryDownloadURL, webpackDownloadURL, checksumDownloadURL) {
  316. hideAllStatus();
  317. $("#downloading").slideDown("fast");
  318. $("#downloadStatusText").text("Waiting for Download Complete (Fallback Mode)");
  319. $("#fallbackmodeExp").show();
  320. $("#downloadProgressBar").find(".progress").text("Downloading");
  321. $("#downloadProgressBar").css("width", "50%");
  322. $(".updateBtn").addClass("disabled");
  323. $.get(`../../system/update/download?webpack=${webpackDownloadURL}&binary=${binaryDownloadURL}&checksum=${checksumDownloadURL}`, function(data) {
  324. if (data.error !== undefined) {
  325. hideAllStatus();
  326. $("#failed").slideDown();
  327. $("#failedErrorMessage").text(data.error);
  328. $(".updateBtn").removeClass("disabled");
  329. } else {
  330. hideAllStatus();
  331. $("#success").slideDown();
  332. checkLauncher();
  333. }
  334. })
  335. }
  336. function checkLauncher() {
  337. $(".updateBtn").removeClass("disabled");
  338. $.get("/system/update/restart", function(data) {
  339. if (data.error !== undefined) {
  340. //No launcher
  341. $("#restartPanel").hide();
  342. } else {
  343. $("#launcherName").text(data);
  344. $("#restartPanel").show();
  345. }
  346. console.log("Launcher check: ", data);
  347. })
  348. }
  349. function restartArozOS() {
  350. if (confirm("CONFIRM RESTART?")) {
  351. window.top.location.href = "../updates/updating.html";
  352. }
  353. }
  354. function cancelUpdateStatus() {
  355. hideAllStatus();
  356. $("#warning").slideDown("fast");
  357. }
  358. function restartLater() {
  359. hideAllStatus();
  360. }
  361. function hideAllStatus() {
  362. $("#warning").slideUp("fast");
  363. $("#confirmDownload").slideUp("fast");
  364. $("#checking").slideUp("fast");
  365. $("#downloading").slideUp("fast");
  366. $("#success").slideUp("fast");
  367. $("#failed").slideUp("fast");
  368. $("#restartPanel").slideUp("fast");
  369. }
  370. </script>
  371. </body>
  372. </html>