github.com/apptainer/singularity@v3.1.1+incompatible/internal/app/singularity/oci_create_linux.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 "encoding/json" 10 "fmt" 11 "io/ioutil" 12 "os" 13 "path/filepath" 14 15 "github.com/opencontainers/runtime-tools/generate" 16 "github.com/sylabs/singularity/internal/pkg/buildcfg" 17 "github.com/sylabs/singularity/internal/pkg/runtime/engines/config" 18 "github.com/sylabs/singularity/internal/pkg/runtime/engines/oci" 19 "github.com/sylabs/singularity/internal/pkg/sylog" 20 "github.com/sylabs/singularity/internal/pkg/util/exec" 21 ) 22 23 // OciCreate creates a container from an OCI bundle 24 func OciCreate(containerID string, args *OciArgs) error { 25 starter := buildcfg.LIBEXECDIR + "/singularity/bin/starter" 26 27 _, err := getState(containerID) 28 if err == nil { 29 return fmt.Errorf("%s already exists", containerID) 30 } 31 32 os.Clearenv() 33 34 absBundle, err := filepath.Abs(args.BundlePath) 35 if err != nil { 36 return fmt.Errorf("failed to determine bundle absolute path: %s", err) 37 } 38 39 if err := os.Chdir(absBundle); err != nil { 40 return fmt.Errorf("failed to change directory to %s: %s", absBundle, err) 41 } 42 43 engineConfig := oci.NewConfig() 44 generator := generate.Generator{Config: &engineConfig.OciConfig.Spec} 45 engineConfig.SetBundlePath(absBundle) 46 engineConfig.SetLogPath(args.LogPath) 47 engineConfig.SetLogFormat(args.LogFormat) 48 engineConfig.SetPidFile(args.PidFile) 49 50 // load config.json from bundle path 51 configJSON := filepath.Join(absBundle, "config.json") 52 fb, err := os.Open(configJSON) 53 if err != nil { 54 return fmt.Errorf("OCI specification file %q is missing or cannot be read", configJSON) 55 } 56 57 data, err := ioutil.ReadAll(fb) 58 if err != nil { 59 return fmt.Errorf("failed to read OCI specification file %s: %s", configJSON, err) 60 } 61 62 fb.Close() 63 64 if err := json.Unmarshal(data, generator.Config); err != nil { 65 return fmt.Errorf("failed to parse OCI specification file %s: %s", configJSON, err) 66 } 67 68 Env := []string{sylog.GetEnvVar()} 69 70 engineConfig.EmptyProcess = args.EmptyProcess 71 engineConfig.SyncSocket = args.SyncSocketPath 72 73 commonConfig := &config.Common{ 74 ContainerID: containerID, 75 EngineName: oci.Name, 76 EngineConfig: engineConfig, 77 } 78 79 configData, err := json.Marshal(commonConfig) 80 if err != nil { 81 sylog.Fatalf("%s", err) 82 } 83 84 procName := fmt.Sprintf("Singularity OCI %s", containerID) 85 cmd, err := exec.PipeCommand(starter, []string{procName}, Env, configData) 86 cmd.Stdout = os.Stdout 87 cmd.Stderr = os.Stderr 88 cmd.Stdin = os.Stdin 89 90 return cmd.Run() 91 }