github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/worker/storageprovisioner/common.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package storageprovisioner
     5  
     6  import (
     7  	"path/filepath"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/names"
    11  
    12  	"github.com/juju/juju/apiserver/params"
    13  	"github.com/juju/juju/environs/config"
    14  	"github.com/juju/juju/storage"
    15  	"github.com/juju/juju/storage/provider/registry"
    16  )
    17  
    18  // storageEntityLife queries the lifecycle state of each specified
    19  // storage entity (volume or filesystem), and then partitions the
    20  // tags by them.
    21  func storageEntityLife(ctx *context, tags []names.Tag) (alive, dying, dead []names.Tag, _ error) {
    22  	lifeResults, err := ctx.life.Life(tags)
    23  	if err != nil {
    24  		return nil, nil, nil, errors.Annotate(err, "getting storage entity life")
    25  	}
    26  	for i, result := range lifeResults {
    27  		if result.Error != nil {
    28  			return nil, nil, nil, errors.Annotatef(
    29  				result.Error, "getting life of %s",
    30  				names.ReadableString(tags[i]),
    31  			)
    32  		}
    33  		switch result.Life {
    34  		case params.Alive:
    35  			alive = append(alive, tags[i])
    36  		case params.Dying:
    37  			dying = append(dying, tags[i])
    38  		case params.Dead:
    39  			dead = append(dead, tags[i])
    40  		}
    41  	}
    42  	return alive, dying, dead, nil
    43  }
    44  
    45  // attachmentLife queries the lifecycle state of each specified
    46  // attachment, and then partitions the IDs by them.
    47  func attachmentLife(ctx *context, ids []params.MachineStorageId) (
    48  	alive, dying, dead []params.MachineStorageId, _ error,
    49  ) {
    50  	lifeResults, err := ctx.life.AttachmentLife(ids)
    51  	if err != nil {
    52  		return nil, nil, nil, errors.Annotate(err, "getting machine attachment life")
    53  	}
    54  	for i, result := range lifeResults {
    55  		if result.Error != nil {
    56  			return nil, nil, nil, errors.Annotatef(
    57  				result.Error, "getting life of %s attached to %s",
    58  				ids[i].AttachmentTag, ids[i].MachineTag,
    59  			)
    60  		}
    61  		switch result.Life {
    62  		case params.Alive:
    63  			alive = append(alive, ids[i])
    64  		case params.Dying:
    65  			dying = append(dying, ids[i])
    66  		case params.Dead:
    67  			dead = append(dead, ids[i])
    68  		}
    69  	}
    70  	return alive, dying, dead, nil
    71  }
    72  
    73  // removeEntities removes each specified Dead entity from state.
    74  func removeEntities(ctx *context, tags []names.Tag) error {
    75  	logger.Debugf("removing entities: %v", tags)
    76  	errorResults, err := ctx.life.Remove(tags)
    77  	if err != nil {
    78  		return errors.Annotate(err, "removing storage entities")
    79  	}
    80  	for i, result := range errorResults {
    81  		if result.Error != nil {
    82  			return errors.Annotatef(result.Error, "removing %s from state", names.ReadableString(tags[i]))
    83  		}
    84  	}
    85  	return nil
    86  }
    87  
    88  // removeAttachments removes each specified attachment from state.
    89  func removeAttachments(ctx *context, ids []params.MachineStorageId) error {
    90  	errorResults, err := ctx.life.RemoveAttachments(ids)
    91  	if err != nil {
    92  		return errors.Annotate(err, "removing attachments")
    93  	}
    94  	for i, result := range errorResults {
    95  		if result.Error != nil {
    96  			return errors.Annotatef(
    97  				result.Error, "removing attachment of %s to %s from state",
    98  				ids[i].AttachmentTag, ids[i].MachineTag,
    99  			)
   100  		}
   101  	}
   102  	return nil
   103  }
   104  
   105  var errNonDynamic = errors.New("non-dynamic storage provider")
   106  
   107  // volumeSource returns a volume source given a name, provider type,
   108  // environment config and storage directory.
   109  //
   110  // TODO(axw) move this to the main storageprovisioner, and have
   111  // it watch for changes to storage source configurations, updating
   112  // a map in-between calls to the volume/filesystem/attachment
   113  // event handlers.
   114  func volumeSource(
   115  	environConfig *config.Config,
   116  	baseStorageDir string,
   117  	sourceName string,
   118  	providerType storage.ProviderType,
   119  ) (storage.VolumeSource, error) {
   120  	provider, sourceConfig, err := sourceParams(providerType, sourceName, baseStorageDir)
   121  	if err != nil {
   122  		return nil, errors.Annotatef(err, "getting storage source %q params", sourceName)
   123  	}
   124  	if !provider.Dynamic() {
   125  		return nil, errNonDynamic
   126  	}
   127  	source, err := provider.VolumeSource(environConfig, sourceConfig)
   128  	if err != nil {
   129  		return nil, errors.Annotatef(err, "getting storage source %q", sourceName)
   130  	}
   131  	return source, nil
   132  }
   133  
   134  // filesystemSource returns a filesystem source given a name, provider type,
   135  // environment config and storage directory.
   136  //
   137  // TODO(axw) move this to the main storageprovisioner, and have
   138  // it watch for changes to storage source configurations, updating
   139  // a map in-between calls to the volume/filesystem/attachment
   140  // event handlers.
   141  func filesystemSource(
   142  	environConfig *config.Config,
   143  	baseStorageDir string,
   144  	sourceName string,
   145  	providerType storage.ProviderType,
   146  ) (storage.FilesystemSource, error) {
   147  	provider, sourceConfig, err := sourceParams(providerType, sourceName, baseStorageDir)
   148  	if err != nil {
   149  		return nil, errors.Annotatef(err, "getting storage source %q params", sourceName)
   150  	}
   151  	source, err := provider.FilesystemSource(environConfig, sourceConfig)
   152  	if err != nil {
   153  		return nil, errors.Annotatef(err, "getting storage source %q", sourceName)
   154  	}
   155  	return source, nil
   156  }
   157  
   158  func sourceParams(providerType storage.ProviderType, sourceName, baseStorageDir string) (storage.Provider, *storage.Config, error) {
   159  	provider, err := registry.StorageProvider(providerType)
   160  	if err != nil {
   161  		return nil, nil, errors.Annotate(err, "getting provider")
   162  	}
   163  	attrs := make(map[string]interface{})
   164  	if baseStorageDir != "" {
   165  		storageDir := filepath.Join(baseStorageDir, sourceName)
   166  		attrs[storage.ConfigStorageDir] = storageDir
   167  	}
   168  	sourceConfig, err := storage.NewConfig(sourceName, providerType, attrs)
   169  	if err != nil {
   170  		return nil, nil, errors.Annotate(err, "getting config")
   171  	}
   172  	return provider, sourceConfig, nil
   173  }