github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/common/modelstatus.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package common
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"gopkg.in/juju/names.v2"
     9  
    10  	"github.com/juju/juju/apiserver/facade"
    11  	"github.com/juju/juju/apiserver/params"
    12  	"github.com/juju/juju/state"
    13  )
    14  
    15  // ModelStatusAPI implements the ModelStatus() API.
    16  type ModelStatusAPI struct {
    17  	authorizer facade.Authorizer
    18  	apiUser    names.UserTag
    19  	backend    ModelManagerBackend
    20  }
    21  
    22  // NewModelStatusAPI creates an implementation providing the ModelStatus() API.
    23  func NewModelStatusAPI(backend ModelManagerBackend, authorizer facade.Authorizer, apiUser names.UserTag) *ModelStatusAPI {
    24  	return &ModelStatusAPI{
    25  		authorizer: authorizer,
    26  		apiUser:    apiUser,
    27  		backend:    backend,
    28  	}
    29  }
    30  
    31  // ModelStatus returns a summary of the model.
    32  func (c *ModelStatusAPI) ModelStatus(req params.Entities) (params.ModelStatusResults, error) {
    33  	models := req.Entities
    34  	status := make([]params.ModelStatus, len(models))
    35  	for i, model := range models {
    36  		modelStatus, err := c.modelStatus(model.Tag)
    37  		if err != nil {
    38  			status[i].Error = ServerError(err)
    39  			continue
    40  		}
    41  		status[i] = modelStatus
    42  	}
    43  	return params.ModelStatusResults{Results: status}, nil
    44  }
    45  
    46  func (c *ModelStatusAPI) modelStatus(tag string) (params.ModelStatus, error) {
    47  	var status params.ModelStatus
    48  	modelTag, err := names.ParseModelTag(tag)
    49  	if err != nil {
    50  		return status, errors.Trace(err)
    51  	}
    52  	st := c.backend
    53  	if modelTag != c.backend.ModelTag() {
    54  		otherSt, releaser, err := c.backend.GetBackend(modelTag.Id())
    55  		if err != nil {
    56  			return status, errors.Trace(err)
    57  		}
    58  		defer releaser()
    59  		st = otherSt
    60  	}
    61  
    62  	model, err := st.Model()
    63  	if err != nil {
    64  		return status, errors.Trace(err)
    65  	}
    66  	isAdmin, err := HasModelAdmin(c.authorizer, c.apiUser, c.backend.ControllerTag(), model)
    67  	if err != nil {
    68  		return status, errors.Trace(err)
    69  	}
    70  	if !isAdmin {
    71  		return status, ErrPerm
    72  	}
    73  
    74  	machines, err := st.AllMachines()
    75  	if err != nil {
    76  		return status, errors.Trace(err)
    77  	}
    78  
    79  	var hostedMachines []Machine
    80  	for _, m := range machines {
    81  		if !m.IsManager() {
    82  			hostedMachines = append(hostedMachines, m)
    83  		}
    84  	}
    85  
    86  	applications, err := st.AllApplications()
    87  	if err != nil {
    88  		return status, errors.Trace(err)
    89  	}
    90  
    91  	modelMachines, err := ModelMachineInfo(st)
    92  	if err != nil {
    93  		return status, errors.Trace(err)
    94  	}
    95  
    96  	result := params.ModelStatus{
    97  		ModelTag:           tag,
    98  		OwnerTag:           model.Owner().String(),
    99  		Life:               params.Life(model.Life().String()),
   100  		HostedMachineCount: len(hostedMachines),
   101  		ApplicationCount:   len(applications),
   102  		Machines:           modelMachines,
   103  	}
   104  
   105  	volumes, err := st.AllVolumes()
   106  	if err != nil {
   107  		return status, errors.Trace(err)
   108  	}
   109  	result.Volumes = ModelVolumeInfo(volumes)
   110  
   111  	filesystems, err := st.AllFilesystems()
   112  	if err != nil {
   113  		return status, errors.Trace(err)
   114  	}
   115  	result.Filesystems = ModelFilesystemInfo(filesystems)
   116  	return result, nil
   117  }
   118  
   119  // ModelFilesystemInfo returns information about filesystems in the model.
   120  func ModelFilesystemInfo(in []state.Filesystem) []params.ModelFilesystemInfo {
   121  	out := make([]params.ModelFilesystemInfo, len(in))
   122  	for i, in := range in {
   123  		var statusString string
   124  		status, err := in.Status()
   125  		if err != nil {
   126  			statusString = err.Error()
   127  		} else {
   128  			statusString = string(status.Status)
   129  		}
   130  		var providerId string
   131  		if info, err := in.Info(); err == nil {
   132  			providerId = info.FilesystemId
   133  		}
   134  		out[i] = params.ModelFilesystemInfo{
   135  			Id:         in.Tag().Id(),
   136  			ProviderId: providerId,
   137  			Status:     statusString,
   138  			Message:    status.Message,
   139  			Detachable: in.Detachable(),
   140  		}
   141  	}
   142  	return out
   143  }
   144  
   145  // ModelVolumeInfo returns information about volumes in the model.
   146  func ModelVolumeInfo(in []state.Volume) []params.ModelVolumeInfo {
   147  	out := make([]params.ModelVolumeInfo, len(in))
   148  	for i, in := range in {
   149  		var statusString string
   150  		status, err := in.Status()
   151  		if err != nil {
   152  			statusString = err.Error()
   153  		} else {
   154  			statusString = string(status.Status)
   155  		}
   156  		var providerId string
   157  		if info, err := in.Info(); err == nil {
   158  			providerId = info.VolumeId
   159  		}
   160  		out[i] = params.ModelVolumeInfo{
   161  			Id:         in.Tag().Id(),
   162  			ProviderId: providerId,
   163  			Status:     statusString,
   164  			Message:    status.Message,
   165  			Detachable: in.Detachable(),
   166  		}
   167  	}
   168  	return out
   169  }