github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/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  	"gopkg.in/juju/names.v2"
     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  )
    16  
    17  // VolumeParams returns the parameters for creating or destroying
    18  // the given volume.
    19  func VolumeParams(
    20  	v state.Volume,
    21  	storageInstance state.StorageInstance,
    22  	modelUUID, controllerUUID string,
    23  	environConfig *config.Config,
    24  	poolManager poolmanager.PoolManager,
    25  	registry storage.ProviderRegistry,
    26  ) (params.VolumeParams, error) {
    27  
    28  	var pool string
    29  	var size uint64
    30  	if stateVolumeParams, ok := v.Params(); ok {
    31  		pool = stateVolumeParams.Pool
    32  		size = stateVolumeParams.Size
    33  	} else {
    34  		volumeInfo, err := v.Info()
    35  		if err != nil {
    36  			return params.VolumeParams{}, errors.Trace(err)
    37  		}
    38  		pool = volumeInfo.Pool
    39  		size = volumeInfo.Size
    40  	}
    41  
    42  	volumeTags, err := StorageTags(storageInstance, modelUUID, controllerUUID, environConfig)
    43  	if err != nil {
    44  		return params.VolumeParams{}, errors.Annotate(err, "computing storage tags")
    45  	}
    46  
    47  	providerType, cfg, err := StoragePoolConfig(pool, poolManager, registry)
    48  	if err != nil {
    49  		return params.VolumeParams{}, errors.Trace(err)
    50  	}
    51  	return params.VolumeParams{
    52  		v.Tag().String(),
    53  		size,
    54  		string(providerType),
    55  		cfg.Attrs(),
    56  		volumeTags,
    57  		nil, // attachment params set by the caller
    58  	}, nil
    59  }
    60  
    61  // StoragePoolConfig returns the storage provider type and
    62  // configuration for a named storage pool. If there is no
    63  // such pool with the specified name, but it identifies a
    64  // storage provider, then that type will be returned with a
    65  // nil configuration.
    66  func StoragePoolConfig(name string, poolManager poolmanager.PoolManager, registry storage.ProviderRegistry) (storage.ProviderType, *storage.Config, error) {
    67  	pool, err := poolManager.Get(name)
    68  	if errors.IsNotFound(err) {
    69  		// If not a storage pool, then maybe a provider type.
    70  		providerType := storage.ProviderType(name)
    71  		if _, err1 := registry.StorageProvider(providerType); err1 != nil {
    72  			return "", nil, errors.Trace(err)
    73  		}
    74  		return providerType, &storage.Config{}, nil
    75  	} else if err != nil {
    76  		return "", nil, errors.Annotatef(err, "getting pool %q", name)
    77  	}
    78  	return pool.Provider(), pool, nil
    79  }
    80  
    81  // VolumesToState converts a slice of params.Volume to a mapping
    82  // of volume tags to state.VolumeInfo.
    83  func VolumesToState(in []params.Volume) (map[names.VolumeTag]state.VolumeInfo, error) {
    84  	m := make(map[names.VolumeTag]state.VolumeInfo)
    85  	for _, v := range in {
    86  		tag, volumeInfo, err := VolumeToState(v)
    87  		if err != nil {
    88  			return nil, errors.Trace(err)
    89  		}
    90  		m[tag] = volumeInfo
    91  	}
    92  	return m, nil
    93  }
    94  
    95  // VolumeToState converts a params.Volume to state.VolumeInfo
    96  // and names.VolumeTag.
    97  func VolumeToState(v params.Volume) (names.VolumeTag, state.VolumeInfo, error) {
    98  	if v.VolumeTag == "" {
    99  		return names.VolumeTag{}, state.VolumeInfo{}, errors.New("Tag is empty")
   100  	}
   101  	volumeTag, err := names.ParseVolumeTag(v.VolumeTag)
   102  	if err != nil {
   103  		return names.VolumeTag{}, state.VolumeInfo{}, errors.Trace(err)
   104  	}
   105  	return volumeTag, state.VolumeInfo{
   106  		v.Info.HardwareId,
   107  		v.Info.WWN,
   108  		v.Info.Size,
   109  		"", // pool is set by state
   110  		v.Info.VolumeId,
   111  		v.Info.Persistent,
   112  	}, nil
   113  }
   114  
   115  // VolumeFromState converts a state.Volume to params.Volume.
   116  func VolumeFromState(v state.Volume) (params.Volume, error) {
   117  	info, err := v.Info()
   118  	if err != nil {
   119  		return params.Volume{}, errors.Trace(err)
   120  	}
   121  	return params.Volume{
   122  		v.VolumeTag().String(),
   123  		VolumeInfoFromState(info),
   124  	}, nil
   125  }
   126  
   127  // VolumeInfoFromState converts a state.VolumeInfo to params.VolumeInfo.
   128  func VolumeInfoFromState(info state.VolumeInfo) params.VolumeInfo {
   129  	return params.VolumeInfo{
   130  		info.VolumeId,
   131  		info.HardwareId,
   132  		info.WWN,
   133  		info.Pool,
   134  		info.Size,
   135  		info.Persistent,
   136  	}
   137  }
   138  
   139  // VolumeAttachmentPlanFromState converts a state.VolumeAttachmentPlan to params.VolumeAttachmentPlan.
   140  func VolumeAttachmentPlanFromState(v state.VolumeAttachmentPlan) (params.VolumeAttachmentPlan, error) {
   141  	planInfo, err := v.PlanInfo()
   142  	if err != nil {
   143  		return params.VolumeAttachmentPlan{}, errors.Trace(err)
   144  	}
   145  
   146  	blockInfo, err := v.BlockDeviceInfo()
   147  	if err != nil {
   148  		if !errors.IsNotFound(err) {
   149  			return params.VolumeAttachmentPlan{}, errors.Trace(err)
   150  		}
   151  	}
   152  	return params.VolumeAttachmentPlan{
   153  		VolumeTag:   v.Volume().String(),
   154  		MachineTag:  v.Machine().String(),
   155  		Life:        params.Life(v.Life().String()),
   156  		PlanInfo:    VolumeAttachmentPlanInfoFromState(planInfo),
   157  		BlockDevice: VolumeAttachmentPlanBlockInfoFromState(blockInfo),
   158  	}, nil
   159  }
   160  
   161  func VolumeAttachmentPlanBlockInfoFromState(blockInfo state.BlockDeviceInfo) storage.BlockDevice {
   162  	return storage.BlockDevice{
   163  		DeviceName:     blockInfo.DeviceName,
   164  		DeviceLinks:    blockInfo.DeviceLinks,
   165  		Label:          blockInfo.Label,
   166  		UUID:           blockInfo.UUID,
   167  		HardwareId:     blockInfo.HardwareId,
   168  		WWN:            blockInfo.WWN,
   169  		BusAddress:     blockInfo.BusAddress,
   170  		Size:           blockInfo.Size,
   171  		FilesystemType: blockInfo.FilesystemType,
   172  		InUse:          blockInfo.InUse,
   173  		MountPoint:     blockInfo.MountPoint,
   174  	}
   175  }
   176  
   177  func VolumeAttachmentPlanInfoFromState(planInfo state.VolumeAttachmentPlanInfo) params.VolumeAttachmentPlanInfo {
   178  	return params.VolumeAttachmentPlanInfo{
   179  		DeviceType:       planInfo.DeviceType,
   180  		DeviceAttributes: planInfo.DeviceAttributes,
   181  	}
   182  }
   183  
   184  // VolumeAttachmentFromState converts a state.VolumeAttachment to params.VolumeAttachment.
   185  func VolumeAttachmentFromState(v state.VolumeAttachment) (params.VolumeAttachment, error) {
   186  	info, err := v.Info()
   187  	if err != nil {
   188  		return params.VolumeAttachment{}, errors.Trace(err)
   189  	}
   190  	return params.VolumeAttachment{
   191  		v.Volume().String(),
   192  		v.Host().String(),
   193  		VolumeAttachmentInfoFromState(info),
   194  	}, nil
   195  }
   196  
   197  // VolumeAttachmentInfoFromState converts a state.VolumeAttachmentInfo to params.VolumeAttachmentInfo.
   198  func VolumeAttachmentInfoFromState(info state.VolumeAttachmentInfo) params.VolumeAttachmentInfo {
   199  	planInfo := &params.VolumeAttachmentPlanInfo{}
   200  	if info.PlanInfo != nil {
   201  		planInfo.DeviceType = info.PlanInfo.DeviceType
   202  		planInfo.DeviceAttributes = info.PlanInfo.DeviceAttributes
   203  	} else {
   204  		planInfo = nil
   205  	}
   206  	return params.VolumeAttachmentInfo{
   207  		info.DeviceName,
   208  		info.DeviceLink,
   209  		info.BusAddress,
   210  		info.ReadOnly,
   211  		planInfo,
   212  	}
   213  }
   214  
   215  // VolumeAttachmentInfosToState converts a map of volume tags to
   216  // params.VolumeAttachmentInfo to a map of volume tags to
   217  // state.VolumeAttachmentInfo.
   218  func VolumeAttachmentInfosToState(in map[string]params.VolumeAttachmentInfo) (map[names.VolumeTag]state.VolumeAttachmentInfo, error) {
   219  	m := make(map[names.VolumeTag]state.VolumeAttachmentInfo)
   220  	for k, v := range in {
   221  		volumeTag, err := names.ParseVolumeTag(k)
   222  		if err != nil {
   223  			return nil, errors.Trace(err)
   224  		}
   225  		m[volumeTag] = VolumeAttachmentInfoToState(v)
   226  	}
   227  	return m, nil
   228  }
   229  
   230  func VolumeAttachmentPlanToState(in params.VolumeAttachmentPlan) (names.MachineTag, names.VolumeTag, state.VolumeAttachmentPlanInfo, state.BlockDeviceInfo, error) {
   231  	machineTag, err := names.ParseMachineTag(in.MachineTag)
   232  	if err != nil {
   233  		return names.MachineTag{}, names.VolumeTag{}, state.VolumeAttachmentPlanInfo{}, state.BlockDeviceInfo{}, err
   234  	}
   235  	volumeTag, err := names.ParseVolumeTag(in.VolumeTag)
   236  	if err != nil {
   237  		return names.MachineTag{}, names.VolumeTag{}, state.VolumeAttachmentPlanInfo{}, state.BlockDeviceInfo{}, err
   238  	}
   239  	info := VolumeAttachmentPlanInfoToState(in.PlanInfo)
   240  	blockInfo := BlockDeviceInfoToState(in.BlockDevice)
   241  	return machineTag, volumeTag, info, blockInfo, nil
   242  }
   243  
   244  func BlockDeviceInfoToState(in storage.BlockDevice) state.BlockDeviceInfo {
   245  	return state.BlockDeviceInfo{
   246  		DeviceName:     in.DeviceName,
   247  		DeviceLinks:    in.DeviceLinks,
   248  		Label:          in.Label,
   249  		UUID:           in.UUID,
   250  		HardwareId:     in.HardwareId,
   251  		WWN:            in.WWN,
   252  		BusAddress:     in.BusAddress,
   253  		Size:           in.Size,
   254  		FilesystemType: in.FilesystemType,
   255  		InUse:          in.InUse,
   256  		MountPoint:     in.MountPoint,
   257  	}
   258  }
   259  
   260  // VolumeAttachmentToState converts a params.VolumeAttachment
   261  // to a state.VolumeAttachmentInfo and tags.
   262  func VolumeAttachmentToState(in params.VolumeAttachment) (names.MachineTag, names.VolumeTag, state.VolumeAttachmentInfo, error) {
   263  	machineTag, err := names.ParseMachineTag(in.MachineTag)
   264  	if err != nil {
   265  		return names.MachineTag{}, names.VolumeTag{}, state.VolumeAttachmentInfo{}, err
   266  	}
   267  	volumeTag, err := names.ParseVolumeTag(in.VolumeTag)
   268  	if err != nil {
   269  		return names.MachineTag{}, names.VolumeTag{}, state.VolumeAttachmentInfo{}, err
   270  	}
   271  	info := VolumeAttachmentInfoToState(in.Info)
   272  	return machineTag, volumeTag, info, nil
   273  }
   274  
   275  func VolumeAttachmentPlanInfoToState(in params.VolumeAttachmentPlanInfo) state.VolumeAttachmentPlanInfo {
   276  	deviceType := in.DeviceType
   277  	if deviceType == "" {
   278  		deviceType = storage.DeviceTypeLocal
   279  	}
   280  
   281  	return state.VolumeAttachmentPlanInfo{
   282  		DeviceType:       deviceType,
   283  		DeviceAttributes: in.DeviceAttributes,
   284  	}
   285  }
   286  
   287  // VolumeAttachmentInfoToState converts a params.VolumeAttachmentInfo
   288  // to a state.VolumeAttachmentInfo.
   289  func VolumeAttachmentInfoToState(in params.VolumeAttachmentInfo) state.VolumeAttachmentInfo {
   290  	planInfo := &state.VolumeAttachmentPlanInfo{}
   291  	if in.PlanInfo != nil {
   292  		planInfo.DeviceAttributes = in.PlanInfo.DeviceAttributes
   293  		planInfo.DeviceType = in.PlanInfo.DeviceType
   294  	} else {
   295  		planInfo = nil
   296  	}
   297  	return state.VolumeAttachmentInfo{
   298  		in.DeviceName,
   299  		in.DeviceLink,
   300  		in.BusAddress,
   301  		in.ReadOnly,
   302  		planInfo,
   303  	}
   304  }
   305  
   306  // ParseVolumeAttachmentIds parses the strings, returning machine storage IDs.
   307  func ParseVolumeAttachmentIds(stringIds []string) ([]params.MachineStorageId, error) {
   308  	ids := make([]params.MachineStorageId, len(stringIds))
   309  	for i, s := range stringIds {
   310  		m, v, err := state.ParseVolumeAttachmentId(s)
   311  		if err != nil {
   312  			return nil, err
   313  		}
   314  		ids[i] = params.MachineStorageId{
   315  			MachineTag:    m.String(),
   316  			AttachmentTag: v.String(),
   317  		}
   318  	}
   319  	return ids, nil
   320  }