/**
* Tencent is pleased to support the open source community by making MSEC available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the GNU General Public License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* https://opensource.org/licenses/GPL-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
package beans.service;
import beans.request.IPPortPair;
import beans.request.ReleasePlan;
import ngse.org.*;
import org.apache.log4j.Logger;
import org.codehaus.jackson.map.ObjectMapper;
import javax.servlet.ServletOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
/**
* Created by Administrator on 2016/2/2.
* 查询某个发布计划的详细信息
*/
public class RollbackReleasePlan extends JsonRPCHandler {
private String plan_id;
private String flsn;
private String slsn;
private String release_type;
private String release_memo;
private String geneCmdFileForRollback()
{
String fmt =
"if [ -e /msec/backup/backup_%s ]; then\n" +
" cd /msec/%s/%s/bin/; chmod a+x ./*; ./srpc.sh stop;\n"+
" rm -rf /msec/%s/%s/*\n"+
" mkdir -p /msec/%s/%s\n"+
" cp -R /msec/backup/backup_%s/* /msec/%s/%s/\n"+
" cd /msec/%s/%s/bin/; chmod a+x ./*; ./srpc.sh start;\n"+
"fi\n";
String cmdFileName = ServletConfig.fileServerRootDir+"/tmp/"+ plan_id+".sh";
String content = String.format(fmt,
plan_id,
flsn, slsn,//cd
flsn, slsn, //rm
flsn, slsn, //mkdir -p
plan_id, flsn, slsn, //cp -R
flsn, slsn); //cd
content = content+CarryOutReleasePlan.showProcessCmds(flsn, slsn);
try {
FileOutputStream out = new FileOutputStream(cmdFileName);
out.write(content.getBytes());
out.close();
}
catch ( Exception e)
{
e.printStackTrace();
return "";
}
return cmdFileName;
}
//safeWrite能够避免因为前端浏览器关闭了连接而导致发布没有执行下去
private void safeWrite(String s, ServletOutputStream out)
{
try
{
out.println(s);
out.flush();
}
catch (Exception e){}
}
private void safeWrite(byte[] b,int offset, int len, ServletOutputStream out)
{
try
{
out.write(b, offset, len);
out.flush();
}
catch (Exception e){}
}
private void updateReleaseMemo(DBUtil util, IPPortPair ipPortPair) throws Exception
{
String sql = "update t_second_level_service_ipinfo set release_memo=? where ip=? and port=?";
ArrayList<Object> params = new ArrayList<Object>();
params.add("roll back");
params.add(ipPortPair.getIp());
params.add(ipPortPair.getPort());
util.updateByPreparedStatement(sql, params);
}
private void doRollback(IPPortPair[] ips,
ServletOutputStream out,
DBUtil util) throws Exception
{
Logger logger = Logger.getLogger(RollbackReleasePlan.class);
RemoteShell remoteShell = new RemoteShell();
String cmdFile = geneCmdFileForRollback();
logger.info("cmd file:" + cmdFile);
byte[] buf = new byte[10240];
for (int i = 0; i < ips.length; i++) {
String ip = ips[i].getIp();
String result = "";
StringBuffer outputFileName = new StringBuffer();
result = remoteShell.SendCmdsToAgentAndRun(cmdFile, ip, outputFileName);
if (result == null || !result.equals("success"))
{
safeWrite(String.format(">>>send cmd file to %s failed:%s", ip, result), out);
continue;
}
safeWrite(String.format("send cmd file to %s succesfully", ip), out);
String localResult = ServletConfig.fileServerRootDir+"/tmp/" + plan_id+".out";
logger.info("run cmd file,get result file:"+localResult);
result = remoteShell.GetFileFromAgent(localResult, outputFileName.toString(), ip);
if (result == null || !result.equals("success"))
{
safeWrite(String.format(">>>get result file from %s failed:%s\n", ip, result), out);
continue;
}
safeWrite(String.format("get result file from %s succesfully\n", ip), out);
FileInputStream in = new FileInputStream(localResult);
while (true)
{
int len = in.read(buf);
if (len < 0)
{
break;
}
safeWrite(buf, 0, len, out);
}
in.close();
safeWrite("--------------------------", out);
//更新该IP的版本信息
updateReleaseMemo(util, ips[i]);
}
out.println("done!");
}
private void updatePlanStatus(DBUtil util, String status) throws Exception
{
String sql = "update t_release_plan set status=? where plan_id=?";
ArrayList<Object> params = new ArrayList<Object>();
params.add(status);
params.add(plan_id);
util.updateByPreparedStatement(sql, params);
}
public JsonRPCResponseBase exec(ReleasePlan request)
{
Logger logger = Logger.getLogger(RollbackReleasePlan.class);
JsonRPCResponseBase resp = new JsonRPCResponseBase();
plan_id = request.getPlan_id();
flsn = request.getFirst_level_service_name();
slsn = request.getSecond_level_service_name();
String result = checkIdentity();
if (!result.equals("success"))
{
resp.setStatus(99);
resp.setMessage(result);
return resp;
}
DBUtil util = new DBUtil();
if (util.getConnection() == null)
{
resp.setStatus(100);
resp.setMessage("db connect failed!");
return resp;
}
try {
String sql = "select dest_ip_list from t_release_plan where plan_id=?";
ArrayList<Object> params = new ArrayList<Object>();
params.add(request.getPlan_id());
Map<String, Object> res = util.findSimpleResult(sql,params);
if (res.get("dest_ip_list") == null )
{
resp.setStatus(100);
resp.setMessage("query dest ip list failed.");
return resp;
}
String dest_ip_list = (String)(res.get("dest_ip_list"));
ObjectMapper objectMapper = new ObjectMapper();
IPPortPair[] ips = objectMapper.readValue(dest_ip_list, IPPortPair[].class);
logger.info("destination IP number;"+ips.length);
//对每个IP执行回滚
getHttpResponse().setContentType("text/html");
getHttpResponse().setCharacterEncoding("UTF-8");
ServletOutputStream out = getHttpResponse().getOutputStream();
safeWrite("<html>", out);
safeWrite("<head>", out);
safeWrite("<title>release result</title>", out);
safeWrite("</head>", out);
safeWrite("<body>", out);
safeWrite("<pre>", out);//这个标签用于原样输出
updatePlanStatus(util, "rolling back");
doRollback( ips, out, util);
safeWrite("</pre>", out);
safeWrite("</body>", out);
safeWrite("</html>", out);
//update plan status
updatePlanStatus(util, "roll back successfully");
try {out.close();}catch (Exception e){}
return null;
}
catch (Exception e)
{
resp.setStatus(100);
resp.setMessage(e.getMessage());
e.printStackTrace();
try {
updatePlanStatus(util, "failed to roll back");
}
catch (Exception e1){}
return resp;
}
finally {
util.releaseConn();
}
}
}