github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/cmd/juju/storage/volume.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package storage
     5  
     6  import (
     7  	"github.com/juju/cmd"
     8  	"github.com/juju/errors"
     9  	"github.com/juju/names"
    10  
    11  	"github.com/juju/juju/apiserver/params"
    12  	jujucmd "github.com/juju/juju/cmd"
    13  	"github.com/juju/juju/cmd/envcmd"
    14  )
    15  
    16  const volumeCmdDoc = `
    17  "juju storage volume" is used to manage storage volumes in
    18   the Juju environment.
    19  `
    20  
    21  const volumeCmdPurpose = "manage storage volumes"
    22  
    23  // NewVolumeSuperCommand creates the storage volume super subcommand and
    24  // registers the subcommands that it supports.
    25  func NewVolumeSuperCommand() cmd.Command {
    26  	poolcmd := Command{
    27  		SuperCommand: *jujucmd.NewSubSuperCommand(cmd.SuperCommandParams{
    28  			Name:        "volume",
    29  			Doc:         volumeCmdDoc,
    30  			UsagePrefix: "juju storage",
    31  			Purpose:     volumeCmdPurpose,
    32  		})}
    33  	poolcmd.Register(envcmd.Wrap(&VolumeListCommand{}))
    34  	return &poolcmd
    35  }
    36  
    37  // VolumeCommandBase is a helper base structure for volume commands.
    38  type VolumeCommandBase struct {
    39  	StorageCommandBase
    40  }
    41  
    42  // VolumeInfo defines the serialization behaviour for storage volume.
    43  type VolumeInfo struct {
    44  	// from params.Volume. This is provider-supplied unique volume id.
    45  	VolumeId string `yaml:"id" json:"id"`
    46  
    47  	// from params.Volume
    48  	HardwareId string `yaml:"hardwareid" json:"hardwareid"`
    49  
    50  	// from params.Volume
    51  	Size uint64 `yaml:"size" json:"size"`
    52  
    53  	// from params.Volume
    54  	Persistent bool `yaml:"persistent" json:"persistent"`
    55  
    56  	// from params.VolumeAttachments
    57  	DeviceName string `yaml:"device,omitempty" json:"device,omitempty"`
    58  
    59  	// from params.VolumeAttachments
    60  	ReadOnly bool `yaml:"read-only" json:"read-only"`
    61  
    62  	// from params.Volume. This is juju volume id.
    63  	Volume string `yaml:"volume,omitempty" json:"volume,omitempty"`
    64  }
    65  
    66  // convertToVolumeInfo returns map of maps with volume info
    67  // keyed first on machine_id and then on volume_id.
    68  func convertToVolumeInfo(all []params.VolumeItem) (map[string]map[string]map[string]VolumeInfo, error) {
    69  	result := map[string]map[string]map[string]VolumeInfo{}
    70  	for _, one := range all {
    71  		if err := convertVolumeItem(one, result); err != nil {
    72  			return nil, errors.Trace(err)
    73  		}
    74  	}
    75  	return result, nil
    76  }
    77  
    78  func convertVolumeItem(item params.VolumeItem, all map[string]map[string]map[string]VolumeInfo) error {
    79  	if len(item.Attachments) != 0 {
    80  		// add info for volume attachments
    81  		return convertVolumeAttachments(item, all)
    82  	}
    83  	unattached, unit, storage := createInfo(item.Volume)
    84  	addOneToAll("unattached", unit, storage, unattached, all)
    85  	return nil
    86  }
    87  
    88  var idFromTag = func(s string) (string, error) {
    89  	tag, err := names.ParseTag(s)
    90  	if err != nil {
    91  		return "", errors.Annotatef(err, "invalid tag %v", tag)
    92  	}
    93  	return tag.Id(), nil
    94  }
    95  
    96  func convertVolumeAttachments(item params.VolumeItem, all map[string]map[string]map[string]VolumeInfo) error {
    97  	for _, one := range item.Attachments {
    98  		machine, err := idFromTag(one.MachineTag)
    99  		if err != nil {
   100  			return errors.Trace(err)
   101  		}
   102  		info, unit, storage := createInfo(item.Volume)
   103  		info.DeviceName = one.Info.DeviceName
   104  		info.ReadOnly = one.Info.ReadOnly
   105  
   106  		addOneToAll(machine, unit, storage, info, all)
   107  	}
   108  	return nil
   109  }
   110  
   111  func addOneToAll(machineId, unitId, storageId string, item VolumeInfo, all map[string]map[string]map[string]VolumeInfo) {
   112  	machineVolumes, ok := all[machineId]
   113  	if !ok {
   114  		machineVolumes = map[string]map[string]VolumeInfo{}
   115  		all[machineId] = machineVolumes
   116  	}
   117  	unitVolumes, ok := machineVolumes[unitId]
   118  	if !ok {
   119  		unitVolumes = map[string]VolumeInfo{}
   120  		machineVolumes[unitId] = unitVolumes
   121  	}
   122  	unitVolumes[storageId] = item
   123  }
   124  
   125  func createInfo(volume params.VolumeInstance) (info VolumeInfo, unit, storage string) {
   126  	info.VolumeId = volume.VolumeId
   127  	info.HardwareId = volume.HardwareId
   128  	info.Size = volume.Size
   129  	info.Persistent = volume.Persistent
   130  
   131  	if v, err := idFromTag(volume.VolumeTag); err == nil {
   132  		info.Volume = v
   133  	}
   134  	var err error
   135  	if storage, err = idFromTag(volume.StorageTag); err != nil {
   136  		storage = "unassigned"
   137  	}
   138  	if unit, err = idFromTag(volume.UnitTag); err != nil {
   139  		unit = "unattached"
   140  	}
   141  	return
   142  }