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 }