github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/apiserver/common/storagecommon/volumes.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package storagecommon
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/names"
     9  
    10  	"github.com/juju/juju/apiserver/params"
    11  	"github.com/juju/juju/environs/config"
    12  	"github.com/juju/juju/state"
    13  	"github.com/juju/juju/storage"
    14  	"github.com/juju/juju/storage/poolmanager"
    15  	"github.com/juju/juju/storage/provider/registry"
    16  )
    17  
    18  type volumeAlreadyProvisionedError struct {
    19  	error
    20  }
    21  
    22  // IsVolumeAlreadyProvisioned returns true if the specified error
    23  // is caused by a volume already being provisioned.
    24  func IsVolumeAlreadyProvisioned(err error) bool {
    25  	_, ok := err.(*volumeAlreadyProvisionedError)
    26  	return ok
    27  }
    28  
    29  // VolumeParams returns the parameters for creating or destroying
    30  // the given volume.
    31  func VolumeParams(
    32  	v state.Volume,
    33  	storageInstance state.StorageInstance,
    34  	environConfig *config.Config,
    35  	poolManager poolmanager.PoolManager,
    36  ) (params.VolumeParams, error) {
    37  
    38  	var pool string
    39  	var size uint64
    40  	if stateVolumeParams, ok := v.Params(); ok {
    41  		pool = stateVolumeParams.Pool
    42  		size = stateVolumeParams.Size
    43  	} else {
    44  		volumeInfo, err := v.Info()
    45  		if err != nil {
    46  			return params.VolumeParams{}, errors.Trace(err)
    47  		}
    48  		pool = volumeInfo.Pool
    49  		size = volumeInfo.Size
    50  	}
    51  
    52  	volumeTags, err := storageTags(storageInstance, environConfig)
    53  	if err != nil {
    54  		return params.VolumeParams{}, errors.Annotate(err, "computing storage tags")
    55  	}
    56  
    57  	providerType, cfg, err := StoragePoolConfig(pool, poolManager)
    58  	if err != nil {
    59  		return params.VolumeParams{}, errors.Trace(err)
    60  	}
    61  	return params.VolumeParams{
    62  		v.Tag().String(),
    63  		size,
    64  		string(providerType),
    65  		cfg.Attrs(),
    66  		volumeTags,
    67  		nil, // attachment params set by the caller
    68  	}, nil
    69  }
    70  
    71  // StoragePoolConfig returns the storage provider type and
    72  // configuration for a named storage pool. If there is no
    73  // such pool with the specified name, but it identifies a
    74  // storage provider, then that type will be returned with a
    75  // nil configuration.
    76  func StoragePoolConfig(name string, poolManager poolmanager.PoolManager) (storage.ProviderType, *storage.Config, error) {
    77  	pool, err := poolManager.Get(name)
    78  	if errors.IsNotFound(err) {
    79  		// If not a storage pool, then maybe a provider type.
    80  		providerType := storage.ProviderType(name)
    81  		if _, err1 := registry.StorageProvider(providerType); err1 != nil {
    82  			return "", nil, errors.Trace(err)
    83  		}
    84  		return providerType, &storage.Config{}, nil
    85  	} else if err != nil {
    86  		return "", nil, errors.Annotatef(err, "getting pool %q", name)
    87  	}
    88  	return pool.Provider(), pool, nil
    89  }
    90  
    91  // VolumesToState converts a slice of params.Volume to a mapping
    92  // of volume tags to state.VolumeInfo.
    93  func VolumesToState(in []params.Volume) (map[names.VolumeTag]state.VolumeInfo, error) {
    94  	m := make(map[names.VolumeTag]state.VolumeInfo)
    95  	for _, v := range in {
    96  		tag, volumeInfo, err := VolumeToState(v)
    97  		if err != nil {
    98  			return nil, errors.Trace(err)
    99  		}
   100  		m[tag] = volumeInfo
   101  	}
   102  	return m, nil
   103  }
   104  
   105  // VolumeToState converts a params.Volume to state.VolumeInfo
   106  // and names.VolumeTag.
   107  func VolumeToState(v params.Volume) (names.VolumeTag, state.VolumeInfo, error) {
   108  	if v.VolumeTag == "" {
   109  		return names.VolumeTag{}, state.VolumeInfo{}, errors.New("Tag is empty")
   110  	}
   111  	volumeTag, err := names.ParseVolumeTag(v.VolumeTag)
   112  	if err != nil {
   113  		return names.VolumeTag{}, state.VolumeInfo{}, errors.Trace(err)
   114  	}
   115  	return volumeTag, state.VolumeInfo{
   116  		v.Info.HardwareId,
   117  		v.Info.Size,
   118  		"", // pool is set by state
   119  		v.Info.VolumeId,
   120  		v.Info.Persistent,
   121  	}, nil
   122  }
   123  
   124  // VolumeFromState converts a state.Volume to params.Volume.
   125  func VolumeFromState(v state.Volume) (params.Volume, error) {
   126  	info, err := v.Info()
   127  	if err != nil {
   128  		return params.Volume{}, errors.Trace(err)
   129  	}
   130  	return params.Volume{
   131  		v.VolumeTag().String(),
   132  		VolumeInfoFromState(info),
   133  	}, nil
   134  }
   135  
   136  // VolumeInfoFromState converts a state.VolumeInfo to params.VolumeInfo.
   137  func VolumeInfoFromState(info state.VolumeInfo) params.VolumeInfo {
   138  	return params.VolumeInfo{
   139  		info.VolumeId,
   140  		info.HardwareId,
   141  		info.Size,
   142  		info.Persistent,
   143  	}
   144  }
   145  
   146  // VolumeAttachmentFromState converts a state.VolumeAttachment to params.VolumeAttachment.
   147  func VolumeAttachmentFromState(v state.VolumeAttachment) (params.VolumeAttachment, error) {
   148  	info, err := v.Info()
   149  	if err != nil {
   150  		return params.VolumeAttachment{}, errors.Trace(err)
   151  	}
   152  	return params.VolumeAttachment{
   153  		v.Volume().String(),
   154  		v.Machine().String(),
   155  		VolumeAttachmentInfoFromState(info),
   156  	}, nil
   157  }
   158  
   159  // VolumeAttachmentInfoFromState converts a state.VolumeAttachmentInfo to params.VolumeAttachmentInfo.
   160  func VolumeAttachmentInfoFromState(info state.VolumeAttachmentInfo) params.VolumeAttachmentInfo {
   161  	return params.VolumeAttachmentInfo{
   162  		info.DeviceName,
   163  		info.DeviceLink,
   164  		info.BusAddress,
   165  		info.ReadOnly,
   166  	}
   167  }
   168  
   169  // VolumeAttachmentInfosToState converts a map of volume tags to
   170  // params.VolumeAttachmentInfo to a map of volume tags to
   171  // state.VolumeAttachmentInfo.
   172  func VolumeAttachmentInfosToState(in map[string]params.VolumeAttachmentInfo) (map[names.VolumeTag]state.VolumeAttachmentInfo, error) {
   173  	m := make(map[names.VolumeTag]state.VolumeAttachmentInfo)
   174  	for k, v := range in {
   175  		volumeTag, err := names.ParseVolumeTag(k)
   176  		if err != nil {
   177  			return nil, errors.Trace(err)
   178  		}
   179  		m[volumeTag] = VolumeAttachmentInfoToState(v)
   180  	}
   181  	return m, nil
   182  }
   183  
   184  // VolumeAttachmentToState converts a params.VolumeAttachment
   185  // to a state.VolumeAttachmentInfo and tags.
   186  func VolumeAttachmentToState(in params.VolumeAttachment) (names.MachineTag, names.VolumeTag, state.VolumeAttachmentInfo, error) {
   187  	machineTag, err := names.ParseMachineTag(in.MachineTag)
   188  	if err != nil {
   189  		return names.MachineTag{}, names.VolumeTag{}, state.VolumeAttachmentInfo{}, err
   190  	}
   191  	volumeTag, err := names.ParseVolumeTag(in.VolumeTag)
   192  	if err != nil {
   193  		return names.MachineTag{}, names.VolumeTag{}, state.VolumeAttachmentInfo{}, err
   194  	}
   195  	info := VolumeAttachmentInfoToState(in.Info)
   196  	return machineTag, volumeTag, info, nil
   197  }
   198  
   199  // VolumeAttachmentInfoToState converts a params.VolumeAttachmentInfo
   200  // to a state.VolumeAttachmentInfo.
   201  func VolumeAttachmentInfoToState(in params.VolumeAttachmentInfo) state.VolumeAttachmentInfo {
   202  	return state.VolumeAttachmentInfo{
   203  		in.DeviceName,
   204  		in.DeviceLink,
   205  		in.BusAddress,
   206  		in.ReadOnly,
   207  	}
   208  }
   209  
   210  // ParseVolumeAttachmentIds parses the strings, returning machine storage IDs.
   211  func ParseVolumeAttachmentIds(stringIds []string) ([]params.MachineStorageId, error) {
   212  	ids := make([]params.MachineStorageId, len(stringIds))
   213  	for i, s := range stringIds {
   214  		m, v, err := state.ParseVolumeAttachmentId(s)
   215  		if err != nil {
   216  			return nil, err
   217  		}
   218  		ids[i] = params.MachineStorageId{
   219  			MachineTag:    m.String(),
   220  			AttachmentTag: v.String(),
   221  		}
   222  	}
   223  	return ids, nil
   224  }