summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pkg/storage/doc.go5
-rw-r--r--pkg/storage/image.go551
-rw-r--r--pkg/storage/image_regexp.go125
-rw-r--r--pkg/storage/runtime.go452
4 files changed, 0 insertions, 1133 deletions
diff --git a/pkg/storage/doc.go b/pkg/storage/doc.go
deleted file mode 100644
index 6366b22a4..000000000
--- a/pkg/storage/doc.go
+++ /dev/null
@@ -1,5 +0,0 @@
-// Package storage provides helper functions for creating and managing CRI pod
-// sandboxes and containers and metadata associated with them in the format
-// that crio understands. The API it provides should be considered to be
-// unstable.
-package storage
diff --git a/pkg/storage/image.go b/pkg/storage/image.go
deleted file mode 100644
index 1ddfe2107..000000000
--- a/pkg/storage/image.go
+++ /dev/null
@@ -1,551 +0,0 @@
-package storage
-
-import (
- "errors"
- "fmt"
- "net"
- "path"
- "regexp"
- "strings"
-
- "github.com/containers/image/copy"
- "github.com/containers/image/docker/reference"
- "github.com/containers/image/image"
- "github.com/containers/image/signature"
- istorage "github.com/containers/image/storage"
- "github.com/containers/image/transports/alltransports"
- "github.com/containers/image/types"
- "github.com/containers/storage"
- distreference "github.com/docker/distribution/reference"
-)
-
-// ImageResult wraps a subset of information about an image: its ID, its names,
-// and the size, if known, or nil if it isn't.
-type ImageResult struct {
- ID string
- Names []string
- Digests []string
- Size *uint64
- ImageRef string
-}
-
-type indexInfo struct {
- name string
- secure bool
-}
-
-type imageService struct {
- store storage.Store
- defaultTransport string
- insecureRegistryCIDRs []*net.IPNet
- indexConfigs map[string]*indexInfo
- registries []string
-}
-
-// ImageServer wraps up various CRI-related activities into a reusable
-// implementation.
-type ImageServer interface {
- // ListImages returns list of all images which match the filter.
- ListImages(systemContext *types.SystemContext, filter string) ([]ImageResult, error)
- // ImageStatus returns status of an image which matches the filter.
- ImageStatus(systemContext *types.SystemContext, filter string) (*ImageResult, error)
- // PullImage imports an image from the specified location.
- PullImage(systemContext *types.SystemContext, imageName string, options *copy.Options) (types.ImageReference, error)
- // UntagImage removes a name from the specified image, and if it was
- // the only name the image had, removes the image.
- UntagImage(systemContext *types.SystemContext, imageName string) error
- // RemoveImage deletes the specified image.
- RemoveImage(systemContext *types.SystemContext, imageName string) error
- // GetStore returns the reference to the storage library Store which
- // the image server uses to hold images, and is the destination used
- // when it's asked to pull an image.
- GetStore() storage.Store
- // CanPull preliminary checks whether we're allowed to pull an image
- CanPull(imageName string, options *copy.Options) (bool, error)
- // ResolveNames takes an image reference and if it's unqualified (w/o hostname),
- // it uses crio's default registries to qualify it.
- ResolveNames(imageName string) ([]string, error)
-}
-
-func (svc *imageService) getRef(name string) (types.ImageReference, error) {
- ref, err := alltransports.ParseImageName(name)
- if err != nil {
- ref2, err2 := istorage.Transport.ParseStoreReference(svc.store, "@"+name)
- if err2 != nil {
- ref3, err3 := istorage.Transport.ParseStoreReference(svc.store, name)
- if err3 != nil {
- return nil, err
- }
- ref2 = ref3
- }
- ref = ref2
- }
- return ref, nil
-}
-
-func (svc *imageService) ListImages(systemContext *types.SystemContext, filter string) ([]ImageResult, error) {
- results := []ImageResult{}
- if filter != "" {
- ref, err := svc.getRef(filter)
- if err != nil {
- return nil, err
- }
- if image, err := istorage.Transport.GetStoreImage(svc.store, ref); err == nil {
- img, err := ref.NewImage(systemContext)
- if err != nil {
- return nil, err
- }
- size := imageSize(img)
- img.Close()
- results = append(results, ImageResult{
- ID: image.ID,
- Names: image.Names,
- Size: size,
- })
- }
- } else {
- images, err := svc.store.Images()
- if err != nil {
- return nil, err
- }
- for _, image := range images {
- ref, err := istorage.Transport.ParseStoreReference(svc.store, "@"+image.ID)
- if err != nil {
- return nil, err
- }
- img, err := ref.NewImage(systemContext)
- if err != nil {
- return nil, err
- }
- size := imageSize(img)
- img.Close()
- results = append(results, ImageResult{
- ID: image.ID,
- Names: image.Names,
- Size: size,
- })
- }
- }
- return results, nil
-}
-
-func (svc *imageService) ImageStatus(systemContext *types.SystemContext, nameOrID string) (*ImageResult, error) {
- ref, err := alltransports.ParseImageName(nameOrID)
- if err != nil {
- ref2, err2 := istorage.Transport.ParseStoreReference(svc.store, "@"+nameOrID)
- if err2 != nil {
- ref3, err3 := istorage.Transport.ParseStoreReference(svc.store, nameOrID)
- if err3 != nil {
- return nil, err
- }
- ref2 = ref3
- }
- ref = ref2
- }
- image, err := istorage.Transport.GetStoreImage(svc.store, ref)
- if err != nil {
- return nil, err
- }
-
- img, err := ref.NewImage(systemContext)
- if err != nil {
- return nil, err
- }
- size := imageSize(img)
- img.Close()
-
- result := ImageResult{
- ID: image.ID,
- Names: image.Names,
- Size: size,
- }
- if len(image.Names) > 0 {
- result.ImageRef = image.Names[0]
- if ref2, err2 := istorage.Transport.ParseStoreReference(svc.store, image.Names[0]); err2 == nil {
- if dref := ref2.DockerReference(); dref != nil {
- result.ImageRef = reference.FamiliarString(dref)
- }
- }
- }
-
- return &result, nil
-}
-
-func imageSize(img types.Image) *uint64 {
- if sum, err := img.Size(); err == nil {
- usum := uint64(sum)
- return &usum
- }
- return nil
-}
-
-func (svc *imageService) CanPull(imageName string, options *copy.Options) (bool, error) {
- srcRef, err := svc.prepareImage(imageName, options)
- if err != nil {
- return false, err
- }
- rawSource, err := srcRef.NewImageSource(options.SourceCtx)
- if err != nil {
- return false, err
- }
- src, err := image.FromSource(options.SourceCtx, rawSource)
- if err != nil {
- rawSource.Close()
- return false, err
- }
- src.Close()
- return true, nil
-}
-
-// prepareImage creates an image reference from an image string and set options
-// for the source context
-func (svc *imageService) prepareImage(imageName string, options *copy.Options) (types.ImageReference, error) {
- if imageName == "" {
- return nil, storage.ErrNotAnImage
- }
-
- srcRef, err := alltransports.ParseImageName(imageName)
- if err != nil {
- if svc.defaultTransport == "" {
- return nil, err
- }
- srcRef2, err2 := alltransports.ParseImageName(svc.defaultTransport + imageName)
- if err2 != nil {
- return nil, err
- }
- srcRef = srcRef2
- }
-
- if options.SourceCtx == nil {
- options.SourceCtx = &types.SystemContext{}
- }
-
- hostname := reference.Domain(srcRef.DockerReference())
- if secure := svc.isSecureIndex(hostname); !secure {
- options.SourceCtx.DockerInsecureSkipTLSVerify = !secure
- }
- return srcRef, nil
-}
-
-func (svc *imageService) PullImage(systemContext *types.SystemContext, imageName string, options *copy.Options) (types.ImageReference, error) {
- policy, err := signature.DefaultPolicy(systemContext)
- if err != nil {
- return nil, err
- }
- policyContext, err := signature.NewPolicyContext(policy)
- if err != nil {
- return nil, err
- }
- if options == nil {
- options = &copy.Options{}
- }
-
- srcRef, err := svc.prepareImage(imageName, options)
- if err != nil {
- return nil, err
- }
-
- dest := imageName
- if srcRef.DockerReference() != nil {
- dest = srcRef.DockerReference().Name()
- if tagged, ok := srcRef.DockerReference().(reference.NamedTagged); ok {
- dest = dest + ":" + tagged.Tag()
- }
- if canonical, ok := srcRef.DockerReference().(reference.Canonical); ok {
- dest = dest + "@" + canonical.Digest().String()
- }
- }
- destRef, err := istorage.Transport.ParseStoreReference(svc.store, dest)
- if err != nil {
- return nil, err
- }
- err = copy.Image(policyContext, destRef, srcRef, options)
- if err != nil {
- return nil, err
- }
- return destRef, nil
-}
-
-func (svc *imageService) UntagImage(systemContext *types.SystemContext, nameOrID string) error {
- ref, err := alltransports.ParseImageName(nameOrID)
- if err != nil {
- ref2, err2 := istorage.Transport.ParseStoreReference(svc.store, "@"+nameOrID)
- if err2 != nil {
- ref3, err3 := istorage.Transport.ParseStoreReference(svc.store, nameOrID)
- if err3 != nil {
- return err
- }
- ref2 = ref3
- }
- ref = ref2
- }
-
- img, err := istorage.Transport.GetStoreImage(svc.store, ref)
- if err != nil {
- return err
- }
-
- if nameOrID != img.ID {
- namedRef, err := svc.prepareImage(nameOrID, &copy.Options{})
- if err != nil {
- return err
- }
-
- name := nameOrID
- if namedRef.DockerReference() != nil {
- name = namedRef.DockerReference().Name()
- if tagged, ok := namedRef.DockerReference().(reference.NamedTagged); ok {
- name = name + ":" + tagged.Tag()
- }
- if canonical, ok := namedRef.DockerReference().(reference.Canonical); ok {
- name = name + "@" + canonical.Digest().String()
- }
- }
-
- prunedNames := make([]string, 0, len(img.Names))
- for _, imgName := range img.Names {
- if imgName != name && imgName != nameOrID {
- prunedNames = append(prunedNames, imgName)
- }
- }
-
- if len(prunedNames) > 0 {
- return svc.store.SetNames(img.ID, prunedNames)
- }
- }
-
- return ref.DeleteImage(systemContext)
-}
-
-func (svc *imageService) RemoveImage(systemContext *types.SystemContext, nameOrID string) error {
- ref, err := alltransports.ParseImageName(nameOrID)
- if err != nil {
- ref2, err2 := istorage.Transport.ParseStoreReference(svc.store, "@"+nameOrID)
- if err2 != nil {
- ref3, err3 := istorage.Transport.ParseStoreReference(svc.store, nameOrID)
- if err3 != nil {
- return err
- }
- ref2 = ref3
- }
- ref = ref2
- }
- return ref.DeleteImage(systemContext)
-}
-
-func (svc *imageService) GetStore() storage.Store {
- return svc.store
-}
-
-func (svc *imageService) isSecureIndex(indexName string) bool {
- if index, ok := svc.indexConfigs[indexName]; ok {
- return index.secure
- }
-
- host, _, err := net.SplitHostPort(indexName)
- if err != nil {
- // assume indexName is of the form `host` without the port and go on.
- host = indexName
- }
-
- addrs, err := net.LookupIP(host)
- if err != nil {
- ip := net.ParseIP(host)
- if ip != nil {
- addrs = []net.IP{ip}
- }
-
- // if ip == nil, then `host` is neither an IP nor it could be looked up,
- // either because the index is unreachable, or because the index is behind an HTTP proxy.
- // So, len(addrs) == 0 and we're not aborting.
- }
-
- // Try CIDR notation only if addrs has any elements, i.e. if `host`'s IP could be determined.
- for _, addr := range addrs {
- for _, ipnet := range svc.insecureRegistryCIDRs {
- // check if the addr falls in the subnet
- if ipnet.Contains(addr) {
- return false
- }
- }
- }
-
- return true
-}
-
-func isValidHostname(hostname string) bool {
- return hostname != "" && !strings.Contains(hostname, "/") &&
- (strings.Contains(hostname, ".") ||
- strings.Contains(hostname, ":") || hostname == "localhost")
-}
-
-func isReferenceFullyQualified(reposName reference.Named) bool {
- indexName, _, _ := splitReposName(reposName)
- return indexName != ""
-}
-
-const (
- // defaultHostname is the default built-in hostname
- defaultHostname = "docker.io"
- // legacyDefaultHostname is automatically converted to DefaultHostname
- legacyDefaultHostname = "index.docker.io"
- // defaultRepoPrefix is the prefix used for default repositories in default host
- defaultRepoPrefix = "library/"
-)
-
-// splitReposName breaks a reposName into an index name and remote name
-func splitReposName(reposName reference.Named) (indexName string, remoteName reference.Named, err error) {
- var remoteNameStr string
- indexName, remoteNameStr = distreference.SplitHostname(reposName)
- if !isValidHostname(indexName) {
- // This is a Docker Index repos (ex: samalba/hipache or ubuntu)
- // 'docker.io'
- indexName = ""
- remoteName = reposName
- } else {
- remoteName, err = withName(remoteNameStr)
- }
- return
-}
-
-func validateName(name string) error {
- if err := validateID(strings.TrimPrefix(name, defaultHostname+"/")); err == nil {
- return fmt.Errorf("Invalid repository name (%s), cannot specify 64-byte hexadecimal strings", name)
- }
- return nil
-}
-
-var validHex = regexp.MustCompile(`^([a-f0-9]{64})$`)
-
-// validateID checks whether an ID string is a valid image ID.
-func validateID(id string) error {
- if ok := validHex.MatchString(id); !ok {
- return fmt.Errorf("image ID %q is invalid", id)
- }
- return nil
-}
-
-// withName returns a named object representing the given string. If the input
-// is invalid ErrReferenceInvalidFormat will be returned.
-func withName(name string) (reference.Named, error) {
- name, err := normalize(name)
- if err != nil {
- return nil, err
- }
- if err := validateName(name); err != nil {
- return nil, err
- }
- r, err := distreference.WithName(name)
- return r, err
-}
-
-// splitHostname splits a repository name to hostname and remotename string.
-// If no valid hostname is found, empty string will be returned as a resulting
-// hostname. Repository name needs to be already validated before.
-func splitHostname(name string) (hostname, remoteName string) {
- i := strings.IndexRune(name, '/')
- if i == -1 || (!strings.ContainsAny(name[:i], ".:") && name[:i] != "localhost") {
- hostname, remoteName = "", name
- } else {
- hostname, remoteName = name[:i], name[i+1:]
- }
- if hostname == legacyDefaultHostname {
- hostname = defaultHostname
- }
- if hostname == defaultHostname && !strings.ContainsRune(remoteName, '/') {
- remoteName = defaultRepoPrefix + remoteName
- }
- return
-}
-
-// normalize returns a repository name in its normalized form, meaning it
-// will contain library/ prefix for official images.
-func normalize(name string) (string, error) {
- host, remoteName := splitHostname(name)
- if strings.ToLower(remoteName) != remoteName {
- return "", errors.New("invalid reference format: repository name must be lowercase")
- }
- if host == defaultHostname {
- if strings.HasPrefix(remoteName, defaultRepoPrefix) {
- remoteName = strings.TrimPrefix(remoteName, defaultRepoPrefix)
- }
- return host + "/" + remoteName, nil
- }
- return name, nil
-}
-
-func (svc *imageService) ResolveNames(imageName string) ([]string, error) {
- r, err := reference.ParseNormalizedNamed(imageName)
- if err != nil {
- return nil, err
- }
- if isReferenceFullyQualified(r) {
- // this means the image is already fully qualified
- return []string{imageName}, nil
- }
- // we got an unqualified image here, we can't go ahead w/o registries configured
- // properly.
- if len(svc.registries) == 0 {
- return nil, errors.New("no registries configured while trying to pull an unqualified image")
- }
- // this means we got an image in the form of "busybox"
- // we need to use additional registries...
- // normalize the unqualified image to be domain/repo/image...
- _, rest := splitDomain(r.Name())
- images := []string{}
- for _, r := range svc.registries {
- images = append(images, path.Join(r, rest))
- }
- return images, nil
-}
-
-// GetImageService returns an ImageServer that uses the passed-in store, and
-// which will prepend the passed-in defaultTransport value to an image name if
-// a name that's passed to its PullImage() method can't be resolved to an image
-// in the store and can't be resolved to a source on its own.
-func GetImageService(store storage.Store, defaultTransport string, insecureRegistries []string, registries []string) (ImageServer, error) {
- if store == nil {
- var err error
- store, err = storage.GetStore(storage.DefaultStoreOptions)
- if err != nil {
- return nil, err
- }
- }
-
- seenRegistries := make(map[string]bool, len(registries))
- cleanRegistries := []string{}
- for _, r := range registries {
- if seenRegistries[r] {
- continue
- }
- cleanRegistries = append(cleanRegistries, r)
- seenRegistries[r] = true
- }
-
- is := &imageService{
- store: store,
- defaultTransport: defaultTransport,
- indexConfigs: make(map[string]*indexInfo),
- insecureRegistryCIDRs: make([]*net.IPNet, 0),
- registries: cleanRegistries,
- }
-
- insecureRegistries = append(insecureRegistries, "127.0.0.0/8")
- // Split --insecure-registry into CIDR and registry-specific settings.
- for _, r := range insecureRegistries {
- // Check if CIDR was passed to --insecure-registry
- _, ipnet, err := net.ParseCIDR(r)
- if err == nil {
- // Valid CIDR.
- is.insecureRegistryCIDRs = append(is.insecureRegistryCIDRs, ipnet)
- } else {
- // Assume `host:port` if not CIDR.
- is.indexConfigs[r] = &indexInfo{
- name: r,
- secure: false,
- }
- }
- }
-
- return is, nil
-}
diff --git a/pkg/storage/image_regexp.go b/pkg/storage/image_regexp.go
deleted file mode 100644
index 96de64884..000000000
--- a/pkg/storage/image_regexp.go
+++ /dev/null
@@ -1,125 +0,0 @@
-package storage
-
-// This is a fork of docker/distribution code to be used when manipulating image
-// references.
-// DO NOT EDIT THIS FILE.
-
-import "regexp"
-
-var (
- // alphaNumericRegexp defines the alpha numeric atom, typically a
- // component of names. This only allows lower case characters and digits.
- alphaNumericRegexp = match(`[a-z0-9]+`)
-
- // separatorRegexp defines the separators allowed to be embedded in name
- // components. This allow one period, one or two underscore and multiple
- // dashes.
- separatorRegexp = match(`(?:[._]|__|[-]*)`)
-
- // nameComponentRegexp restricts registry path component names to start
- // with at least one letter or number, with following parts able to be
- // separated by one period, one or two underscore and multiple dashes.
- nameComponentRegexp = expression(
- alphaNumericRegexp,
- optional(repeated(separatorRegexp, alphaNumericRegexp)))
-
- // domainComponentRegexp restricts the registry domain component of a
- // repository name to start with a component as defined by domainRegexp
- // and followed by an optional port.
- domainComponentRegexp = match(`(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])`)
-
- // domainRegexp defines the structure of potential domain components
- // that may be part of image names. This is purposely a subset of what is
- // allowed by DNS to ensure backwards compatibility with Docker image
- // names.
- domainRegexp = expression(
- domainComponentRegexp,
- optional(repeated(literal(`.`), domainComponentRegexp)),
- optional(literal(`:`), match(`[0-9]+`)))
-
- // NameRegexp is the format for the name component of references. The
- // regexp has capturing groups for the domain and name part omitting
- // the separating forward slash from either.
- NameRegexp = expression(
- optional(domainRegexp, literal(`/`)),
- nameComponentRegexp,
- optional(repeated(literal(`/`), nameComponentRegexp)))
-
- // anchoredNameRegexp is used to parse a name value, capturing the
- // domain and trailing components.
- anchoredNameRegexp = anchored(
- optional(capture(domainRegexp), literal(`/`)),
- capture(nameComponentRegexp,
- optional(repeated(literal(`/`), nameComponentRegexp))))
-
- // IdentifierRegexp is the format for string identifier used as a
- // content addressable identifier using sha256. These identifiers
- // are like digests without the algorithm, since sha256 is used.
- IdentifierRegexp = match(`([a-f0-9]{64})`)
-
- // ShortIdentifierRegexp is the format used to represent a prefix
- // of an identifier. A prefix may be used to match a sha256 identifier
- // within a list of trusted identifiers.
- ShortIdentifierRegexp = match(`([a-f0-9]{6,64})`)
-)
-
-// match compiles the string to a regular expression.
-var match = regexp.MustCompile
-
-// literal compiles s into a literal regular expression, escaping any regexp
-// reserved characters.
-func literal(s string) *regexp.Regexp {
- re := match(regexp.QuoteMeta(s))
-
- if _, complete := re.LiteralPrefix(); !complete {
- panic("must be a literal")
- }
-
- return re
-}
-
-func splitDomain(name string) (string, string) {
- match := anchoredNameRegexp.FindStringSubmatch(name)
- if len(match) != 3 {
- return "", name
- }
- return match[1], match[2]
-}
-
-// expression defines a full expression, where each regular expression must
-// follow the previous.
-func expression(res ...*regexp.Regexp) *regexp.Regexp {
- var s string
- for _, re := range res {
- s += re.String()
- }
-
- return match(s)
-}
-
-// optional wraps the expression in a non-capturing group and makes the
-// production optional.
-func optional(res ...*regexp.Regexp) *regexp.Regexp {
- return match(group(expression(res...)).String() + `?`)
-}
-
-// repeated wraps the regexp in a non-capturing group to get one or more
-// matches.
-func repeated(res ...*regexp.Regexp) *regexp.Regexp {
- return match(group(expression(res...)).String() + `+`)
-}
-
-// group wraps the regexp in a non-capturing group.
-func group(res ...*regexp.Regexp) *regexp.Regexp {
- return match(`(?:` + expression(res...).String() + `)`)
-}
-
-// capture wraps the expression in a capturing group.
-func capture(res ...*regexp.Regexp) *regexp.Regexp {
- return match(`(` + expression(res...).String() + `)`)
-}
-
-// anchored anchors the regular expression by adding start and end delimiters.
-func anchored(res ...*regexp.Regexp) *regexp.Regexp {
- return match(`^` + expression(res...).String() + `$`)
-}
diff --git a/pkg/storage/runtime.go b/pkg/storage/runtime.go
deleted file mode 100644
index bc402f413..000000000
--- a/pkg/storage/runtime.go
+++ /dev/null
@@ -1,452 +0,0 @@
-package storage
-
-import (
- "encoding/json"
- "fmt"
- "time"
-
- "github.com/containers/image/copy"
- istorage "github.com/containers/image/storage"
- "github.com/containers/image/transports/alltransports"
- "github.com/containers/image/types"
- "github.com/containers/storage"
- "github.com/opencontainers/image-spec/specs-go/v1"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
-)
-
-var (
- // ErrInvalidPodName is returned when a pod name specified to a
- // function call is found to be invalid (most often, because it's
- // empty).
- ErrInvalidPodName = errors.New("invalid pod name")
- // ErrInvalidImageName is returned when an image name specified to a
- // function call is found to be invalid (most often, because it's
- // empty).
- ErrInvalidImageName = errors.New("invalid image name")
- // ErrInvalidContainerName is returned when a container name specified
- // to a function call is found to be invalid (most often, because it's
- // empty).
- ErrInvalidContainerName = errors.New("invalid container name")
- // ErrInvalidSandboxID is returned when a sandbox ID specified to a
- // function call is found to be invalid (because it's either
- // empty or doesn't match a valid sandbox).
- ErrInvalidSandboxID = errors.New("invalid sandbox ID")
- // ErrInvalidContainerID is returned when a container ID specified to a
- // function call is found to be invalid (because it's either
- // empty or doesn't match a valid container).
- ErrInvalidContainerID = errors.New("invalid container ID")
-)
-
-type runtimeService struct {
- storageImageServer ImageServer
- pauseImage string
-}
-
-// ContainerInfo wraps a subset of information about a container: its ID and
-// the locations of its nonvolatile and volatile per-container directories,
-// along with a copy of the configuration blob from the image that was used to
-// create the container, if the image had a configuration.
-type ContainerInfo struct {
- ID string
- Dir string
- RunDir string
- Config *v1.Image
-}
-
-// RuntimeServer wraps up various CRI-related activities into a reusable
-// implementation.
-type RuntimeServer interface {
- // CreatePodSandbox creates a pod infrastructure container, using the
- // specified PodID for the infrastructure container's ID. In the CRI
- // view of things, a sandbox is distinct from its containers, including
- // its infrastructure container, but at this level the sandbox is
- // essentially the same as its infrastructure container, with a
- // container's membership in a pod being signified by it listing the
- // same pod ID in its metadata that the pod's other members do, and
- // with the pod's infrastructure container having the same value for
- // both its pod's ID and its container ID.
- // Pointer arguments can be nil. Either the image name or ID can be
- // omitted, but not both. All other arguments are required.
- CreatePodSandbox(systemContext *types.SystemContext, podName, podID, imageName, imageID, containerName, metadataName, uid, namespace string, attempt uint32, copyOptions *copy.Options) (ContainerInfo, error)
- // RemovePodSandbox deletes a pod sandbox's infrastructure container.
- // The CRI expects that a sandbox can't be removed unless its only
- // container is its infrastructure container, but we don't enforce that
- // here, since we're just keeping track of it for higher level APIs.
- RemovePodSandbox(idOrName string) error
-
- // GetContainerMetadata returns the metadata we've stored for a container.
- GetContainerMetadata(idOrName string) (RuntimeContainerMetadata, error)
- // SetContainerMetadata updates the metadata we've stored for a container.
- SetContainerMetadata(idOrName string, metadata RuntimeContainerMetadata) error
-
- // CreateContainer creates a container with the specified ID.
- // Pointer arguments can be nil. Either the image name or ID can be
- // omitted, but not both. All other arguments are required.
- CreateContainer(systemContext *types.SystemContext, podName, podID, imageName, imageID, containerName, containerID, metadataName string, attempt uint32, mountLabel string, copyOptions *copy.Options) (ContainerInfo, error)
- // DeleteContainer deletes a container, unmounting it first if need be.
- DeleteContainer(idOrName string) error
-
- // StartContainer makes sure a container's filesystem is mounted, and
- // returns the location of its root filesystem, which is not guaranteed
- // by lower-level drivers to never change.
- StartContainer(idOrName string) (string, error)
- // StopContainer attempts to unmount a container's root filesystem,
- // freeing up any kernel resources which may be limited.
- StopContainer(idOrName string) error
-
- // GetWorkDir returns the path of a nonvolatile directory on the
- // filesystem (somewhere under the Store's Root directory) which can be
- // used to store arbitrary data that is specific to the container. It
- // will be removed automatically when the container is deleted.
- GetWorkDir(id string) (string, error)
- // GetRunDir returns the path of a volatile directory (does not survive
- // the host rebooting, somewhere under the Store's RunRoot directory)
- // on the filesystem which can be used to store arbitrary data that is
- // specific to the container. It will be removed automatically when
- // the container is deleted.
- GetRunDir(id string) (string, error)
-}
-
-// RuntimeContainerMetadata is the structure that we encode as JSON and store
-// in the metadata field of storage.Container objects. It is used for
-// specifying attributes of pod sandboxes and containers when they are being
-// created, and allows a container's MountLabel, and possibly other values, to
-// be modified in one read/write cycle via calls to
-// RuntimeServer.ContainerMetadata, RuntimeContainerMetadata.SetMountLabel,
-// and RuntimeServer.SetContainerMetadata.
-type RuntimeContainerMetadata struct {
- // Pod is true if this is the pod's infrastructure container.
- Pod bool `json:"pod,omitempty"` // Applicable to both PodSandboxes and Containers
- // The pod's name and ID, kept for use by upper layers in determining
- // which containers belong to which pods.
- PodName string `json:"pod-name"` // Applicable to both PodSandboxes and Containers, mandatory
- PodID string `json:"pod-id"` // Applicable to both PodSandboxes and Containers, mandatory
- // The provided name and the ID of the image that was used to
- // instantiate the container.
- ImageName string `json:"image-name"` // Applicable to both PodSandboxes and Containers
- ImageID string `json:"image-id"` // Applicable to both PodSandboxes and Containers
- // The container's name, which for an infrastructure container is usually PodName + "-infra".
- ContainerName string `json:"name"` // Applicable to both PodSandboxes and Containers, mandatory
- // The name as originally specified in PodSandbox or Container CRI metadata.
- MetadataName string `json:"metadata-name"` // Applicable to both PodSandboxes and Containers, mandatory
- UID string `json:"uid,omitempty"` // Only applicable to pods
- Namespace string `json:"namespace,omitempty"` // Only applicable to pods
- Attempt uint32 `json:"attempt,omitempty"` // Applicable to both PodSandboxes and Containers
- CreatedAt int64 `json:"created-at"` // Applicable to both PodSandboxes and Containers
- MountLabel string `json:"mountlabel,omitempty"` // Applicable to both PodSandboxes and Containers
-}
-
-// SetMountLabel updates the mount label held by a RuntimeContainerMetadata
-// object.
-func (metadata *RuntimeContainerMetadata) SetMountLabel(mountLabel string) {
- metadata.MountLabel = mountLabel
-}
-
-func (r *runtimeService) createContainerOrPodSandbox(systemContext *types.SystemContext, podName, podID, imageName, imageID, containerName, containerID, metadataName, uid, namespace string, attempt uint32, mountLabel string, options *copy.Options) (ContainerInfo, error) {
- var ref types.ImageReference
- if podName == "" || podID == "" {
- return ContainerInfo{}, ErrInvalidPodName
- }
- if imageName == "" && imageID == "" {
- return ContainerInfo{}, ErrInvalidImageName
- }
- if containerName == "" {
- return ContainerInfo{}, ErrInvalidContainerName
- }
- if metadataName == "" {
- metadataName = containerName
- }
-
- // Check if we have the specified image.
- ref, err := istorage.Transport.ParseStoreReference(r.storageImageServer.GetStore(), imageName)
- if err != nil {
- // Maybe it's some other transport's copy of the image?
- otherRef, err2 := alltransports.ParseImageName(imageName)
- if err2 == nil && otherRef.DockerReference() != nil {
- ref, err = istorage.Transport.ParseStoreReference(r.storageImageServer.GetStore(), otherRef.DockerReference().Name())
- }
- if err != nil {
- // Maybe the image ID is sufficient?
- ref, err = istorage.Transport.ParseStoreReference(r.storageImageServer.GetStore(), "@"+imageID)
- if err != nil {
- return ContainerInfo{}, err
- }
- }
- }
- img, err := istorage.Transport.GetStoreImage(r.storageImageServer.GetStore(), ref)
- if img == nil && errors.Cause(err) == storage.ErrImageUnknown && imageName == r.pauseImage {
- image := imageID
- if imageName != "" {
- image = imageName
- }
- if image == "" {
- return ContainerInfo{}, ErrInvalidImageName
- }
- logrus.Debugf("couldn't find image %q, retrieving it", image)
- ref, err = r.storageImageServer.PullImage(systemContext, image, options)
- if err != nil {
- return ContainerInfo{}, err
- }
- img, err = istorage.Transport.GetStoreImage(r.storageImageServer.GetStore(), ref)
- if err != nil {
- return ContainerInfo{}, err
- }
- logrus.Debugf("successfully pulled image %q", image)
- }
- if img == nil && errors.Cause(err) == storage.ErrImageUnknown {
- if imageID == "" {
- return ContainerInfo{}, fmt.Errorf("image %q not present in image store", imageName)
- }
- if imageName == "" {
- return ContainerInfo{}, fmt.Errorf("image with ID %q not present in image store", imageID)
- }
- return ContainerInfo{}, fmt.Errorf("image %q with ID %q not present in image store", imageName, imageID)
- }
-
- // Pull out a copy of the image's configuration.
- image, err := ref.NewImage(systemContext)
- if err != nil {
- return ContainerInfo{}, err
- }
- defer image.Close()
-
- imageConfig, err := image.OCIConfig()
- if err != nil {
- return ContainerInfo{}, err
- }
-
- // Update the image name and ID.
- if imageName == "" && len(img.Names) > 0 {
- imageName = img.Names[0]
- }
- imageID = img.ID
-
- // Build metadata to store with the container.
- metadata := RuntimeContainerMetadata{
- Pod: containerID == podID,
- PodName: podName,
- PodID: podID,
- ImageName: imageName,
- ImageID: imageID,
- ContainerName: containerName,
- MetadataName: metadataName,
- UID: uid,
- Namespace: namespace,
- Attempt: attempt,
- CreatedAt: time.Now().Unix(),
- MountLabel: mountLabel,
- }
- mdata, err := json.Marshal(&metadata)
- if err != nil {
- return ContainerInfo{}, err
- }
-
- // Build the container.
- names := []string{metadata.ContainerName}
- if metadata.Pod {
- names = append(names, metadata.PodName)
- }
- container, err := r.storageImageServer.GetStore().CreateContainer(containerID, names, img.ID, "", string(mdata), nil)
- if err != nil {
- if metadata.Pod {
- logrus.Debugf("failed to create pod sandbox %s(%s): %v", metadata.PodName, metadata.PodID, err)
- } else {
- logrus.Debugf("failed to create container %s(%s): %v", metadata.ContainerName, containerID, err)
- }
- return ContainerInfo{}, err
- }
- if metadata.Pod {
- logrus.Debugf("created pod sandbox %q", container.ID)
- } else {
- logrus.Debugf("created container %q", container.ID)
- }
-
- // If anything fails after this point, we need to delete the incomplete
- // container before returning.
- defer func() {
- if err != nil {
- if err2 := r.storageImageServer.GetStore().DeleteContainer(container.ID); err2 != nil {
- if metadata.Pod {
- logrus.Infof("%v deleting partially-created pod sandbox %q", err2, container.ID)
- } else {
- logrus.Infof("%v deleting partially-created container %q", err2, container.ID)
- }
- return
- }
- logrus.Infof("deleted partially-created container %q", container.ID)
- }
- }()
-
- // Add a name to the container's layer so that it's easier to follow
- // what's going on if we're just looking at the storage-eye view of things.
- layerName := metadata.ContainerName + "-layer"
- names, err = r.storageImageServer.GetStore().Names(container.LayerID)
- if err != nil {
- return ContainerInfo{}, err
- }
- names = append(names, layerName)
- err = r.storageImageServer.GetStore().SetNames(container.LayerID, names)
- if err != nil {
- return ContainerInfo{}, err
- }
-
- // Find out where the container work directories are, so that we can return them.
- containerDir, err := r.storageImageServer.GetStore().ContainerDirectory(container.ID)
- if err != nil {
- return ContainerInfo{}, err
- }
- if metadata.Pod {
- logrus.Debugf("pod sandbox %q has work directory %q", container.ID, containerDir)
- } else {
- logrus.Debugf("container %q has work directory %q", container.ID, containerDir)
- }
-
- containerRunDir, err := r.storageImageServer.GetStore().ContainerRunDirectory(container.ID)
- if err != nil {
- return ContainerInfo{}, err
- }
- if metadata.Pod {
- logrus.Debugf("pod sandbox %q has run directory %q", container.ID, containerRunDir)
- } else {
- logrus.Debugf("container %q has run directory %q", container.ID, containerRunDir)
- }
-
- return ContainerInfo{
- ID: container.ID,
- Dir: containerDir,
- RunDir: containerRunDir,
- Config: imageConfig,
- }, nil
-}
-
-func (r *runtimeService) CreatePodSandbox(systemContext *types.SystemContext, podName, podID, imageName, imageID, containerName, metadataName, uid, namespace string, attempt uint32, copyOptions *copy.Options) (ContainerInfo, error) {
- return r.createContainerOrPodSandbox(systemContext, podName, podID, imageName, imageID, containerName, podID, metadataName, uid, namespace, attempt, "", copyOptions)
-}
-
-func (r *runtimeService) CreateContainer(systemContext *types.SystemContext, podName, podID, imageName, imageID, containerName, containerID, metadataName string, attempt uint32, mountLabel string, copyOptions *copy.Options) (ContainerInfo, error) {
- return r.createContainerOrPodSandbox(systemContext, podName, podID, imageName, imageID, containerName, containerID, metadataName, "", "", attempt, mountLabel, copyOptions)
-}
-
-func (r *runtimeService) RemovePodSandbox(idOrName string) error {
- container, err := r.storageImageServer.GetStore().Container(idOrName)
- if err != nil {
- if errors.Cause(err) == storage.ErrContainerUnknown {
- return ErrInvalidSandboxID
- }
- return err
- }
- err = r.storageImageServer.GetStore().DeleteContainer(container.ID)
- if err != nil {
- logrus.Debugf("failed to delete pod sandbox %q: %v", container.ID, err)
- return err
- }
- return nil
-}
-
-func (r *runtimeService) DeleteContainer(idOrName string) error {
- if idOrName == "" {
- return ErrInvalidContainerID
- }
- container, err := r.storageImageServer.GetStore().Container(idOrName)
- if err != nil {
- return err
- }
- err = r.storageImageServer.GetStore().DeleteContainer(container.ID)
- if err != nil {
- logrus.Debugf("failed to delete container %q: %v", container.ID, err)
- return err
- }
- return nil
-}
-
-func (r *runtimeService) SetContainerMetadata(idOrName string, metadata RuntimeContainerMetadata) error {
- mdata, err := json.Marshal(&metadata)
- if err != nil {
- logrus.Debugf("failed to encode metadata for %q: %v", idOrName, err)
- return err
- }
- return r.storageImageServer.GetStore().SetMetadata(idOrName, string(mdata))
-}
-
-func (r *runtimeService) GetContainerMetadata(idOrName string) (RuntimeContainerMetadata, error) {
- metadata := RuntimeContainerMetadata{}
- mdata, err := r.storageImageServer.GetStore().Metadata(idOrName)
- if err != nil {
- return metadata, err
- }
- if err = json.Unmarshal([]byte(mdata), &metadata); err != nil {
- return metadata, err
- }
- return metadata, nil
-}
-
-func (r *runtimeService) StartContainer(idOrName string) (string, error) {
- container, err := r.storageImageServer.GetStore().Container(idOrName)
- if err != nil {
- if errors.Cause(err) == storage.ErrContainerUnknown {
- return "", ErrInvalidContainerID
- }
- return "", err
- }
- metadata := RuntimeContainerMetadata{}
- if err = json.Unmarshal([]byte(container.Metadata), &metadata); err != nil {
- return "", err
- }
- mountPoint, err := r.storageImageServer.GetStore().Mount(container.ID, metadata.MountLabel)
- if err != nil {
- logrus.Debugf("failed to mount container %q: %v", container.ID, err)
- return "", err
- }
- logrus.Debugf("mounted container %q at %q", container.ID, mountPoint)
- return mountPoint, nil
-}
-
-func (r *runtimeService) StopContainer(idOrName string) error {
- if idOrName == "" {
- return ErrInvalidContainerID
- }
- container, err := r.storageImageServer.GetStore().Container(idOrName)
- if err != nil {
- return err
- }
- err = r.storageImageServer.GetStore().Unmount(container.ID)
- if err != nil {
- logrus.Debugf("failed to unmount container %q: %v", container.ID, err)
- return err
- }
- logrus.Debugf("unmounted container %q", container.ID)
- return nil
-}
-
-func (r *runtimeService) GetWorkDir(id string) (string, error) {
- container, err := r.storageImageServer.GetStore().Container(id)
- if err != nil {
- if errors.Cause(err) == storage.ErrContainerUnknown {
- return "", ErrInvalidContainerID
- }
- return "", err
- }
- return r.storageImageServer.GetStore().ContainerDirectory(container.ID)
-}
-
-func (r *runtimeService) GetRunDir(id string) (string, error) {
- container, err := r.storageImageServer.GetStore().Container(id)
- if err != nil {
- if errors.Cause(err) == storage.ErrContainerUnknown {
- return "", ErrInvalidContainerID
- }
- return "", err
- }
- return r.storageImageServer.GetStore().ContainerRunDirectory(container.ID)
-}
-
-// GetRuntimeService returns a RuntimeServer that uses the passed-in image
-// service to pull and manage images, and its store to manage containers based
-// on those images.
-func GetRuntimeService(storageImageServer ImageServer, pauseImage string) RuntimeServer {
- return &runtimeService{
- storageImageServer: storageImageServer,
- pauseImage: pauseImage,
- }
-}