/
driver.go
233 lines (196 loc) · 5.94 KB
/
driver.go
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
package driver
import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
"syscall"
)
const (
DriverURL = "/var/lib/gocker/overlay/"
)
// 创建一个overlay2的文件系统
func NewWorkSpace(volume, imageName, layerName string) {
//DEBUG
Sugar.Debugf("New work space in : %v",OverlayDir + layerName)
if err := CreateReadOnlyLayer(imageName, layerName); err != nil {
Sugar.Errorf("create lowerdir %s error %v", layerName+"/lower", err)
}
if err := CreateWriteLayer(layerName); err != nil {
Sugar.Errorf("create writer lay %s error %v", layerName, err)
}
if volume != "" {
volumeURLs := strings.Split(volume, ":")
length := len(volumeURLs)
if length == 2 && volumeURLs[0] != "" && volumeURLs[1] != "" {
//TODO
Sugar.Infof("volume.len >=2 and volume is %v", volumeURLs)
} else {
Sugar.Infof("Volume parmeter input is not correct")
}
}
}
// 创建只读的lower层
// 复制一份可执行文件过来
// TODO: 支持java等的语言
func CreateReadOnlyLayer(imageName, layerName string) error {
lowerdirUrl := DriverURL + "/" + layerName + "/" + "lower"
exist, err := PathExists(lowerdirUrl)
if err != nil {
Sugar.Infof("Fail to judege whether lowerdir %s exists, %v", lowerdirUrl, err)
return nil
}
// 注意权限!这里创建的是只读
if !exist {
if err := os.MkdirAll(lowerdirUrl, 0622); err != nil {
Sugar.Errorf("Mkdir %s error %v", lowerdirUrl, err)
return err
}
}
// readlink 在获取 /bin/sh 会变成 dash
//programUrl, err := os.Readlink(imageName)
//if err != nil {
// Sugar.Errorf("Run program %s is not exist",programUrl)
// return err
//}
programUrl := imageName
programPath := lowerdirUrl + "/" + filepath.Dir(programUrl)
// 判断是否在 . 或 / 下
if programPath == "." || programPath == "/" {
programPath = ""
}
dstProgramUrl := lowerdirUrl + programUrl
if err := os.MkdirAll(programPath, 0700); err != nil {
Sugar.Errorf("Mkdir %s error %v", programUrl, err)
return err
}
if err := copyFile(programUrl, dstProgramUrl); err != nil {
Sugar.Errorf("copy run programurl %s error %v", programUrl, err)
}
return nil
}
//拷贝文件 要拷贝的文件路径 拷贝到哪里
func copyFile(source, dest string) error {
if source == "" || dest == "" {
Sugar.Info("source or dest is null")
return fmt.Errorf("src--%s or dst--%s is null")
}
//打开文件资源
source_open, err := os.Open(source)
//养成好习惯。操作文件时候记得添加 defer 关闭文件资源代码
if err != nil {
return err
}
defer source_open.Close()
//只写模式打开文件 如果文件不存在进行创建 并赋予 644的权限。详情查看linux 权限解释
dest_open, err := os.OpenFile(dest, os.O_CREATE|os.O_WRONLY, 0744)
if err != nil {
return err
}
//养成好习惯。操作文件时候记得添加 defer 关闭文件资源代码
defer dest_open.Close()
//进行数据拷贝
_, copy_err := io.Copy(dest_open, source_open)
if copy_err != nil {
return err
} else {
return nil
}
}
// 创建并挂载 work,upper,merged
func CreateWriteLayer(layerName string) error {
basedir := OverlayDir + layerName
lowerdir := basedir + "/lower"
workdir := basedir + "/work"
if err := os.MkdirAll(workdir, 0755); err != nil {
Sugar.Errorf("Mkdir %s error %v", workdir, err)
return err
}
upperdir := basedir + "/upper"
if err := os.MkdirAll(upperdir, 0755); err != nil {
Sugar.Errorf("Mkdir %s error %v", workdir, err)
return err
}
mergeddir := basedir + "/merged"
if err := os.MkdirAll(mergeddir, 0755); err != nil {
Sugar.Errorf("Mkdir %s error %v", workdir, err)
return err
}
opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lowerdir, upperdir, workdir)
// MS_NOSUID 文件系统执行程序时,不要使用该用户ID和组ID
if err := syscall.Mount("none", mergeddir, "overlay", syscall.MS_NOSUID, opts); err != nil {
Sugar.Errorf("mount overlay opts : %s error %v", opts, err)
return err
}
return nil
}
// 删除容器overlay filesystem(仅保留lower层
func DeleteWorkSpace(volueme, layerName string) {
if volueme != "" {
volumeURLs := strings.Split(volueme, ":")
length := len(volumeURLs)
if length == 2 && volumeURLs[0] != "" && volumeURLs[1] != "" {
DeleteVolumes(volumeURLs, layerName)
}
}
if err := DeleteMountPoint(layerName); err == nil {
// umount 成功后才能删除其他overlay层
DeleteWriteLayer(layerName)
}
}
func DeleteMountPoint(overlayDir string) error {
mergeddir := OverlayDir + overlayDir + "/merged"
if err := syscall.Unmount(mergeddir, 0); err != nil {
Sugar.Errorf("Unmount %s error %v", overlayDir, err)
return err
}
if err := os.RemoveAll(mergeddir); err != nil {
Sugar.Errorf("Remove mountpoint dir %s error %v", mergeddir, err)
return err
}
return nil
}
func DeleteVolumes(volumeURLs []string, layName string) error {
mntURL := fmt.Sprintf(OverlayDir, layName)
volume := mntURL + "/" + volumeURLs[1]
if err := syscall.Unmount(volume, 0); err != nil {
Sugar.Errorf("Umount volume %s error %v", volume, err)
return err
}
return nil
}
// 从磁盘上删除overlay层
// 一定要先unmount后才进行删除!!!
func DeleteWriteLayer(layerName string) {
workdir := OverlayDir + layerName + "/workdir"
if err := os.RemoveAll(workdir); err != nil {
Sugar.Warnf("Remove overlay %s error %v", workdir, err)
}
upperdir := OverlayDir + layerName + "/upper"
if err := os.RemoveAll(upperdir); err != nil {
Sugar.Warnf("Remove overlay %s error %v", workdir, err)
}
mergeddir := OverlayDir + layerName + "/merged"
if err := os.RemoveAll(mergeddir); err != nil {
Sugar.Warnf("Remove overlay %s error %v", workdir, err)
}
}
//TODO
//func MountVolume(volumeURLs []string, containerName string) error {
// parentUrl := volumeURLs[0]
// if err := os.MkdirAll(parentUrl,0700);err != nil {
//
// }
//}
// 判断文件/文件夹是否存在
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}