github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/cmd/juju/storage/storage.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  // The storage command provides a storage management interface,
     5  // for manipulating and inspecting storage entities (volumes,
     6  // filesystems, charm storage).
     7  package storage
     8  
     9  import (
    10  	"github.com/juju/errors"
    11  	"github.com/juju/names"
    12  
    13  	"github.com/juju/juju/api/storage"
    14  	"github.com/juju/juju/apiserver/params"
    15  	"github.com/juju/juju/cmd/juju/common"
    16  	"github.com/juju/juju/cmd/modelcmd"
    17  )
    18  
    19  // StorageCommandBase is a helper base structure that has a method to get the
    20  // storage managing client.
    21  type StorageCommandBase struct {
    22  	modelcmd.ModelCommandBase
    23  }
    24  
    25  // NewStorageAPI returns a storage api for the root api endpoint
    26  // that the environment command returns.
    27  func (c *StorageCommandBase) NewStorageAPI() (*storage.Client, error) {
    28  	root, err := c.NewAPIRoot()
    29  	if err != nil {
    30  		return nil, err
    31  	}
    32  	return storage.NewClient(root), nil
    33  }
    34  
    35  // StorageInfo defines the serialization behaviour of the storage information.
    36  type StorageInfo struct {
    37  	Kind        string              `yaml:"kind" json:"kind"`
    38  	Status      EntityStatus        `yaml:"status" json:"status"`
    39  	Persistent  bool                `yaml:"persistent" json:"persistent"`
    40  	Attachments *StorageAttachments `yaml:"attachments" json:"attachments"`
    41  }
    42  
    43  // StorageAttachments contains details about all attachments to a storage
    44  // instance.
    45  type StorageAttachments struct {
    46  	// Units is a mapping from unit ID to unit storage attachment details.
    47  	Units map[string]UnitStorageAttachment `yaml:"units" json:"units"`
    48  }
    49  
    50  // UnitStorageAttachment contains details of a unit storage attachment.
    51  type UnitStorageAttachment struct {
    52  	// MachineId is the ID of the machine that the unit is assigned to.
    53  	//
    54  	// This is omitempty to cater for legacy results, where the machine
    55  	// information is not available.
    56  	MachineId string `yaml:"machine,omitempty" json:"machine,omitempty"`
    57  
    58  	// Location is the location of the storage attachment.
    59  	Location string `yaml:"location,omitempty" json:"location,omitempty"`
    60  
    61  	// TODO(axw) per-unit status when we have it in state.
    62  }
    63  
    64  // formatStorageDetails takes a set of StorageDetail and
    65  // creates a mapping from storage ID to storage details.
    66  func formatStorageDetails(storages []params.StorageDetails) (map[string]StorageInfo, error) {
    67  	if len(storages) == 0 {
    68  		return nil, nil
    69  	}
    70  	output := make(map[string]StorageInfo)
    71  	for _, details := range storages {
    72  		storageTag, storageInfo, err := createStorageInfo(details)
    73  		if err != nil {
    74  			return nil, errors.Trace(err)
    75  		}
    76  		output[storageTag.Id()] = storageInfo
    77  	}
    78  	return output, nil
    79  }
    80  
    81  func createStorageInfo(details params.StorageDetails) (names.StorageTag, StorageInfo, error) {
    82  	storageTag, err := names.ParseStorageTag(details.StorageTag)
    83  	if err != nil {
    84  		return names.StorageTag{}, StorageInfo{}, errors.Trace(err)
    85  	}
    86  
    87  	info := StorageInfo{
    88  		Kind: details.Kind.String(),
    89  		Status: EntityStatus{
    90  			details.Status.Status,
    91  			details.Status.Info,
    92  			// TODO(axw) we should support formatting as ISO time
    93  			common.FormatTime(details.Status.Since, false),
    94  		},
    95  		Persistent: details.Persistent,
    96  	}
    97  
    98  	if len(details.Attachments) > 0 {
    99  		unitStorageAttachments := make(map[string]UnitStorageAttachment)
   100  		for unitTagString, attachmentDetails := range details.Attachments {
   101  			unitTag, err := names.ParseUnitTag(unitTagString)
   102  			if err != nil {
   103  				return names.StorageTag{}, StorageInfo{}, errors.Trace(err)
   104  			}
   105  			var machineId string
   106  			if attachmentDetails.MachineTag != "" {
   107  				machineTag, err := names.ParseMachineTag(attachmentDetails.MachineTag)
   108  				if err != nil {
   109  					return names.StorageTag{}, StorageInfo{}, errors.Trace(err)
   110  				}
   111  				machineId = machineTag.Id()
   112  			}
   113  			unitStorageAttachments[unitTag.Id()] = UnitStorageAttachment{
   114  				machineId,
   115  				attachmentDetails.Location,
   116  			}
   117  		}
   118  		info.Attachments = &StorageAttachments{unitStorageAttachments}
   119  	}
   120  
   121  	return storageTag, info, nil
   122  }