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

     1  // Copyright 2015 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  
     9  	"github.com/juju/juju/apiserver/params"
    10  	"github.com/juju/juju/core/instance"
    11  	"github.com/juju/juju/core/status"
    12  	"github.com/juju/juju/state"
    13  	"github.com/juju/juju/state/multiwatcher"
    14  )
    15  
    16  // StateJobs translates a slice of multiwatcher jobs to their equivalents in state.
    17  func StateJobs(jobs []multiwatcher.MachineJob) ([]state.MachineJob, error) {
    18  	newJobs := make([]state.MachineJob, len(jobs))
    19  	for i, job := range jobs {
    20  		newJob, err := machineJobFromParams(job)
    21  		if err != nil {
    22  			return nil, err
    23  		}
    24  		newJobs[i] = newJob
    25  	}
    26  	return newJobs, nil
    27  }
    28  
    29  // machineJobFromParams returns the job corresponding to multiwatcher.MachineJob.
    30  func machineJobFromParams(job multiwatcher.MachineJob) (state.MachineJob, error) {
    31  	switch job {
    32  	case multiwatcher.JobHostUnits:
    33  		return state.JobHostUnits, nil
    34  	case multiwatcher.JobManageModel:
    35  		return state.JobManageModel, nil
    36  	default:
    37  		return -1, errors.Errorf("invalid machine job %q", job)
    38  	}
    39  }
    40  
    41  type origStateInterface interface {
    42  	Machine(string) (*state.Machine, error)
    43  }
    44  
    45  type stateInterface interface {
    46  	Machine(string) (Machine, error)
    47  }
    48  
    49  type stateShim struct {
    50  	origStateInterface
    51  }
    52  
    53  func (st *stateShim) Machine(id string) (Machine, error) {
    54  	return st.origStateInterface.Machine(id)
    55  }
    56  
    57  type Machine interface {
    58  	Id() string
    59  	InstanceId() (instance.Id, error)
    60  	InstanceNames() (instance.Id, string, error)
    61  	WantsVote() bool
    62  	HasVote() bool
    63  	Status() (status.StatusInfo, error)
    64  	ContainerType() instance.ContainerType
    65  	HardwareCharacteristics() (*instance.HardwareCharacteristics, error)
    66  	Life() state.Life
    67  	ForceDestroy() error
    68  	Destroy() error
    69  	AgentPresence() (bool, error)
    70  	IsManager() bool
    71  }
    72  
    73  func DestroyMachines(st origStateInterface, force bool, ids ...string) error {
    74  	return destroyMachines(&stateShim{st}, force, ids...)
    75  }
    76  
    77  func destroyMachines(st stateInterface, force bool, ids ...string) error {
    78  	var errs []error
    79  	for _, id := range ids {
    80  		machine, err := st.Machine(id)
    81  		switch {
    82  		case errors.IsNotFound(err):
    83  			err = errors.Errorf("machine %s does not exist", id)
    84  		case err != nil:
    85  		case force:
    86  			err = machine.ForceDestroy()
    87  		case machine.Life() != state.Alive:
    88  			continue
    89  		default:
    90  			err = machine.Destroy()
    91  		}
    92  		if err != nil {
    93  			errs = append(errs, err)
    94  		}
    95  	}
    96  	return DestroyErr("machines", ids, errs)
    97  }
    98  
    99  // ModelMachineInfo returns information about machine hardware for
   100  // alive top level machines (not containers).
   101  func ModelMachineInfo(st ModelManagerBackend) (machineInfo []params.ModelMachineInfo, _ error) {
   102  	machines, err := st.AllMachines()
   103  	if err != nil {
   104  		return nil, errors.Trace(err)
   105  	}
   106  	for _, m := range machines {
   107  		if m.Life() != state.Alive {
   108  			continue
   109  		}
   110  		var status string
   111  		// This is suboptimal as if there are many machines,
   112  		// we are making many calls into the DB for each machine.
   113  		statusInfo, err := m.Status()
   114  		if err == nil {
   115  			status = string(statusInfo.Status)
   116  		} else {
   117  			status = err.Error()
   118  		}
   119  		mInfo := params.ModelMachineInfo{
   120  			Id:        m.Id(),
   121  			HasVote:   m.HasVote(),
   122  			WantsVote: m.WantsVote(),
   123  			Status:    status,
   124  			Message:   statusInfo.Message,
   125  		}
   126  		instId, displayName, err := m.InstanceNames()
   127  		switch {
   128  		case err == nil:
   129  			mInfo.InstanceId = string(instId)
   130  			mInfo.DisplayName = displayName
   131  		case errors.IsNotProvisioned(err):
   132  			// ok, but no instance ID to get.
   133  		default:
   134  			return nil, errors.Trace(err)
   135  		}
   136  		if m.ContainerType() != "" && m.ContainerType() != instance.NONE {
   137  			machineInfo = append(machineInfo, mInfo)
   138  			continue
   139  		}
   140  		// Only include cores for physical machines.
   141  		hw, err := m.HardwareCharacteristics()
   142  		if err != nil && !errors.IsNotFound(err) {
   143  			return nil, errors.Trace(err)
   144  		}
   145  		if hw != nil && hw.String() != "" {
   146  			hwParams := &params.MachineHardware{
   147  				Cores:            hw.CpuCores,
   148  				Arch:             hw.Arch,
   149  				Mem:              hw.Mem,
   150  				RootDisk:         hw.RootDisk,
   151  				CpuPower:         hw.CpuPower,
   152  				Tags:             hw.Tags,
   153  				AvailabilityZone: hw.AvailabilityZone,
   154  			}
   155  			mInfo.Hardware = hwParams
   156  		}
   157  		machineInfo = append(machineInfo, mInfo)
   158  	}
   159  	return machineInfo, nil
   160  }