control.php 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. <?php
  2. /**
  3. * The control file of instance module of ZenTaoPMS.
  4. *
  5. * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
  6. * @license ZPL (http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
  7. * @author Sun Guangming <sunguangming@easycorp.ltd>
  8. * @package instance
  9. * @version $Id$
  10. * @link https://www.zentao.net
  11. * @property instanceModel $instance
  12. * @property instanceZen $instanceZen
  13. * @property cneModel $cne
  14. */
  15. class instance extends control
  16. {
  17. /**
  18. * Construct function.
  19. *
  20. * @param string $moduleName
  21. * @param string $methodName
  22. * @access public
  23. * @return void
  24. */
  25. public function __construct($moduleName = '', $methodName = '')
  26. {
  27. parent::__construct($moduleName, $methodName);
  28. $this->loadModel('action');
  29. $this->loadModel('cne');
  30. $this->loadModel('store');
  31. }
  32. /**
  33. * 查看应用详情。
  34. * Show instance view.
  35. *
  36. * @param int $id
  37. * @param string $type
  38. * @param string $tab
  39. * @access public
  40. * @return void
  41. */
  42. public function view($id, $type = 'store', $tab = 'baseinfo')
  43. {
  44. if(!commonModel::hasPriv('space', 'browse')) $this->loadModel('common')->deny('space', 'browse', false);
  45. if($type === 'store')
  46. {
  47. $this->instanceZen->storeView($id, $tab);
  48. }
  49. else
  50. {
  51. $instance = $this->loadModel('gitea')->fetchByID($id);
  52. $instance->status = 'running';
  53. $instance->source = 'user';
  54. $instance->externalID = $instance->id;
  55. $instance->runDuration = 0;
  56. $instance->appName = $instance->type;
  57. $instance->createdAt = $instance->createdDate;
  58. $instanceMetric = new stdclass();
  59. $instanceMetric->cpu = 0;
  60. $instanceMetric->memory = 0;
  61. $instanceMetric->disk = 0;
  62. $this->view->title = $instance->name;
  63. $this->view->instance = $instance;
  64. $this->view->actions = $this->loadModel('action')->getList($instance->type, $id);
  65. $this->view->defaultAccount = '';
  66. $this->view->instanceMetric = $instanceMetric;
  67. $this->view->dbList = array();
  68. }
  69. $this->view->users = $this->loadModel('user')->getPairs('noletter');
  70. $this->view->tab = $tab;
  71. $this->view->type = $type;
  72. $this->display();
  73. }
  74. /**
  75. * 设置应用。
  76. * Setting instance.
  77. *
  78. * @param int $id
  79. * @param string $component 0|mysql
  80. * @access public
  81. * @return void
  82. */
  83. public function setting($id, $component = '0')
  84. {
  85. if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
  86. $instance = $this->instance->getByID($id);
  87. $currentResource = $this->cne->getAppConfig($instance);
  88. if(empty($component)) $component = false;
  89. $diskSettings = $this->cne->getDiskSettings($instance, $component);
  90. $this->lang->instance->errors->invalidDiskSize = sprintf($this->lang->instance->errors->invalidDiskSize, $diskSettings->size, $diskSettings->limit);
  91. $this->lang->instance->tips->resizeDisk = sprintf($this->lang->instance->tips->resizeDisk, $diskSettings->size, $diskSettings->limit);
  92. if(!empty($_POST))
  93. {
  94. $newInstance = fixer::input('post')->trim('name')->get();
  95. $memoryKb = $this->post->memory_kb;
  96. if(intval($currentResource->max->memory / 1024) != $memoryKb)
  97. {
  98. /* Check free memory size is enough or not. */
  99. $clusterResource = $this->cne->cneMetrics();
  100. $freeMemory = intval($clusterResource->metrics->memory->allocatable * 0.9); // Remain 10% memory for system.
  101. if($memoryKb * 1024 > $freeMemory) $this->send(array('result' => 'fail', 'message' => $this->lang->instance->errors->notEnoughResource));
  102. /* Request CNE to adjust memory size. */
  103. $instance->oldValue = $currentResource->max->memory;
  104. if(!$this->instance->updateMemorySize($instance, $memoryKb * 1024))
  105. {
  106. return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  107. }
  108. }
  109. $cpu = $this->post->cpu;
  110. if($currentResource->max->cpu != $cpu)
  111. {
  112. $instance->oldValue = $currentResource->max->cpu;
  113. if(!$this->instance->updateCpuSize($instance, $cpu))
  114. {
  115. return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  116. }
  117. }
  118. $disk = $this->post->disk_gb;
  119. if(is_numeric($disk) && $disk != $diskSettings->size && $disk != $diskSettings->requestSize)
  120. {
  121. if($disk < $diskSettings->size || $disk > $diskSettings->limit) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->errors->invalidDiskSize));
  122. $instance->oldValue = $diskSettings->size;
  123. if(!$this->instance->updateVolSize($instance, $disk . 'Gi', $diskSettings->name)) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  124. }
  125. if(empty($component))
  126. {
  127. $this->instance->updateByID($id, $newInstance);
  128. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  129. if($newInstance->name != $instance->name)
  130. {
  131. $this->action->create('instance', $instance->id, 'editName', '', json_encode(array('result' => array('result' => 'success'), 'data' => array('oldName' => $instance->name, 'newName' => $newInstance->name))));
  132. }
  133. }
  134. return $this->send(array('result' => 'success', 'load' => true, 'closeModal' => true));
  135. }
  136. $this->view->diskSettings = $diskSettings;
  137. $this->view->currentResource = $currentResource;
  138. $this->view->instance = $instance;
  139. $this->display();
  140. }
  141. /**
  142. * 升级一个应用。
  143. * Upgrade a instance.
  144. *
  145. * @param int $id
  146. * @access public
  147. * @return mixed
  148. */
  149. public function upgrade($id)
  150. {
  151. if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
  152. $instance = $this->instance->getByID($id);
  153. $instance->latestVersion = $this->store->appLatestVersion($instance->appID, $instance->version);
  154. if($_POST)
  155. {
  156. if(empty($instance->latestVersion)) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->noHigherVersion, 'closeModal' => true));
  157. $postData = fixer::input('post')->get();
  158. if($postData->confirm == 'yes') $success = $this->instance->upgrade($instance, $instance->latestVersion->version, $instance->latestVersion->app_version);
  159. $logExtra = array('result' => 'success', 'data' => array('oldVersion' => $instance->appVersion, 'newVersion' => $instance->latestVersion->app_version));
  160. if(!$success)
  161. {
  162. $logExtra['result'] = 'fail';
  163. $this->action->create('instance', $instance->id, 'upgrade', '', json_encode($logExtra));
  164. return $this->send(array('result' => 'fail', 'message' => !empty($logExtra['message']) ? $logExtra['message'] : $this->lang->instance->notices['upgradeFail'], 'closeModal' => true));
  165. }
  166. $this->action->create('instance', $instance->id, 'upgrade', '', json_encode($logExtra));
  167. return $this->send(array('result' => 'success', 'message' => $this->lang->instance->notices['upgradeSuccess'], 'load' => $this->createLink('instance', 'view', "id=$id"), 'closeModal' => true));
  168. }
  169. $this->view->title = $this->lang->instance->upgrade . $instance->name;
  170. $this->view->instance = $instance;
  171. $this->display();
  172. }
  173. /**
  174. * 访问一个应用。
  175. * Visit a app.
  176. *
  177. * @param int $id
  178. * @param int $externalID
  179. * @access public
  180. * @return void
  181. */
  182. public function visit($id, $externalID = 0)
  183. {
  184. if(!commonModel::hasPriv('space', 'browse')) $this->loadModel('common')->deny('space', 'browse', false);
  185. if(!$externalID)
  186. {
  187. $instance = $this->instance->getByID($id);
  188. $url = $this->instance->url($instance);
  189. }
  190. else
  191. {
  192. $pipeline = $this->loadModel('pipeline')->getByID($externalID);
  193. $url = $pipeline->url;
  194. }
  195. return $this->send(array('result' => 'success', 'callback' => "window.open('{$url}')"));
  196. }
  197. /**
  198. * 创建手工配置外部应用。
  199. * Create a external app.
  200. *
  201. * @param string $type
  202. * @access public
  203. * @return void
  204. */
  205. public function createExternalApp($type)
  206. {
  207. if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
  208. $this->loadModel('sonarqube');
  209. $this->app->loadLang('pipeline');
  210. $externalApp = form::data($this->config->instance->form->create)
  211. ->add('createdBy', isset($this->app->user->account) ? $this->app->user->account : '')
  212. ->get();
  213. $externalApp->type = $type;
  214. $externalApp->url = rtrim($externalApp->url, '/');
  215. if(!$this->instance->checkAppNameUnique($externalApp->name)) return $this->send(array('result' => false, 'message' => array('name' => sprintf($this->lang->error->repeat, $this->lang->pipeline->name, $externalApp->name))));
  216. $appID = $this->loadModel('pipeline')->create($externalApp);
  217. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  218. $this->loadModel('action')->create($type, $appID, 'created');
  219. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('space', 'browse')));
  220. }
  221. /**
  222. * 编辑手工配置外部应用。
  223. * Edit a external app.
  224. *
  225. * @param int $externalID
  226. * @access public
  227. * @return void
  228. */
  229. public function editExternalApp($externalID)
  230. {
  231. if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
  232. $oldApp = $this->loadModel('pipeline')->getByID($externalID);
  233. if($_POST)
  234. {
  235. $instance = form::data($this->config->instance->form->edit)
  236. ->add('editedBy', isset($this->app->user->account) ? $this->app->user->account : '')
  237. ->get();
  238. $this->pipeline->update($externalID, $instance);
  239. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  240. $app = $this->pipeline->getByID($externalID);
  241. $actionID = $this->loadModel('action')->create($app->type, $externalID, 'edited');
  242. $changes = common::createChanges($oldApp, $app);
  243. $this->action->logHistory($actionID, $changes);
  244. return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true, 'closeModal' => true));
  245. }
  246. $this->app->loadLang('space');
  247. $this->app->loadLang('sonarqube');
  248. $this->view->app = $oldApp;
  249. $this->display();
  250. }
  251. /**
  252. * 删除一个外部应用。
  253. * Delete a external app.
  254. *
  255. * @param int $externalID
  256. * @access public
  257. * @return void
  258. */
  259. public function deleteExternalApp($externalID)
  260. {
  261. if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
  262. $oldApp = $this->loadModel('pipeline')->getByID($externalID);
  263. $actionID = $this->pipeline->deleteByObject($externalID, $oldApp->type);
  264. if(!$actionID)
  265. {
  266. $response['result'] = 'fail';
  267. $response['callback'] = sprintf('zui.Modal.alert("%s");', $this->lang->pipeline->delError);
  268. return $this->send($response);
  269. }
  270. $app = $this->pipeline->getByID($externalID);
  271. $changes = common::createChanges($oldApp, $app);
  272. $this->loadModel('action')->logHistory($actionID, $changes);
  273. $response['load'] = true;
  274. $response['message'] = zget($this->lang->instance->notices, 'uninstallSuccess');
  275. $response['result'] = 'success';
  276. return $this->send($response);
  277. }
  278. /**
  279. * 安装应用。
  280. * Install app.
  281. *
  282. * @param int $appID
  283. * @param string $checkResource
  284. * @access public
  285. * @return void
  286. */
  287. public function install($appID, $checkResource = 'true')
  288. {
  289. if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
  290. $cloudApp = $this->store->getAppInfo($appID);
  291. if(empty($cloudApp)) return $this->send(array('result' => 'fail', 'load' => array('alert' => $this->lang->instance->errors->noAppInfo)));
  292. $versionList = $this->store->appVersionList($cloudApp->id);
  293. $mysqlList = $this->cne->sharedDBList('mysql');
  294. $pgList = $this->cne->sharedDBList('postgresql');
  295. if(!empty($_POST))
  296. {
  297. $customData = form::data($this->config->instance->form->install)->get();
  298. if($customData->version && isset($versionList[$customData->version])) $customData->app_version = $versionList[$customData->version]->app_version;
  299. $this->instanceZen->checkForInstall($customData);
  300. if($checkResource == 'true')
  301. {
  302. $resource = new stdclass();
  303. $resource->cpu = $cloudApp->cpu;
  304. $resource->memory = $cloudApp->memory;
  305. $result = $this->cne->tryAllocate(array($resource));
  306. if(!isset($result->code) || $result->code != 200) return $this->send(array('callback' => 'alertResource()'));
  307. }
  308. /* If select the version, replace the latest version of App by selected version. */
  309. if($customData->version)
  310. {
  311. $cloudApp->version = $customData->version;
  312. $cloudApp->app_version = $customData->app_version;
  313. }
  314. $sharedDB = new stdclass();
  315. if(isset($cloudApp->dependencies->mysql) && $customData->dbType == 'sharedDB')
  316. {
  317. $sharedDB = zget($mysqlList, $customData->dbService, $sharedDB);
  318. }
  319. elseif(isset($cloudApp->dependencies->postgresql) && $customData->dbType == 'sharedDB')
  320. {
  321. $sharedDB = zget($pgList, $customData->dbService, $sharedDB);
  322. }
  323. $instance = $this->instance->install($cloudApp, $sharedDB, $customData);
  324. if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
  325. if(!$instance) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->notices['installFail']));
  326. return $this->send(array('result' => 'success', 'message' => $this->lang->instance->notices['installSuccess'], 'load' => $this->createLink('instance', 'view', "id=$instance->id"), 'closeModal' => true));
  327. }
  328. $this->view->versionList = array();
  329. foreach($versionList as $version) $this->view->versionList[$version->version] = $version->app_version . " ({$version->version})";
  330. $this->view->title = $this->lang->instance->install . $cloudApp->alias;
  331. $this->view->cloudApp = $cloudApp;
  332. $this->view->thirdDomain = $this->instance->randThirdDomain();
  333. $this->view->mysqlList = $this->instance->dbListToOptions($mysqlList);
  334. $this->view->pgList = $this->instance->dbListToOptions($pgList);
  335. $this->display();
  336. }
  337. /**
  338. * 卸载应用。
  339. * Uninstall app instance.
  340. *
  341. * @param int $instanceID
  342. * @param string $type
  343. * @access public
  344. * @return void
  345. */
  346. public function ajaxUninstall($instanceID, $type = '')
  347. {
  348. if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
  349. if($type !== 'store')
  350. {
  351. $instance = $this->loadModel('pipeline')->getByID($instanceID);
  352. if(!$instance) return $this->send(array('result' => 'success', 'message' => $this->lang->instance->notices['success'], 'load' => $this->createLink('space', 'browse')));
  353. if($instance->type == 'nexus') return $this->deleteExternalApp($instance->id);
  354. return $this->fetch($instance->type, 'delete', array('id' => $instance->id));
  355. }
  356. $instance = $this->instance->getByID($instanceID);
  357. if(!$instance) return $this->send(array('result' => 'success', 'message' => $this->lang->instance->notices['success'], 'load' => $this->createLink('space', 'browse')));
  358. $externalApp = $this->loadModel('space')->getExternalAppByApp($instance);
  359. if($externalApp)
  360. {
  361. $actionID = $this->loadModel('pipeline')->deleteByObject($externalApp->id, strtolower($instance->appName));
  362. if(!$actionID) return $this->send(array('result' => 'fail', 'message' => $this->lang->pipeline->delError));
  363. }
  364. $success = $this->instance->uninstall($instance);
  365. $this->action->create('instance', $instance->id, 'uninstall', '', json_encode(array('result' => $success, 'app' => array('alias' => $instance->appName, 'app_version' => $instance->version))));
  366. /* Synchronize deletion of backup tasks. */
  367. /* 同步删除备份任务。 */
  368. $this->instance->deleteBackupCron($instance);
  369. if($success) return $this->send(array('result' => 'success', 'message' => zget($this->lang->instance->notices, 'uninstallSuccess'), 'load' => $this->createLink('space', 'browse')));
  370. return $this->send(array('result' => 'fail', 'message' => zget($this->lang->instance->notices, 'uninstallFail')));
  371. }
  372. /**
  373. * 启动应用实例。
  374. * Start app instance.
  375. *
  376. * @param int $instanceID
  377. * @access public
  378. * @return void
  379. */
  380. public function ajaxStart($instanceID)
  381. {
  382. if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
  383. $instance = $this->instance->getByID($instanceID);
  384. if(!$instance) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->instanceNotExists));
  385. $result = $this->instance->start($instance);
  386. $this->action->create('instance', $instance->id, 'start', '', json_encode(array('result' => $result, 'app' => array('alias' => $instance->appName, 'app_version' => $instance->version))));
  387. if($result->code == 200) return $this->send(array('result' => 'success', 'load' => true, 'message' => zget($this->lang->instance->notices, 'startSuccess')));
  388. return $this->send(array('result' => 'fail', 'message' => !empty($result->message) ? $result->message : zget($this->lang->instance->notices, 'startFail')));
  389. }
  390. /**
  391. * 停止应用实例。
  392. * Stop app instance.
  393. *
  394. * @param int $instanceID
  395. * @access public
  396. * @return void
  397. */
  398. public function ajaxStop($instanceID)
  399. {
  400. if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
  401. $instance = $this->instance->getByID($instanceID);
  402. if(!$instance) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->instanceNotExists));
  403. $result = $this->instance->stop($instance);
  404. $this->action->create('instance', $instance->id, 'stop', '', json_encode(array('result' => $result, 'app' => array('alias' => $instance->appName, 'app_version' => $instance->version))));
  405. if($result->code == 200) return $this->send(array('result' => 'success', 'load' => true, 'message' => zget($this->lang->instance->notices, 'stopSuccess')));
  406. return $this->send(array('result' => 'fail', 'message' => !empty($result->message) ? $result->message : zget($this->lang->instance->notices, 'stopFail')));
  407. }
  408. /**
  409. * 查看应用的运行状态。
  410. * Query status of app instance.
  411. *
  412. * @access public
  413. * @return void
  414. */
  415. public function ajaxStatus()
  416. {
  417. $postData = fixer::input('post')->setDefault('idList', array())->get();
  418. $instances = $this->instance->getByIdList($postData->idList);
  419. $statusList = $this->instance->batchFresh($instances);
  420. return $this->send(array('result' => 'success', 'data' => $statusList));
  421. }
  422. /**
  423. * 授权数据库。
  424. * Generate database auth parameters and jump to login page.
  425. *
  426. * @access public
  427. * @return void
  428. */
  429. public function ajaxDBAuthUrl()
  430. {
  431. if(!commonModel::hasPriv('space', 'browse')) $this->loadModel('common')->deny('space', 'browse', false);
  432. $post = fixer::input('post')
  433. ->setDefault('namespace', 'default')
  434. ->setDefault('instanceID', 0)
  435. ->setDefault('dbType', '')
  436. ->get();
  437. if(empty($post->dbName)) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->errors->dbNameIsEmpty));
  438. $instance = $this->instance->getByID((int)$post->instanceID);
  439. if(empty($instance)) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->instanceNotExists));
  440. $detail = $this->loadModel('cne')->appDBDetail($instance, $post->dbName);
  441. if(empty($detail)) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->errors->notFoundDB));
  442. $dbAuth = array();
  443. $dbAuth['driver'] = zget($this->config->instance->adminer->dbTypes, $post->dbType, '');
  444. $dbAuth['server'] = $detail->host . ':' . $detail->port;
  445. $dbAuth['username'] = $detail->username;
  446. $dbAuth['db'] = $detail->database;
  447. $dbAuth['password'] = $detail->password;
  448. $url = '/adminer?' . http_build_query($dbAuth);
  449. $this->send(array('result' => 'success', 'message' => '', 'data' => array('url' => $url)));
  450. }
  451. /**
  452. * 定时任务:同步GitFox数据。(方法用于DevOps解决方案)
  453. * Sync GitFox data (for DevOps solution).
  454. *
  455. * @access public
  456. * @return void
  457. */
  458. public function syncGitFoxData()
  459. {
  460. if(!file_exists($this->app->basePath . 'extension' . DS . 'custom' . DS . 'gitfox' . DS . 'control.php')) return false;
  461. $this->loadModel('instance')->syncGitFoxData();
  462. return true;
  463. }
  464. /**
  465. * Instance Backup List.
  466. * 应用备份列表。
  467. * @param int $id
  468. * @param int $recPerPage
  469. * @param int $pageID
  470. * @return void
  471. */
  472. public function backupList($id, $recPerPage = 5, $pageID = 1)
  473. {
  474. /* Initialize Backup List. */
  475. $instance = $this->instance->getByID($id);
  476. $backupList = $this->instance->backupList($instance);
  477. /* Pager. */
  478. $this->app->loadClass('pager', true);
  479. $recTotal = count($backupList);
  480. $pager = new pager($recTotal, $recPerPage, $pageID);
  481. $backupList = array_chunk($backupList, $pager->recPerPage);
  482. $backupList = empty($backupList) ? array() : $backupList[$pageID - 1];
  483. $this->view->instance = $instance;
  484. $this->view->pager = $pager;
  485. $this->view->backupList = $backupList;
  486. $this->display();
  487. }
  488. /**
  489. * Restore instance by ajax.
  490. * 还原应用。
  491. * @access public
  492. * @return void
  493. * @param int $instanceID
  494. * @param string $backupName
  495. */
  496. public function ajaxRestore($instanceID, $backupName)
  497. {
  498. if(empty($instanceID) || empty($backupName)) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->errors->wrongRequestData));
  499. $backupName = base64_decode(helper::safe64Decode($backupName));
  500. $instance = $this->instance->getByID($instanceID);
  501. if(empty($instance)) return $this->send(array('result' => 'fail', 'load' => array('alert' => $this->lang->instance->instanceNotExists)));
  502. $success = $this->instance->restore($instance, $this->app->user, $backupName);
  503. if(!$success)
  504. {
  505. $this->action->create('instance', $instance->id, 'restore', '', json_encode(array('result' => array('result' => 'fail'))));
  506. return $this->send(array('result' => 'fail', 'message' => zget($this->lang->instance->notices, 'restoreFail') ));
  507. }
  508. $this->action->create('instance', $instance->id, 'restore', '', json_encode(array('result' => array('result' => 'success'))));
  509. return $this->send(array('result' => 'success', 'message' => zget($this->lang->instance->notices, 'restoreSuccess'), 'load' => true));
  510. }
  511. /**
  512. * 手动备份。
  513. * Manual backup.
  514. *
  515. * @param int $id
  516. * @param string $component 0|mysql
  517. * @access public
  518. * @return void
  519. */
  520. public function manualBackup($id)
  521. {
  522. $instance = $this->instance->getByID($id);
  523. $success = $this->instance->backup($instance, $this->app->user);
  524. if(!$success)
  525. {
  526. $this->action->create('instance', $instance->id, 'manualbackup', '', json_encode(array('result' => 'fail')));
  527. return $this->send(array('result' => 'fail', 'message' => zget($this->lang->instance->notices, 'backupFail')));
  528. }
  529. $this->action->create('instance', $instance->id, 'manualbackup', '', json_encode(array('result' => 'success')));
  530. return $this->send(array('result' => 'success', 'message' => zget($this->lang->instance->notices, 'backupSuccess')));
  531. }
  532. /**
  533. * 备份设置。
  534. * backup settings.
  535. *
  536. * @param int $id
  537. * @param string $component 0|mysql
  538. * @access public
  539. * @return void
  540. * @param int $instanceID
  541. */
  542. public function backupSettings($instanceID)
  543. {
  544. $instance = $this->instance->getByID($instanceID);
  545. if($_POST)
  546. {
  547. $this->instance->saveBackupSettings($instance);
  548. if(dao::isError()) return $this->send(array('result' => 'fail', 'load' => array('alert' => dao::getError())));
  549. $locate = $this->createLink('instance', 'view', 'id=' . $instanceID);
  550. return $this->send(array('result' => 'success', 'load' => array('alert' => $this->lang->saveSuccess, 'locate' => $locate, 'closeModal' => true)));
  551. }
  552. $this->view->instance = $instance;
  553. $this->view->backupSettings = $this->instance->getBackupSettings($instanceID);
  554. $this->display();
  555. }
  556. /**
  557. * Cron task of auto backup.
  558. * 定时备份。
  559. *
  560. * @param $instanceID
  561. * @return int|null
  562. * @param string $instanceID
  563. */
  564. public function cronBackup($instanceID)
  565. {
  566. $instance = $this->instance->getByID((int)$instanceID);
  567. if(empty($instance)) return $this->send(array('result' => 'success', 'message' => $this->lang->instance->instanceNotExists));
  568. $sysUser = new stdclass;
  569. $sysUser->account = 'system';
  570. $success = $this->instance->autoBackup($instance, $sysUser);
  571. if(!$success)
  572. {
  573. return $this->send(array('result' => 'fail', 'message' => zget($this->lang->instance->notices, 'backupFail')));
  574. }
  575. return $this->send(array('result' => 'success', 'message' => zget($this->lang->instance->notices, 'backupSuccess')));
  576. }
  577. /**
  578. * Cron cleaning backup.
  579. * 定时清理备份。
  580. *
  581. * @return void
  582. */
  583. public function cronCleanBackup()
  584. {
  585. if(!$this->config->inQuickon) return $this->send(array('result' => 'success', 'message' => $this->lang->instance->notices['NoCleanBackupFiles']));
  586. /* Init instance list. */
  587. $instances = $this->loadModel('space')->getSpaceInstances(0, 'running');
  588. if(empty($instances)) return $this->send(array('result' => 'success', 'message' => $this->lang->instance->notices['NoCleanBackupFiles']));
  589. /* Cycle cleaning backup. */
  590. $sysUser = new stdclass;
  591. $sysUser->account = 'system';
  592. foreach($instances as $instance) $this->instance->cleanBackup($instance, $sysUser);
  593. return $this->send(array('result' => 'success', 'message' => $this->lang->instance->notices['cleanBackupSuccess']));
  594. }
  595. /**
  596. * Delete backup by ajax.
  597. * 删除备份。
  598. * @param int $backupID
  599. * @access public
  600. * @return void
  601. * @param string $instanceID
  602. * @param string $backupName
  603. */
  604. public function ajaxDeleteBackup($instanceID, $backupName)
  605. {
  606. $instance = $this->instance->getByID((int)$instanceID);
  607. if(empty($instance)) $this->send(array('result' => 'success', 'message' => $this->lang->instance->instanceNotExists));
  608. $backupName = base64_decode(helper::safe64Decode($backupName));
  609. $success = $this->instance->deleteBackup($instance, $backupName);
  610. if(!$success) return $this->send(array('result' => 'fail', 'message' => zget($this->lang->instance->notices, 'deleteFail')));
  611. $this->action->create('instance', $instance->id, 'manualdeletebackup', '', json_encode(array('result' => 'success')));
  612. return $this->send(array('result' => 'success', 'message' => zget($this->lang->instance->notices, 'deleteSuccess'), 'load' => $this->createLink('instance', 'view', 'id=' . $instanceID)));
  613. }
  614. /**
  615. * Ajax 方式获取组件列表。
  616. * ajax Get Components.
  617. * @param int $id
  618. * @return void
  619. */
  620. public function ajaxGetComponents($id)
  621. {
  622. $componentList = array();
  623. $instance = $this->instance->getByID($id);
  624. $components = $this->cne->getComponents($instance);
  625. if(empty($components->data)) return print(json_encode($componentList));
  626. foreach($components->data as $component)
  627. {
  628. $componentList[] = array('value' => $component->name, 'text' => $component->name);
  629. }
  630. return print(json_encode($componentList));
  631. }
  632. /**
  633. * Ajax 方式获取 Pods 列表。
  634. * ajax Get Pods.
  635. * @param int $id
  636. * @return void
  637. */
  638. public function ajaxGetPods($id)
  639. {
  640. $podList = [];
  641. $instance = $this->instance->getByID($id);
  642. $formData = form::data($this->config->instance->form->events)->get();
  643. $pods = $this->cne->getPods($instance, $formData->component);
  644. if(empty($pods->data)) return print(json_encode($podList));
  645. foreach($pods->data as $pod)
  646. {
  647. $podList[] = array('value' => $pod->name, 'text' => $pod->name);
  648. }
  649. return print(json_encode($podList));
  650. }
  651. /**
  652. * watch Logs page.
  653. * 查看日志页面.
  654. *
  655. * @param int $id
  656. * @return void
  657. */
  658. public function logs($id)
  659. {
  660. if (!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
  661. $instance = $this->instance->getByID($id);
  662. $this->view->instance = $instance;
  663. $this->view->title = $this->lang->instance->log->viewButton;
  664. $this->display();
  665. }
  666. /**
  667. * Get logs api.
  668. * 获取日志接口。
  669. * @param int $id
  670. * @return void
  671. */
  672. public function showLogs($id)
  673. {
  674. $instance = $this->instance->getByID($id);
  675. $formData = form::data($this->config->instance->form->events)->get();
  676. $component = $formData->component;
  677. $pod = $formData->pod;
  678. $previous = $formData->previous == 1;
  679. $container = $formData->container;
  680. $data = $this->cne->getAppLogs($instance, $component, $pod, $container, $previous) ?? new stdClass();
  681. return print(json_encode($data));
  682. }
  683. /**
  684. * watch Events page.
  685. * 查看事件页面.
  686. *
  687. * @param int $id
  688. * @return void
  689. */
  690. public function events($id)
  691. {
  692. if (!commonModel::hasPriv('instance', 'manage'))
  693. {
  694. $this->loadModel('common')->deny('instance', 'manage', false);
  695. }
  696. $this->view->instance = $this->instance->getByID($id);
  697. $this->display();
  698. }
  699. /**
  700. * Get Events api.
  701. * 获取日志接口。
  702. * @param int $id
  703. * @return void
  704. */
  705. public function showEvents($id)
  706. {
  707. $instance = $this->instance->getByID($id);
  708. $formData = form::data($this->config->instance->form->events)->get();
  709. $data = $this->cne->getEvents($instance, $formData->component) ?? new stdClass();
  710. return print(json_encode($data));
  711. }
  712. }