func (c *container) Cleanup(portoConn porto.API) { if !c.cleanupEnabled { return } var err error if err = portoConn.UnlinkVolume(c.volumePath, c.containerID); err != nil { apexctx.GetLogger(c.ctx).WithField("id", c.containerID).WithError(err).Warnf("Unlink volume %s", c.volumePath) } else { apexctx.GetLogger(c.ctx).WithField("id", c.containerID).Debugf("Unlink volume %s successfully", c.volumePath) } if err = portoConn.UnlinkVolume(c.volumePath, "self"); err != nil { apexctx.GetLogger(c.ctx).WithField("id", "self").WithError(err).Warnf("Unlink volume %s", c.volumePath) } else { apexctx.GetLogger(c.ctx).WithField("id", "self").Debugf("Unlink volume %s successfully", c.volumePath) } if err = portoConn.Destroy(c.containerID); err != nil { apexctx.GetLogger(c.ctx).WithField("id", c.containerID).WithError(err).Warn("Destroy error") } else { apexctx.GetLogger(c.ctx).WithField("id", c.containerID).Debugf("Destroyed") } if err = os.RemoveAll(c.rootDir); err != nil { apexctx.GetLogger(c.ctx).WithField("id", c.containerID).WithError(err).Warnf("Remove dirs %s", c.rootDir) } else { apexctx.GetLogger(c.ctx).WithField("id", c.containerID).Debugf("Remove dirs %s successfully", c.rootDir) } }
func newContainer(ctx context.Context, portoConn porto.API, cfg containerConfig, info execInfo) (cnt *container, err error) { apexctx.GetLogger(ctx).WithField("container", cfg.ID).Debugf("exec newContainer() with containerConfig: %s; execInfo: %s;", cfg, info) volumeProperties := map[string]string{ "backend": cfg.VolumeBackend, "layers": cfg.Layer, "private": "cocaine-app", } if err = info.applyVolumeLimits(ctx, cfg.ID, volumeProperties); err != nil { return nil, err } volumePath := filepath.Join(cfg.Root, "volume") if err = os.MkdirAll(volumePath, 0775); err != nil { return nil, err } defer func(err *error) { if *err != nil { apexctx.GetLogger(ctx).WithField("container", cfg.ID).Infof("cleaunup unfinished container footprint due to error %v", *err) portoConn.UnlinkVolume(volumePath, cfg.ID) os.RemoveAll(volumePath) } }(&err) volumeDescription, err := portoConn.CreateVolume(volumePath, volumeProperties) apexctx.GetLogger(ctx).WithField("container", cfg.ID).Debugf("create volume with volumeProperties: %s", volumeProperties) if err != nil { if !isEqualPortoError(err, portorpc.EError_VolumeAlreadyExists) { apexctx.GetLogger(ctx).WithError(err).WithField("container", cfg.ID).Error("unable to create volume") return nil, err } apexctx.GetLogger(ctx).WithField("container", cfg.ID).Info("volume already exists") } else { apexctx.GetLogger(ctx).WithField("container", cfg.ID).Infof("created volume %v", volumeDescription) } if err = portoConn.Create(cfg.ID); err != nil { return nil, err } if cfg.SetImgURI { info.env["image_uri"] = info.portoProfile.Registry() + "/" + info.name } if err = portoConn.SetProperty(cfg.ID, "bind", formatBinds(&info)); err != nil { return nil, err } if err = portoConn.SetProperty(cfg.ID, "command", formatCommand(info.executable, info.args)); err != nil { return nil, err } if err = portoConn.SetProperty(cfg.ID, "env", formatEnv(info.env)); err != nil { return nil, err } if info.ulimits != "" { if err = portoConn.SetProperty(cfg.ID, "ulimit", info.ulimits); err != nil { return nil, err } } if cwd := info.Cwd(); cwd != "" { if err = portoConn.SetProperty(cfg.ID, "cwd", cwd); err != nil { return nil, err } } if err = portoConn.SetProperty(cfg.ID, "net", pickNetwork(string(info.NetworkMode()))); err != nil { return nil, err } if err = portoConn.SetProperty(cfg.ID, "enable_porto", "false"); err != nil { return nil, err } if err = portoConn.SetProperty(cfg.ID, "root", volumePath); err != nil { return nil, err } if err = portoConn.LinkVolume(volumePath, cfg.ID); err != nil { return nil, err } if err = info.portoProfile.applyContainerLimits(ctx, portoConn, cfg.ID); err != nil { return nil, err } cnt = &container{ ctx: ctx, containerID: cfg.ID, rootDir: cfg.Root, volumePath: volumePath, cleanupEnabled: cfg.CleanupEnabled, SetImgURI: cfg.SetImgURI, output: ioutil.Discard, } return cnt, nil }