Example #1
0
func (self *Pool) SetDisabled(uuid string, disabled bool) (*Manifest, errors.Error) {
	// Find manifest with the given uuid
	manifest, ok := self.findManifest(uuid)
	if !ok {
		return nil, errors.ResourceNotFound(nil)
	}

	if !disabled && manifest.State == StateUnactivated {
		// Image must be activated before it can be enabled
		return nil, errors.ServiceUnavailableError(nil)
	}

	self.lock()
	defer self.unlock()

	// Enable / disable the image
	if disabled {
		manifest.State = StateDisabled
	} else {
		manifest.State = StateActive
	}

	manifest.Disabled = disabled

	// Save manifests to disk
	if err := saveManifests(self.manifests); err != nil {
		return nil, errors.InternalError(err)
	}

	return manifest, nil
}
Example #2
0
func (self *Pool) Activate(uuid string) (*Manifest, errors.Error) {
	// Find manifest with the given uuid
	manifest, ok := self.findManifest(uuid)
	if !ok {
		return nil, errors.ResourceNotFound(nil)
	}

	// Make sure that an image file has been uploaded
	if len(manifest.Files) == 0 {
		return nil, errors.NoActivationNoFile(nil)
	}

	// Make sure it has not been activated before
	if manifest.State != StateUnactivated {
		return nil, errors.ImageAlreadyActivated(nil)
	}

	self.lock()
	defer self.unlock()

	// Activate image
	manifest.State = StateActive
	manifest.Disabled = false
	manifest.PublishedAt = time.Now().Format(time.RFC3339)

	// Save manifests to disk
	if err := saveManifests(self.manifests); err != nil {
		return nil, errors.InternalError(err)
	}

	return manifest, nil
}
Example #3
0
func (self *Pool) Get(uuid string) (*Manifest, errors.Error) {
	manifest, ok := self.findManifest(uuid)
	if !ok {
		return nil, errors.ResourceNotFound(nil)
	}

	return manifest, nil
}
Example #4
0
func (self *Pool) GetFile(uuid string) (io.ReadCloser, *FileMetadata, errors.Error) {
	manifest, ok := self.findManifest(uuid)
	if !ok {
		err := fmt.Errorf("Manifest not found")
		return nil, nil, errors.ResourceNotFound(err)
	}

	if len(manifest.Files) == 0 {
		err := fmt.Errorf("Manifest has no files")
		return nil, nil, errors.ResourceNotFound(err)
	}

	// Find image extension by compression type
	compression := manifest.Files[0].Compression
	ext := FileExtensions[compression]

	// Find absolute path for image and md5file
	imageFpath := filepath.Join(self.imageDir, fmt.Sprintf("%s.%s", uuid, ext))
	md5Fpath := filepath.Join(self.imageDir, uuid+".md5")

	// Read md5 sum from file
	md5sum, err := ioutil.ReadFile(md5Fpath)
	if err != nil {
		return nil, nil, errors.InternalError(err)
	}

	// Open file
	f, err := os.Open(imageFpath)
	if err != nil {
		return nil, nil, errors.InternalError(err)
	}

	metadata := &FileMetadata{
		Md5sum: md5sum,
		Size:   manifest.Files[0].Size,
	}

	return f, metadata, nil
}
Example #5
0
func (self *Pool) Delete(uuid string) errors.Error {
	// Find manifest with matching uuid
	_, ok := self.findManifest(uuid)
	if !ok {
		return errors.ResourceNotFound(nil)
	}

	self.lock()

	// Remove manifest from internal slice first
	manifests := make([]*Manifest, 0)
	for _, m := range self.manifests {
		if m.Uuid != uuid {
			manifests = append(manifests, m)
		}
	}
	self.manifests = manifests

	// Save manifests to disk
	if err := saveManifests(self.manifests); err != nil {
		return errors.InternalError(err)
	}

	// No need to keep lock anymore
	self.unlock()

	// Find all files starting with the uuid of the image
	pattern := filepath.Join(self.imageDir, uuid+".*")
	matches, err := filepath.Glob(pattern)
	if err != nil {
		return errors.InternalError(err)
	}

	// Delete files
	for _, fname := range matches {
		os.Remove(fname)
	}

	return nil
}
Example #6
0
func (self *Pool) AddFile(uuid, compression string, reader io.Reader) (*Manifest, errors.Error) {
	// Find manifest with matching uuid
	manifest, ok := self.findManifest(uuid)
	if !ok {
		return nil, errors.ResourceNotFound(nil)
	}

	// Make sure the manifest has the correct state
	if manifest.State != StateUnactivated {
		return nil, errors.ImageAlreadyActivated(nil)
	}

	// Resolve file extension for the given compression type
	ext, ok := FileExtensions[compression]
	if !ok {
		return nil, errors.InvalidParameter(nil)
	}

	// Find absolute path for image and md5file
	imageFpath := filepath.Join(self.imageDir, fmt.Sprintf("%s.%s", uuid, ext))
	md5Fpath := filepath.Join(self.imageDir, uuid+".md5")

	// Create destination directory if it does not exist
	err := os.MkdirAll(self.imageDir, 0775)
	if err != nil {
		return nil, errors.InternalError(err)
	}

	// Open image file
	f, err := os.Create(imageFpath)
	if err != nil {
		return nil, errors.InternalError(err)
	}

	// Remember to close files
	defer f.Close()

	// Calcluate sha1 and md5 sum while writing image to disk
	// Sha1 is a required field in the manifest
	shaHash := sha1.New()
	sha1Reader := io.TeeReader(reader, shaHash)

	// Md5 is needed by imgadm client which expects the
	// content-md5 header to be present
	md5Hash := md5.New()
	md5Reader := io.TeeReader(sha1Reader, md5Hash)

	// Write image to disk
	nBytes, err := io.Copy(f, md5Reader)
	if err != nil {
		return nil, errors.Upload(err)
	}

	// Write md5sum to file
	md5sum := md5Hash.Sum(nil)
	if err := ioutil.WriteFile(md5Fpath, md5sum, 0660); err != nil {
		return nil, errors.InternalError(err)
	}

	// Add image file to manifest
	imageFile := &ImageFile{
		Sha1:        fmt.Sprintf("%x", shaHash.Sum(nil)),
		Compression: compression,
		Size:        nBytes,
	}

	// Update manifest
	self.lock()
	defer self.unlock()
	manifest.Files = []*ImageFile{imageFile}

	// Save manifests to disk
	if err := saveManifests(self.manifests); err != nil {
		return nil, errors.InternalError(err)
	}

	return manifest, nil
}