github.com/apptainer/singularity@v3.1.1+incompatible/internal/pkg/runtime/engines/singularity/create.go (about)

     1  // Copyright (c) 2018-2019, Sylabs Inc. All rights reserved.
     2  // This software is licensed under a 3-clause BSD license. Please consult the
     3  // LICENSE.md file distributed with the sources of this project regarding your
     4  // rights to use or distribute this software.
     5  
     6  package singularity
     7  
     8  import (
     9  	"fmt"
    10  	"net"
    11  	"net/rpc"
    12  	"os"
    13  	"path/filepath"
    14  
    15  	specs "github.com/opencontainers/runtime-spec/specs-go"
    16  	"github.com/sylabs/singularity/internal/pkg/buildcfg"
    17  	"github.com/sylabs/singularity/internal/pkg/runtime/engines/config"
    18  	singularityConfig "github.com/sylabs/singularity/internal/pkg/runtime/engines/singularity/config"
    19  	"github.com/sylabs/singularity/internal/pkg/runtime/engines/singularity/rpc/client"
    20  )
    21  
    22  // CreateContainer creates a container
    23  func (engine *EngineOperations) CreateContainer(pid int, rpcConn net.Conn) error {
    24  	if engine.CommonConfig.EngineName != singularityConfig.Name {
    25  		return fmt.Errorf("engineName configuration doesn't match runtime name")
    26  	}
    27  
    28  	if engine.EngineConfig.GetInstanceJoin() {
    29  		return nil
    30  	}
    31  
    32  	configurationFile := buildcfg.SYSCONFDIR + "/singularity/singularity.conf"
    33  	if err := config.Parser(configurationFile, engine.EngineConfig.File); err != nil {
    34  		return fmt.Errorf("Unable to parse singularity.conf file: %s", err)
    35  	}
    36  
    37  	rpcOps := &client.RPC{
    38  		Client: rpc.NewClient(rpcConn),
    39  		Name:   engine.CommonConfig.EngineName,
    40  	}
    41  	if rpcOps.Client == nil {
    42  		return fmt.Errorf("failed to initialiaze RPC client")
    43  	}
    44  
    45  	if engine.EngineConfig.GetInstance() {
    46  		namespaces := []struct {
    47  			nstype       string
    48  			ns           specs.LinuxNamespaceType
    49  			checkEnabled bool
    50  		}{
    51  			{"pid", specs.PIDNamespace, false},
    52  			{"uts", specs.UTSNamespace, false},
    53  			{"ipc", specs.IPCNamespace, false},
    54  			{"mnt", specs.MountNamespace, false},
    55  			{"cgroup", specs.CgroupNamespace, false},
    56  			{"net", specs.NetworkNamespace, false},
    57  			{"user", specs.UserNamespace, true},
    58  		}
    59  
    60  		path := fmt.Sprintf("/proc/%d/ns", pid)
    61  		ppid := os.Getpid()
    62  
    63  		for _, n := range namespaces {
    64  			has, err := rpcOps.HasNamespace(ppid, n.nstype)
    65  			if err == nil && (has || n.checkEnabled) {
    66  				enabled := false
    67  				if n.checkEnabled {
    68  					if engine.EngineConfig.OciConfig.Linux != nil {
    69  						for _, namespace := range engine.EngineConfig.OciConfig.Linux.Namespaces {
    70  							if n.ns == namespace.Type {
    71  								enabled = true
    72  								break
    73  							}
    74  						}
    75  					}
    76  				}
    77  				if has || enabled {
    78  					nspath := filepath.Join(path, n.nstype)
    79  					engine.EngineConfig.OciConfig.AddOrReplaceLinuxNamespace(string(n.ns), nspath)
    80  				}
    81  			} else if err != nil {
    82  				return fmt.Errorf("failed to check %s root and container namespace: %s", n.ns, err)
    83  			}
    84  		}
    85  	}
    86  
    87  	return create(engine, rpcOps, pid)
    88  }