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