github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/upgradedatabase/shim.go (about)

     1  // Copyright 2019 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package upgradedatabase
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/version/v2"
    11  
    12  	"github.com/juju/juju/core/status"
    13  	"github.com/juju/juju/mongo"
    14  	"github.com/juju/juju/state"
    15  )
    16  
    17  // Logger represents the methods required to emit log messages.
    18  type Logger interface {
    19  	Debugf(message string, args ...interface{})
    20  	Infof(message string, args ...interface{})
    21  	Errorf(message string, args ...interface{})
    22  }
    23  
    24  // Clock provides an interface for dealing with clocks.
    25  type Clock interface {
    26  	// Now returns the current clock time.
    27  	Now() time.Time
    28  
    29  	// After waits for the duration to elapse and then sends the
    30  	// current time on the returned channel.
    31  	After(time.Duration) <-chan time.Time
    32  }
    33  
    34  // UpgradeInfo describes methods for working with the state representation of
    35  // an upgrade-in-progress.
    36  type UpgradeInfo interface {
    37  	// Status returns the current status of the upgrade.
    38  	Status() state.UpgradeStatus
    39  
    40  	// SetStatus sets the current status of the upgrade.
    41  	SetStatus(status state.UpgradeStatus) error
    42  
    43  	// Watch returns a watcher that notifies of changes to the UpgradeInfo.
    44  	Watch() state.NotifyWatcher
    45  
    46  	// Refresh refreshes the UpgradeInfo from state.
    47  	Refresh() error
    48  }
    49  
    50  // Pool describes methods required by the upgradeDB worker,
    51  // supplied by a state pool.
    52  type Pool interface {
    53  	// IsPrimary returns true if the Mongo primary is
    54  	// running on the machine with the input ID.
    55  	IsPrimary(string) (bool, error)
    56  
    57  	// SetStatus updates the status of the machine with the input ID.
    58  	SetStatus(string, status.Status, string) error
    59  
    60  	// EnsureUpgradeInfo ensures that a document exists in the "upgradeInfo"
    61  	// collection for coordinating the current upgrade.
    62  	EnsureUpgradeInfo(string, version.Number, version.Number) (UpgradeInfo, error)
    63  
    64  	// Close closes the state pool.
    65  	Close() error
    66  }
    67  
    68  type pool struct {
    69  	*state.StatePool
    70  }
    71  
    72  // IsPrimary (Pool) returns true if the Mongo primary is
    73  // running on the controller with the input ID.
    74  func (p *pool) IsPrimary(controllerId string) (bool, error) {
    75  	st, err := p.SystemState()
    76  	if err != nil {
    77  		return false, errors.Trace(err)
    78  	}
    79  
    80  	// For IAAS models, controllers are machines.
    81  	// For CAAS models, until we support HA, there is only one Mongo
    82  	// and it is the primary.
    83  	hasMachine, err := p.hasMachine()
    84  	if err != nil {
    85  		return false, errors.Trace(err)
    86  	}
    87  	// TODO(CAAS) - bug 1849030 support HA
    88  	if !hasMachine {
    89  		return true, nil
    90  	}
    91  
    92  	machine, err := st.Machine(controllerId)
    93  	if err != nil {
    94  		return false, errors.Trace(err)
    95  	}
    96  	isPrimary, err := mongo.IsMaster(st.MongoSession(), machine)
    97  	return isPrimary, errors.Trace(err)
    98  }
    99  
   100  func (p *pool) hasMachine() (bool, error) {
   101  	systemState, err := p.SystemState()
   102  	if err != nil {
   103  		return false, errors.Trace(err)
   104  	}
   105  	model, err := systemState.Model()
   106  	if err != nil {
   107  		return false, errors.Trace(err)
   108  	}
   109  	return model.Type() == state.ModelTypeIAAS, nil
   110  }
   111  
   112  // SetStatus (Pool) updates the status of the machine with the input ID.
   113  func (p *pool) SetStatus(controllerId string, sts status.Status, msg string) error {
   114  	hasMachine, err := p.hasMachine()
   115  	if err != nil {
   116  		return errors.Trace(err)
   117  	}
   118  	if !hasMachine {
   119  		// TODO(CAAS) - bug 1849030 support HA
   120  		// Nothing we can do for now because we do not have any machine for CAAS controller.
   121  		return nil
   122  	}
   123  	systemState, err := p.SystemState()
   124  	if err != nil {
   125  		return errors.Trace(err)
   126  	}
   127  	machine, err := systemState.Machine(controllerId)
   128  	if err != nil {
   129  		return errors.Trace(err)
   130  	}
   131  
   132  	now := time.Now()
   133  	return errors.Trace(machine.SetStatus(status.StatusInfo{
   134  		Status:  sts,
   135  		Message: msg,
   136  		Since:   &now,
   137  	}))
   138  }
   139  
   140  // EnsureUpgradeInfo (Pool) ensures that a document exists in the "upgradeInfo"
   141  // collection for coordinating the current upgrade.
   142  func (p *pool) EnsureUpgradeInfo(controllerId string, fromVersion, toVersion version.Number) (UpgradeInfo, error) {
   143  	systemState, err := p.SystemState()
   144  	if err != nil {
   145  		return nil, errors.Trace(err)
   146  	}
   147  	info, err := systemState.EnsureUpgradeInfo(controllerId, fromVersion, toVersion)
   148  	return info, errors.Trace(err)
   149  }