// init prepares the LXContainer for this LXD Container // TODO: This gets called on each load of the container, // we might be able to split this is up into c.Start(). func (c *containerLXD) init() error { templateConfBase := "ubuntu" templateConfDir := os.Getenv("LXC_TEMPLATE_CONFIG") if templateConfDir == "" { templateConfDir = "/usr/share/lxc/config" } cc, err := lxc.NewContainer(c.NameGet(), c.daemon.lxcpath) if err != nil { return err } c.c = cc logfile := c.LogFilePathGet() if err := os.MkdirAll(filepath.Dir(logfile), 0700); err != nil { return err } if err = c.c.SetLogFile(logfile); err != nil { return err } personality, err := shared.ArchitecturePersonality(c.architecture) if err == nil { if err := c.c.SetConfigItem("lxc.arch", personality); err != nil { return err } } err = c.c.SetConfigItem("lxc.include", fmt.Sprintf("%s/%s.common.conf", templateConfDir, templateConfBase)) if err != nil { return err } if !c.IsPrivileged() { err = c.c.SetConfigItem("lxc.include", fmt.Sprintf("%s/%s.userns.conf", templateConfDir, templateConfBase)) if err != nil { return err } } if err := c.c.SetConfigItem("lxc.rootfs", c.RootfsPathGet()); err != nil { return err } if err := c.c.SetConfigItem("lxc.loglevel", "0"); err != nil { return err } if err := c.c.SetConfigItem("lxc.utsname", c.NameGet()); err != nil { return err } if err := c.c.SetConfigItem("lxc.tty", "0"); err != nil { return err } if err := setupDevLxdMount(c.c); err != nil { return err } /* apply profiles */ for _, p := range c.profiles { if err := c.applyProfile(p); err != nil { return err } } if err := c.setupMacAddresses(); err != nil { return err } /* now add the lxc.* entries for the configured devices */ if err := c.applyDevices(); err != nil { return err } if !c.IsPrivileged() { c.idmapset = c.daemon.IdmapSet // TODO - per-tenant idmaps } if err := c.mountShared(); err != nil { return err } if err := c.applyIdmapSet(); err != nil { return err } if err := c.applyConfig(c.config, false); err != nil { return err } return nil }
func newLxdContainer(name string, daemon *Daemon) (*lxdContainer, error) { d := &lxdContainer{ daemon: daemon, ephemeral: false, architecture: -1, cType: -1, id: -1} ephemInt := -1 templateConfBase := "ubuntu" templateConfDir := os.Getenv("LXC_TEMPLATE_CONFIG") if templateConfDir == "" { templateConfDir = "/usr/share/lxc/config" } q := "SELECT id, architecture, type, ephemeral FROM containers WHERE name=?" arg1 := []interface{}{name} arg2 := []interface{}{&d.id, &d.architecture, &d.cType, &ephemInt} err := dbQueryRowScan(daemon.db, q, arg1, arg2) if err != nil { return nil, err } if d.id == -1 { return nil, fmt.Errorf("Unknown container") } if ephemInt == 1 { d.ephemeral = true } c, err := lxc.NewContainer(name, daemon.lxcpath) if err != nil { return nil, err } d.c = c dir := shared.LogPath(c.Name()) err = os.MkdirAll(dir, 0700) if err != nil { return nil, err } if err = d.c.SetLogFile(filepath.Join(dir, "lxc.log")); err != nil { return nil, err } personality, err := shared.ArchitecturePersonality(d.architecture) if err == nil { err = c.SetConfigItem("lxc.arch", personality) if err != nil { return nil, err } } err = c.SetConfigItem("lxc.include", fmt.Sprintf("%s/%s.common.conf", templateConfDir, templateConfBase)) if err != nil { return nil, err } if !d.isPrivileged() { err = c.SetConfigItem("lxc.include", fmt.Sprintf("%s/%s.userns.conf", templateConfDir, templateConfBase)) if err != nil { return nil, err } } config, err := dbGetConfig(daemon.db, d.id) if err != nil { return nil, err } d.config = config profiles, err := dbGetProfiles(daemon.db, d.id) if err != nil { return nil, err } d.profiles = profiles d.devices = shared.Devices{} d.name = name rootfsPath := shared.VarPath("lxc", name, "rootfs") err = c.SetConfigItem("lxc.rootfs", rootfsPath) if err != nil { return nil, err } err = c.SetConfigItem("lxc.loglevel", "0") if err != nil { return nil, err } err = c.SetConfigItem("lxc.utsname", name) if err != nil { return nil, err } err = c.SetConfigItem("lxc.tty", "0") if err != nil { return nil, err } if err := setupDevLxdMount(c); err != nil { return nil, err } /* apply profiles */ for _, p := range profiles { err := applyProfile(daemon, d, p) if err != nil { return nil, err } } /* get container_devices */ newdevs, err := dbGetDevices(daemon.db, d.name, false) if err != nil { return nil, err } for k, v := range newdevs { d.devices[k] = v } if err := d.setupMacAddresses(daemon); err != nil { return nil, err } /* now add the lxc.* entries for the configured devices */ err = d.applyDevices() if err != nil { return nil, err } if !d.isPrivileged() { d.idmapset = daemon.IdmapSet // TODO - per-tenant idmaps } err = d.applyIdmapSet() if err != nil { return nil, err } err = d.applyConfig(d.config, false) if err != nil { return nil, err } return d, nil }
// init prepares the LXContainer for this LXD Container // TODO: This gets called on each load of the container, // we might be able to split this is up into c.Start(). func (c *containerLXD) init() error { templateConfBase := "ubuntu" templateConfDir := os.Getenv("LXD_LXC_TEMPLATE_CONFIG") if templateConfDir == "" { templateConfDir = "/usr/share/lxc/config" } cc, err := lxc.NewContainer(c.NameGet(), c.daemon.lxcpath) if err != nil { return err } c.c = cc logfile := c.LogFilePathGet() if err := os.MkdirAll(filepath.Dir(logfile), 0700); err != nil { return err } if err = c.c.SetLogFile(logfile); err != nil { return err } personality, err := shared.ArchitecturePersonality(c.architecture) if err == nil { if err := c.c.SetConfigItem("lxc.arch", personality); err != nil { return err } } err = c.c.SetConfigItem("lxc.include", fmt.Sprintf("%s/%s.common.conf", templateConfDir, templateConfBase)) if err != nil { return err } if err := c.c.SetConfigItem("lxc.rootfs", c.RootfsPathGet()); err != nil { return err } if err := c.c.SetConfigItem("lxc.loglevel", "0"); err != nil { return err } if err := c.c.SetConfigItem("lxc.utsname", c.NameGet()); err != nil { return err } if err := c.c.SetConfigItem("lxc.tty", "0"); err != nil { return err } if err := setupDevLxdMount(c.c); err != nil { return err } for _, p := range c.profiles { if err := c.applyProfile(p); err != nil { return err } } // base per-container config should override profile config, so we apply it second if err := c.applyConfig(c.baseConfig); err != nil { return err } if !c.IsPrivileged() || runningInUserns { err = c.c.SetConfigItem("lxc.include", fmt.Sprintf("%s/%s.userns.conf", templateConfDir, templateConfBase)) if err != nil { return err } } if c.IsNesting() { shared.Debugf("Setting up %s for nesting", c.name) orig := c.c.ConfigItem("lxc.mount.auto") auto := "" if len(orig) == 1 { auto = orig[0] } if !strings.Contains(auto, "cgroup") { auto = fmt.Sprintf("%s %s", auto, "cgroup:mixed") err = c.c.SetConfigItem("lxc.mount.auto", auto) if err != nil { return err } } /* * mount extra /proc and /sys to work around kernel * restrictions on remounting them when covered */ err = c.c.SetConfigItem("lxc.mount.entry", "proc dev/.lxc/proc proc create=dir,optional") if err != nil { return err } err = c.c.SetConfigItem("lxc.mount.entry", "sys dev/.lxc/sys sysfs create=dir,optional") if err != nil { return err } } /* * Until stacked apparmor profiles are possible, we have to run nested * containers unconfined */ if aaEnabled { if aaConfined() { curProfile := aaProfile() shared.Debugf("Running %s in current profile %s (nested container)", c.name, curProfile) curProfile = strings.TrimSuffix(curProfile, " (enforce)") if err := c.c.SetConfigItem("lxc.aa_profile", curProfile); err != nil { return err } } else if err := c.c.SetConfigItem("lxc.aa_profile", AAProfileName(c)); err != nil { return err } } if err := c.c.SetConfigItem("lxc.seccomp", SeccompProfilePath(c)); err != nil { return err } if err := c.setupMacAddresses(); err != nil { return err } // Allow overwrites of devices for k, v := range c.baseDevices { c.devices[k] = v } /* now add the lxc.* entries for the configured devices */ if err := c.applyDevices(); err != nil { return err } if !c.IsPrivileged() { if c.daemon.IdmapSet == nil { return fmt.Errorf("user has no subuids") } c.idmapset = c.daemon.IdmapSet // TODO - per-tenant idmaps } if err := c.mountShared(); err != nil { return err } if err := c.applyIdmapSet(); err != nil { return err } if err := c.applyPostDeviceConfig(); err != nil { return err } return nil }