459 lines
12 KiB
JavaScript
459 lines
12 KiB
JavaScript
Tea.context(function () {
|
||
let that = this
|
||
|
||
// 计算总待升级数
|
||
this.totalUpgradeCount = 0
|
||
this.modules.forEach(function (mod) {
|
||
mod.expanded = true
|
||
that.totalUpgradeCount += mod.count
|
||
if (mod.clusters != null) {
|
||
mod.clusters.forEach(function (cluster) {
|
||
cluster.expanded = true
|
||
if (cluster.nodes != null) {
|
||
cluster.nodes.forEach(function (node) {
|
||
node.isUpgrading = false
|
||
node.isChecked = false
|
||
})
|
||
}
|
||
})
|
||
}
|
||
})
|
||
|
||
// 正在升级的节点ID集合(按模块)
|
||
this.upgradingNodeIds = {
|
||
"node": [],
|
||
"dns": [],
|
||
"httpdns": []
|
||
}
|
||
|
||
// 启动状态轮询
|
||
this.$delay(function () {
|
||
this.pollStatus()
|
||
})
|
||
|
||
/**
|
||
* 获取节点详情页URL
|
||
*/
|
||
this.nodeDetailURL = function (moduleCode, clusterId, nodeId) {
|
||
switch (moduleCode) {
|
||
case "node":
|
||
return "/clusters/cluster/node?clusterId=" + clusterId + "&nodeId=" + nodeId
|
||
case "dns":
|
||
return "/ns/clusters/cluster/node?clusterId=" + clusterId + "&nodeId=" + nodeId
|
||
case "httpdns":
|
||
return "/httpdns/clusters/cluster/node?clusterId=" + clusterId + "&nodeId=" + nodeId
|
||
default:
|
||
return "#"
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 判断节点升级是否已完成(成功)
|
||
*/
|
||
this.isNodeUpgradeFinished = function (node) {
|
||
return node.installStatus != null && node.installStatus.isFinished && node.installStatus.isOk
|
||
}
|
||
|
||
/**
|
||
* 全选/取消全选
|
||
*/
|
||
this.toggleCheckAll = function (cluster) {
|
||
if (cluster.nodes == null) return
|
||
let allChecked = that.isAllChecked(cluster)
|
||
cluster.nodes.forEach(function (node) {
|
||
if (!that.isNodeUpgradeFinished(node)) {
|
||
node.isChecked = !allChecked
|
||
}
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 是否全部选中
|
||
*/
|
||
this.isAllChecked = function (cluster) {
|
||
if (cluster.nodes == null || cluster.nodes.length == 0) return false
|
||
let checkableNodes = cluster.nodes.filter(function (node) {
|
||
return !that.isNodeUpgradeFinished(node)
|
||
})
|
||
if (checkableNodes.length == 0) return false
|
||
return checkableNodes.every(function (node) { return node.isChecked })
|
||
}
|
||
|
||
/**
|
||
* 计算集群内选中的节点数
|
||
*/
|
||
this.countCheckedNodesInCluster = function (cluster) {
|
||
if (cluster.nodes == null) return 0
|
||
return cluster.nodes.filter(function (node) { return node.isChecked }).length
|
||
}
|
||
|
||
/**
|
||
* 全部升级
|
||
*/
|
||
this.upgradeAll = function () {
|
||
var vue = this
|
||
teaweb.confirm("确定要升级所有模块的所有待升级节点吗?", function () {
|
||
vue.$post("/settings/upgrade/upgradeNode")
|
||
.params({
|
||
module: "",
|
||
scope: "all",
|
||
clusterId: 0,
|
||
nodeId: 0
|
||
})
|
||
.success(function () {
|
||
// 标记所有节点为升级中
|
||
that.modules.forEach(function (mod) {
|
||
if (mod.clusters != null) {
|
||
mod.clusters.forEach(function (cluster) {
|
||
if (cluster.nodes != null) {
|
||
cluster.nodes.forEach(function (node) {
|
||
node.installStatus = {
|
||
isRunning: true,
|
||
isFinished: false,
|
||
isOk: false,
|
||
error: "",
|
||
errorCode: ""
|
||
}
|
||
node.isUpgrading = true
|
||
that.trackNode(mod.code, node.id)
|
||
})
|
||
}
|
||
})
|
||
}
|
||
})
|
||
})
|
||
.fail(function (resp) {
|
||
teaweb.warn("升级请求失败:" + resp.message)
|
||
})
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 按模块升级
|
||
*/
|
||
this.upgradeModule = function (moduleCode) {
|
||
var vue = this
|
||
teaweb.confirm("确定要升级该模块的所有待升级节点吗?", function () {
|
||
vue.$post("/settings/upgrade/upgradeNode")
|
||
.params({
|
||
module: moduleCode,
|
||
scope: "module",
|
||
clusterId: 0,
|
||
nodeId: 0
|
||
})
|
||
.success(function () {
|
||
that.markModuleUpgrading(moduleCode)
|
||
})
|
||
.fail(function (resp) {
|
||
teaweb.warn("升级请求失败:" + resp.message)
|
||
})
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 按集群升级
|
||
*/
|
||
this.upgradeCluster = function (moduleCode, clusterId) {
|
||
var vue = this
|
||
teaweb.confirm("确定要升级该集群的所有待升级节点吗?", function () {
|
||
vue.$post("/settings/upgrade/upgradeNode")
|
||
.params({
|
||
module: moduleCode,
|
||
scope: "cluster",
|
||
clusterId: clusterId,
|
||
nodeId: 0
|
||
})
|
||
.success(function () {
|
||
that.markClusterUpgrading(moduleCode, clusterId)
|
||
})
|
||
.fail(function (resp) {
|
||
teaweb.warn("升级请求失败:" + resp.message)
|
||
})
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 批量升级集群内选中的节点
|
||
*/
|
||
this.upgradeBatchInCluster = function (moduleCode, cluster) {
|
||
if (cluster.nodes == null) return
|
||
var checkedNodes = cluster.nodes.filter(function (node) { return node.isChecked })
|
||
if (checkedNodes.length == 0) return
|
||
|
||
var vue = this
|
||
teaweb.confirm("确定要批量升级选中的 " + checkedNodes.length + " 个节点吗?", function () {
|
||
checkedNodes.forEach(function (node) {
|
||
node.installStatus = {
|
||
isRunning: true,
|
||
isFinished: false,
|
||
isOk: false,
|
||
error: "",
|
||
errorCode: ""
|
||
}
|
||
node.isUpgrading = true
|
||
node.isChecked = false
|
||
that.trackNode(moduleCode, node.id)
|
||
|
||
vue.$post("/settings/upgrade/upgradeNode")
|
||
.params({
|
||
module: moduleCode,
|
||
scope: "node",
|
||
clusterId: 0,
|
||
nodeId: node.id
|
||
})
|
||
})
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 升级单个节点
|
||
*/
|
||
this.upgradeNode = function (moduleCode, node) {
|
||
var vue = this
|
||
teaweb.confirm("确定要升级节点 \"" + node.name + "\" 吗?", function () {
|
||
node.installStatus = {
|
||
isRunning: true,
|
||
isFinished: false,
|
||
isOk: false,
|
||
error: "",
|
||
errorCode: ""
|
||
}
|
||
node.isUpgrading = true
|
||
that.trackNode(moduleCode, node.id)
|
||
|
||
vue.$post("/settings/upgrade/upgradeNode")
|
||
.params({
|
||
module: moduleCode,
|
||
scope: "node",
|
||
clusterId: 0,
|
||
nodeId: node.id
|
||
})
|
||
.success(function () { })
|
||
.fail(function (resp) {
|
||
node.isUpgrading = false
|
||
teaweb.warn("升级请求失败:" + resp.message)
|
||
})
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 标记模块下所有节点为升级中
|
||
*/
|
||
this.markModuleUpgrading = function (moduleCode) {
|
||
that.modules.forEach(function (mod) {
|
||
if (mod.code == moduleCode && mod.clusters != null) {
|
||
mod.clusters.forEach(function (cluster) {
|
||
if (cluster.nodes != null) {
|
||
cluster.nodes.forEach(function (node) {
|
||
node.installStatus = {
|
||
isRunning: true,
|
||
isFinished: false,
|
||
isOk: false,
|
||
error: "",
|
||
errorCode: ""
|
||
}
|
||
node.isUpgrading = true
|
||
that.trackNode(moduleCode, node.id)
|
||
})
|
||
}
|
||
})
|
||
}
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 标记集群下所有节点为升级中
|
||
*/
|
||
this.markClusterUpgrading = function (moduleCode, clusterId) {
|
||
that.modules.forEach(function (mod) {
|
||
if (mod.code == moduleCode && mod.clusters != null) {
|
||
mod.clusters.forEach(function (cluster) {
|
||
if (cluster.id == clusterId && cluster.nodes != null) {
|
||
cluster.nodes.forEach(function (node) {
|
||
node.installStatus = {
|
||
isRunning: true,
|
||
isFinished: false,
|
||
isOk: false,
|
||
error: "",
|
||
errorCode: ""
|
||
}
|
||
node.isUpgrading = true
|
||
that.trackNode(moduleCode, node.id)
|
||
})
|
||
}
|
||
})
|
||
}
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 追踪节点升级状态
|
||
*/
|
||
this.trackNode = function (moduleCode, nodeId) {
|
||
if (that.upgradingNodeIds[moduleCode] == null) {
|
||
that.upgradingNodeIds[moduleCode] = []
|
||
}
|
||
if (that.upgradingNodeIds[moduleCode].indexOf(nodeId) < 0) {
|
||
that.upgradingNodeIds[moduleCode].push(nodeId)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 状态轮询
|
||
*/
|
||
this.pollStatus = function () {
|
||
var vue = this
|
||
|
||
// 检查是否有正在升级的节点
|
||
let hasUpgrading = false
|
||
for (let key in that.upgradingNodeIds) {
|
||
if (that.upgradingNodeIds[key].length > 0) {
|
||
hasUpgrading = true
|
||
break
|
||
}
|
||
}
|
||
|
||
if (!hasUpgrading) {
|
||
setTimeout(function () { that.pollStatus() }, 5000)
|
||
return
|
||
}
|
||
|
||
vue.$post("/settings/upgrade/status")
|
||
.params({
|
||
nodeIdsJSON: JSON.stringify(that.upgradingNodeIds)
|
||
})
|
||
.success(function (resp) {
|
||
let statuses = resp.data.statuses
|
||
if (statuses == null) {
|
||
return
|
||
}
|
||
|
||
// 更新各模块节点状态
|
||
for (let moduleCode in statuses) {
|
||
let nodeStatuses = statuses[moduleCode]
|
||
if (nodeStatuses == null) {
|
||
continue
|
||
}
|
||
nodeStatuses.forEach(function (ns) {
|
||
that.updateNodeStatus(moduleCode, ns.id, ns.installStatus)
|
||
})
|
||
}
|
||
})
|
||
.done(function () {
|
||
setTimeout(function () { that.pollStatus() }, 3000)
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 更新节点安装状态
|
||
*/
|
||
this.updateNodeStatus = function (moduleCode, nodeId, installStatus) {
|
||
that.modules.forEach(function (mod) {
|
||
if (mod.code == moduleCode && mod.clusters != null) {
|
||
mod.clusters.forEach(function (cluster) {
|
||
if (cluster.nodes != null) {
|
||
cluster.nodes.forEach(function (node) {
|
||
if (node.id == nodeId && installStatus != null) {
|
||
node.installStatus = installStatus
|
||
// 仅在升级完成(isFinished)时才移除跟踪
|
||
// 不要仅凭 !isRunning 就移除,因为批量升级时排队的节点尚未开始
|
||
if (installStatus.isFinished) {
|
||
node.isUpgrading = false
|
||
let idx = that.upgradingNodeIds[moduleCode].indexOf(nodeId)
|
||
if (idx >= 0) {
|
||
that.upgradingNodeIds[moduleCode].splice(idx, 1)
|
||
}
|
||
|
||
if (installStatus.isOk) {
|
||
// 升级成功,延迟后从列表中移除
|
||
setTimeout(function () {
|
||
let nIdx = cluster.nodes.indexOf(node)
|
||
if (nIdx >= 0) {
|
||
cluster.nodes.splice(nIdx, 1)
|
||
cluster.count--
|
||
mod.count--
|
||
that.totalUpgradeCount--
|
||
|
||
if (cluster.count <= 0) {
|
||
let cIdx = mod.clusters.indexOf(cluster)
|
||
if (cIdx >= 0) {
|
||
mod.clusters.splice(cIdx, 1)
|
||
}
|
||
}
|
||
if (mod.count <= 0) {
|
||
let mIdx = that.modules.indexOf(mod)
|
||
if (mIdx >= 0) {
|
||
that.modules.splice(mIdx, 1)
|
||
}
|
||
}
|
||
}
|
||
}, 2000)
|
||
} else {
|
||
// 升级失败,根据 errorCode 给出具体提示
|
||
that.handleUpgradeError(moduleCode, node, installStatus)
|
||
}
|
||
}
|
||
}
|
||
})
|
||
}
|
||
})
|
||
}
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 处理升级错误,根据 errorCode 提供更友好的提示
|
||
*/
|
||
this.handleUpgradeError = function (moduleCode, node, installStatus) {
|
||
let errorCode = installStatus.errorCode || ""
|
||
let errMsg = installStatus.error || ""
|
||
|
||
switch (errorCode) {
|
||
case "EMPTY_LOGIN":
|
||
case "EMPTY_SSH_HOST":
|
||
case "EMPTY_SSH_PORT":
|
||
case "EMPTY_GRANT":
|
||
// SSH 信息未配置的错误,不弹窗(页面上已有"没有设置"提示)
|
||
break
|
||
case "CREATE_ROOT_DIRECTORY_FAILED":
|
||
teaweb.warn("节点 \"" + node.name + "\" 创建根目录失败:" + errMsg)
|
||
break
|
||
case "INSTALL_HELPER_FAILED":
|
||
teaweb.warn("节点 \"" + node.name + "\" 安装助手失败:" + errMsg)
|
||
break
|
||
case "TEST_FAILED":
|
||
teaweb.warn("节点 \"" + node.name + "\" 环境测试失败:" + errMsg)
|
||
break
|
||
case "RPC_TEST_FAILED":
|
||
teaweb.warn("节点 \"" + node.name + "\" RPC通讯测试失败:" + errMsg)
|
||
break
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 更新自动升级状态
|
||
*/
|
||
this.updateAutoUpgrade = function () {
|
||
var vue = this
|
||
|
||
// @change 已经翻转了值,先记录新值并立即恢复
|
||
let newValue = that.config.autoUpgrade
|
||
that.config.autoUpgrade = !newValue
|
||
|
||
let msg = newValue ? "确定要开启自动升级功能吗?开启后节点会自动下载安装新版本。" : "确定要关闭自动升级功能吗?关闭后只能通过这里手动执行升级。"
|
||
teaweb.confirm(msg, function () {
|
||
vue.$post("/settings/upgrade")
|
||
.params({
|
||
autoUpgrade: newValue ? 1 : 0
|
||
})
|
||
.success(function () {
|
||
that.config.autoUpgrade = newValue
|
||
teaweb.successToast("设置保存成功")
|
||
})
|
||
.fail(function (resp) {
|
||
teaweb.warn("设置保存失败:" + resp.message)
|
||
})
|
||
})
|
||
}
|
||
})
|