github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/cmd/juju/storage/filesystem.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  	"fmt"
     8  
     9  	"github.com/juju/cmd"
    10  	"github.com/juju/errors"
    11  	"github.com/juju/names"
    12  
    13  	"github.com/juju/juju/apiserver/params"
    14  	"github.com/juju/juju/cmd/juju/common"
    15  )
    16  
    17  // FilesystemCommandBase is a helper base structure for filesystem commands.
    18  type FilesystemCommandBase struct {
    19  	StorageCommandBase
    20  }
    21  
    22  // FilesystemInfo defines the serialization behaviour for storage filesystem.
    23  type FilesystemInfo struct {
    24  	// from params.Filesystem. This is provider-supplied unique filesystem id.
    25  	ProviderFilesystemId string `yaml:"provider-id,omitempty" json:"provider-id,omitempty"`
    26  
    27  	// Volume is the ID of the volume that the filesystem is backed by, if any.
    28  	Volume string
    29  
    30  	// Storage is the ID of the storage instance that the filesystem is
    31  	// assigned to, if any.
    32  	Storage string
    33  
    34  	// Attachments is the set of entities attached to the filesystem.
    35  	Attachments *FilesystemAttachments
    36  
    37  	// from params.FilesystemInfo
    38  	Size uint64 `yaml:"size" json:"size"`
    39  
    40  	// from params.FilesystemInfo.
    41  	Status EntityStatus `yaml:"status,omitempty" json:"status,omitempty"`
    42  }
    43  
    44  type FilesystemAttachments struct {
    45  	Machines map[string]MachineFilesystemAttachment `yaml:"machines,omitempty" json:"machines,omitempty"`
    46  	Units    map[string]UnitStorageAttachment       `yaml:"units,omitempty" json:"units,omitempty"`
    47  }
    48  
    49  type MachineFilesystemAttachment struct {
    50  	MountPoint string `yaml:"mount-point" json:"mount-point"`
    51  	ReadOnly   bool   `yaml:"read-only" json:"read-only"`
    52  }
    53  
    54  // generateListFilesystemOutput returns a map filesystem IDs to filesystem info
    55  func (c *listCommand) generateListFilesystemsOutput(ctx *cmd.Context, api StorageListAPI) (output interface{}, err error) {
    56  
    57  	results, err := api.ListFilesystems(c.ids)
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  
    62  	// filter out valid output, if any
    63  	var valid []params.FilesystemDetails
    64  	for _, result := range results {
    65  		if result.Error == nil {
    66  			valid = append(valid, result.Result...)
    67  			continue
    68  		}
    69  		// display individual error
    70  		fmt.Fprintf(ctx.Stderr, "%v\n", result.Error)
    71  	}
    72  	if len(valid) == 0 {
    73  		return nil, nil
    74  	}
    75  	info, err := convertToFilesystemInfo(valid)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	switch c.out.Name() {
    80  	case "yaml", "json":
    81  		output = map[string]map[string]FilesystemInfo{"filesystems": info}
    82  	default:
    83  		output = info
    84  	}
    85  
    86  	return output, nil
    87  }
    88  
    89  // convertToFilesystemInfo returns a map of filesystem IDs to filesystem info.
    90  func convertToFilesystemInfo(all []params.FilesystemDetails) (map[string]FilesystemInfo, error) {
    91  	result := make(map[string]FilesystemInfo)
    92  	for _, one := range all {
    93  		filesystemTag, info, err := createFilesystemInfo(one)
    94  		if err != nil {
    95  			return nil, errors.Trace(err)
    96  		}
    97  		result[filesystemTag.Id()] = info
    98  	}
    99  	return result, nil
   100  }
   101  
   102  func createFilesystemInfo(details params.FilesystemDetails) (names.FilesystemTag, FilesystemInfo, error) {
   103  	filesystemTag, err := names.ParseFilesystemTag(details.FilesystemTag)
   104  	if err != nil {
   105  		return names.FilesystemTag{}, FilesystemInfo{}, errors.Trace(err)
   106  	}
   107  
   108  	var info FilesystemInfo
   109  	info.ProviderFilesystemId = details.Info.FilesystemId
   110  	info.Size = details.Info.Size
   111  	info.Status = EntityStatus{
   112  		details.Status.Status,
   113  		details.Status.Info,
   114  		// TODO(axw) we should support formatting as ISO time
   115  		common.FormatTime(details.Status.Since, false),
   116  	}
   117  
   118  	if details.VolumeTag != "" {
   119  		volumeId, err := idFromTag(details.VolumeTag)
   120  		if err != nil {
   121  			return names.FilesystemTag{}, FilesystemInfo{}, errors.Trace(err)
   122  		}
   123  		info.Volume = volumeId
   124  	}
   125  
   126  	if len(details.MachineAttachments) > 0 {
   127  		machineAttachments := make(map[string]MachineFilesystemAttachment)
   128  		for machineTag, attachment := range details.MachineAttachments {
   129  			machineId, err := idFromTag(machineTag)
   130  			if err != nil {
   131  				return names.FilesystemTag{}, FilesystemInfo{}, errors.Trace(err)
   132  			}
   133  			machineAttachments[machineId] = MachineFilesystemAttachment{
   134  				attachment.MountPoint,
   135  				attachment.ReadOnly,
   136  			}
   137  		}
   138  		info.Attachments = &FilesystemAttachments{
   139  			Machines: machineAttachments,
   140  		}
   141  	}
   142  
   143  	if details.Storage != nil {
   144  		storageTag, storageInfo, err := createStorageInfo(*details.Storage)
   145  		if err != nil {
   146  			return names.FilesystemTag{}, FilesystemInfo{}, errors.Trace(err)
   147  		}
   148  		info.Storage = storageTag.Id()
   149  		if storageInfo.Attachments != nil {
   150  			info.Attachments.Units = storageInfo.Attachments.Units
   151  		}
   152  	}
   153  
   154  	return filesystemTag, info, nil
   155  }