github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/apiserver/diskmanager/diskmanager.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package diskmanager 5 6 import ( 7 "github.com/juju/loggo" 8 "github.com/juju/names" 9 10 "github.com/juju/juju/apiserver/common" 11 "github.com/juju/juju/apiserver/params" 12 "github.com/juju/juju/state" 13 "github.com/juju/juju/storage" 14 ) 15 16 func init() { 17 common.RegisterStandardFacade("DiskManager", 1, NewDiskManagerAPI) 18 } 19 20 var logger = loggo.GetLogger("juju.apiserver.diskmanager") 21 22 // DiskManagerAPI provides access to the DiskManager API facade. 23 type DiskManagerAPI struct { 24 st stateInterface 25 authorizer common.Authorizer 26 getAuthFunc common.GetAuthFunc 27 } 28 29 var getState = func(st *state.State) stateInterface { 30 return stateShim{st} 31 } 32 33 // NewDiskManagerAPI creates a new server-side DiskManager API facade. 34 func NewDiskManagerAPI( 35 st *state.State, 36 resources *common.Resources, 37 authorizer common.Authorizer, 38 ) (*DiskManagerAPI, error) { 39 40 if !authorizer.AuthMachineAgent() { 41 return nil, common.ErrPerm 42 } 43 44 authEntityTag := authorizer.GetAuthTag() 45 getAuthFunc := func() (common.AuthFunc, error) { 46 return func(tag names.Tag) bool { 47 // A machine agent can always access its own machine. 48 return tag == authEntityTag 49 }, nil 50 } 51 52 return &DiskManagerAPI{ 53 st: getState(st), 54 authorizer: authorizer, 55 getAuthFunc: getAuthFunc, 56 }, nil 57 } 58 59 func (d *DiskManagerAPI) SetMachineBlockDevices(args params.SetMachineBlockDevices) (params.ErrorResults, error) { 60 result := params.ErrorResults{ 61 Results: make([]params.ErrorResult, len(args.MachineBlockDevices)), 62 } 63 canAccess, err := d.getAuthFunc() 64 if err != nil { 65 return result, err 66 } 67 for i, arg := range args.MachineBlockDevices { 68 tag, err := names.ParseMachineTag(arg.Machine) 69 if err != nil { 70 result.Results[i].Error = common.ServerError(common.ErrPerm) 71 continue 72 } 73 if !canAccess(tag) { 74 err = common.ErrPerm 75 } else { 76 // TODO(axw) create volumes for block devices without matching 77 // volumes, if and only if the block device has a serial. Under 78 // the assumption of unique (to a machine) serial IDs, this 79 // gives us a guaranteed *persistently* unique way of identifying 80 // the volume. 81 // 82 // NOTE: we must predicate the above on there being no unprovisioned 83 // volume attachments for the machine, otherwise we would have 84 // a race between the volume attachment info being recorded and 85 // the diskmanager publishing block devices and erroneously creating 86 // volumes. 87 err = d.st.SetMachineBlockDevices(tag.Id(), stateBlockDeviceInfo(arg.BlockDevices)) 88 // TODO(axw) set volume/filesystem attachment info. 89 } 90 result.Results[i].Error = common.ServerError(err) 91 } 92 return result, nil 93 } 94 95 func stateBlockDeviceInfo(devices []storage.BlockDevice) []state.BlockDeviceInfo { 96 result := make([]state.BlockDeviceInfo, len(devices)) 97 for i, dev := range devices { 98 result[i] = state.BlockDeviceInfo{ 99 dev.DeviceName, 100 dev.DeviceLinks, 101 dev.Label, 102 dev.UUID, 103 dev.HardwareId, 104 dev.BusAddress, 105 dev.Size, 106 dev.FilesystemType, 107 dev.InUse, 108 dev.MountPoint, 109 } 110 } 111 return result 112 }