Beispiel #1
0
func iconGet(name, origin string) Response {
	lock, err := lockfile.Lock(dirs.SnapLockFile, true)
	if err != nil {
		return InternalError("unable to acquire lock: %v", err)
	}
	defer lock.Unlock()

	bag := lightweight.PartBagByName(name, origin)
	if bag == nil || len(bag.Versions) == 0 {
		return NotFound("unable to find snap with name %q and origin %q", name, origin)
	}

	part := bag.LoadBest()
	if part == nil {
		return NotFound("unable to load snap with name %q and origin %q", name, origin)
	}

	path := filepath.Clean(part.Icon())
	if !strings.HasPrefix(path, dirs.SnapSnapsDir) {
		// XXX: how could this happen?
		return BadRequest("requested icon is not in snap path")
	}

	return FileResponse(path)
}
Beispiel #2
0
func snapConfig(c *Command, r *http.Request) Response {
	vars := muxVars(r)
	name := vars["name"]
	origin := vars["origin"]
	if name == "" || origin == "" {
		return BadRequest("missing name or origin")
	}
	pkgName := name + "." + origin

	lock, err := lockfile.Lock(dirs.SnapLockFile, true)
	if err != nil {
		return InternalError("unable to acquire lock: %v", err)
	}
	defer lock.Unlock()

	bag := lightweight.PartBagByName(name, origin)
	if bag == nil {
		return NotFound("no snap found with name %q and origin %q", name, origin)
	}

	idx := bag.ActiveIndex()
	if idx < 0 {
		return BadRequest("unable to configure non-active snap")
	}

	part, err := bag.Load(idx)
	if err != nil {
		return InternalError("unable to load active snap: %v", err)
	}

	bs, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return BadRequest("reading config request body gave %v", err)
	}

	overlord := getConfigurator()
	config, err := overlord.Configure(part.(*snappy.SnapPart), bs)
	if err != nil {
		return InternalError("unable to retrieve config for %s: %v", pkgName, err)
	}

	return SyncResponse(config)
}
Beispiel #3
0
func getSnapInfo(c *Command, r *http.Request) Response {
	vars := muxVars(r)
	name := vars["name"]
	origin := vars["origin"]

	lock, err := lockfile.Lock(dirs.SnapLockFile, true)
	if err != nil {
		return InternalError("unable to acquire lock: %v", err)
	}
	defer lock.Unlock()

	repo := newRemoteRepo()
	var part snappy.Part
	if parts, _ := repo.Details(name, origin); len(parts) > 0 {
		part = parts[0]
	}

	bag := lightweight.PartBagByName(name, origin)
	if bag == nil && part == nil {
		return NotFound("unable to find snap with name %q and origin %q", name, origin)
	}

	route := c.d.router.Get(c.Path)
	if route == nil {
		return InternalError("router can't find route for snap %s.%s", name, origin)
	}

	url, err := route.URL("name", name, "origin", origin)
	if err != nil {
		return InternalError("route can't build URL for snap %s.%s: %v", name, origin, err)
	}

	result := webify(bag.Map(part), url.String())

	return SyncResponse(result)
}
Beispiel #4
0
func snapService(c *Command, r *http.Request) Response {
	route := c.d.router.Get(operationCmd.Path)
	if route == nil {
		return InternalError("router can't find route for operation")
	}

	vars := muxVars(r)
	name := vars["name"]
	origin := vars["origin"]
	if name == "" || origin == "" {
		return BadRequest("missing name or origin")
	}
	appName := vars["service"]
	pkgName := name + "." + origin

	action := "status"

	if r.Method != "GET" {
		decoder := json.NewDecoder(r.Body)
		var cmd map[string]string
		if err := decoder.Decode(&cmd); err != nil {
			return BadRequest("can't decode request body into service command: %v", err)
		}

		action = cmd["action"]
	}

	var lock lockfile.LockedFile
	reachedAsync := false
	switch action {
	case "status", "start", "stop", "restart", "enable", "disable":
		var err error
		lock, err = lockfile.Lock(dirs.SnapLockFile, true)

		if err != nil {
			return InternalError("unable to acquire lock: %v", err)
		}

		defer func() {
			if !reachedAsync {
				lock.Unlock()
			}
		}()
	default:
		return BadRequest("unknown action %s", action)
	}

	bag := lightweight.PartBagByName(name, origin)
	idx := bag.ActiveIndex()
	if idx < 0 {
		return NotFound("unable to find snap with name %q and origin %q", name, origin)
	}

	ipart, err := bag.Load(idx)
	if err != nil {
		return InternalError("unable to load active snap: %v", err)
	}

	part, ok := ipart.(*snappy.SnapPart)
	if !ok {
		return InternalError("active snap is not a *snappy.SnapPart: %T", ipart)
	}
	apps := part.Apps()

	if len(apps) == 0 {
		return NotFound("snap %q has no services", pkgName)
	}

	appmap := make(map[string]*appDesc, len(apps))
	for i := range apps {
		if apps[i].Daemon == "" {
			continue
		}
		appmap[apps[i].Name] = &appDesc{Spec: apps[i], Op: action}
	}

	if appName != "" && appmap[appName] == nil {
		return NotFound("snap %q has no service %q", pkgName, appName)
	}

	// note findServices takes the *bare* name
	actor, err := findServices(name, appName, &progress.NullProgress{})
	if err != nil {
		return InternalError("no services for %q [%q] found: %v", pkgName, appName, err)
	}

	f := func() interface{} {
		status, err := actor.ServiceStatus()
		if err != nil {
			logger.Noticef("unable to get status for %q [%q]: %v", pkgName, appName, err)
			return err
		}

		for i := range status {
			if desc, ok := appmap[status[i].ServiceName]; ok {
				desc.Status = status[i]
			} else {
				// shouldn't really happen, but can't hurt
				appmap[status[i].ServiceName] = &appDesc{Status: status[i]}
			}
		}

		if appName == "" {
			return appmap
		}

		return appmap[appName]
	}

	if action == "status" {
		return SyncResponse(f())
	}

	reachedAsync = true

	return AsyncResponse(c.d.AddTask(func() interface{} {
		defer lock.Unlock()

		switch action {
		case "start":
			err = actor.Start()
		case "stop":
			err = actor.Stop()
		case "enable":
			err = actor.Enable()
		case "disable":
			err = actor.Disable()
		case "restart":
			err = actor.Restart()
		}

		if err != nil {
			logger.Noticef("unable to %s %q [%q]: %v\n", action, pkgName, appName, err)
			return err
		}

		return f()
	}).Map(route))
}