// LoadContainer loads a Container Runtime Manifest (as prepared by stage0) and // its associated Application Manifests, under $root/stage1/opt/stage1/$apphash func LoadContainer(root string) (*Container, error) { c := &Container{ Root: root, Apps: make(map[string]*schema.AppManifest), } buf, err := ioutil.ReadFile(rktpath.ContainerManifestPath(c.Root)) if err != nil { return nil, fmt.Errorf("failed reading container runtime manifest: %v", err) } cm := &schema.ContainerRuntimeManifest{} if err := json.Unmarshal(buf, cm); err != nil { return nil, fmt.Errorf("failed unmarshalling container runtime manifest: %v", err) } c.Manifest = cm for _, app := range c.Manifest.Apps { ampath := rktpath.AppManifestPath(c.Root, app.ImageID) buf, err := ioutil.ReadFile(ampath) if err != nil { return nil, fmt.Errorf("failed reading app manifest %q: %v", ampath, err) } am := &schema.AppManifest{} if err = json.Unmarshal(buf, am); err != nil { return nil, fmt.Errorf("failed unmarshalling app manifest %q: %v", ampath, err) } name := am.Name.String() if _, ok := c.Apps[name]; ok { return nil, fmt.Errorf("got multiple definitions for app: %s", name) } c.Apps[name] = am } return c, nil }
// Setup sets up a filesystem for a container based on the given config. // The directory containing the filesystem is returned, and any error encountered. func Setup(cfg Config) (string, error) { if cfg.Debug { log.SetOutput(os.Stderr) } cuuid, err := types.NewUUID(uuid.New()) if err != nil { return "", fmt.Errorf("error creating UID: %v", err) } // TODO(jonboulle): collision detection/mitigation // Create a directory for this container dir := filepath.Join(cfg.ContainersDir, cuuid.String()) if err := os.MkdirAll(dir, 0700); err != nil { return "", fmt.Errorf("error creating directory: %v", err) } log.Printf("Unpacking stage1 rootfs") if cfg.Stage1Rootfs != "" { err = unpackRootfs(cfg.Stage1Rootfs, rktpath.Stage1RootfsPath(dir)) } else { err = unpackBuiltinRootfs(rktpath.Stage1RootfsPath(dir)) } if err != nil { return "", fmt.Errorf("error unpacking rootfs: %v", err) } log.Printf("Writing stage1 init") var in io.Reader if cfg.Stage1Init != "" { in, err = os.Open(cfg.Stage1Init) if err != nil { return "", fmt.Errorf("error loading stage1 init binary: %v", err) } } else { init_bin, err := stage1_init.Asset("s1init") if err != nil { return "", fmt.Errorf("error accessing stage1 init bindata: %v", err) } in = bytes.NewBuffer(init_bin) } fn := filepath.Join(dir, initPath) out, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY, 0555) if err != nil { return "", fmt.Errorf("error opening stage1 init for writing: %v", err) } if _, err := io.Copy(out, in); err != nil { return "", fmt.Errorf("error writing stage1 init: %v", err) } if err := out.Close(); err != nil { return "", fmt.Errorf("error closing stage1 init: %v", err) } log.Printf("Wrote filesystem to %s\n", dir) cm := schema.ContainerRuntimeManifest{ ACKind: "ContainerRuntimeManifest", UUID: *cuuid, Apps: make(schema.AppList, 0), } v, err := types.NewSemVer(version.Version) if err != nil { return "", fmt.Errorf("error creating version: %v", err) } cm.ACVersion = *v for _, img := range cfg.Images { am, err := setupImage(cfg, img, dir) if err != nil { return "", fmt.Errorf("error setting up image %s: %v", img, err) } if cm.Apps.Get(am.Name) != nil { return "", fmt.Errorf("error: multiple apps with name %s", am.Name) } a := schema.App{ Name: am.Name, ImageID: img, Isolators: am.Isolators, Annotations: am.Annotations, } cm.Apps = append(cm.Apps, a) } var sVols []types.Volume for key, path := range cfg.Volumes { v := types.Volume{ Kind: "host", Source: path, ReadOnly: true, Fulfills: []types.ACName{ types.ACName(key), }, } sVols = append(sVols, v) } // TODO(jonboulle): check that app mountpoint expectations are // satisfied here, rather than waiting for stage1 cm.Volumes = sVols cdoc, err := json.Marshal(cm) if err != nil { return "", fmt.Errorf("error marshalling container manifest: %v", err) } log.Printf("Writing container manifest") fn = rktpath.ContainerManifestPath(dir) if err := ioutil.WriteFile(fn, cdoc, 0700); err != nil { return "", fmt.Errorf("error writing container manifest: %v", err) } return dir, nil }