lxcfs-tools/libmount/container_work.go
zhangsong34 57c27bce2e modify package from iSulad-lxcfs-toolkit to lxcfs-tools
Signed-off-by: zhangsong34 <zhangsong34@huawei.com>
2020-01-21 17:14:32 +08:00

136 lines
3.4 KiB
Go

// Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved.
// lxcfs-tools is licensed under the Mulan PSL v1.
// You can use this software according to the terms and conditions of the Mulan PSL v1.
// You may obtain a copy of Mulan PSL v1 at:
// http://license.coscl.org.cn/MulanPSL
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
// PURPOSE.
// See the Mulan PSL v1 for more details.
// Description: mount/umount in container namespace
// Author: zhangsong
// Create: 2019-05-31
package libmount
import (
"encoding/json"
"fmt"
"lxcfs-tools/libmount/nsexec"
"os"
"strconv"
"strings"
"syscall"
"github.com/docker/docker/pkg/reexec"
)
var (
lxcfsPath = "/var/lib/lxc/lxcfs/cgroup"
)
func init() {
reexec.Register(nsexec.NsEnterReexecName, WorkInContainer)
}
func setupPipe(name string) (*os.File, error) {
v := os.Getenv(name)
fd, err := strconv.Atoi(v)
if err != nil {
return nil, fmt.Errorf("unable to convert %s=%s to int", name, v)
}
return os.NewFile(uintptr(fd), "pipe"), nil
}
func setupWorkType(name string) (int, error) {
v := os.Getenv(name)
worktype, err := strconv.Atoi(v)
if err != nil {
return -1, fmt.Errorf("unable to convert %s=%s to int", name, v)
}
return worktype, nil
}
// WorkInContainer will handle command in new namespace(container).
func WorkInContainer() {
var err error
var worktype int
var pipe *os.File
pipe, err = setupPipe(nsexec.InitPipe)
if err != nil {
fmt.Fprintf(os.Stderr, "%v", err)
return
}
// when pipe setup, should always send back the errors.
defer func() {
var msg nsexec.ErrMsg
if err != nil {
msg.Error = fmt.Sprintf("%s", err.Error())
}
if err := nsexec.WriteJSON(pipe, msg); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
}
}()
worktype, err = setupWorkType(nsexec.WorkType)
if err != nil {
return
}
// handle work here:
switch worktype {
case nsexec.MountMsg:
err = doMount(pipe)
case nsexec.UmountMsg:
err = doUmount(pipe)
default:
err = fmt.Errorf("unkown worktype=(%d)", worktype)
}
// do not need to check err here because we have check in defer
return
}
func doMount(pipe *os.File) error {
var mount nsexec.Mount
if err := json.NewDecoder(pipe).Decode(&mount); err != nil {
return err
}
// remount lxcfs cgroup path readonly
if err := syscall.Mount(mount.Rootfs+lxcfsPath, mount.Rootfs+lxcfsPath, "none", syscall.MS_BIND, ""); err != nil {
return err
}
if err := syscall.Mount(mount.Rootfs+lxcfsPath, mount.Rootfs+lxcfsPath, "none", syscall.MS_BIND|syscall.MS_REMOUNT|syscall.MS_RDONLY, ""); err != nil {
return err
}
for i := 0; i < len(mount.SrcPaths) && i < len(mount.DestPaths); i++ {
if err := syscall.Mount(mount.SrcPaths[i], mount.DestPaths[i], "none", syscall.MS_BIND, ""); err != nil {
return err
}
}
return nil
}
func doUmount(pipe *os.File) error {
var umount nsexec.Umount
if err := json.NewDecoder(pipe).Decode(&umount); err != nil {
return err
}
for i := 0; i < len(umount.Paths); i++ {
if err := syscall.Unmount(umount.Paths[i], syscall.MNT_DETACH); err != nil {
if !strings.Contains(err.Error(), "invalid argument") {
return err
}
}
}
if err := syscall.Unmount(lxcfsPath, 0); err != nil {
if !strings.Contains(err.Error(), "invalid argument") {
return err
}
}
return nil
}