Example #1
0
// aciInfoToV1AlphaAPIImage takes an aciInfo object and construct the v1alpha.Image object.
func aciInfoToV1AlphaAPIImage(store *imagestore.Store, aciInfo *imagestore.ACIInfo) (*v1alpha.Image, error) {
	manifest, err := store.GetImageManifestJSON(aciInfo.BlobKey)
	if err != nil {
		stderr.PrintE("failed to read the image manifest", err)
		return nil, err
	}

	var im schema.ImageManifest
	if err = json.Unmarshal(manifest, &im); err != nil {
		stderr.PrintE("failed to unmarshal image manifest", err)
		return nil, err
	}

	version, ok := im.Labels.Get("version")
	if !ok {
		version = "latest"
	}

	return &v1alpha.Image{
		BaseFormat: &v1alpha.ImageFormat{
			// Only support appc image now. If it's a docker image, then it
			// will be transformed to appc before storing in the disk store.
			Type:    v1alpha.ImageType_IMAGE_TYPE_APPC,
			Version: schema.AppContainerVersion.String(),
		},
		Id:              aciInfo.BlobKey,
		Name:            im.Name.String(),
		Version:         version,
		ImportTimestamp: aciInfo.ImportTime.Unix(),
		Manifest:        manifest,
		Size:            aciInfo.Size + aciInfo.TreeStoreSize,
		Annotations:     convertAnnotationsToKeyValue(im.Annotations),
		Labels:          convertLabelsToKeyValue(im.Labels),
	}, nil
}
Example #2
0
File: io.go Project: intelsdi-x/rkt
// getTmpROC returns a removeOnClose instance wrapping a temporary
// file provided by the passed store. The actual file name is based on
// a hash of the passed path.
func getTmpROC(s *imagestore.Store, path string) (*removeOnClose, error) {
	h := sha512.New()
	h.Write([]byte(path))
	pathHash := s.HashToKey(h)

	tmp, err := s.TmpNamedFile(pathHash)
	if err != nil {
		return nil, errwrap.Wrap(errors.New("error setting up temporary file"), err)
	}

	// let's lock the file to avoid concurrent writes to the temporary file, it
	// will go away when removing the temp file
	_, err = lock.TryExclusiveLock(tmp.Name(), lock.RegFile)
	if err != nil {
		if err != lock.ErrLocked {
			return nil, errwrap.Wrap(errors.New("failed to lock temporary file"), err)
		}
		log.Printf("another rkt instance is downloading this file, waiting...")
		_, err = lock.ExclusiveLock(tmp.Name(), lock.RegFile)
		if err != nil {
			return nil, errwrap.Wrap(errors.New("failed to lock temporary file"), err)
		}
	}

	return &removeOnClose{File: tmp}, nil
}
Example #3
0
func rmImages(s *imagestore.Store, images []string) error {
	imageMap := make(map[string]string)

	for _, img := range images {
		key, err := getStoreKeyFromAppOrHash(s, img)
		if err != nil {
			stderr.Error(err)
			continue
		}

		aciinfo, err := s.GetACIInfoWithBlobKey(key)
		if err != nil {
			stderr.PrintE(fmt.Sprintf("error retrieving aci infos for image %q", key), err)
			continue
		}

		imageMap[key] = aciinfo.Name
	}

	done := 0
	errors := 0
	staleErrors := 0

	for key, name := range imageMap {
		if err := s.RemoveACI(key); err != nil {
			if serr, ok := err.(*imagestore.StoreRemovalError); ok {
				staleErrors++
				stderr.PrintE(fmt.Sprintf("some files cannot be removed for image %q (%q)", key, name), serr)
			} else {
				errors++
				stderr.PrintE(fmt.Sprintf("error removing aci for image %q (%q)", key, name), err)
				continue
			}
		}
		stdout.Printf("successfully removed aci for image: %q", key)
		done++
	}

	if done > 0 {
		stderr.Printf("%d image(s) successfully removed", done)
	}

	// If anything didn't complete, return exit status of 1
	if (errors + staleErrors) > 0 {
		if staleErrors > 0 {
			stderr.Printf("%d image(s) removed but left some stale files", staleErrors)
		}
		if errors > 0 {
			stderr.Printf("%d image(s) cannot be removed", errors)
		}
		return fmt.Errorf("error(s) found while removing images")
	}

	return nil
}
Example #4
0
func remoteForURL(s *imagestore.Store, u *url.URL) (*imagestore.Remote, error) {
	urlStr := u.String()
	rem, err := s.GetRemote(urlStr)
	if err != nil {
		if err == imagestore.ErrRemoteNotFound {
			return nil, nil
		}

		return nil, errwrap.Wrap(fmt.Errorf("failed to fetch remote for URL %q", urlStr), err)
	}

	return rem, nil
}
Example #5
0
// getImageInfoFromDisk for a given image ID, returns the *v1alpha.Image object.
func (s *v1AlphaAPIServer) getImageInfoFromDisk(store *imagestore.Store, imageID string) (*v1alpha.Image, error) {
	aciInfo, err := store.GetACIInfoWithBlobKey(imageID)
	if err != nil {
		stderr.PrintE(fmt.Sprintf("failed to get ACI info for image %q", imageID), err)
		return nil, err
	}

	image, err := aciInfoToV1AlphaAPIImage(store, aciInfo)
	if err != nil {
		stderr.PrintE(fmt.Sprintf("failed to convert ACI to v1alphaAPIImage for image %q", imageID), err)
		return nil, err
	}
	return image, nil
}
Example #6
0
func getStoreKeyFromAppOrHash(s *imagestore.Store, input string) (string, error) {
	var key string
	if _, err := types.NewHash(input); err == nil {
		key, err = s.ResolveKey(input)
		if err != nil {
			return "", errwrap.Wrap(errors.New("cannot resolve image ID"), err)
		}
	} else {
		key, err = getStoreKeyFromApp(s, input)
		if err != nil {
			return "", errwrap.Wrap(errors.New("cannot find image"), err)
		}
	}
	return key, nil
}
Example #7
0
File: image_gc.go Project: nak3/rkt
func gcStore(s *imagestore.Store, gracePeriod time.Duration) error {
	var imagesToRemove []string
	aciinfos, err := s.GetAllACIInfos([]string{"lastused"}, true)
	if err != nil {
		return errwrap.Wrap(errors.New("failed to get aciinfos"), err)
	}
	for _, ai := range aciinfos {
		if time.Now().Sub(ai.LastUsed) <= gracePeriod {
			break
		}
		imagesToRemove = append(imagesToRemove, ai.BlobKey)
	}

	if err := rmImages(s, imagesToRemove); err != nil {
		return err
	}

	return nil
}
Example #8
0
func getStoreKeyFromApp(s *imagestore.Store, img string) (string, error) {
	app, err := discovery.NewAppFromString(img)
	if err != nil {
		return "", errwrap.Wrap(fmt.Errorf("cannot parse the image name %q", img), err)
	}
	labels, err := types.LabelsFromMap(app.Labels)
	if err != nil {
		return "", errwrap.Wrap(fmt.Errorf("invalid labels in the image %q", img), err)
	}
	key, err := s.GetACI(app.Name, labels)
	if err != nil {
		switch err.(type) {
		case imagestore.ACINotFoundError:
			return "", err
		default:
			return "", errwrap.Wrap(fmt.Errorf("cannot find image %q", img), err)
		}
	}
	return key, nil
}
Example #9
0
// TODO(sgotti) when the TreeStore will use an interface, change it to a
// test implementation without relying on store/imagestore
func testStoreWriteACI(dir string, s *imagestore.Store) (string, error) {
	imj := `
		{
		    "acKind": "ImageManifest",
		    "acVersion": "0.8.8",
		    "name": "example.com/test01"
		}
	`

	entries := []*aci.ACIEntry{
		// An empty dir
		{
			Header: &tar.Header{
				Name:     "rootfs/a",
				Typeflag: tar.TypeDir,
			},
		},
		{
			Contents: "hello",
			Header: &tar.Header{
				Name: "hello.txt",
				Size: 5,
			},
		},
		{
			Header: &tar.Header{
				Name:     "rootfs/link.txt",
				Linkname: "rootfs/hello.txt",
				Typeflag: tar.TypeSymlink,
			},
		},
		// dangling symlink
		{
			Header: &tar.Header{
				Name:     "rootfs/link2.txt",
				Linkname: "rootfs/missingfile.txt",
				Typeflag: tar.TypeSymlink,
			},
		},
		{
			Header: &tar.Header{
				Name:     "rootfs/fifo",
				Typeflag: tar.TypeFifo,
			},
		},
	}
	aci, err := aci.NewACI(dir, imj, entries)
	if err != nil {
		return "", err
	}
	defer aci.Close()

	// Rewind the ACI
	if _, err := aci.Seek(0, 0); err != nil {
		return "", err
	}

	// Import the new ACI
	key, err := s.WriteACI(aci, imagestore.ACIFetchInfo{Latest: false})
	if err != nil {
		return "", err
	}
	return key, nil
}
Example #10
0
func rmImages(s *imagestore.Store, images []string) error {
	done := 0
	errors := 0
	staleErrors := 0
	imageMap := make(map[string]string)
	imageCounter := make(map[string]int)

	for _, pkey := range images {
		errors++
		h, err := types.NewHash(pkey)
		if err != nil {
			var found bool
			keys, found, err := s.ResolveName(pkey)
			if len(keys) > 0 {
				errors += len(keys) - 1
			}
			if err != nil {
				stderr.Error(err)
				continue
			}
			if !found {
				stderr.Printf("image name %q not found", pkey)
				continue
			}
			for _, key := range keys {
				imageMap[key] = pkey
				imageCounter[key]++
			}
		} else {
			key, err := s.ResolveKey(h.String())
			if err != nil {
				stderr.PrintE(fmt.Sprintf("image ID %q not valid", pkey), err)
				continue
			}
			if key == "" {
				stderr.Printf("image ID %q doesn't exist", pkey)
				continue
			}

			aciinfo, err := s.GetACIInfoWithBlobKey(key)
			if err != nil {
				stderr.PrintE(fmt.Sprintf("error retrieving aci infos for image %q", key), err)
				continue
			}
			imageMap[key] = aciinfo.Name
			imageCounter[key]++
		}
	}

	// Adjust the error count by subtracting duplicate IDs from it,
	// therefore allowing only one error per ID.
	for _, c := range imageCounter {
		if c > 1 {
			errors -= c - 1
		}
	}

	for key, name := range imageMap {
		if err := s.RemoveACI(key); err != nil {
			if serr, ok := err.(*imagestore.StoreRemovalError); ok {
				staleErrors++
				stderr.PrintE(fmt.Sprintf("some files cannot be removed for image %q (%q)", key, name), serr)
			} else {
				stderr.PrintE(fmt.Sprintf("error removing aci for image %q (%q)", key, name), err)
				continue
			}
		}
		stdout.Printf("successfully removed aci for image: %q", key)
		errors--
		done++
	}

	if done > 0 {
		stderr.Printf("%d image(s) successfully removed", done)
	}

	// If anything didn't complete, return exit status of 1
	if (errors + staleErrors) > 0 {
		if staleErrors > 0 {
			stderr.Printf("%d image(s) removed but left some stale files", staleErrors)
		}
		if errors > 0 {
			stderr.Printf("%d image(s) cannot be removed", errors)
		}
		return fmt.Errorf("error(s) found while removing images")
	}

	return nil
}