github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/core/description/blockdevice.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package description
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/schema"
     9  )
    10  
    11  // BlockDevice represents a block device on a machine.
    12  type BlockDevice interface {
    13  	Name() string
    14  	Links() []string
    15  	Label() string
    16  	UUID() string
    17  	HardwareID() string
    18  	BusAddress() string
    19  	Size() uint64
    20  	FilesystemType() string
    21  	InUse() bool
    22  	MountPoint() string
    23  }
    24  
    25  type blockdevices struct {
    26  	Version       int            `yaml:"version"`
    27  	BlockDevices_ []*blockdevice `yaml:"block-devices"`
    28  }
    29  
    30  func (d *blockdevices) add(args BlockDeviceArgs) *blockdevice {
    31  	dev := newBlockDevice(args)
    32  	d.BlockDevices_ = append(d.BlockDevices_, dev)
    33  	return dev
    34  }
    35  
    36  type blockdevice struct {
    37  	Name_           string   `yaml:"name"`
    38  	Links_          []string `yaml:"links,omitempty"`
    39  	Label_          string   `yaml:"label,omitempty"`
    40  	UUID_           string   `yaml:"uuid,omitempty"`
    41  	HardwareID_     string   `yaml:"hardware-id,omitempty"`
    42  	BusAddress_     string   `yaml:"bus-address,omitempty"`
    43  	Size_           uint64   `yaml:"size"`
    44  	FilesystemType_ string   `yaml:"fs-type,omitempty"`
    45  	InUse_          bool     `yaml:"in-use"`
    46  	MountPoint_     string   `yaml:"mount-point,omitempty"`
    47  }
    48  
    49  // BlockDeviceArgs is an argument struct used to add a block device to a Machine.
    50  type BlockDeviceArgs struct {
    51  	Name           string
    52  	Links          []string
    53  	Label          string
    54  	UUID           string
    55  	HardwareID     string
    56  	BusAddress     string
    57  	Size           uint64
    58  	FilesystemType string
    59  	InUse          bool
    60  	MountPoint     string
    61  }
    62  
    63  func newBlockDevice(args BlockDeviceArgs) *blockdevice {
    64  	bd := &blockdevice{
    65  		Name_:           args.Name,
    66  		Links_:          make([]string, len(args.Links)),
    67  		Label_:          args.Label,
    68  		UUID_:           args.UUID,
    69  		HardwareID_:     args.HardwareID,
    70  		BusAddress_:     args.BusAddress,
    71  		Size_:           args.Size,
    72  		FilesystemType_: args.FilesystemType,
    73  		InUse_:          args.InUse,
    74  		MountPoint_:     args.MountPoint,
    75  	}
    76  	copy(bd.Links_, args.Links)
    77  	return bd
    78  }
    79  
    80  // Name implements BlockDevice.
    81  func (b *blockdevice) Name() string {
    82  	return b.Name_
    83  }
    84  
    85  // Links implements BlockDevice.
    86  func (b *blockdevice) Links() []string {
    87  	return b.Links_
    88  }
    89  
    90  // Label implements BlockDevice.
    91  func (b *blockdevice) Label() string {
    92  	return b.Label_
    93  }
    94  
    95  // UUID implements BlockDevice.
    96  func (b *blockdevice) UUID() string {
    97  	return b.UUID_
    98  }
    99  
   100  // HardwareID implements BlockDevice.
   101  func (b *blockdevice) HardwareID() string {
   102  	return b.HardwareID_
   103  }
   104  
   105  // BusAddress implements BlockDevice.
   106  func (b *blockdevice) BusAddress() string {
   107  	return b.BusAddress_
   108  }
   109  
   110  // Size implements BlockDevice.
   111  func (b *blockdevice) Size() uint64 {
   112  	return b.Size_
   113  }
   114  
   115  // FilesystemType implements BlockDevice.
   116  func (b *blockdevice) FilesystemType() string {
   117  	return b.FilesystemType_
   118  }
   119  
   120  // InUse implements BlockDevice.
   121  func (b *blockdevice) InUse() bool {
   122  	return b.InUse_
   123  }
   124  
   125  // MountPoint implements BlockDevice.
   126  func (b *blockdevice) MountPoint() string {
   127  	return b.MountPoint_
   128  }
   129  
   130  func importBlockDevices(source interface{}) ([]*blockdevice, error) {
   131  	checker := versionedChecker("block-devices")
   132  	coerced, err := checker.Coerce(source, nil)
   133  	if err != nil {
   134  		return nil, errors.Annotatef(err, "block devices version schema check failed")
   135  	}
   136  	valid := coerced.(map[string]interface{})
   137  
   138  	version := int(valid["version"].(int64))
   139  	importFunc, ok := blockdeviceDeserializationFuncs[version]
   140  	if !ok {
   141  		return nil, errors.NotValidf("version %d", version)
   142  	}
   143  	sourceList := valid["block-devices"].([]interface{})
   144  	return importBlockDeviceList(sourceList, importFunc)
   145  }
   146  
   147  func importBlockDeviceList(sourceList []interface{}, importFunc blockdeviceDeserializationFunc) ([]*blockdevice, error) {
   148  	result := make([]*blockdevice, 0, len(sourceList))
   149  	for i, value := range sourceList {
   150  		source, ok := value.(map[string]interface{})
   151  		if !ok {
   152  			return nil, errors.Errorf("unexpected value for block device %d, %T", i, value)
   153  		}
   154  		device, err := importFunc(source)
   155  		if err != nil {
   156  			return nil, errors.Annotatef(err, "block device %d", i)
   157  		}
   158  		result = append(result, device)
   159  	}
   160  	return result, nil
   161  }
   162  
   163  type blockdeviceDeserializationFunc func(map[string]interface{}) (*blockdevice, error)
   164  
   165  var blockdeviceDeserializationFuncs = map[int]blockdeviceDeserializationFunc{
   166  	1: importBlockDeviceV1,
   167  }
   168  
   169  func importBlockDeviceV1(source map[string]interface{}) (*blockdevice, error) {
   170  	fields := schema.Fields{
   171  		"name":        schema.String(),
   172  		"links":       schema.List(schema.String()),
   173  		"label":       schema.String(),
   174  		"uuid":        schema.String(),
   175  		"hardware-id": schema.String(),
   176  		"bus-address": schema.String(),
   177  		"size":        schema.ForceUint(),
   178  		"fs-type":     schema.String(),
   179  		"in-use":      schema.Bool(),
   180  		"mount-point": schema.String(),
   181  	}
   182  
   183  	defaults := schema.Defaults{
   184  		"links":       schema.Omit,
   185  		"label":       "",
   186  		"uuid":        "",
   187  		"hardware-id": "",
   188  		"bus-address": "",
   189  		"fs-type":     "",
   190  		"mount-point": "",
   191  	}
   192  	checker := schema.FieldMap(fields, defaults)
   193  
   194  	coerced, err := checker.Coerce(source, nil)
   195  	if err != nil {
   196  		return nil, errors.Annotatef(err, "block device v1 schema check failed")
   197  	}
   198  	valid := coerced.(map[string]interface{})
   199  	// From here we know that the map returned from the schema coercion
   200  	// contains fields of the right type.
   201  	result := &blockdevice{
   202  		Name_:           valid["name"].(string),
   203  		Links_:          convertToStringSlice(valid["links"]),
   204  		Label_:          valid["label"].(string),
   205  		UUID_:           valid["uuid"].(string),
   206  		HardwareID_:     valid["hardware-id"].(string),
   207  		BusAddress_:     valid["bus-address"].(string),
   208  		Size_:           valid["size"].(uint64),
   209  		FilesystemType_: valid["fs-type"].(string),
   210  		InUse_:          valid["in-use"].(bool),
   211  		MountPoint_:     valid["mount-point"].(string),
   212  	}
   213  
   214  	return result, nil
   215  }