1044 lines
42 KiB
PHP
1044 lines
42 KiB
PHP
<?php
|
|
/**
|
|
* The control file of instance module of QuCheng.
|
|
*
|
|
* @copyright Copyright 2021-2022 北京渠成软件有限公司(BeiJing QuCheng Software Co,LTD, www.qucheng.com)
|
|
* @license ZPL (http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
|
* @author Jianhua Wang <wangjianhua@easycorp.ltd>
|
|
* @package instance
|
|
* @version $Id$
|
|
* @link https://www.qucheng.com
|
|
*/
|
|
class instance extends control
|
|
{
|
|
/**
|
|
* Construct function.
|
|
*
|
|
* @param string $moduleName
|
|
* @param string $methodName
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function __construct($moduleName = '', $methodName = '')
|
|
{
|
|
parent::__construct($moduleName, $methodName);
|
|
$this->loadModel('action');
|
|
$this->loadModel('cne');
|
|
$this->loadModel('store');
|
|
}
|
|
|
|
/**
|
|
* Show instance view.
|
|
*
|
|
* @param int $id
|
|
* @param int $recTotal
|
|
* @param int $recPerPage
|
|
* @param int $page
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function view($id, $type = 'store', $tab ='baseinfo' )
|
|
{
|
|
if(!commonModel::hasPriv('space', 'browse')) $this->loadModel('common')->deny('space', 'browse', false);
|
|
if($type === 'store')
|
|
{
|
|
$this->storeView($id, $tab);
|
|
}
|
|
else
|
|
{
|
|
$instance = $this->loadModel('gitea')->getByID($id);
|
|
$instance->status = '';
|
|
$instance->source = 'user';
|
|
$instance->externalID = $instance->id;
|
|
$instance->runDuration = 0;
|
|
$instance->appName = $instance->type;
|
|
$instance->createdAt = $instance->createdDate;
|
|
|
|
$instanceMetric = new stdclass();
|
|
$instanceMetric->cpu = 0;
|
|
$instanceMetric->memory = 0;
|
|
|
|
$this->view->title = $instance->name;
|
|
$this->view->instance = $instance;
|
|
$this->view->cloudApp = array();
|
|
$this->view->seniorAppList = array();
|
|
$this->view->actions = $this->loadModel('action')->getList($instance->type, $id);
|
|
$this->view->defaultAccount = '';
|
|
$this->view->instanceMetric = $instanceMetric;
|
|
$this->view->currentResource = '';
|
|
$this->view->customItems = array();
|
|
$this->view->backupList = array();
|
|
$this->view->hasRestoreLog = false;
|
|
$this->view->latestBackup = array();
|
|
$this->view->dbList = array();
|
|
$this->view->domain = '';
|
|
}
|
|
|
|
$this->view->users = $this->loadModel('user')->getPairs('noletter');
|
|
$this->view->tab = $tab;
|
|
$this->view->type = $type;
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* Show instance view.
|
|
*
|
|
* @param int $id
|
|
* @param int $recTotal
|
|
* @param int $recPerPage
|
|
* @param int $page
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
protected function storeView($id, $tab ='baseinfo' )
|
|
{
|
|
if(!commonModel::hasPriv('space', 'browse')) $this->loadModel('common')->deny('space', 'browse', false);
|
|
$this->loadModel('system');
|
|
$this->app->loadLang('system');
|
|
|
|
$instance = $this->instance->getByID($id);
|
|
if(empty($instance)) return print(js::alert($this->lang->instance->instanceNotExists) . js::locate($this->createLink('space', 'browse')));
|
|
|
|
$instance->latestVersion = $this->store->appLatestVersion($instance->appID, $instance->version);
|
|
|
|
$instance = $this->instance->freshStatus($instance);
|
|
|
|
$instanceMetric = $this->cne->instancesMetrics(array($instance));
|
|
$instanceMetric = $instanceMetric[$instance->id];
|
|
$this->lang->switcherMenu = $this->instance->getSwitcher($instance);
|
|
|
|
$backupList = array();
|
|
$latestBackup = new stdclass;
|
|
if($tab == 'backup') $backupList = $this->instance->backupList($instance);
|
|
if(count($backupList)) $latestBackup = reset($backupList);
|
|
|
|
$hasRestoreLog = false;
|
|
foreach($backupList as $backup)
|
|
{
|
|
$backup->latest_restore_time = 0;
|
|
$backup->latest_restore_status = '';
|
|
foreach($backup->restores as $restore)
|
|
{
|
|
$hasRestoreLog = true;
|
|
if($restore->create_time > $backup->latest_restore_time)
|
|
{
|
|
$backup->latest_restore_time = $restore->create_time;
|
|
$backup->latest_restore_status = $restore->status;
|
|
}
|
|
}
|
|
}
|
|
|
|
$dbList = $this->cne->appDBList($instance);
|
|
$currentResource = $this->cne->getAppConfig($instance);
|
|
$customItems = $this->cne->getCustomItems($instance);
|
|
|
|
if($instance->status == 'running') $this->instanceZen->saveAuthInfo($instance);
|
|
if(in_array(strtolower($instance->appName), $this->config->instance->devopsApps))
|
|
{
|
|
$url = strstr(getWebRoot(true), ':', true) . '://' . $instance->domain;
|
|
$pipeline = $this->loadModel('pipeline')->getByUrl($url);
|
|
$instance->externalID = $pipeline->id;
|
|
|
|
}
|
|
|
|
$this->view->title = $instance->appName;
|
|
$this->view->instance = $instance;
|
|
$this->view->cloudApp = $this->loadModel('store')->getAppInfoByChart($instance->chart, $instance->channel, false);
|
|
$this->view->seniorAppList = $tab == 'baseinfo' ? $this->instance->seniorAppList($instance, $instance->channel) : array();
|
|
$this->view->actions = $this->loadModel('action')->getList('instance', $id);
|
|
$this->view->defaultAccount = $this->cne->getDefaultAccount($instance);
|
|
$this->view->instanceMetric = $instanceMetric;
|
|
$this->view->currentResource = $currentResource;
|
|
$this->view->customItems = $customItems;
|
|
$this->view->backupList = $backupList;
|
|
$this->view->hasRestoreLog = $hasRestoreLog;
|
|
$this->view->latestBackup = $latestBackup;
|
|
$this->view->dbList = $dbList;
|
|
$this->view->domain = $this->cne->getDomain($instance);
|
|
$this->view->tab = $tab;
|
|
}
|
|
|
|
/**
|
|
* Display or save auto backup settings.
|
|
*
|
|
* @param int $instanceID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function backupSettings($instanceID)
|
|
{
|
|
$instance = $this->instance->getByID($instanceID);
|
|
|
|
if($_POST)
|
|
{
|
|
$this->instance->saveAutoBackupSettings($instance);
|
|
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
|
|
|
$backupSettings = $this->instance->getAutoBackupSettings($instanceID);
|
|
|
|
$startTime = strtotime($backupSettings->backupTime);
|
|
if($startTime < time()) $startTime = strtotime("+1 day $backupSettings->backupTime");
|
|
|
|
if($backupSettings->autoBackup)
|
|
{
|
|
$startBackupMessage = sprintf($this->lang->instance->backup->firstStartTime, $instance->name, date('Y-m-d H:i:s', $startTime));
|
|
return $this->send(array('result' => 'success', 'message' => $startBackupMessage));
|
|
}
|
|
|
|
return $this->send(array('result' => 'success', 'message' => $this->lang->instance->backup->disableAutoBackup));
|
|
}
|
|
|
|
$backupSettings = $this->instance->getAutoBackupSettings($instanceID);
|
|
|
|
$this->view->title = $this->lang->instance->backup->autoBackup;
|
|
$this->view->instance = $instance;
|
|
$this->view->backupSettings = $backupSettings;
|
|
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* Display or save auto restore settings.
|
|
*
|
|
* @param int $instanceID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function restoreSettings($instanceID)
|
|
{
|
|
$instance = $this->instance->getByID($instanceID);
|
|
|
|
if($_POST)
|
|
{
|
|
$this->instance->saveAutoRestoreSettings($instance);
|
|
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
|
|
|
$restoreSettings = $this->instance->getAutoRestoreSettings($instanceID);
|
|
|
|
$startTime = strtotime($restoreSettings->restoreTime);
|
|
if($startTime < time()) $startTime = strtotime("+1 day $restoreSettings->restoreTime");
|
|
|
|
if($restoreSettings->autoRestore)
|
|
{
|
|
$startRestoreMessage = sprintf($this->lang->instance->restore->firstStartTime, $instance->name, date('Y-m-d H:i:s', $startTime));
|
|
return $this->send(array('result' => 'success', 'message' => $startRestoreMessage));
|
|
}
|
|
|
|
return $this->send(array('result' => 'success', 'message' => $this->lang->instance->restore->disableAutoRestore));
|
|
}
|
|
|
|
$this->view->title = $this->lang->instance->restore->autoRestore;
|
|
$this->view->instance = $instance;
|
|
$this->view->restoreSettings = $this->instance->getAutoRestoreSettings($instanceID);
|
|
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* Cron task of auto backup.
|
|
*
|
|
* @param string $key
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function autoBackup($key)
|
|
{
|
|
if($this->config->instance->enableAutoRestore) return; // Only one of auto backup and auto restore can be enabled.
|
|
|
|
$this->app->saveLog('Run auto backup at: ' . date('Y-md-d H:i:s'));
|
|
|
|
if($key != helper::readKey()) return;
|
|
|
|
$this->instance->autoBackup();
|
|
}
|
|
|
|
/**
|
|
* Cron task of auto restore.
|
|
*
|
|
* @param string $key
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function autoRestore($key)
|
|
{
|
|
if(!$this->config->instance->enableAutoRestore) return; // Only one of auto backup and auto restore can be enabled.
|
|
|
|
$this->app->saveLog('Run auto restore at: ' . date('Y-md-d H:i:s'));
|
|
|
|
if($key != helper::readKey()) return;
|
|
|
|
$this->instance->autoRestore();
|
|
}
|
|
|
|
/**
|
|
* Edit instance app name.
|
|
*
|
|
* @param int $id
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function setting($id)
|
|
{
|
|
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
|
|
$currentResource = new stdclass;
|
|
$instance = $this->instance->getByID($id);
|
|
$currentResource = $this->cne->getAppConfig($instance);
|
|
if(!empty($_POST))
|
|
{
|
|
$newInstance = fixer::input('post')->trim('name')->get();
|
|
$memoryKb = $newInstance->memory_kb;
|
|
unset($newInstance->memory_kb);
|
|
|
|
if(intval($currentResource->max->memory / 1024) != $memoryKb)
|
|
{
|
|
/* Check free memory size is enough or not. */
|
|
$clusterResource = $this->cne->cneMetrics();
|
|
$freeMemory = intval($clusterResource->metrics->memory->allocatable * 0.9); // Remain 10% memory for system.
|
|
if($memoryKb * 1024 > $freeMemory) $this->send(array('result' => 'fail', 'message' => $this->lang->instance->errors->notEnoughResource));
|
|
|
|
/* Request CNE to adjust memory size. */
|
|
if(!$this->instance->updateMemorySize($instance, $memoryKb * 1024))
|
|
{
|
|
$this->send(array('result' => 'fail', 'message' => dao::getError()));
|
|
}
|
|
}
|
|
|
|
$this->instance->updateByID($id, $newInstance);
|
|
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
|
if($newInstance->name != $instance->name)
|
|
{
|
|
$this->action->create('instance', $instance->id, 'editname', '', json_encode(array('result' => array('result' => 'success'), 'data' => array('oldName' => $instance->name, 'newName' => $newInstance->name))));
|
|
}
|
|
return $this->send(array('result' => 'success', 'load' => true, 'closeModal' => true));
|
|
}
|
|
|
|
$this->view->currentResource = $currentResource;
|
|
$this->view->instance = $instance;
|
|
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* Upgrade to senior serial.
|
|
*
|
|
* @param int $instanceID
|
|
* @param int $seniorAppID
|
|
* @param string $confirm
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function toSenior($instanceID, $seniorAppID, $confirm = 'no')
|
|
{
|
|
$instance = $this->instance->getByID($instanceID);
|
|
$cloudApp = $this->store->getAppInfo($seniorAppID, $instance->channel, false);
|
|
if(empty($cloudApp)) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->errors->noAppInfo));
|
|
|
|
if($confirm == 'yes')
|
|
{
|
|
$success = $this->instance->upgradeToSenior($instance, $cloudApp);
|
|
if($success) $this->send(array('result' => 'success', 'message' => '', 'locate' => $this->inLink('view', "id=$instance->id")));
|
|
|
|
$this->send(array('result' => 'fail', 'message' => dao::getError()));
|
|
}
|
|
|
|
$this->view->title = $this->lang->instance->upgradeToSenior;
|
|
$this->view->instance = $instance;
|
|
$this->view->cloudApp = $cloudApp;
|
|
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* Upgrade instnace
|
|
*
|
|
* @param int $id
|
|
* @access public
|
|
* @return mixed
|
|
*/
|
|
public function upgrade($id)
|
|
{
|
|
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
|
|
$instance = $this->instance->getByID($id);
|
|
$instance->latestVersion = $this->store->appLatestVersion($instance->appID, $instance->version);
|
|
|
|
if($_POST)
|
|
{
|
|
if(empty($instance->latestVersion)) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->noHigherVersion, 'closeModal' => true));
|
|
|
|
$postData = fixer::input('post')->get();
|
|
|
|
if($postData->confirm == 'yes') $success = $this->instance->upgrade($instance, $instance->latestVersion->version, $instance->latestVersion->app_version);
|
|
|
|
$logExtra = array('result' => 'success', 'data' => array('oldVersion' => $instance->appVersion, 'newVersion' => $instance->latestVersion->app_version));
|
|
if(!$success)
|
|
{
|
|
$logExtra['result'] = 'fail';
|
|
$this->action->create('instance', $instance->id, 'upgrade', '', json_encode($logExtra));
|
|
return $this->send(array('result' => 'fail', 'message' => !empty($logExtra['message']) ? $logExtra['message'] : $this->lang->instance->notices['upgradeFail'], 'closeModal' => true));
|
|
}
|
|
|
|
$this->action->create('instance', $instance->id, 'upgrade', '', json_encode($logExtra));
|
|
return $this->send(array('result' => 'success', 'message' => $this->lang->instance->notices['upgradeSuccess'], 'load' => $this->createLink('instance', 'view', "id=$id"), 'closeModal' => true));
|
|
}
|
|
|
|
$this->view->title = $this->lang->instance->upgrade . $instance->name;
|
|
$this->view->instance = $instance;
|
|
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* 访问一个应用。
|
|
* Visit a app.
|
|
*
|
|
* @param int $id
|
|
* @param int $externalID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function visit(int $id, int $externalID = 0): void
|
|
{
|
|
if(!commonModel::hasPriv('space', 'browse')) $this->loadModel('common')->deny('space', 'browse', false);
|
|
if(!$externalID)
|
|
{
|
|
$instance = $this->instance->getByID($id);
|
|
$url = $this->instance->url($instance);
|
|
}
|
|
else
|
|
{
|
|
$pipeline = $this->loadModel('pipeline')->getByID($externalID);
|
|
$url = $pipeline->url;
|
|
}
|
|
|
|
$this->locate($url);
|
|
}
|
|
|
|
/**
|
|
* 创建手工配置外部应用。
|
|
* Create a external app.
|
|
*
|
|
* @param string $type
|
|
* @access public
|
|
* @return viod
|
|
*/
|
|
public function createExternalApp(string $type)
|
|
{
|
|
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
|
|
|
|
$this->app->loadModuleConfig('sonarqube');
|
|
$this->app->loadLang('pipeline');
|
|
|
|
$externalApp = form::data($this->config->sonarqube->form->create)
|
|
->add('type', $type)
|
|
->add('private',md5(rand(10,113450)))
|
|
->add('createdBy', $this->app->user->account)
|
|
->add('createdDate', helper::now())
|
|
->trim('url,account,password')
|
|
->skipSpecial('url,token,account,password')
|
|
->remove('token,appType')
|
|
->get();
|
|
$externalApp->url = rtrim($externalApp->url, '/');
|
|
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))));
|
|
|
|
$appID = $this->loadModel('pipeline')->create($externalApp);
|
|
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
|
|
|
$this->loadModel('action')->create($type, $appID, 'created');
|
|
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('space', 'browse')));
|
|
}
|
|
|
|
/**
|
|
* 编辑手工配置外部应用。
|
|
* Edit a external app.
|
|
*
|
|
* @param int $externalID
|
|
* @access public
|
|
* @return viod
|
|
*/
|
|
public function editExternalApp(int $externalID)
|
|
{
|
|
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
|
|
|
|
$oldApp = $this->loadModel('pipeline')->getByID($externalID);
|
|
|
|
if($_POST)
|
|
{
|
|
$this->pipeline->update($externalID);
|
|
$app = $this->pipeline->getByID($externalID);
|
|
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
|
|
|
$this->loadModel('action');
|
|
$actionID = $this->action->create($app->type, $externalID, 'edited');
|
|
$changes = common::createChanges($oldApp, $app);
|
|
$this->action->logHistory($actionID, $changes);
|
|
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true, 'closeModal' => true));
|
|
}
|
|
|
|
$this->app->loadLang('space');
|
|
$this->app->loadLang('sonarqube');
|
|
|
|
$this->view->app = $oldApp;
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* 删除一个外部应用。
|
|
* Delete a external app.
|
|
*
|
|
* @param int $externalID
|
|
* @access public
|
|
* @return viod
|
|
*/
|
|
public function deleteExternalApp(int $externalID)
|
|
{
|
|
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
|
|
|
|
$oldApp = $this->loadModel('pipeline')->getByID($externalID);
|
|
$actionID = $this->pipeline->delete($externalID, $oldApp->type);
|
|
if(!$actionID)
|
|
{
|
|
$response['result'] = 'fail';
|
|
$response['callback'] = sprintf('zui.Modal.alert("%s");', $this->lang->pipeline->delError);
|
|
return $this->send($response);
|
|
}
|
|
|
|
$app = $this->pipeline->getByID($externalID);
|
|
$changes = common::createChanges($oldApp, $app);
|
|
$this->loadModel('action')->logHistory($actionID, $changes);
|
|
|
|
$response['load'] = true;
|
|
$response['message'] = zget($this->lang->instance->notices, 'uninstallSuccess');
|
|
$response['result'] = 'success';
|
|
|
|
return $this->send($response);
|
|
}
|
|
|
|
/**
|
|
* (Not used at present.) Install app by custom settings.
|
|
*
|
|
* @param int $id
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function customInstall($id)
|
|
{
|
|
// Disable custom installation in version 1.0.
|
|
$storeUrl = $this->createLink('store', 'appview', "id=$id");
|
|
return js::execute("window.parent.location.href='{$storeUrl}';");
|
|
}
|
|
|
|
/**
|
|
* Install app.
|
|
*
|
|
* @param int $appID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function install($appID)
|
|
{
|
|
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
|
|
$cloudApp = $this->store->getAppInfo($appID);
|
|
if(empty($cloudApp)) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->errors->noAppInfo));
|
|
|
|
if(empty($this->config->demoAccounts))
|
|
{
|
|
$clusterResource = $this->cne->cneMetrics();
|
|
$freeMemory = intval($clusterResource->metrics->memory->allocatable * 0.9); // Remain 10% memory for system.
|
|
if($cloudApp->memory > $freeMemory)
|
|
{
|
|
$cloudApp = $cloudApp;
|
|
$gapMemory = helper::formatKB(intval(($cloudApp->memory - $freeMemory)));
|
|
$requiredMemory = helper::formatKB(intval($cloudApp->memory));
|
|
$freeMemory = helper::formatKB(intval($freeMemory));
|
|
|
|
return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->instance->errors->notEnoughMemory, $cloudApp->alias, $requiredMemory, $freeMemory, $gapMemory)));
|
|
}
|
|
}
|
|
|
|
$versionList = $this->store->appVersionList($cloudApp->id);
|
|
$mysqlList = $this->cne->sharedDBList('mysql');
|
|
$pgList = $this->cne->sharedDBList('postgresql');
|
|
if(!empty($_POST))
|
|
{
|
|
$customData = fixer::input('post')
|
|
->trim('customName')->setDefault('customName', '')
|
|
->trim('customDomain')->setDefault('customDomain', '')
|
|
->trim('version')->setDefault('version', '')
|
|
->trim('dbType')->setDefault('dbType', 'unsharedDB')
|
|
->trim('dbService')
|
|
->setDefault('app_version', '')
|
|
->get();
|
|
if($customData->version && isset($versionList[$customData->version])) $customData->app_version = $versionList[$customData->version]->app_version;
|
|
|
|
if(isset($this->config->instance->keepDomainList[$customData->customDomain]) || $this->instance->domainExists($customData->customDomain)) return $this->send(array('result' => 'fail', 'message' => $customData->customDomain . $this->lang->instance->errors->domainExists));
|
|
|
|
if(!$customData->customName)
|
|
{
|
|
dao::$errors['customName'] = sprintf($this->lang->error->notempty, $this->lang->instance->name);
|
|
return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
|
}
|
|
if(!$this->instance->checkAppNameUnique($customData->customName)) return $this->send(array('result' => false, 'message' => array('customName' => sprintf($this->lang->error->repeat, $this->lang->instance->name, $customData->customName))));
|
|
|
|
if(!validater::checkLength($customData->customDomain, 20, 2)) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->errors->domainLength));
|
|
if(!validater::checkREG($customData->customDomain, '/^[a-z\d]+$/')) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->errors->wrongDomainCharacter));
|
|
|
|
/* If select the version, replace the latest version of App by selected version. */
|
|
if($customData->version)
|
|
{
|
|
$cloudApp->version = $customData->version;
|
|
$cloudApp->app_version = $customData->app_version;
|
|
}
|
|
|
|
$sharedDB = new stdclass;
|
|
if(isset($cloudApp->dependencies->mysql) && $customData->dbType == 'sharedDB')
|
|
{
|
|
$sharedDB = zget($mysqlList, $customData->dbService);
|
|
}
|
|
elseif(isset($cloudApp->dependencies->postgresql) && $customData->dbType == 'sharedDB')
|
|
{
|
|
$sharedDB = zget($pgList, $customData->dbService);
|
|
}
|
|
$instance = $this->instance->install($cloudApp, $sharedDB, $customData);
|
|
if(!$instance) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->notices['installFail']));
|
|
|
|
unset($_GET['onlybody']);
|
|
return $this->send(array('result' => 'success', 'message' => $this->lang->instance->notices['installSuccess'], 'load' => $this->createLink('instance', 'view', "id=$instance->id"), 'closeModal' => true));
|
|
}
|
|
|
|
$this->lang->switcherMenu = $this->instance->getInstallSwitcher($cloudApp);
|
|
|
|
$this->view->position[] = $this->view->title;
|
|
|
|
$this->view->title = $this->lang->instance->install . $cloudApp->alias;
|
|
$this->view->cloudApp = $cloudApp;
|
|
|
|
$this->view->versionList = array();
|
|
foreach($versionList as $version) $this->view->versionList[$version->version] = $version->app_version . " ({$version->version})";
|
|
|
|
$this->view->thirdDomain = $this->instance->randThirdDomain();
|
|
$this->view->mysqlList = $this->instance->dbListToOptions($mysqlList);
|
|
$this->view->pgList = $this->instance->dbListToOptions($pgList);
|
|
|
|
$this->display();
|
|
}
|
|
|
|
/**
|
|
* Uninstall app instance.
|
|
*
|
|
* @param int $instanceID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function ajaxUninstall($instanceID, $type = '')
|
|
{
|
|
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
|
|
if($type !== 'store')
|
|
{
|
|
$instance = $this->loadModel('pipeline')->getByID($instanceID);
|
|
if(!$instance) return $this->send(array('result' => 'success', 'message' => $this->lang->instance->notices['success'], 'load' => $this->createLink('space', 'browse')));
|
|
|
|
if($instance->type == 'nexus') return $this->deleteExternalApp($instance->id);
|
|
return $this->fetch($instance->type, 'delete', array('id' => $instance->id));
|
|
}
|
|
$instance = $this->instance->getByID($instanceID);
|
|
if(!$instance) return $this->send(array('result' => 'success', 'message' => $this->lang->instance->notices['success'], 'load' => $this->createLink('space', 'browse')));
|
|
|
|
$externalApp = $this->loadModel('space')->getExternalAppByApp($instance);
|
|
if($externalApp)
|
|
{
|
|
$actionID = $this->loadModel('pipeline')->delete($externalApp->id, strtolower($instance->appName));
|
|
if(!$actionID) return $this->send(array('result' => 'fail', 'message' => $this->lang->pipeline->delError));
|
|
}
|
|
|
|
$success = $this->instance->uninstall($instance);
|
|
$this->action->create('instance', $instance->id, 'uninstall', '', json_encode(array('result' => $success, 'app' => array('alias' => $instance->appName, 'app_version' => $instance->version))));
|
|
if($success) return $this->send(array('result' => 'success', 'message' => zget($this->lang->instance->notices, 'uninstallSuccess'), 'load' => $this->createLink('space', 'browse')));
|
|
|
|
return $this->send(array('result' => 'fail', 'message' => zget($this->lang->instance->notices, 'uninstallFail')));
|
|
}
|
|
|
|
/**
|
|
* Start app instance.
|
|
*
|
|
* @param int $instanceID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function ajaxStart($instanceID)
|
|
{
|
|
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
|
|
$instance = $this->instance->getByID($instanceID);
|
|
if(!$instance) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->instanceNotExists));
|
|
|
|
$result = $this->instance->start($instance);
|
|
$this->action->create('instance', $instance->id, 'start', '', json_encode(array('result' => $result, 'app' => array('alias' => $instance->appName, 'app_version' => $instance->version))));
|
|
|
|
if($result->code == 200) return $this->send(array('result' => 'success', 'load' => true, 'message' => zget($this->lang->instance->notices, 'startSuccess')));
|
|
|
|
return $this->send(array('result' => 'fail', 'message' => !empty($result->message) ? $result->message : zget($this->lang->instance->notices, 'startFail')));
|
|
}
|
|
|
|
/**
|
|
* Stop app instance.
|
|
*
|
|
* @param int $instanceID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function ajaxStop($instanceID)
|
|
{
|
|
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
|
|
$instance = $this->instance->getByID($instanceID);
|
|
if(!$instance) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->instanceNotExists));
|
|
|
|
$result = $this->instance->stop($instance);
|
|
$this->action->create('instance', $instance->id, 'stop', '', json_encode(array('result' => $result, 'app' => array('alias' => $instance->appName, 'app_version' => $instance->version))));
|
|
if($result->code == 200) return $this->send(array('result' => 'success', 'load' => true, 'message' => zget($this->lang->instance->notices, 'stopSuccess')));
|
|
|
|
return $this->send(array('result' => 'fail', 'message' => !empty($result->message) ? $result->message : zget($this->lang->instance->notices, 'stopFail')));
|
|
}
|
|
|
|
/**
|
|
* Query status of app instance.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function ajaxStatus()
|
|
{
|
|
if(!commonModel::hasPriv('space', 'browse')) $this->loadModel('common')->deny('space', 'browse', false);
|
|
$postData = fixer::input('post')->setDefault('idList', array())->get();
|
|
|
|
$instances = $this->instance->getByIdList($postData->idList);
|
|
$statusList = $this->instance->batchFresh($instances);
|
|
|
|
return $this->send(array('result' => 'success', 'data' => $statusList));
|
|
}
|
|
|
|
/**
|
|
* Backup instnacd by ajax.
|
|
*
|
|
* @param int $instanceID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function ajaxBackup($instanceID)
|
|
{
|
|
$instance = $this->instance->getByID($instanceID);
|
|
$success = $this->instance->backup($instance, $this->app->user);
|
|
if(!$success)
|
|
{
|
|
$this->action->create('instance', $instance->id, 'backup', '', json_encode(array('result' => array('result' => 'fail'))));
|
|
return $this->send(array('result' => 'fail', 'message' => zget($this->lang->instance->notices, 'backupFail')));
|
|
}
|
|
|
|
$this->action->create('instance', $instance->id, 'backup', '', json_encode(array('result' => array('result' => 'success'))));
|
|
return $this->send(array('result' => 'success', 'message' => zget($this->lang->instance->notices, 'backupSuccess')));
|
|
}
|
|
|
|
/**
|
|
* Restore instance by ajax
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function ajaxRestore()
|
|
{
|
|
$postData = fixer::input('post')
|
|
->trim('instanceID')
|
|
->trim('backupName')->get();
|
|
|
|
if(empty($postData->instanceID) || empty($postData->backupName)) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->wrongRequestData));
|
|
|
|
$instance = $this->instance->getByID($postData->instanceID);
|
|
if(empty($instance))return print(js::alert($this->lang->instance->instanceNotExists) . js::locate($this->createLink('space', 'browse')));
|
|
|
|
$success = $this->instance->restore($instance, $this->app->user, $postData->backupName);
|
|
if(!$success)
|
|
{
|
|
$this->action->create('instance', $instance->id, 'restore', '', json_encode(array('result' => array('result' => 'fail'))));
|
|
return $this->send(array('result' => 'fail', 'message' => zget($this->lang->instance->notices, 'restoreFail')));
|
|
}
|
|
|
|
$this->action->create('instance', $instance->id, 'restore', '', json_encode(array('result' => array('result' => 'success'))));
|
|
return $this->send(array('result' => 'success', 'message' => zget($this->lang->instance->notices, 'restoreSuccess')));
|
|
}
|
|
|
|
/**
|
|
* Delete backup by ajax.
|
|
*
|
|
* @param int $backupID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function ajaxDeleteBackup($backupID)
|
|
{
|
|
$success = $this->instance->deleteBackup($backupID, $this->app->user);
|
|
if(!$success) return $this->send(array('result' => 'fail', 'message' => zget($this->lang->instance->notices, 'deleteFail')));
|
|
|
|
return $this->send(array('result' => 'success', 'message' => zget($this->lang->instance->notices, 'deleteSuccess')));
|
|
}
|
|
|
|
/**
|
|
* Generate database auth parameters and jump to login page.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function ajaxDBAuthUrl()
|
|
{
|
|
if(!commonModel::hasPriv('space', 'browse')) $this->loadModel('common')->deny('space', 'browse', false);
|
|
$post = fixer::input('post')
|
|
->setDefault('namespace', 'default')
|
|
->setDefault('instanceID', 0)
|
|
->setDefault('dbType', '')
|
|
->get();
|
|
if(empty($post->dbName)) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->errors->dbNameIsEmpty));
|
|
|
|
$instance = $this->instance->getByID($post->instanceID);
|
|
if(empty($instance)) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->instanceNotExists));
|
|
|
|
$detail = $this->loadModel('cne')->appDBDetail($instance, $post->dbName);
|
|
if(empty($detail)) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->errors->notFoundDB));
|
|
|
|
$dbAuth = array();
|
|
$dbAuth['driver'] = zget($this->config->instance->adminer->dbTypes, $post->dbType, '');
|
|
$dbAuth['server'] = $detail->host . ':' . $detail->port;
|
|
$dbAuth['username'] = $detail->username;
|
|
$dbAuth['db'] = $detail->database;
|
|
$dbAuth['password'] = $detail->password;
|
|
|
|
$url = '/adminer?' . http_build_query($dbAuth);
|
|
$this->send(array('result' => 'success', 'message' => '', 'data' => array('url' => $url)));
|
|
}
|
|
|
|
/**
|
|
* Adjust instance memory size by ajax.
|
|
*
|
|
* @param int $instanceID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function ajaxAdjustMemory($instanceID)
|
|
{
|
|
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
|
|
$postData = fixer::input('post')->get();
|
|
|
|
/* Check free memory size is enough or not. */
|
|
$clusterResource = $this->cne->cneMetrics();
|
|
$freeMemory = intval($clusterResource->metrics->memory->allocatable * 0.9); // Remain 10% memory for system.
|
|
if($postData->memory_kb * 1024 > $freeMemory) $this->send(array('result' => 'fail', 'message' => $this->lang->instance->errors->notEnoughResource));
|
|
|
|
/* Request CNE to adjust memory size. */
|
|
$instance = $this->instance->getByID($instanceID);
|
|
if(!$this->instance->updateMemorySize($instance, $postData->memory_kb * 1024))
|
|
{
|
|
$this->send(array('result' => 'fail', 'message' => dao::getError()));
|
|
}
|
|
|
|
$this->send(array('result' => 'success', 'message' => ''));
|
|
}
|
|
|
|
/**
|
|
* Switch LDAP between enable and disable by ajax.
|
|
*
|
|
* @param int $instanceID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function ajaxSwitchLDAP($instanceID)
|
|
{
|
|
$instance = $this->instance->getByID($instanceID);
|
|
$postData = fixer::input('post')->get();
|
|
|
|
if($this->instance->switchLDAP($instance, $postData->enableLDAP == 'true'))
|
|
{
|
|
$this->send(array('result' => 'success', 'message' => ''));
|
|
}
|
|
|
|
$this->send(array('result' => 'fail', 'message' => $this->lang->instance->errors->switchLDAPFailed));
|
|
}
|
|
|
|
/**
|
|
* Switch SMTP between enable and disable by ajax.
|
|
*
|
|
* @param int $instanceID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function ajaxSwitchSMTP($instanceID)
|
|
{
|
|
$instance = $this->instance->getByID($instanceID);
|
|
$postData = fixer::input('post')->get();
|
|
|
|
if($this->instance->switchSMTP($instance, $postData->enableSMTP == 'true'))
|
|
{
|
|
$this->send(array('result' => 'success', 'message' => ''));
|
|
}
|
|
|
|
$this->send(array('result' => 'fail', 'message' => $this->lang->instance->errors->switchSMTPFailed));
|
|
}
|
|
|
|
/**
|
|
* Update custom settings by ajax. For example: env variables.
|
|
*
|
|
* @param int $instanceID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function ajaxUpdateCustom($instanceID)
|
|
{
|
|
$instance = $this->instance->getByID($instanceID);
|
|
if(!$instance) $this->send(array('result' => 'fail', 'message' => $this->lang->instance->instanceNotExists));
|
|
|
|
$postData = fixer::input('post')->get();
|
|
|
|
$settings = new stdclass;
|
|
$settings->force_restart = true;
|
|
$settings->settings_map = new stdclass;
|
|
$settings->settings_map->custom = $postData;
|
|
|
|
if($this->cne->updateConfig($instance, $settings))
|
|
{
|
|
$this->action->create('instance', $instanceID, 'updatecustom', '', json_encode($settings));
|
|
$this->send(array('result' => 'success', 'message' => ''));
|
|
}
|
|
|
|
$this->send(array('result' => 'fail', 'message' => $this->lang->instance->errors->setEnvFailed));
|
|
}
|
|
|
|
/**
|
|
* Delete expired demo instance by cron.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function deleteExpiredDemoInstance()
|
|
{
|
|
if(empty($this->config->demoAccounts)) return $this->send(array('result' => 'fail', 'message' => 'This api is only for demo enviroment.'));
|
|
|
|
$this->instance->deleteExpiredDemoInstance();
|
|
|
|
$this->send(array('result' => 'success', 'message' => ''));
|
|
}
|
|
|
|
/**
|
|
* Get instance info for q tool in console.
|
|
*
|
|
* @param int $id
|
|
* @access public
|
|
* @return mixed
|
|
*/
|
|
public function apiDetail($id)
|
|
{
|
|
if(!$this->checkCneToken())
|
|
{
|
|
helper::setStatus(401);
|
|
return print(json_encode(array('code' => 401, 'message' => 'Invalid token.')));
|
|
}
|
|
|
|
if(empty($id)) return print(json_encode(array('code' => 401, 'message' => 'Invalid id.')));
|
|
|
|
$instance = $this->instance->getByID($id);
|
|
if(empty($instance)) return print(json_encode(array('code' => 404, 'message' => 'Not found.', 'data' => array())));
|
|
|
|
$instance->space = $instance->spaceData && isset($instance->spaceData->k8space) ? $instance->spaceData->k8space : '';
|
|
unset($instance->desc);
|
|
unset($instance->spaceData);
|
|
|
|
return print(json_encode(array('code' => 200, 'message' => 'success', 'data' => $instance)));
|
|
}
|
|
|
|
/**
|
|
* Get instances list by account through api for q tool.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function apiBrowse()
|
|
{
|
|
if(!$this->checkCneToken())
|
|
{
|
|
helper::setStatus(401);
|
|
return print(json_encode(array('code' => 401, 'message' => 'Invalid token.')));
|
|
}
|
|
|
|
$requestBody = json_decode(file_get_contents("php://input"));
|
|
$account = zget($requestBody, 'account', '');
|
|
if(empty($account)) return print(json_encode(array('code' => 700, 'message' => 'Account is required.', 'data' => new stdclass)));
|
|
|
|
$recPerPage = zget($requestBody, 'perPage', 20);
|
|
$pageID = zget($requestBody, 'page', 1);
|
|
|
|
$this->app->loadClass('pager', true);
|
|
$pager = pager::init(0, $recPerPage, $pageID);
|
|
|
|
$instanceList = $this->instance->getByAccount($account, $pager);
|
|
|
|
$result = new stdclass;
|
|
$result->list = $instanceList;
|
|
$result->page = $pageID;
|
|
$result->perPage = $recPerPage;
|
|
$result->pageTotal = $pager->pageTotal;
|
|
$result->total = $pager->recTotal;
|
|
|
|
return print(json_encode(array('code' => 200, 'message' => 'success', 'data' => $result)));
|
|
}
|
|
|
|
/**
|
|
* Install app by api for q tool.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function apiInstall()
|
|
{
|
|
if(!$this->checkCneToken())
|
|
{
|
|
helper::setStatus(401);
|
|
return print(json_encode(array('code' => 401, 'message' => 'Invalid token.')));
|
|
}
|
|
|
|
$requestBody = json_decode(file_get_contents("php://input"));
|
|
$chart = zget($requestBody , 'chart', '');
|
|
if(empty($chart)) return print(json_encode(array('code' => 701, 'message' => 'Param chart is required.')));
|
|
|
|
$user = null;
|
|
$account = zget($requestBody, 'account', '');
|
|
if($account) $user = $this->loadModel('user')->getById($account);
|
|
if(empty($user)) $user = $this->loadModel('company')->getAdmin();
|
|
if(empty($user)) return print(json_encode(array('code' => 703, 'message' => 'No user.')));
|
|
|
|
$this->app->user = $user;
|
|
|
|
$name = zget($requestBody , 'name', '');
|
|
$channel = zget($requestBody , 'channel', 'stable');
|
|
$k8name = zget($requestBody , 'k8name', '');
|
|
if($k8name && $this->instance->k8nameExists($k8name)) return print(json_encode(array('code' => 706, 'message' => $k8name . ' has been used, please change it and try again.')));
|
|
|
|
$thirdDomain = zget($requestBody , 'domain', '');
|
|
if($this->instance->domainExists($thirdDomain)) return print(json_encode(array('code' => 705, 'message' => $thirdDomain . ' has been used, please change it and try again.')));
|
|
|
|
$cloudApp = $this->store->getAppInfoByChart($chart, $channel, false);
|
|
if(empty($cloudApp)) return print(json_encode(array('code' => 702, 'message' => 'App not found.')));
|
|
|
|
$result = $this->instance->apiInstall($cloudApp, $thirdDomain, $name, $k8name, $channel);
|
|
|
|
if($result) return print(json_encode(array('code' => 200, 'message' => 'success', 'data' => new stdclass)));
|
|
|
|
return print(json_encode(array('code' => 704, 'message' => 'Fail to install app.', 'data' => new stdclass)));
|
|
}
|
|
|
|
/**
|
|
* Check CNE token.
|
|
*
|
|
* @access private
|
|
* @return bool
|
|
*/
|
|
private function checkCneToken()
|
|
{
|
|
$token = zget($_SERVER, 'HTTP_TOKEN');
|
|
return $token == $this->config->CNE->api->token;
|
|
}
|
|
}
|