diff --git a/module/zanode/control.php b/module/zanode/control.php
index e7cae7beef..b1b5a81d91 100644
--- a/module/zanode/control.php
+++ b/module/zanode/control.php
@@ -45,7 +45,7 @@ class zanode extends control
$showFeature = false;
$accounts = !empty($this->config->global->skipAutomation) ? $this->config->global->skipAutomation : '';
- if(strpos(",$accounts,", $this->app->user->account) === false)
+ if(strpos(",$accounts,", $this->app->user->account) === false)
{
$showFeature = true;
$accounts .= ',' . $this->app->user->account;
@@ -164,6 +164,7 @@ class zanode extends control
$this->view->token = !empty($vnc->token) ? $vnc->token:'';
$this->view->title = $this->lang->zanode->view;
$this->view->zanode = $node;
+ $this->view->snapshotList = $this->zanode->getSnapshotList($id);
$this->view->actions = $this->loadModel('action')->getList('zanode', $id);
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->display();
@@ -285,6 +286,37 @@ class zanode extends control
$this->display();
}
+ /**
+ * Create snapshot.
+ *
+ * @param int $zanodeID
+ * @access public
+ * @return void
+ */
+ public function createSnapshot($nodeID = 0)
+ {
+ $task = '';
+ $node = $this->zanode->getNodeByID($nodeID);
+
+ if($_POST)
+ {
+ $this->zanode->createSnapshot($nodeID);
+
+ if(dao::isError())
+ {
+ $response['result'] = 'fail';
+ $response['message'] = dao::getError();
+ return $this->send($response);
+ }
+ return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'reload'));
+ }
+
+ $this->view->task = $task;
+ $this->view->node = $node;
+ $this->view->rate = !empty($task->rate) ? $task->rate : 0;
+ $this->display();
+ }
+
/**
* Desctroy node.
*
@@ -333,6 +365,26 @@ class zanode extends control
$this->display();
}
+ public function browseSnapshot($nodeID, $browseType = 'all', $param = 0, $orderBy = 'id', $recTotal = 0, $recPerPage = 20, $pageID = 1)
+ {
+ $this->app->loadLang('zahost');
+ $this->app->loadClass('pager', $static = true);
+ $pager = pager::init($recTotal, $recPerPage, $pageID);
+
+ $snapshotList = $this->zanode->getSnapshotList($nodeID, $browseType, $param, $orderBy, $pager);
+
+ $this->view->title = $this->lang->zanode->browseSnapshot;
+ $this->view->nodeID = $nodeID;
+ $this->view->snapshotList = $snapshotList;
+ $this->view->users = $this->loadModel('user')->getPairs('noletter');
+ $this->view->pager = $pager;
+ $this->view->param = $param;
+ $this->view->orderBy = $orderBy;
+ $this->view->browseType = $browseType;
+
+ $this->display();
+ }
+
/**
* Ajax get template pairs by api.
*
diff --git a/module/zanode/css/browsesnapshot.css b/module/zanode/css/browsesnapshot.css
new file mode 100644
index 0000000000..5218ddb6ee
--- /dev/null
+++ b/module/zanode/css/browsesnapshot.css
@@ -0,0 +1,6 @@
+#main{min-width: 0!important;padding:0!important;}
+body{background-color: #fff!important;}
+
+.c-createdBy {width: 100px;}
+.c-datetime {width: 130px;}
+.c-status {width: 80px;}
diff --git a/module/zanode/lang/zh-cn.php b/module/zanode/lang/zh-cn.php
index 30bb81be88..f38ede7cf5 100644
--- a/module/zanode/lang/zh-cn.php
+++ b/module/zanode/lang/zh-cn.php
@@ -79,6 +79,14 @@ $lang->zanode->createImageSuccess = '镜像导出成功,您可以使用此镜
$lang->zanode->createImageFail = '镜像导出失败';
$lang->zanode->createImageButton = '去创建';
+$lang->zanode->snapshotName = '快照名称';
+$lang->zanode->browseSnapshot = '快照列表';
+$lang->zanode->createSnapshot = '创建快照';
+$lang->zanode->editSnapshot = '编辑快照';
+$lang->zanode->restoreSnapshot = '还原快照';
+$lang->zanode->deleteSnapshot = '删除快照';
+$lang->zanode->snapshotEmpty = '无快照';
+
$lang->zanode->imageNameEmpty = '名称不能为空';
$lang->zanode->runTimeout = '自动执行失败,请检查宿主机和执行节点状态';
@@ -89,6 +97,7 @@ $lang->zanode->apiError['fail'] = '执行失败,请检查宿主机和执行
$lang->zanode->publicList[0] = '不共享';
$lang->zanode->publicList[1] = '共享';
+$lang->zanode->statusList['creating'] = '创建中';
$lang->zanode->statusList['created'] = '已创建';
$lang->zanode->statusList['launch'] = '运行中';
$lang->zanode->statusList['ready'] = '运行中';
diff --git a/module/zanode/model.php b/module/zanode/model.php
index af034bfdfa..7e054b9022 100644
--- a/module/zanode/model.php
+++ b/module/zanode/model.php
@@ -28,6 +28,10 @@ class zanodemodel extends model
const KVM_EXPORT_PATH = '/api/v1/kvm/exportVm';
const KVM_STATUS_PATH = '/api/v1/task/getStatus';
+ const SNAPSHOT_CREATE_PATH = '/api/v1/snaps/addCreateSnap';
+ const SNAPSHOT_REVERT_PATH = '/api/v1/snaps/addRevertSnap';
+ const SNAPSHOT_REMOVE_PATH = '/api/v1/snaps/removeSnap';
+
/**
* Set lang;
*
@@ -167,6 +171,64 @@ class zanodemodel extends model
return false;
}
+ /**
+ * Create Snapshot by zanode.
+ *
+ * @param int $zanodeID
+ * @access public
+ * @return void
+ */
+ public function createSnapshot($zanodeID = 0)
+ {
+ $data = fixer::input('post')->get();
+
+ if(empty($data->name)) dao::$errors['name'] = $this->lang->zanode->imageNameEmpty;
+ if(dao::isError()) return false;
+
+ $node = $this->getNodeByID($zanodeID);
+
+ $newSnapshot = new stdClass();
+ $newSnapshot->host = $node->id;
+ $newSnapshot->name = $data->name;
+ $newSnapshot->desc = $data->desc;
+ $newSnapshot->status = 'creating';
+ $newSnapshot->osName = $node->osName;
+ $newSnapshot->from = 'snapshot';
+ $newSnapshot->createdBy = $this->app->user->account;
+ $newSnapshot->createdDate = helper::now();
+
+ $this->dao->insert(TABLE_IMAGE)
+ ->data($newSnapshot)
+ ->autoCheck()
+ ->exec();
+
+ if(dao::isError()) return false;
+
+ $newID = $this->dao->lastInsertID();
+
+ /* Prepare create params. */
+ $agnetUrl = 'http://' . $node->ip . ':' . $node->hzap;
+ $param = array(
+ 'name' => $data->name,
+ 'task' => $newID,
+ 'type' => 'createSnap',
+ 'vm' => $node->name
+ );
+
+ $result = json_decode(commonModel::http($agnetUrl . static::SNAPSHOT_CREATE_PATH, json_encode($param,JSON_NUMERIC_CHECK), null, array("Authorization:$node->tokenSN")));
+
+ if(!empty($result) and $result->code == 'success')
+ {
+ $this->loadModel('action')->create('zanodesnapshot', $id, 'created');
+ return $newID;
+ }
+
+ $this->dao->delete()->from(TABLE_IMAGE)->where('id')->eq($newID)->exec();
+ dao::$errors[] = (!empty($result) and !empty($result->msg)) ? $result->msg : $this->app->lang->fail;
+ return false;
+ }
+
+
/**
* Action Node.
*
@@ -212,7 +274,7 @@ class zanodemodel extends model
public function destroy($id)
{
$node = $this->getNodeByID($id);
-
+
if($node)
{
$req = array( 'name' => $node->name );
@@ -520,6 +582,18 @@ class zanodemodel extends model
->fetch();
}
+ public function getSnapshotList($nodeID, $browseType = 'all', $param = 0, $orderBy = 'id', $pager = null)
+ {
+ $snapshotList = $this->dao->select('*')->from(TABLE_IMAGE)
+ ->where('host')->eq($nodeID)
+ ->andWhere('`from`')->eq('snapshot')
+ ->orderBy($orderBy)
+ ->page($pager)
+ ->fetchAll('name');
+
+ return $snapshotList;
+ }
+
/**
* Get Node by id.
*
diff --git a/module/zanode/view/browsesnapshot.html.php b/module/zanode/view/browsesnapshot.html.php
new file mode 100644
index 0000000000..9dd54111ed
--- /dev/null
+++ b/module/zanode/view/browsesnapshot.html.php
@@ -0,0 +1,56 @@
+
+ * @package zahost
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+getModuleRoot() . 'common/view/header.html.php';?>
+
+
+ recTotal}&recPerPage={$pager->recPerPage}";?>
+
+
+
+ zanode->snapshotEmpty;?>
+
+
+
+
+
+
+ | zahost->image->name);?> |
+ zahost->status;?> |
+ zahost->createdBy;?> |
+ zahost->createdDate;?> |
+ actions;?> |
+
+
+
+
+
+ status == 'completed' ? zget($snapshot, 'path', '') : '';?>
+ | name;?> |
+ '>zanode->statusList, $snapshot->status, '');?> |
+ createdBy, '')?> |
+ createdDate;?> |
+
+ createLink('zanode', 'editsnapshot', "snapshotID={$snapshot->id}"), '', 'hiddenwin', "title={$lang->zanode->editSnapshot}");?>
+ createLink('zahost', 'restoreSnapshot', "nodeID={$nodeID}&snapshotID={$snapshot->id}"), '', 'hiddenwin', "title={$lang->zanode->restoreSnapshot}");?>
+ createLink('zahost', 'deleteSnapshot', "snapshotID={$snapshot->id}"), '', 'hiddenwin', "title={$lang->zanode->deleteSnapshot}");?>
+ |
+
+
+
+
+
+
+
+getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/module/zanode/view/createsnapshot.html.php b/module/zanode/view/createsnapshot.html.php
new file mode 100644
index 0000000000..d591de2663
--- /dev/null
+++ b/module/zanode/view/createsnapshot.html.php
@@ -0,0 +1,64 @@
+
+ * @package task
+ * @version
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
+task);?>
+id);?>
+zanode); ?>
+
+
+
+
+
+
+ zanode->createSnapshot;?>
+
+
+
+
zanode->pending;?>
+
+ parent}");
+ $link = str_replace('onlybody=yes', '', $link);
+ $link = trim($link, '?');
+ ?>
+
zanode->createSnapshotSuccess . html::a($link, $lang->zanode->createSnapshotButton, "_parent", "style='color:#2e7fff;'");?>
+
zanode->createSnapshotFail;?>
+
+
+
+
+
+
diff --git a/module/zanode/view/view.html.php b/module/zanode/view/view.html.php
index 2aec77c69a..168fa86a9f 100644
--- a/module/zanode/view/view.html.php
+++ b/module/zanode/view/view.html.php
@@ -147,6 +147,14 @@ $account = strpos($zanode->osName, "windows") ? $config->zanode->defaultWinAccou
zanode->desc; ?>
desc) ? htmlspecialchars_decode($zanode->desc) : $lang->noData; ?>
+
+
+
zanode->browseSnapshot;?>
+
+ createLink('zanode', 'browseSnapshot', "nodeID=$zanode->id", '', true) . "' frameborder='no' allowfullscreen='true' mozallowfullscreen='true' webkitallowfullscreen='true' allowtransparency='true' scrolling='auto' onload='setIframeHeight(this)' style='min-height:300px;'>";?>
+
+
+
printExtendFields($zanode, 'div', "position=left&inForm=0&inCell=1"); ?>
@@ -164,6 +172,9 @@ $account = strpos($zanode->osName, "windows") ? $config->zanode->defaultWinAccou
$rebootAttr = "title='{$lang->zanode->reboot}' target='hiddenwin'";
$rebootAttr .= $zanode->status == 'shutoff' ? ' class="btn disabled"' : "class='btn' target='hiddenwin' onclick='if(confirm(\"{$lang->zanode->confirmReboot}\")==false) return false;'";
+
+ $snapshotAttr = "title='{$lang->zanode->createSnapshot}'";
+ $snapshotAttr .= $zanode->status != 'running' ? ' class="btn disabled"' : ' class="btn iframe"';
common::printLink('zanode', 'getVNC', "id={$zanode->id}", " " . $lang->zanode->getVNC, in_array($zanode->status ,array('running', 'launch', 'wait')) ? '_blank' : '', "title='{$lang->zanode->getVNC}' class='btn desktop " . (in_array($zanode->status ,array('running', 'launch', 'wait')) ? '':'disabled') . "'", '');
if($zanode->status == "suspend")
@@ -185,6 +196,7 @@ $account = strpos($zanode->osName, "windows") ? $config->zanode->defaultWinAccou
}
common::printLink('zanode', 'reboot', "zanodeID={$zanode->id}", " " . $lang->zanode->rebootNode, '', $rebootAttr);
+ common::printLink('zanode', 'createSnapshot', "zanodeID={$zanode->id}", " " . $lang->zanode->createSnapshot, '', $snapshotAttr, true, true);
}
?>