github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/core/status/status.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package status 5 6 import ( 7 "time" 8 ) 9 10 // Status used to represent the status of an entity, but has recently become 11 // and applies to "workloads" as well, which we don't currently model, for no 12 // very clear reason. 13 // 14 // Status values currently apply to machine (agents), unit (agents), unit 15 // (workloads), application (workloads), volumes, filesystems, and models. 16 type Status string 17 18 // String returns a string representation of the Status. 19 func (s Status) String() string { 20 return string(s) 21 } 22 23 // StatusInfo holds a Status and associated information. 24 type StatusInfo struct { 25 Status Status 26 Message string 27 Data map[string]interface{} 28 Since *time.Time 29 } 30 31 // StatusSetter represents a type whose status can be set. 32 type StatusSetter interface { 33 SetStatus(StatusInfo) error 34 } 35 36 // StatusGetter represents a type whose status can be read. 37 type StatusGetter interface { 38 Status() (StatusInfo, error) 39 } 40 41 // ModificationStatusGetter represents a type whose modification status can be 42 // read. 43 type ModificationStatusGetter interface { 44 ModificationStatus() (StatusInfo, error) 45 } 46 47 const ( 48 // Status values common to machine and unit agents. 49 50 // Error means the entity requires human intervention 51 // in order to operate correctly. 52 Error Status = "error" 53 54 // Started is set when: 55 // The entity is actively participating in the model. 56 // For unit agents, this is a state we preserve for backwards 57 // compatibility with scripts during the life of Juju 1.x. 58 // In Juju 2.x, the agent-state will remain “active” and scripts 59 // will watch the unit-state instead for signals of application readiness. 60 Started Status = "started" 61 ) 62 63 const ( 64 // Status values specific to machine agents. 65 66 // Pending is set when: 67 // The machine is not yet participating in the model. 68 Pending Status = "pending" 69 70 // Stopped is set when: 71 // The machine's agent will perform no further action, other than 72 // to set the unit to Dead at a suitable moment. 73 Stopped Status = "stopped" 74 75 // Down is set when: 76 // The machine ought to be signalling activity, but it cannot be 77 // detected. 78 Down Status = "down" 79 ) 80 81 const ( 82 // Status values specific to unit agents. 83 84 // Allocating is set when: 85 // The machine on which a unit is to be hosted is still being 86 // spun up in the cloud. 87 Allocating Status = "allocating" 88 89 // Rebooting is set when: 90 // The machine on which this agent is running is being rebooted. 91 // The juju-agent should move from rebooting to idle when the reboot is complete. 92 Rebooting Status = "rebooting" 93 94 // Executing is set when: 95 // The agent is running a hook or action. The human-readable message should reflect 96 // which hook or action is being run. 97 Executing Status = "executing" 98 99 // Idle is set when: 100 // Once the agent is installed and running it will notify the Juju server and its state 101 // becomes "idle". It will stay "idle" until some action (e.g. it needs to run a hook) or 102 // error (e.g it loses contact with the Juju server) moves it to a different state. 103 Idle Status = "idle" 104 105 // Failed is set when: 106 // The unit agent has failed in some way,eg the agent ought to be signalling 107 // activity, but it cannot be detected. It might also be that the unit agent 108 // detected an unrecoverable condition and managed to tell the Juju server about it. 109 Failed Status = "failed" 110 111 // Lost is set when: 112 // The juju agent has not communicated with the juju server for an unexpectedly long time; 113 // the unit agent ought to be signalling activity, but none has been detected. 114 Lost Status = "lost" 115 ) 116 117 const ( 118 // Status values specific to applications and units, reflecting the 119 // state of the software itself. 120 121 // Unset is only for applications, and is a placeholder status. 122 // The core/cache package deals with aggregating the unit status 123 // to the application level. 124 Unset Status = "unset" 125 126 // Maintenance is set when: 127 // The unit is not yet providing services, but is actively doing stuff 128 // in preparation for providing those services. 129 // This is a "spinning" state, not an error state. 130 // It reflects activity on the unit itself, not on peers or related units. 131 Maintenance Status = "maintenance" 132 133 // Terminated is set when: 134 // This unit used to exist, we have a record of it (perhaps because of storage 135 // allocated for it that was flagged to survive it). Nonetheless, it is now gone. 136 Terminated Status = "terminated" 137 138 // Unknown is set when: 139 // A unit-agent has finished calling install, config-changed, and start, 140 // but the charm has not called status-set yet. 141 Unknown Status = "unknown" 142 143 // Waiting is set when: 144 // The unit is unable to progress to an active state because an application to 145 // which it is related is not running. 146 Waiting Status = "waiting" 147 148 // Blocked is set when: 149 // The unit needs manual intervention to get back to the Running state. 150 Blocked Status = "blocked" 151 152 // Active is set when: 153 // The unit believes it is correctly offering all the services it has 154 // been asked to offer. 155 Active Status = "active" 156 ) 157 158 const ( 159 // Status values specific to storage. 160 161 // Attaching indicates that the storage is being attached 162 // to a machine. 163 Attaching Status = "attaching" 164 165 // Attached indicates that the storage is attached to a 166 // machine. 167 Attached Status = "attached" 168 169 // Detaching indicates that the storage is being detached 170 // from a machine. 171 Detaching Status = "detaching" 172 173 // Detached indicates that the storage is not attached to 174 // any machine. 175 Detached Status = "detached" 176 ) 177 178 const ( 179 // Status values specific to models. 180 181 // Available indicates that the model is available for use. 182 Available Status = "available" 183 184 // Busy indicates that the model is not available for use because it is 185 // running a process that must take the model offline, such as a migration, 186 // upgrade, or backup. This is a spinning state, it is not an error state, 187 // and it should be expected that the model will eventually go back to 188 // available. 189 Busy Status = "busy" 190 ) 191 192 const ( 193 // Status values specific to relations. 194 195 // Joining is used to signify that a relation should become joined soon. 196 Joining Status = "joining" 197 198 // Joined is the normal status for a healthy, alive relation. 199 Joined Status = "joined" 200 201 // Broken is the status for when a relation life goes to Dead. 202 Broken Status = "broken" 203 204 // Suspending is used to signify that a relation will be temporarily broken 205 // pending action to resume it. 206 Suspending Status = "suspending" 207 208 // Suspended is used to signify that a relation is temporarily broken pending 209 // action to resume it. 210 Suspended Status = "suspended" 211 ) 212 213 const ( 214 // Status values that are common to several entities. 215 216 // Destroying indicates that the entity is being destroyed. 217 // 218 // This is valid for volumes, filesystems, and models. 219 Destroying Status = "destroying" 220 ) 221 222 // InstanceStatus 223 const ( 224 Empty Status = "" 225 Provisioning Status = "allocating" 226 Running Status = "running" 227 ProvisioningError Status = "provisioning error" 228 ) 229 230 // ModificationStatus 231 const ( 232 Applied Status = "applied" 233 ) 234 235 const ( 236 MessageWaitForMachine = "waiting for machine" 237 MessageWaitForContainer = "waiting for container" 238 MessageInstallingAgent = "installing agent" 239 MessageInitializingAgent = "agent initialising" 240 MessageInstallingCharm = "installing charm software" 241 ) 242 243 // KnownModificationStatus returns true if the status has a known value for 244 // a modification of an instance. 245 func (s Status) KnownModificationStatus() bool { 246 switch s { 247 case 248 Idle, 249 Applied, 250 Error, 251 Unknown: 252 return true 253 } 254 return false 255 } 256 257 func (s Status) KnownInstanceStatus() bool { 258 switch s { 259 case 260 Pending, 261 ProvisioningError, 262 Allocating, 263 Running, 264 Error, 265 Unknown: 266 return true 267 } 268 return false 269 } 270 271 // KnownAgentStatus returns true if status has a known value for an agent. 272 // It includes every status that has ever been valid for a unit or machine agent. 273 // This is used by the apiserver client facade to filter out unknown values. 274 func (s Status) KnownAgentStatus() bool { 275 switch s { 276 case 277 Allocating, 278 Error, 279 Failed, 280 Rebooting, 281 Executing, 282 Idle: 283 return true 284 } 285 return false 286 } 287 288 // KnownWorkloadStatus returns true if status has a known value for a workload. 289 // It includes every status that has ever been valid for a unit agent. 290 // This is used by the apiserver client facade to filter out unknown values. 291 func (s Status) KnownWorkloadStatus() bool { 292 if ValidWorkloadStatus(s) { 293 return true 294 } 295 switch s { 296 case Error: // include error so that we can filter on what the spec says is valid 297 return true 298 default: 299 return false 300 } 301 } 302 303 // ValidWorkloadStatus returns true if status has a valid value (that is to say, 304 // a value that it's OK to set) for units or applications. 305 func ValidWorkloadStatus(status Status) bool { 306 switch status { 307 case 308 Blocked, 309 Maintenance, 310 Waiting, 311 Active, 312 Unknown, 313 Terminated: 314 return true 315 default: 316 return false 317 } 318 } 319 320 // WorkloadMatches returns true if the candidate matches status, 321 // taking into account that the candidate may be a legacy 322 // status value which has been deprecated. 323 func (s Status) WorkloadMatches(candidate Status) bool { 324 return s == candidate 325 } 326 327 // ValidModelStatus returns true if status has a valid value (that is to say, 328 // a value that it's OK to set) for models. 329 func ValidModelStatus(status Status) bool { 330 switch status { 331 case 332 Available, 333 Busy, 334 Destroying, 335 Suspended, // For model, this means that its cloud credential is invalid and model will not be doing any cloud calls. 336 Error: 337 return true 338 default: 339 return false 340 } 341 } 342 343 // Matches returns true if the candidate matches status, 344 // taking into account that the candidate may be a legacy 345 // status value which has been deprecated. 346 func (s Status) Matches(candidate Status) bool { 347 return s == candidate 348 } 349 350 // DeriveStatus is used to determine the application 351 // status from a set of unit status values. 352 func DeriveStatus(statuses []StatusInfo) StatusInfo { 353 // By providing an unknown default, we get a reasonable answer 354 // even if there are no units. 355 result := StatusInfo{ 356 Status: Unknown, 357 } 358 for _, unitStatus := range statuses { 359 currentSeverity := statusSeverities[result.Status] 360 unitSeverity := statusSeverities[unitStatus.Status] 361 if unitSeverity > currentSeverity { 362 result.Status = unitStatus.Status 363 result.Message = unitStatus.Message 364 result.Data = unitStatus.Data 365 result.Since = unitStatus.Since 366 } 367 } 368 return result 369 } 370 371 // statusSeverities holds status values with a severity measure. 372 // Status values with higher severity are used in preference to others. 373 var statusSeverities = map[Status]int{ 374 Error: 100, 375 Blocked: 90, 376 Maintenance: 80, // Maintenance (us busy) is higher than Waiting (someone else busy) 377 Waiting: 70, 378 Active: 60, 379 Terminated: 50, 380 Unknown: 40, 381 }