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