You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

301 lines
14 KiB

using Tiobon.Core.OPS.Tool.OPS.Tool.Helper;
using Tiobon.Core.OPS.Tool.OPS.Tool.Model;
using Tiobon.Core.OPS.Tool.OPS.Tool.View;
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
using System.Windows.Forms;
using System.Text.RegularExpressions;
namespace Tiobon.Core.OPS.Tool.OPS.Tool.Src
{
public class Module_method
{
#region 全局变量
SSHHelper sSH = new SSHHelper(Const.config.ip, Const.config.ssh_port, Const.config.ssh_user, Const.config.ssh_passwd);
SFTPHelper sFTP = new SFTPHelper(Const.config.ip, Const.config.ssh_port, Const.config.ssh_user, Const.config.ssh_passwd);
bool isLinux = Const.config.system == "Linux";
public Action End_Init;
Module module_conf;
#endregion
#region 获取配置信息
public Module GetConf(string filepath)
{
Const.ExtractSpecifyZipFile(filepath, "Config/", "", new List<string> { "README.ihdis" });
string fm = File.ReadAllText("Config/README.ihdis");
JavaScriptSerializer js = new JavaScriptSerializer();
module_conf = js.Deserialize<Module>(fm);
return module_conf;
}
#endregion
#region 检测压缩包是否损坏
public bool Is_BadZip(string path)
{
try
{
ZipFile entry = new ZipFile(path);
return true;
}
catch
{
return false;
}
}
#endregion
#region 模块安装
public void Install(string filepath, Action<string> handle)
{
bool isLinux = Const.config.system == "Linux";
var hospital = Const.config.install_item_dir.Split('/').Last();
if (isLinux)
{
var installpath = $"/home/{Const.config.ssh_user}/ihdis/tools/{module_conf.Name}";
var webpath = $"/home/{Const.config.ssh_user}/ihdis/produse";
try
{
sSH.Connect();
var tmpdir = $"/tmp/{module_conf.Name}{new Random().Next(10000, 20000)}";
//1,上传文件
handle?.Invoke("正在上传文件...");
Upload(filepath, handle);
//2,解压到临时目录
handle?.Invoke("正在解压到临时目录...");
sSH.Excute_Longcmd($"unzip -qo /home/{Const.config.ssh_user}/ihdis/tools/{filepath.Split('\\')[filepath.Split('\\').Length - 1]} -d {tmpdir}");
if (File.Exists("Config/README.ihdis"))
{
sFTP.Connect();
sFTP.Put("Config/README.ihdis", $"{tmpdir}", "README.ihdis");
sFTP.Disconnect();
}
var tmp = Const.config.install_item_dir.Split('/');
var item = Const.MultiEnvs.Where(o => o.Ip == Const.config.ip && o.FileName == tmp[tmp.Length - 1]).FirstOrDefault();
//3,运行init.sh脚本
sSH.Excute_Longcmd_NoError($"cd {installpath} && sudo docker-compose down ");
sSH.Excute_Longcmd_NoError($"rm -rf {installpath}");
handle?.Invoke("运行init.sh脚本...");
sSH.Excute_Longcmd_NoError($"sudo sh {tmpdir}/init.sh {tmpdir} {installpath} {webpath}");
sSH.Excute_Longcmd($"sed -i \"s/JL_NETWORK=.*/JL_NETWORK={item.FileName}_oi_net/\" {installpath}/.env");
//4.启动docker
handle?.Invoke("启动插件...");
sSH.Excute_Longcmd_NoError($"cd {installpath} && sudo docker-compose up -d ");
// 5, 添加开机启动
handle?.Invoke("添加开机启动...");
PluginAutoRestart(installpath, module_conf.Name);
// 6,清理缓存
handle?.Invoke("清理缓存...");
sSH.Excute_Longcmd($"sudo bash -c 'echo 3 > /proc/sys/vm/drop_caches'");
//7.删除临时文件
sSH.Excute_Longcmd($"rm -r {tmpdir}");
var tmp1 = filepath.Split('\\');
string filename = tmp1[tmp1.Length - 1];
if (sFTP.Exists($"/home/{Const.config.ssh_user}/ihdis/tools/" + filename))
sFTP.Delete($"/home/{Const.config.ssh_user}/ihdis/tools/" + filename);
handle?.Invoke("安装完成...");
sSH.Disconnect();
}
catch (Exception ex)
{
MessageBox.Show($"安装过程出错,请截图错误信息或复制日志后联系工程师!\r\n\r\n{ex.Message}");
}
}
else
{
#region Windows
var tmpdir = $"{Path.GetTempPath()}{module_conf.Name}{new Random().Next(10000, 20000)}";
//1.解压目录
Const.write_task_log("正在解压安装包...");
if (!Directory.Exists(tmpdir))
Directory.CreateDirectory(tmpdir);
Const.ExtractZipFile(filepath, tmpdir, "", null);
//2.创建安装目录
var installpath = $"{Const.config.install_dir}\\tools\\{module_conf.Name}";
if (!Directory.Exists(installpath))
Directory.CreateDirectory(installpath);
//3.进行插件初始化
handle?.Invoke("正在初始化插件...");
Init(tmpdir, installpath, hospital, handle);
Const.DeleteADirectory(tmpdir + "\\");
handle?.Invoke("安装完成...");
Thread.Sleep(2000);
#endregion
}
End_Init();
}
#endregion
#region 插件开机启动
public void PluginAutoRestart(string installPath, string model)
{
try
{
sSH.Excute_Longcmd($"sudo cd {installPath}");
sSH.Excute_Longcmd($"sudo echo '#!/bin/bash' > autostart_{model}.sh");
sSH.Excute_Longcmd($"sudo echo '#chkconfig:345 95 95' >> autostart_{model}.sh");
sSH.Excute_Longcmd($"sudo echo '#description:开机自启脚本' >> autostart_{model}.sh");
sSH.Excute_Longcmd($"sudo echo 'cd {installPath}' >> autostart_{model}.sh");
sSH.Excute_Longcmd($"sudo echo 'sudo docker-compose restart' >> autostart_{model}.sh");
sSH.Excute_Longcmd($"sudo mv autostart_{model}.sh /etc/rc.d/init.d");
sSH.Excute_Longcmd($"sudo chmod +x /etc/rc.d/init.d/autostart_{model}.sh");
sSH.Excute_Longcmd($"cd /etc/rc.d/init.d");
sSH.Excute_Longcmd($"sudo chkconfig --add autostart_{model}.sh");
//sSH.Excute_Longcmd($"chkconfig --list");
sSH.Excute_Longcmd($"sudo chkconfig autostart_{model}.sh on");
}
catch (Exception ex)
{
MessageBox.Show($"插件开机启动失败,请截图错误信息或复制日志后联系工程师!\r\n\r\n{ex.Message}");
}
}
#endregion
#region 上传文件
public void Upload(string filepath, Action<string> handle)
{
try
{
var tmp = filepath.Split('\\');
string filename = tmp[tmp.Length - 1];
sFTP.Connect();
if (sFTP.Exists($"/home/{Const.config.ssh_user}/ihdis/tools/" + filename))
{
handle?.Invoke($"删除同名更新包...");
sFTP.Delete($"/home/{Const.config.ssh_user}/ihdis/tools/" + filename);
handle?.Invoke($"【{filename}】删除完成...");
}
handle?.Invoke($"开始上传更新包...");
sFTP.Put(filepath, $"/home/{Const.config.ssh_user}/ihdis/tools/", filename);
handle?.Invoke($"更新包上传完成...");
sFTP.Disconnect();
}
catch (Exception ex)
{
MessageBox.Show($"上传文件失败,请截图错误信息或复制日志后联系工程师!\r\n\r\n{ex.Message}");
}
}
#endregion
/// <summary>
/// 初始化插件
/// </summary>
/// <param name="tmpdir"></param>
/// <param name="installPath"></param>
/// <param name="hospital"></param>
public void Init(string tmpdir, string installPath, string hospital, Action<string> handle)
{
var allOldLines = new List<string>();
if (File.Exists($"{installPath}\\.env"))
allOldLines = File.ReadAllLines($"{installPath}\\.env").ToList<string>();
Const.CopyDir(tmpdir, installPath);
var env = File.ReadAllText($"{tmpdir}\\.env").ToLower();
var tmp = Const.config.install_item_dir.Split('/');
var item = Const.MultiEnvs.Where(o => o.Ip == Const.config.ip && o.FileName == tmp[tmp.Length - 1]).FirstOrDefault();
// 判断安装插件类型
if (env.Contains("ts"))
{
Const.CopyDir($"{installPath}\\conf", $"{installPath}\\code");
CmdHelper.RunCmd($"docker load -i {installPath}\\ts.base.tar.gz\r\ndocker tag hh/ts:base hh/ts:1.33.0", out _);
}
else if (env.Contains("fsc"))
{
CmdHelper.RunCmd($"docker import {installPath}\\fsc.tar.gz hh/fsc:1.0.0", out _);
}
else if (env.Contains("hdis_qc")) // 质控插件
{
var allLines = File.ReadAllLines($"{tmpdir}\\.env").ToList<string>();
var projectNameStr = "PROJECT_NAME=";
var apiVersionStr = "API_VERSION=";
var webVersionStr = "WEB_VERSION=";
var projectName = allLines.Where(o => o.Contains(projectNameStr)).FirstOrDefault()?.Split('=')[1];
var apiVersion = allLines.Where(o => o.Contains(apiVersionStr)).FirstOrDefault()?.Split('=')[1];
var webVersion = allLines.Where(o => o.Contains(apiVersionStr)).FirstOrDefault()?.Split('=')[1];
#region 删除旧镜像
if (allOldLines.Any())
{
handle?.Invoke("开始删除旧镜像...");
var projectName1 = allOldLines.Where(o => o.Contains(projectNameStr)).FirstOrDefault()?.Split('=')[1];
var apiVersion1 = allOldLines.Where(o => o.Contains(apiVersionStr)).FirstOrDefault()?.Split('=')[1];
var webVersion1 = allOldLines.Where(o => o.Contains(apiVersionStr)).FirstOrDefault()?.Split('=')[1];
CmdHelper.RunCmd($"docker rmi {projectName1}/api:{apiVersion1}", out _);
CmdHelper.RunCmd($"docker rmi {projectName1}/web:{webVersion1}", out _);
handle?.Invoke("完成删除旧镜像...");
}
#endregion
handle?.Invoke("挂载镜像...");
#region 替换端口号、子网掩码
var newEnv = File.ReadAllText($"{tmpdir}\\.env").Replace("produce_oi_net", $"{item.FileName}_oi_net");
File.WriteAllText($"{installPath}/.env", newEnv);
var yml = File.ReadAllText($"{installPath}/docker-compose.yml");
yml = yml.Replace("produce_oi_net", $"{item.FileName}_oi_net");
File.WriteAllText($"{installPath}/docker-compose.yml", yml);
#endregion
//生成Docker Desktop挂载目录
Main_method.AddDockerMountPath(yml, installPath);
CmdHelper.RunCmd($"docker images --format \"{{{{.Repository}}}}:{{{{.Tag}}}}\"", out string res);
if (!res.Contains($"{projectName}/api:{apiVersion}"))
CmdHelper.RunCmd($"docker load -i {installPath}\\images\\{projectName}_api_{apiVersion}.tar", out _);
if (!res.Contains($"{projectName}/web:{apiVersion}"))
CmdHelper.RunCmd($"docker load -i {installPath}\\images\\{projectName}_web_{webVersion}.tar", out _);
handle?.Invoke("挂载镜像完成...");
}
var resultLog = string.Empty;
handle?.Invoke("正在启动容器...");
CmdHelper.RunCmd($"{installPath.Split(':')[0].Trim()}: \r\ncd {$"{installPath}/"}" +
$"\r\ndocker-compose up -d \r\nexit", out resultLog);
if (env.Contains("ts"))
{
var webPath = $"{Const.config.install_dir}\\{hospital}";
var webConf = $"{webPath}\\conf\\nginx\\site\\web.conf";
var webConfLines = File.ReadAllLines(webConf).ToList<string>();
if (!webConfLines.Any(o => o.Contains("ts/ts")))
{
webConfLines.Insert(6, " location /ts/ {");
webConfLines.Insert(7, " proxy_pass http://ts/ts/;");
webConfLines.Insert(8, " }");
File.WriteAllLines(webConf, webConfLines);
handle?.Invoke("正在重启nginx...");
CmdHelper.RunCmd($"{webPath.Split(':')[0].Trim()}: \r\ncd {$"{webPath}/"}" +
$"\r\ndocker-compose restart nginx \r\nexit", out _);
}
}
}
}
}