zhangqian
2023-10-13 13194e787d51e4ce07dfc35341d536fb5db7aaa3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package service
 
import (
    "aps_crm/pkg/logx"
    "aps_crm/utils"
    "errors"
    "fmt"
    "io/ioutil"
    "os"
    "os/exec"
)
 
/*
    管理dir类型的container的生命周期的管理器
*/
 
type DirContainerImpl struct{}
 
// Image 获取容器化用户一整套运行环境的基础目录
func (slf *DirContainerImpl) Image() string {
    return "/var/data/aps/sys"
}
 
// GetContainerRoot 获取容器目录的根路径地址
func (slf *DirContainerImpl) GetContainerRoot() string {
    return "/var/data/aps/container"
}
 
/*
    将生成的用户id写入到新分配的container(配置文件)中,container中所有进程启动后注册到etcd
 
时,内部服务的key都包含有此主账号的id。container内部中的服务调用时,只会调用到内部注册有此用户id的
key的服务,所有container对外部来说是隔离的。
*/
func (slf *DirContainerImpl) Init(cId string) error {
    logx.Infof("DirContainerImpl Init cId:", cId)
    root := slf.GetContainerRoot()
    uDir := root + "/" + cId
    if !utils.DirExists(uDir) {
        if err := os.MkdirAll(uDir, os.ModePerm); err != nil {
            logx.Errorf("mkdir container Root err:", err)
            return err
        }
    } else {
        logx.Errorf("container ", cId, " exist")
        return errors.New("container " + cId + " exist")
    }
    if !utils.DirExists(slf.Image()) {
        logx.Errorf("saas 系统运行环境文件不存在,请检查")
        return errors.New("saas 系统运行环境文件不存在,请检查")
    }
    var err error
    defer func() {
        if err != nil {
            logx.Errorf("rollback err:", err)
            os.RemoveAll(uDir)
        }
    }()
    _, err = utils.CopyDirByCmd(slf.Image()+"/*", uDir)
    if err != nil {
        logx.Errorf("CopyDirByCmd err:", err)
        return err
    }
    //将创建容器的主账号id写入到容器中
    err = ioutil.WriteFile(uDir+"/bin/container.txt", []byte(cId), os.ModePerm)
    if err != nil {
        logx.Errorf("ioutil.WriteFile err:", err)
        return err
    }
    //配置开机启动
 
    //启动容器
    err = slf.Start(cId)
    if err != nil {
        logx.Errorf("start container err:", err, " id:", cId)
        return err
    }
 
    return nil
}
 
// Start 启动指定的用户容器
func (slf *DirContainerImpl) Start(cId string) error {
    uroot := slf.GetContainerRoot() + "/" + cId
    sh := fmt.Sprintf("%s %s &", uroot+"/start.sh", uroot)
    cmd := exec.Command("sh", "-C", sh)
    ret, e := cmd.Output()
    if e != nil {
        return e
    }
    logx.Infof("start container "+cId+", ret: ", ret)
    return nil
}
 
// Stop 停止指定的用户容器
func (slf *DirContainerImpl) Stop(cId string) error {
    uroot := slf.GetContainerRoot() + "/" + cId
    sh := fmt.Sprintf("%s %s", uroot+"/stop.sh", uroot)
    cmd := exec.Command("sh", "-C", sh)
    ret, e := cmd.Output()
    if e != nil {
        return e
    }
    logx.Infof("stop container "+cId+", ret: ", ret)
    return nil
}
 
// Restart 重新启动指定的用户容器
func (slf *DirContainerImpl) Restart(cId string) error {
    err := slf.Stop(cId)
    if err != nil {
        return err
    }
    err = slf.Start(cId)
    if err != nil {
        return err
    }
    return nil
}
 
// BakData 备份容器中的用户数据
func (slf *DirContainerImpl) BakData(cId string) error {
    bdir := slf.GetContainerRoot() + "/bak"
    if !utils.DirExists(bdir) {
        err := os.MkdirAll(bdir, os.ModePerm)
        if err != nil {
            return err
        }
    }
    ret, err := utils.CopyDirByCmd(slf.GetContainerRoot()+"/"+cId, bdir)
    if err != nil {
        return err
    }
    logx.Infof("Bake container:", cId, " ret:", ret)
    return nil
}
 
// Destroy 删除指定的用户容器
func (slf *DirContainerImpl) Destroy(cId string) error {
    if err := slf.BakData(cId); err != nil {
        return err
    }
    err := slf.Stop(cId)
    if err != nil {
        return err
    }
    uroot := slf.GetContainerRoot() + "/" + cId
    if utils.DirExists(uroot) {
        os.RemoveAll(uroot)
    }
    return nil
}
 
func (slf *DirContainerImpl) watch() {
    return
}