Răsfoiți Sursa

一键部署

maxiaoshan 3 ani în urmă
părinte
comite
8fbdad5293
4 a modificat fișierele cu 335 adăugiri și 43 ștergeri
  1. 16 8
      src/vps/aliecs.go
  2. 96 9
      src/vps/vps.go
  3. 11 1
      src/web/templates/head.html
  4. 212 25
      src/web/templates/vps/vpslist.html

+ 16 - 8
src/vps/aliecs.go

@@ -53,19 +53,23 @@ func RunInstances(name, image, stype string, public bool, num, hours int, ok *bo
 	}
 }
 
-func runInstances(zoneMap ZoneMap, name, widthOut, stype, image string, pernum, hours int) bool {
-	log.Println("apply ecs:", zoneMap, name, widthOut, stype, pernum, hours)
+func runInstances(zoneMap ZoneMap, name, widthOut, stype, imageId string, pernum, hours int) bool {
+	log.Println("apply ecs:", zoneMap, name, imageId, widthOut, stype, pernum, hours)
 	applyOk := false
 	launchTemplateId := zoneMap.LaunchTemplateId4
 	if stype == "8" {
 		launchTemplateId = zoneMap.LaunchTemplateId8
 	}
-	res := GET("RunInstances", [][]string{
+	if hours == 0 { //表示无期限
+		hours = 24 * 365 * 3 //阿里竞价服务器最长申请3年
+	}
+	autoReleaseTime := time.Now().Add(time.Duration(hours) * time.Hour).UTC().Format("2006-01-02T15:04:05Z")
+	param := [][]string{
 		[]string{"RegionId", "cn-beijing"},             //实例所属的地域ID
 		[]string{"ZoneId", zoneMap.ZoneId},             //实例所属的可用区ID(设置了VSwitchId参数,则设置的ZoneId参数必须和交换机所在的可用区保持一致)
 		[]string{"VSwitchId", zoneMap.VswitchId},       //虚拟交换机ID
 		[]string{"LaunchTemplateId", launchTemplateId}, //启动模板ID
-		//[]string{"ImageId", "centos_7_06_64_20G_alibase_20181212.vhd"},//镜像ID
+		//[]string{"ImageId", "m-2zec9baha8ezvrd0hj8e"}, //镜像ID
 		//[]string{"InstanceType", "ecs.ic5.large"},
 		//[]string{"SecurityGroupId", "sg-bp16x3td2evrejhkshp7"},[]string{"InternetMaxBandwidthIn", "50"},
 		[]string{"InternetMaxBandwidthOut", widthOut},  //公网出带宽最大值
@@ -76,8 +80,12 @@ func runInstances(zoneMap ZoneMap, name, widthOut, stype, image string, pernum,
 		[]string{"UniqueSuffix", "true"},               //当创建多台实例时,是否为HostName和InstanceName自动添加有序后缀
 		[]string{"Password", Password},
 		[]string{"Amount", fmt.Sprint(pernum)},
-		[]string{"AutoReleaseTime", time.Now().Add(time.Duration(hours) * time.Hour).UTC().Format("2006-01-02T15:04:05Z")},
-	})
+		[]string{"AutoReleaseTime", autoReleaseTime},
+	}
+	if imageId != "" {
+		param = append(param, []string{"ImageId", imageId})
+	}
+	res := GET("RunInstances", param)
 	if tmp, ok := res["InstanceIdSets"].(map[string]interface{}); ok {
 		if t, ok := tmp["InstanceIdSet"].([]interface{}); ok {
 			applyOk = true
@@ -87,7 +95,8 @@ func runInstances(zoneMap ZoneMap, name, widthOut, stype, image string, pernum,
 					"InstanceId": v,
 					"TaskName":   name,
 					"UseFor":     "lua",
-					"VpsState":   0,
+					"EcsState":   "notdeploy",
+					"EcsStype":   []string{},
 				})
 			}
 		} else {
@@ -150,7 +159,6 @@ func DeleteInstance(InstanceId string, ok *bool) {
 	if len(res) > 0 {
 		*ok = true
 	}
-	util.MgoE.Update("ecs", `{"InstanceId":"`+InstanceId+`"}`, map[string]interface{}{"$set": map[string]interface{}{"Status": "Deleted"}}, true, false)
 	qu.Debug("DeleteInstance", res)
 }
 

+ 96 - 9
src/vps/vps.go

@@ -4,22 +4,24 @@ import (
 	"github.com/go-xweb/xweb"
 	qu "qfw/util"
 	"strings"
+	"time"
 	"util"
 )
 
 type Vps struct {
 	*xweb.Action
-	vpsList xweb.Mapper `xweb:"/center/vps"`        //服务器管理列表
-	apply   xweb.Mapper `xweb:"/center/vps/apply"`  //申请实例
-	update  xweb.Mapper `xweb:"/center/vps/update"` //更新实例
-	delay   xweb.Mapper `xweb:"/center/vps/delay"`  //延迟实例
-	//deploy     xweb.Mapper `xweb:"/center/vps/deploy"`     //部署实例
-	release xweb.Mapper `xweb:"/center/vps/release"` //释放实例
-	delete  xweb.Mapper `xweb:"/center/vps/delete"`  //删除信息
-	//allDeploy  xweb.Mapper `xweb:"/center/vps/alldeploy"`  //一键部署
+	vpsList    xweb.Mapper `xweb:"/center/vps"`            //服务器管理列表
+	apply      xweb.Mapper `xweb:"/center/vps/apply"`      //申请实例
+	update     xweb.Mapper `xweb:"/center/vps/update"`     //更新实例
+	delay      xweb.Mapper `xweb:"/center/vps/delay"`      //延时实例
+	deploy     xweb.Mapper `xweb:"/center/vps/deploy"`     //部署实例
+	release    xweb.Mapper `xweb:"/center/vps/release"`    //释放实例
+	delete     xweb.Mapper `xweb:"/center/vps/delete"`     //删除信息
+	allDeploy  xweb.Mapper `xweb:"/center/vps/alldeploy"`  //一键部署
 	allRelease xweb.Mapper `xweb:"/center/vps/allrelease"` //一键释放
 }
 
+//列表
 func (vps *Vps) VpsList() {
 	defer qu.Catch()
 	draw, _ := vps.GetInteger("draw")
@@ -34,12 +36,18 @@ func (vps *Vps) VpsList() {
 		count := util.MgoE.Count("ecs", query)
 		qu.Debug("query:", query, count)
 		list, _ := util.MgoE.Find("ecs", query, nil, nil, false, start, limit)
+		for _, l := range *list {
+			autoReleaseTime := qu.ObjToString(l["AutoReleaseTime"])
+			parseTime, _ := time.Parse("2006-01-02T15:04Z", autoReleaseTime)
+			l["AutoReleaseTime"] = parseTime.In(time.Local).Format(qu.Date_Full_Layout)
+		}
 		vps.ServeJson(map[string]interface{}{"draw": draw, "data": *list, "recordsFiltered": count, "recordsTotal": count})
 	} else {
 		vps.Render("vps/vpslist.html")
 	}
 }
 
+//申请
 func (vps *Vps) Apply() {
 	defer qu.Catch()
 	vpsname := vps.GetString("vpsname")
@@ -53,6 +61,7 @@ func (vps *Vps) Apply() {
 	vps.ServeJson(map[string]interface{}{"ok": ok})
 }
 
+//更新
 func (vps *Vps) Update() {
 	defer qu.Catch()
 	qu.Debug("更新实例...")
@@ -61,6 +70,7 @@ func (vps *Vps) Update() {
 	vps.ServeJson(map[string]interface{}{"ok": ok})
 }
 
+//延时
 func (vps *Vps) Delay() {
 	defer qu.Catch()
 	delayid := vps.GetString("delayid")
@@ -90,6 +100,7 @@ func (vps *Vps) Delay() {
 	vps.ServeJson(map[string]interface{}{"ok": allOk, "msg": msg})
 }
 
+//释放
 func (vps *Vps) Release() {
 	defer qu.Catch()
 	instanceId := vps.GetString("instanceId")
@@ -98,9 +109,81 @@ func (vps *Vps) Release() {
 	if instanceId != "" {
 		DeleteInstance(instanceId, &ok)
 	}
+	if ok {
+		autoReleaseTime := time.Now().UTC().Format("2006-01-02T15:04Z")
+		util.MgoE.Update("ecs", `{"InstanceId":"`+instanceId+`"}`, map[string]interface{}{"$set": map[string]interface{}{"Status": "Deleted", "AutoReleaseTime": autoReleaseTime, "releaseTime": time.Now().Unix()}}, false, false)
+	}
 	vps.ServeJson(map[string]interface{}{"ok": ok})
 }
 
+//部署
+func (vps *Vps) Deploy() {
+	defer qu.Catch()
+	instanceId := vps.GetString("instanceId")
+	ip := vps.GetString("ip")
+	stype := vps.GetString("stype")
+	qu.Debug("部署实例:", instanceId, ip, stype)
+	sshStr := ""
+	stypeArr := []string{}
+	if stype == "data" { //数据
+		sshStr = DataSshStr
+		stypeArr = append(stypeArr, stype)
+	} else if stype == "special" { //专用
+		sshStr = SpecialSshStr
+		stypeArr = append(stypeArr, stype)
+	} else if stype == "file" { //附件
+		sshStr = FileSshStr
+		stypeArr = append(stypeArr, stype)
+	} else { //所有
+		sshStr = AllSshStr
+		stypeArr = []string{"data", "special", "file"}
+	}
+	qu.Debug(sshStr)
+	ok := RunSsh(ip, Password, sshStr, 22)
+	if ok {
+		util.MgoE.Update("ecs", map[string]interface{}{"InstanceId": instanceId}, map[string]interface{}{
+			"$set":      map[string]interface{}{"EcsState": "deploy"},
+			"$addToSet": map[string]interface{}{"EcsStype": map[string]interface{}{"$each": stypeArr}},
+		}, false, false)
+	}
+	vps.ServeJson(map[string]interface{}{"ok": ok})
+}
+
+//一键部署
+func (vps *Vps) AllDeploy() {
+	defer qu.Catch()
+	qu.Debug("部署所有实例...")
+	stype := vps.GetString("stype")
+	stypeArr := strings.Split(stype, ",")
+	sshStr := `
+#!/bin/bash
+`
+	for _, stype = range stypeArr {
+		sshStr += SshStrMap[stype]
+	}
+	qu.Debug(sshStr)
+	allOk := true
+	failedAll := []string{}
+	list, _ := util.MgoE.Find("ecs", map[string]interface{}{"Status": "Running"}, nil, map[string]interface{}{"ip_ww": 1, "InstanceId": 1}, false, -1, -1)
+	for _, l := range *list {
+		ip := qu.ObjToString(l["ip_ww"])
+		instanceId := qu.ObjToString(l["InstanceId"])
+		ok := RunSsh(ip, Password, sshStr, 22)
+		if !ok {
+			failedAll = append(failedAll, instanceId)
+			allOk = false
+		} else {
+			util.MgoE.Update("ecs", map[string]interface{}{"InstanceId": instanceId}, map[string]interface{}{
+				"$set":      map[string]interface{}{"EcsState": "deploy"},
+				"$addToSet": map[string]interface{}{"EcsStype": map[string]interface{}{"$each": []string{"data", "file", "special"}}},
+			}, false, false)
+		}
+	}
+	msg := "释放失败实例:" + strings.Join(failedAll, ",")
+	vps.ServeJson(map[string]interface{}{"ok": allOk, "msg": msg})
+}
+
+//一键释放
 func (vps *Vps) AllRelease() {
 	defer qu.Catch()
 	qu.Debug("释放所有实例...")
@@ -114,12 +197,16 @@ func (vps *Vps) AllRelease() {
 		if !ok {
 			failedAll = append(failedAll, instanceId)
 			allOk = false
+		} else {
+			autoReleaseTime := time.Now().UTC().Format("2006-01-02T15:04Z")
+			util.MgoE.Update("ecs", `{"InstanceId":"`+instanceId+`"}`, map[string]interface{}{"$set": map[string]interface{}{"Status": "Deleted", "AutoReleaseTime": autoReleaseTime, "releaseTime": time.Now().Unix()}}, false, false)
 		}
 	}
 	msg := "释放失败实例:" + strings.Join(failedAll, ",")
 	vps.ServeJson(map[string]interface{}{"ok": allOk, "msg": msg})
 }
 
+//删除
 func (vps *Vps) Delete() {
 	defer qu.Catch()
 	instanceId := vps.GetString("instanceId")
@@ -128,7 +215,7 @@ func (vps *Vps) Delete() {
 	if instanceId != "" {
 		ok = util.MgoE.Del("ecs", map[string]interface{}{"InstanceId": instanceId})
 	} else {
-		ok = util.MgoE.Del("ecs", nil)
+		ok = util.MgoE.Del("ecs", map[string]interface{}{"Status": "Deleted"})
 	}
 	vps.ServeJson(map[string]interface{}{"ok": ok})
 }

+ 11 - 1
src/web/templates/head.html

@@ -571,7 +571,17 @@
 
         {{if eq (session "auth") 4}}
 		  <li data="index_yhgl"><a href="/center/user.html"><i class="glyphicon glyphicon-user"></i> <span>用户管理</span></a></li>
-		  <li data="index_vps"><a href="/center/vps"><i class="fa fa-server"></i> <span>服务器管理</span></a></li>
+		  <li class="treeview" data="index_vps">
+			  <a href="#"><i class="fa fa-server"></i> <span>服务器管理</span>
+				  <span class="pull-right-container">
+                	<i class="fa fa-angle-left pull-right"></i>
+            	  </span>
+			  </a>
+			  <ul class="treeview-menu">
+				  <li><a href="/center/vps"><i class="fa fa-link"></i>服务器列表</a></li>
+				  <li><a href="/admin/task/export"><i class="fa fa-link"></i>监控信息</a></li>
+			  </ul>
+		  </li>
 		  {{else if eq (session "auth") 3}}
 			<li data="index"><a href="/center"><i class="glyphicon glyphicon-eye-open"></i> <span>脚本列表</span></a></li>
 			<li data="index_rwgl"><a href="/center/managerTask"><i class="glyphicon glyphicon glyphicon-tasks"></i> <span>任务管理</span></a></li>

+ 212 - 25
src/web/templates/vps/vpslist.html

@@ -13,9 +13,9 @@
 						</div>
 						<form class="form-horizontal" role="form">
 							<div class="form-group">
-								<label for="vpsname" class="col-sm-2 control-label">实例名称 :</label>
+								<label for="vpsname" class="col-sm-2 control-label">任务名称 :</label>
 								<div class="col-sm-10">
-									<input type="text" class="form-control" id="vpsname" placeholder="请输入实例名称">
+									<input type="text" class="form-control" id="vpsname" placeholder="请输入任务名称">
 								</div>
 							</div>
 							<div class="form-group">
@@ -33,7 +33,7 @@
 							<div class="form-group">
 								<label for="vpsduration" class="col-sm-2 control-label">时长(h):</label>
 								<div class="col-sm-10">
-									<input type="text" class="form-control" id="vpsduration" placeholder="请输入申请时长">
+									<input type="text" class="form-control" id="vpsduration" value="0">
 								</div>
 							</div>
 <!--							<div class="form-group">-->
@@ -117,6 +117,61 @@
 	</div><!-- /.modal -->
 </div>
 <!-- 模态框(Modal) -->
+<!-- 部署实例(Modal) -->
+<div class="modal fade" id="deployvps" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+	<div class="modal-dialog">
+		<div class="modal-content">
+			<div class="modal-header">
+				<div class="modal-header">
+					<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+					<div class="edit-form">
+						<div class="edit-info">
+							<span class="glyphicon glyphicon-tasks" aria-hidden="true"></span>
+							<span class="info">部署实例</span>
+						</div>
+						<form class="form-horizontal" role="form">
+							<div class="form-group">
+								<label for="stype" class="col-sm-2 control-label">服务类型 :</label>
+								<div class="col-sm-10" id="stype">
+									<input type="checkbox" value="data">数据
+									<input type="checkbox" value="special">专用
+									<input type="checkbox" value="file">附件
+								</div>
+							</div>
+							<div class="form-group">
+								<div class="col-sm-offset-2 col-sm-10 operateStyle">
+									<input type="button"  onclick="alldeploy()" class="btn btn-success saveBtn" value="确认">
+									<input type="button" onclick="cancelAdd()" class="btn btn-default" value="取消">
+								</div>
+							</div>
+						</form>
+					</div>
+				</div>
+			</div>
+		</div><!-- /.modal-content -->
+	</div><!-- /.modal -->
+</div>
+<!-- 模态框(Modal) -->
+<!-- loading实例(Modal) -->
+<div class="modal fade" id="loading" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" data-backdrop="static" data-keyboard="false">>
+	<div class="modal-dialog">
+		<div class="modal-content" style="margin-top: 220px">
+			<div class="modal-header">
+				<div class="modal-header">
+					<div class="edit-form">
+						<form class="form-horizontal" role="form">
+							<div class="form-group">
+								<span class="info">正在加载...</span>
+								<span class="fa fa-spin fa-spinner" aria-hidden="true"></span>
+							</div>
+						</form>
+					</div>
+				</div>
+			</div>
+		</div><!-- /.modal-content -->
+	</div><!-- /.modal -->
+</div>
+<!-- 模态框(Modal) -->
 <div class="content-wrapper">
 	<section class="content-header">
 	   <h1>
@@ -124,17 +179,17 @@
 		 <small>
 			 <button class="btn btn-success" onclick='applymodal()'>申请实例</button>
 			 <button class="btn btn-success" onclick='update()'>更新实例</button>
-			 <button class="btn btn-info" onclick='delaymodal("")'>一键延时</button>
+			 <button class="btn btn-info" onclick='delaymodal("","")'>一键延时</button>
 <!--			 <button class="btn btn-success" onclick='delaymodal()'>延时设置</button>-->
-			 <button class="btn btn-info" onclick='tasks()'>一键部署</button>
+			 <button class="btn btn-info" onclick='deploymodal()'>一键部署</button>
 			 <button class="btn btn-danger" onclick='allrelease()'>一键释放</button>
-			 <button class="btn btn-danger" onclick='deletevps()'>一键删除</button>
+			 <button class="btn btn-danger" onclick='deletevps("","")'>一键删除</button>
 		 </small>
 	   </h1>
 	<!--时间-->
 	   <ol class="breadcrumb">
 		 <li><a href="#"><i class="fa fa-dashboard"></i> 阿里实例</a></li>
-		 <li class="active">列表</li>
+		 <li class="active">实例列表</li>
 	   </ol>
 	 </section>
 	<section id="taskerrmsg" class="content hide" style="min-height:0px;">
@@ -154,8 +209,8 @@
 							<th>实例ID</th>
 							<th>实例IP(内网/公网)</th>
 							<th>释放时间</th>
-							<th>运行状态</th>
-							<th>功能</th>
+							<th>状态</th>
+							<th>部署</th>
 							<th>操作</th>
 						</tr>
 					</thead>
@@ -183,10 +238,15 @@
 				"searching": false,
 				"ordering": false,
 				"info": true,
-				"autoWidth": true,
+				"autoWidth": false,
 				"processing": true,
 				"columns": [
-					{"data": "TaskName"},
+					{"data": "TaskName",render:function(val,a,row){
+						if(val == undefined){
+							val = ""
+						}
+						return val;
+					}},
 					{"data": "InstanceName",render:function(val,a,row){
 						if(val == undefined){
 							val = ""
@@ -208,24 +268,48 @@
 						}
 						return val;
 					}},
-					{"data": "AutoReleaseTime",render:function(val,a,row){
+					{"data": "AutoReleaseTime",width:"75px",render:function(val,a,row){
 						if(val == undefined){
 							val = ""
+						}else{
+
 						}
 						return val;
 					}},
-					{"data": "VpsState"},
+					{"data": "EcsState",render:function (val,a,row) {
+						if(val == "notdeploy"){
+							val = "未部署"
+						}else if(val == "deploy"){
+							val = "已部署"
+						}else if(val == "stop"){
+							val = "已停止"
+						}else{
+							val = ""
+						}
+						return val;
+					}},//未部署、已部署、已停止
 					{"data": "_id",render:function(val,a,row){
+						let classHtmlMap = {'data':'<a class="btn btn-sm btn-warning"','special':'<a class="btn btn-sm btn-warning"','file':'<a class="btn btn-sm btn-warning"'};
+						for (var i in row.EcsStype){
+							let stype = row.EcsStype[i]
+							classHtmlMap[stype] = '<a class="btn btn-sm btn-success" disabled'
+						}
 						tmp = '<div>' +
-							'<a class="btn btn-sm btn-info" onclick="delaymodal(\''+row.InstanceId+'\')">延时</a>&nbsp;' +
-							'<a class="btn btn-sm btn-info" onclick="retrieveTask()">部署</a>' +
-							'</div>';
+							classHtmlMap['data']+' onclick="deploy(this,\''+row.Status+'\',\''+row.InstanceId+'\',\''+row.ip_ww+'\',\'data\')">数据</a>&nbsp;'+
+							classHtmlMap['special']+' onclick="deploy(this,\''+row.Status+'\',\''+row.InstanceId+'\',\''+row.ip_ww+'\',\'special\')">专用</a>&nbsp;' +
+							classHtmlMap['file']+' onclick="deploy(this,\''+row.Status+'\',\''+row.InstanceId+'\',\''+row.ip_ww+'\',\'file\')">附件</a>&nbsp;'
+						if(row.EcsState != "deploy"){
+							tmp = tmp +
+								'<a class="btn btn-sm btn-info" onclick="deploy(this,\''+row.Status+'\',\''+row.InstanceId+'\',\''+row.ip_ww+'\',\'all\')">一键启用' +
+								'</div>';
+						}
 						return tmp
 					}},
 					{"data": "_id",render:function(val,a,row){
 						tmp = '<div>' +
-							'<a class="btn btn-sm btn-danger" onclick="releasevps(\''+row.InstanceId+'\')">释放</a>&nbsp;' +
-							'<a class="btn btn-sm btn-danger" onclick="deletevps(\''+row.InstanceId+'\')">删除</a>'+
+							'<a class="btn btn-sm btn-info" onclick="delaymodal(\''+row.InstanceId+'\',\''+row.Status+'\')">延时</a>&nbsp;' +
+							'<a class="btn btn-sm btn-danger" onclick="releasevps(\''+row.InstanceId+'\',\''+row.Status+'\')">释放</a>&nbsp;' +
+							'<a class="btn btn-sm btn-danger" onclick="deletevps(\''+row.InstanceId+'\',\''+row.Status+'\')">删除</a>'+
 							// '<a class="btn btn-sm btn-primary" onclick="checkMethod(\'' + row.s_projectid + '\',\'' + val + '\',\'' + row.s_sourceinfo + '\')">删除</a>&nbsp;&nbsp;' +
 						'</div>';
 						return tmp
@@ -233,10 +317,17 @@
 				]
 			});
 		});
-		function delaymodal(instanceId) {
+		function deploymodal() {
+			$("#deployvps").modal("show");
+		}
+		function delaymodal(instanceId,status) {
 			if(instanceId == ""){//一键延时
 				$("#delay").css("display","none");
-			}else{//单个实例延时
+			}else {//单个实例延时
+				if(status != "Running"){
+					alert("服务器不可用!")
+					return
+				}
 				$("#delayid").val(instanceId)
 				$("#delay").css("display","");
 			}
@@ -248,6 +339,7 @@
 		function cancelAdd(){
 			$("#delayvps").modal("hide");
 			$("#applyvps").modal("hide");
+			$("#deployvps").modal("hide");
 		}
 		//申请实例
 		function apply() {
@@ -255,10 +347,16 @@
 			let vpsimage = $("#vpsimage").val();
 			let vpsnum = $("#vpsnum").val();
 			let vpsduration = $("#vpsduration").val();
-			if (vpsname == ""||vpsimage==""||vpsnum == ""||vpsduration == ""){
+			if (vpsname == ""||vpsnum == ""||vpsduration == ""){
 				alert("请填写完整的信息!")
 				return
 			}
+			if(vpsnum > 100 || vpsnum < 1){
+				alert("申请机器数量异常!")
+				return
+			}
+			$("#applyvps").modal("hide");
+			$("#loading").modal("show");
 			let vpstype = $("#vpstype").val();
 			let vpspublic = $("#vpspublic").val();
 			$.ajax({
@@ -266,9 +364,9 @@
 				type:"post",
 				data:{"vpsname":vpsname,"vpsimage":vpsimage,"vpsnum":vpsnum,"vpsduration":vpsduration,"vpstype":vpstype,"vpspublic":vpspublic},
 				success:function (r){
+					$("#loading").modal("hide");
 					if(r&&r.ok){
 						showTip("申请成功", 1000);
-						$("#applyvps").modal("hide");
 						setTimeout(function (){
 							window.location.reload();
 						}, 1000);
@@ -281,10 +379,12 @@
 		//更新实例
 		function update() {
 			showConfirm("确定更新实例?", function() {
+				$("#loading").modal("show");
 				$.ajax({
 					url:"/center/vps/update",
 					type:"post",
 					success:function (r){
+						$("#loading").modal("hide");
 						if(r&&r.ok){
 							showTip("更新成功", 1000);
 							window.location.reload();
@@ -297,20 +397,22 @@
 		}
 		//延时
 		function delay() {
+			$("#delayvps").modal("hide");
 			let delayid = $("#delayid").val();
 			let delaytime = $("#delaytime").val();
 			if (delaytime == ""){
 				alert("请填写完整的信息!")
 				return
 			}
+			$("#loading").modal("show");
 			$.ajax({
 				url:"/center/vps/delay",
 				type:"post",
 				data:{"delaytime":delaytime,"delayid":delayid},
 				success:function (r){
+					$("#loading").modal("hide");
 					if(r&&r.ok){
 						showTip("设置成功", 1000);
-						$("#delayvps").modal("hide");
 						setTimeout(function (){
 							window.location.reload();
 						}, 1000);
@@ -323,13 +425,19 @@
 			})
 		}
 		//释放
-		function releasevps(instanceId) {
+		function releasevps(instanceId,status) {
+			if(status == "Deleted"){
+				alert("服务器已释放!")
+				return
+			}
 			showConfirm("确定释放实例?", function() {
+				$("#loading").modal("show");
 				$.ajax({
 					url:"/center/vps/release",
 					type:"post",
 					data:{"instanceId":instanceId},
 					success:function (r){
+						$("#loading").modal("hide");
 						if(r&&r.ok){
 							showTip("释放成功",1000);
 							setTimeout(function (){
@@ -345,12 +453,15 @@
 		//一键释放
 		function allrelease() {
 			showConfirm("确定释放所有实例?", function() {
+				$("#loading").modal("show");
 				$.ajax({
 					url:"/center/vps/allrelease",
 					type:"post",
 					success:function (r){
+						$("#loading").modal("hide");
 						if(r&&r.ok){
 							showTip("释放成功", 1000);
+							$("#delayvps").modal("hide");
 							setTimeout(function (){
 								window.location.reload();
 							}, 1000);
@@ -362,14 +473,53 @@
 				})
 			})
 		}
+		//一键部署
+		function alldeploy() {
+			let stypeArr = [];
+			$("#stype input[type=checkbox]").each(function(){
+				if($(this).prop("checked")){
+					stypeArr.push($(this).val());
+				}
+			});
+			let stype = stypeArr.join(",");
+			if(stype == ""){
+				alert("请选择服务类型!")
+				return;
+			}
+			$("#deployvps").modal("hide");
+			$("#loading").modal("show");
+			$.ajax({
+				url:"/center/vps/alldeploy",
+				type:"post",
+				data:{"stype":stype},
+				success:function (r){
+					$("#loading").modal("hide");
+					if(r&&r.ok){
+						showTip("部署成功", 1000);
+						setTimeout(function (){
+							window.location.reload();
+						}, 1000);
+					}else{
+						showMsg(r.msg, function () {
+						});
+					}
+				}
+			})
+		}
 		//删除
-		function deletevps(instanceId) {
+		function deletevps(instanceId,status) {
+			// if(instanceId != "" && status != "Deleted"){
+			// 	alert("服务器未释放!")
+			// 	return
+			// }
 			showConfirm("确定删除实例信息?", function() {
+				$("#loading").modal("show");
 				$.ajax({
 					url:"/center/vps/delete",
 					type:"post",
 					data:{"instanceId":instanceId},
 					success:function (r){
+						$("#loading").modal("hide");
 						if(r&&r.ok){
 							showTip("删除成功", 1000);
 							setTimeout(function (){
@@ -382,6 +532,43 @@
 				})
 			})
 		}
+		//部署实例
+		function deploy(e,status,instanceId,ip,stype) {
+			if($(e).attr('disabled')){
+				return;
+			}
+			if( status != "Running"){
+				alert("服务器不可用!")
+				return
+			}
+			let val = "所有";
+			if(stype == "data"){
+				val = "数据";
+			}else if(stype == "special"){
+				val = "专用";
+			}else if(stype == "file") {
+				val = "附件";
+			}
+			showConfirm("确定启用"+val+"服务?", function() {
+				$("#loading").modal("show");
+				$.ajax({
+					url:"/center/vps/deploy",
+					type:"post",
+					data:{"instanceId":instanceId,"ip":ip,"stype":stype},
+					success:function (r){
+						$("#loading").modal("hide");
+						if(r&&r.ok){
+							showTip("部署成功", 1000);
+							setTimeout(function (){
+								window.location.reload();
+							}, 1000);
+						}else{
+							showTip("部署失败", 1000);
+						}
+					}
+				})
+			})
+		}
 	</script>
 </div>
 {{include "bottom.html"}}