github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/jujud/agent/machine/manifolds.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package machine 5 6 import ( 7 "net/http" 8 "runtime" 9 "time" 10 11 "github.com/juju/clock" 12 "github.com/juju/errors" 13 "github.com/juju/loggo" 14 "github.com/juju/proxy" 15 "github.com/juju/pubsub" 16 "github.com/juju/utils/voyeur" 17 "github.com/juju/version" 18 "github.com/prometheus/client_golang/prometheus" 19 "gopkg.in/juju/names.v2" 20 "gopkg.in/juju/worker.v1" 21 "gopkg.in/juju/worker.v1/dependency" 22 23 coreagent "github.com/juju/juju/agent" 24 "github.com/juju/juju/api" 25 "github.com/juju/juju/api/base" 26 "github.com/juju/juju/api/crosscontroller" 27 apideployer "github.com/juju/juju/api/deployer" 28 "github.com/juju/juju/cmd/jujud/agent/engine" 29 "github.com/juju/juju/container/lxd" 30 "github.com/juju/juju/core/machinelock" 31 "github.com/juju/juju/core/presence" 32 "github.com/juju/juju/core/raftlease" 33 "github.com/juju/juju/feature" 34 "github.com/juju/juju/state" 35 proxyconfig "github.com/juju/juju/utils/proxy" 36 jworker "github.com/juju/juju/worker" 37 "github.com/juju/juju/worker/agent" 38 "github.com/juju/juju/worker/apiaddressupdater" 39 "github.com/juju/juju/worker/apicaller" 40 "github.com/juju/juju/worker/apiconfigwatcher" 41 "github.com/juju/juju/worker/apiserver" 42 "github.com/juju/juju/worker/apiservercertwatcher" 43 "github.com/juju/juju/worker/auditconfigupdater" 44 "github.com/juju/juju/worker/authenticationworker" 45 "github.com/juju/juju/worker/centralhub" 46 "github.com/juju/juju/worker/certupdater" 47 "github.com/juju/juju/worker/common" 48 "github.com/juju/juju/worker/controllerport" 49 "github.com/juju/juju/worker/credentialvalidator" 50 "github.com/juju/juju/worker/dblogpruner" 51 "github.com/juju/juju/worker/deployer" 52 "github.com/juju/juju/worker/diskmanager" 53 "github.com/juju/juju/worker/externalcontrollerupdater" 54 "github.com/juju/juju/worker/fanconfigurer" 55 "github.com/juju/juju/worker/featureflag" 56 "github.com/juju/juju/worker/fortress" 57 "github.com/juju/juju/worker/gate" 58 "github.com/juju/juju/worker/globalclockupdater" 59 "github.com/juju/juju/worker/hostkeyreporter" 60 "github.com/juju/juju/worker/httpserver" 61 "github.com/juju/juju/worker/httpserverargs" 62 "github.com/juju/juju/worker/identityfilewriter" 63 leasemanager "github.com/juju/juju/worker/lease/manifold" 64 "github.com/juju/juju/worker/logger" 65 "github.com/juju/juju/worker/logsender" 66 "github.com/juju/juju/worker/machineactions" 67 "github.com/juju/juju/worker/machiner" 68 "github.com/juju/juju/worker/migrationflag" 69 "github.com/juju/juju/worker/migrationminion" 70 "github.com/juju/juju/worker/modelcache" 71 "github.com/juju/juju/worker/modelworkermanager" 72 "github.com/juju/juju/worker/peergrouper" 73 prworker "github.com/juju/juju/worker/presence" 74 "github.com/juju/juju/worker/proxyupdater" 75 psworker "github.com/juju/juju/worker/pubsub" 76 "github.com/juju/juju/worker/raft" 77 "github.com/juju/juju/worker/raft/raftbackstop" 78 "github.com/juju/juju/worker/raft/raftclusterer" 79 "github.com/juju/juju/worker/raft/raftflag" 80 "github.com/juju/juju/worker/raft/raftforwarder" 81 "github.com/juju/juju/worker/raft/rafttransport" 82 "github.com/juju/juju/worker/reboot" 83 "github.com/juju/juju/worker/restorewatcher" 84 "github.com/juju/juju/worker/resumer" 85 "github.com/juju/juju/worker/singular" 86 workerstate "github.com/juju/juju/worker/state" 87 "github.com/juju/juju/worker/stateconfigwatcher" 88 "github.com/juju/juju/worker/storageprovisioner" 89 "github.com/juju/juju/worker/terminationworker" 90 "github.com/juju/juju/worker/toolsversionchecker" 91 "github.com/juju/juju/worker/txnpruner" 92 "github.com/juju/juju/worker/upgrader" 93 "github.com/juju/juju/worker/upgradeseries" 94 "github.com/juju/juju/worker/upgradesteps" 95 ) 96 97 const ( 98 // globalClockUpdaterUpdateInterval is the interval between 99 // global clock updates. 100 globalClockUpdaterUpdateInterval = 1 * time.Second 101 102 // globalClockUpdaterBackoffDelay is the amount of time to 103 // delay when a concurrent global clock update is detected. 104 globalClockUpdaterBackoffDelay = 10 * time.Second 105 106 // leaseRequestTopic is the pubsub topic that lease FSM updates 107 // will be published on. 108 leaseRequestTopic = "lease.request" 109 ) 110 111 // ManifoldsConfig allows specialisation of the result of Manifolds. 112 type ManifoldsConfig struct { 113 114 // AgentName is the name of the machine agent, like "machine-12". 115 // This will never change during the execution of an agent, and 116 // is used to provide this as config into a worker rather than 117 // making the worker get it from the agent worker itself. 118 AgentName string 119 120 // Agent contains the agent that will be wrapped and made available to 121 // its dependencies via a dependency.Engine. 122 Agent coreagent.Agent 123 124 // AgentConfigChanged is set whenever the machine agent's config 125 // is updated. 126 AgentConfigChanged *voyeur.Value 127 128 // RootDir is the root directory that any worker that needs to 129 // access local filesystems should use as a base. In actual use it 130 // will be "" but it may be overridden in tests. 131 RootDir string 132 133 // PreviousAgentVersion passes through the version the machine 134 // agent was running before the current restart. 135 PreviousAgentVersion version.Number 136 137 // UpgradeStepsLock is passed to the upgrade steps gate to 138 // coordinate workers that shouldn't do anything until the 139 // upgrade-steps worker is done. 140 UpgradeStepsLock gate.Lock 141 142 // UpgradeCheckLock is passed to the upgrade check gate to 143 // coordinate workers that shouldn't do anything until the 144 // upgrader worker completes it's first check. 145 UpgradeCheckLock gate.Lock 146 147 // OpenController is function used by the controller manifold to 148 // create a *state.Controller. 149 OpenController func(coreagent.Config) (*state.Controller, error) 150 151 // OpenStatePool is function used by the state manifold to create a 152 // *state.StatePool. 153 OpenStatePool func(coreagent.Config) (*state.StatePool, error) 154 155 // OpenStateForUpgrade is a function the upgradesteps worker can 156 // use to establish a connection to state. 157 OpenStateForUpgrade func() (*state.StatePool, error) 158 159 // StartAPIWorkers is passed to the apiworkers manifold. It starts 160 // workers which rely on an API connection (which have not yet 161 // been converted to work directly with the dependency engine). 162 StartAPIWorkers func(api.Connection) (worker.Worker, error) 163 164 // PreUpgradeSteps is a function that is used by the upgradesteps 165 // worker to ensure that conditions are OK for an upgrade to 166 // proceed. 167 PreUpgradeSteps func(*state.StatePool, coreagent.Config, bool, bool) error 168 169 // LogSource defines the channel type used to send log message 170 // structs within the machine agent. 171 LogSource logsender.LogRecordCh 172 173 // newDeployContext gives the tests the opportunity to create a deployer.Context 174 // that can be used for testing so as to avoid (1) deploying units to the system 175 // running the tests and (2) get access to the *State used internally, so that 176 // tests can be run without waiting for the 5s watcher refresh time to which we would 177 // otherwise be restricted. 178 NewDeployContext func(st *apideployer.State, agentConfig coreagent.Config) deployer.Context 179 180 // Clock supplies timekeeping services to various workers. 181 Clock clock.Clock 182 183 // ValidateMigration is called by the migrationminion during the 184 // migration process to check that the agent will be ok when 185 // connected to the new target controller. 186 ValidateMigration func(base.APICaller) error 187 188 // PrometheusRegisterer is a prometheus.Registerer that may be used 189 // by workers to register Prometheus metric collectors. 190 PrometheusRegisterer prometheus.Registerer 191 192 // CentralHub is the primary hub that exists in the apiserver. 193 CentralHub *pubsub.StructuredHub 194 195 // PubSubReporter is the introspection reporter for the pubsub forwarding 196 // worker. 197 PubSubReporter psworker.Reporter 198 199 // PresenceRecorder 200 PresenceRecorder presence.Recorder 201 202 // UpdateLoggerConfig is a function that will save the specified 203 // config value as the logging config in the agent.conf file. 204 UpdateLoggerConfig func(string) error 205 206 // UpdateControllerAPIPort is a function that will save the updated 207 // controller api port in the agent.conf file. 208 UpdateControllerAPIPort func(int) error 209 210 // NewAgentStatusSetter provides upgradesteps.StatusSetter. 211 NewAgentStatusSetter func(apiConn api.Connection) (upgradesteps.StatusSetter, error) 212 213 // ControllerLeaseDuration defines for how long this agent will ask 214 // for controller administration rights. 215 ControllerLeaseDuration time.Duration 216 217 // LogPruneInterval defines how frequently logs are pruned from 218 // the database. 219 LogPruneInterval time.Duration 220 221 // TransactionPruneInterval defines how frequently mgo/txn transactions 222 // are pruned from the database. 223 TransactionPruneInterval time.Duration 224 225 // SetStatePool is used by the state worker for informing the agent of 226 // the StatePool that it creates, so we can pass it to the introspection 227 // worker running outside of the dependency engine. 228 SetStatePool func(*state.StatePool) 229 230 // RegisterIntrospectionHTTPHandlers is a function that calls the 231 // supplied function to register introspection HTTP handlers. The 232 // function will be passed a path and a handler; the function may 233 // alter the path as it sees fit, e.g. by adding a prefix. 234 RegisterIntrospectionHTTPHandlers func(func(path string, _ http.Handler)) 235 236 // NewModelWorker returns a new worker for managing the model with 237 // the specified UUID and type. 238 NewModelWorker func(modelUUID string, modelType state.ModelType) (worker.Worker, error) 239 240 // ControllerSupportsSpaces is a function that reports whether or 241 // not the controller model, represented by the given *state.State, 242 // supports network spaces. 243 ControllerSupportsSpaces func(*state.State) (bool, error) 244 245 // MachineLock is a central source for acquiring the machine lock. 246 // This is used by a number of workers to ensure serialisation of actions 247 // across the machine. 248 MachineLock machinelock.Lock 249 250 // MuxShutdownWait is the maximum time the http-server worker will wait 251 // for all mux clients to gracefully terminate before the http-worker 252 // exits regardless. 253 MuxShutdownWait time.Duration 254 } 255 256 // Manifolds returns a set of co-configured manifolds covering the 257 // various responsibilities of a machine agent. 258 // 259 // Thou Shalt Not Use String Literals In This Function. Or Else. 260 func Manifolds(config ManifoldsConfig) dependency.Manifolds { 261 262 // connectFilter exists: 263 // 1) to let us retry api connections immediately on password change, 264 // rather than causing the dependency engine to wait for a while; 265 // 2) to ensure that certain connection failures correctly trigger 266 // complete agent removal. (It's not safe to let any agent other 267 // than the machine mess around with SetCanUninstall). 268 connectFilter := func(err error) error { 269 cause := errors.Cause(err) 270 if cause == apicaller.ErrConnectImpossible { 271 err2 := coreagent.SetCanUninstall(config.Agent) 272 if err2 != nil { 273 return errors.Trace(err2) 274 } 275 return jworker.ErrTerminateAgent 276 } else if cause == apicaller.ErrChangedPassword { 277 return dependency.ErrBounce 278 } 279 return err 280 } 281 var externalUpdateProxyFunc func(proxy.Settings) error 282 if runtime.GOOS == "linux" { 283 externalUpdateProxyFunc = lxd.ConfigureLXDProxies 284 } 285 286 newExternalControllerWatcherClient := func(apiInfo *api.Info) ( 287 externalcontrollerupdater.ExternalControllerWatcherClientCloser, error, 288 ) { 289 conn, err := apicaller.NewExternalControllerConnection(apiInfo) 290 if err != nil { 291 return nil, errors.Trace(err) 292 } 293 return crosscontroller.NewClient(conn), nil 294 } 295 296 agentConfig := config.Agent.CurrentConfig() 297 machineTag := agentConfig.Tag().(names.MachineTag) 298 controllerTag := agentConfig.Controller() 299 300 leaseFSM := raftlease.NewFSM() 301 302 manifolds := dependency.Manifolds{ 303 // The agent manifold references the enclosing agent, and is the 304 // foundation stone on which most other manifolds ultimately depend. 305 agentName: agent.Manifold(config.Agent), 306 307 // The termination worker returns ErrTerminateAgent if a 308 // termination signal is received by the process it's running 309 // in. It has no inputs and its only output is the error it 310 // returns. It depends on the uninstall file having been 311 // written *by the manual provider* at install time; it would 312 // be Very Wrong Indeed to use SetCanUninstall in conjunction 313 // with this code. 314 terminationName: terminationworker.Manifold(), 315 316 clockName: clockManifold(config.Clock), 317 318 // Each machine agent has a flag manifold/worker which 319 // reports whether or not the agent is a controller. 320 isControllerFlagName: isControllerFlagManifold(), 321 322 // The stateconfigwatcher manifold watches the machine agent's 323 // configuration and reports if state serving info is 324 // present. It will bounce itself if state serving info is 325 // added or removed. It is intended as a dependency just for 326 // the state manifold. 327 stateConfigWatcherName: stateconfigwatcher.Manifold(stateconfigwatcher.ManifoldConfig{ 328 AgentName: agentName, 329 AgentConfigChanged: config.AgentConfigChanged, 330 }), 331 332 // The centralhub manifold watches the state config to make sure it 333 // only starts for machines that are api servers. Currently the hub is 334 // passed in as config, but when the apiserver and peergrouper are 335 // updated to use the dependency engine, the centralhub manifold 336 // should also take the agentName so the worker can get the machine ID 337 // for the creation of the hub. 338 centralHubName: centralhub.Manifold(centralhub.ManifoldConfig{ 339 StateConfigWatcherName: stateConfigWatcherName, 340 Hub: config.CentralHub, 341 }), 342 343 // The pubsub manifold gets the APIInfo from the agent config, 344 // and uses this as a basis to talk to the other API servers. 345 // The worker subscribes to the messages sent by the peergrouper 346 // that defines the set of machines that are the API servers. 347 // All non-local messages that originate from the machine that 348 // is running the worker get forwarded to the other API servers. 349 // This worker does not run in non-API server machines through 350 // the hub dependency, as that is only available if the machine 351 // is an API server. 352 pubSubName: psworker.Manifold(psworker.ManifoldConfig{ 353 AgentName: agentName, 354 CentralHubName: centralHubName, 355 Clock: config.Clock, 356 Logger: loggo.GetLogger("juju.worker.pubsub"), 357 NewWorker: psworker.NewWorker, 358 Reporter: config.PubSubReporter, 359 }), 360 361 // The presence manifold listens to pubsub messages about the pubsub 362 // forwarding connections and api connection and disconnections to 363 // establish a view on which agents are "alive". 364 presenceName: prworker.Manifold(prworker.ManifoldConfig{ 365 AgentName: agentName, 366 CentralHubName: centralHubName, 367 StateConfigWatcherName: stateConfigWatcherName, 368 Recorder: config.PresenceRecorder, 369 Logger: loggo.GetLogger("juju.worker.presence"), 370 NewWorker: prworker.NewWorker, 371 }), 372 373 /* TODO(menn0) - this is currently unused, pending further 374 * refactoring in the state package. 375 376 // The controller manifold creates a *state.Controller and 377 // makes it available to other manifolds. It pings the MongoDB 378 // session regularly and will die if pings fail. 379 controllerName: workercontroller.Manifold(workercontroller.ManifoldConfig{ 380 AgentName: agentName, 381 StateConfigWatcherName: stateConfigWatcherName, 382 OpenController: config.OpenController, 383 }), 384 */ 385 386 // The state manifold creates a *state.State and makes it 387 // available to other manifolds. It pings the mongodb session 388 // regularly and will die if pings fail. 389 stateName: workerstate.Manifold(workerstate.ManifoldConfig{ 390 AgentName: agentName, 391 StateConfigWatcherName: stateConfigWatcherName, 392 OpenStatePool: config.OpenStatePool, 393 PrometheusRegisterer: config.PrometheusRegisterer, 394 SetStatePool: config.SetStatePool, 395 }), 396 397 // The modelcache manifold creates a cache.Controller and keeps 398 // it up to date using an all model watcher. The controller is then 399 // used by the apiserver. 400 modelCacheName: modelcache.Manifold(modelcache.ManifoldConfig{ 401 StateName: stateName, 402 Logger: loggo.GetLogger("juju.worker.modelcache"), 403 PrometheusRegisterer: config.PrometheusRegisterer, 404 NewWorker: modelcache.NewWorker, 405 }), 406 407 // The api-config-watcher manifold monitors the API server 408 // addresses in the agent config and bounces when they 409 // change. It's required as part of model migrations. 410 apiConfigWatcherName: apiconfigwatcher.Manifold(apiconfigwatcher.ManifoldConfig{ 411 AgentName: agentName, 412 AgentConfigChanged: config.AgentConfigChanged, 413 }), 414 415 // The certificate-watcher manifold monitors the API server 416 // certificate in the agent config for changes, and parses 417 // and offers the result to other manifolds. This is only 418 // run by state servers. 419 certificateWatcherName: ifController(apiservercertwatcher.Manifold(apiservercertwatcher.ManifoldConfig{ 420 AgentName: agentName, 421 AgentConfigChanged: config.AgentConfigChanged, 422 })), 423 424 // The api caller is a thin concurrent wrapper around a connection 425 // to some API server. It's used by many other manifolds, which all 426 // select their own desired facades. It will be interesting to see 427 // how this works when we consolidate the agents; might be best to 428 // handle the auth changes server-side..? 429 apiCallerName: apicaller.Manifold(apicaller.ManifoldConfig{ 430 AgentName: agentName, 431 APIConfigWatcherName: apiConfigWatcherName, 432 APIOpen: api.Open, 433 NewConnection: apicaller.ScaryConnect, 434 Filter: connectFilter, 435 }), 436 437 // The upgrade steps gate is used to coordinate workers which 438 // shouldn't do anything until the upgrade-steps worker has 439 // finished running any required upgrade steps. The flag of 440 // similar name is used to implement the isFullyUpgraded func 441 // that keeps upgrade concerns out of unrelated manifolds. 442 upgradeStepsGateName: gate.ManifoldEx(config.UpgradeStepsLock), 443 upgradeStepsFlagName: gate.FlagManifold(gate.FlagManifoldConfig{ 444 GateName: upgradeStepsGateName, 445 NewWorker: gate.NewFlagWorker, 446 }), 447 448 // The upgrade check gate is used to coordinate workers which 449 // shouldn't do anything until the upgrader worker has 450 // completed its first check for a new tools version to 451 // upgrade to. The flag of similar name is used to implement 452 // the isFullyUpgraded func that keeps upgrade concerns out of 453 // unrelated manifolds. 454 upgradeCheckGateName: gate.ManifoldEx(config.UpgradeCheckLock), 455 upgradeCheckFlagName: gate.FlagManifold(gate.FlagManifoldConfig{ 456 GateName: upgradeCheckGateName, 457 NewWorker: gate.NewFlagWorker, 458 }), 459 460 // The upgrader is a leaf worker that returns a specific error 461 // type recognised by the machine agent, causing other workers 462 // to be stopped and the agent to be restarted running the new 463 // tools. We should only need one of these in a consolidated 464 // agent, but we'll need to be careful about behavioural 465 // differences, and interactions with the upgrade-steps 466 // worker. 467 upgraderName: upgrader.Manifold(upgrader.ManifoldConfig{ 468 AgentName: agentName, 469 APICallerName: apiCallerName, 470 UpgradeStepsGateName: upgradeStepsGateName, 471 UpgradeCheckGateName: upgradeCheckGateName, 472 PreviousAgentVersion: config.PreviousAgentVersion, 473 }), 474 475 // The upgradesteps worker runs soon after the machine agent 476 // starts and runs any steps required to upgrade to the 477 // running jujud version. Once upgrade steps have run, the 478 // upgradesteps gate is unlocked and the worker exits. 479 upgradeStepsName: upgradesteps.Manifold(upgradesteps.ManifoldConfig{ 480 AgentName: agentName, 481 APICallerName: apiCallerName, 482 UpgradeStepsGateName: upgradeStepsGateName, 483 OpenStateForUpgrade: config.OpenStateForUpgrade, 484 PreUpgradeSteps: config.PreUpgradeSteps, 485 NewAgentStatusSetter: config.NewAgentStatusSetter, 486 }), 487 488 // The migration workers collaborate to run migrations; 489 // and to create a mechanism for running other workers 490 // so they can't accidentally interfere with a migration 491 // in progress. Such a manifold should (1) depend on the 492 // migration-inactive flag, to know when to start or die; 493 // and (2) occupy the migration-fortress, so as to avoid 494 // possible interference with the minion (which will not 495 // take action until it's gained sole control of the 496 // fortress). 497 // 498 // Note that the fortress itself will not be created 499 // until the upgrade process is complete; this frees all 500 // its dependencies from upgrade concerns. 501 migrationFortressName: ifFullyUpgraded(fortress.Manifold()), 502 migrationInactiveFlagName: migrationflag.Manifold(migrationflag.ManifoldConfig{ 503 APICallerName: apiCallerName, 504 Check: migrationflag.IsTerminal, 505 NewFacade: migrationflag.NewFacade, 506 NewWorker: migrationflag.NewWorker, 507 }), 508 migrationMinionName: migrationminion.Manifold(migrationminion.ManifoldConfig{ 509 AgentName: agentName, 510 APICallerName: apiCallerName, 511 FortressName: migrationFortressName, 512 APIOpen: api.Open, 513 ValidateMigration: config.ValidateMigration, 514 NewFacade: migrationminion.NewFacade, 515 NewWorker: migrationminion.NewWorker, 516 }), 517 518 // We run clock updaters for every controller machine to 519 // ensure the lease clock is updated monotonically and at a 520 // rate no faster than real time. 521 // 522 // If the legacy-leases feature flag is set the global clock 523 // updater updates the lease clock in the database. . 524 globalClockUpdaterName: ifLegacyLeasesEnabled(globalclockupdater.Manifold(globalclockupdater.ManifoldConfig{ 525 ClockName: clockName, 526 StateName: stateName, 527 NewWorker: globalclockupdater.NewWorker, 528 UpdateInterval: globalClockUpdaterUpdateInterval, 529 BackoffDelay: globalClockUpdaterBackoffDelay, 530 Logger: loggo.GetLogger("juju.worker.globalclockupdater.mongo"), 531 })), 532 // We also run another clock updater to feed time updates into 533 // the lease FSM. 534 leaseClockUpdaterName: globalclockupdater.Manifold(globalclockupdater.ManifoldConfig{ 535 ClockName: clockName, 536 LeaseManagerName: leaseManagerName, 537 RaftName: raftForwarderName, 538 NewWorker: globalclockupdater.NewWorker, 539 UpdateInterval: globalClockUpdaterUpdateInterval, 540 BackoffDelay: globalClockUpdaterBackoffDelay, 541 Logger: loggo.GetLogger("juju.worker.globalclockupdater.raft"), 542 }), 543 544 // Each controller machine runs a singular worker which will 545 // attempt to claim responsibility for running certain workers 546 // that must not be run concurrently by multiple agents. 547 isPrimaryControllerFlagName: ifController(singular.Manifold(singular.ManifoldConfig{ 548 ClockName: clockName, 549 APICallerName: apiCallerName, 550 Duration: config.ControllerLeaseDuration, 551 Claimant: machineTag, 552 Entity: controllerTag, 553 NewFacade: singular.NewFacade, 554 NewWorker: singular.NewWorker, 555 })), 556 557 // The serving-info-setter manifold sets grabs the state 558 // serving info from the API connection and writes it to the 559 // agent config. 560 servingInfoSetterName: ifNotMigrating(ServingInfoSetterManifold(ServingInfoSetterConfig{ 561 AgentName: agentName, 562 APICallerName: apiCallerName, 563 })), 564 565 // The apiworkers manifold starts workers which rely on the 566 // machine agent's API connection but have not been converted 567 // to work directly under the dependency engine. It waits for 568 // upgrades to be finished before starting these workers. 569 apiWorkersName: ifNotMigrating(APIWorkersManifold(APIWorkersConfig{ 570 APICallerName: apiCallerName, 571 StartAPIWorkers: config.StartAPIWorkers, 572 })), 573 574 // The reboot manifold manages a worker which will reboot the 575 // machine when requested. It needs an API connection and 576 // waits for upgrades to be complete. 577 rebootName: ifNotMigrating(reboot.Manifold(reboot.ManifoldConfig{ 578 AgentName: agentName, 579 APICallerName: apiCallerName, 580 MachineLock: config.MachineLock, 581 Clock: config.Clock, 582 })), 583 584 // The logging config updater is a leaf worker that indirectly 585 // controls the messages sent via the log sender or rsyslog, 586 // according to changes in environment config. We should only need 587 // one of these in a consolidated agent. 588 loggingConfigUpdaterName: ifNotMigrating(logger.Manifold(logger.ManifoldConfig{ 589 AgentName: agentName, 590 APICallerName: apiCallerName, 591 UpdateAgentFunc: config.UpdateLoggerConfig, 592 })), 593 594 // The diskmanager worker periodically lists block devices on the 595 // machine it runs on. This worker will be run on all Juju-managed 596 // machines (one per machine agent). 597 diskManagerName: ifNotMigrating(diskmanager.Manifold(diskmanager.ManifoldConfig{ 598 AgentName: agentName, 599 APICallerName: apiCallerName, 600 })), 601 602 // The proxy config updater is a leaf worker that sets http/https/apt/etc 603 // proxy settings. 604 proxyConfigUpdater: ifNotMigrating(proxyupdater.Manifold(proxyupdater.ManifoldConfig{ 605 AgentName: agentName, 606 APICallerName: apiCallerName, 607 Logger: loggo.GetLogger("juju.worker.proxyupdater"), 608 WorkerFunc: proxyupdater.NewWorker, 609 ExternalUpdate: externalUpdateProxyFunc, 610 InProcessUpdate: proxyconfig.DefaultConfig.Set, 611 RunFunc: proxyupdater.RunWithStdIn, 612 })), 613 614 // The api address updater is a leaf worker that rewrites agent config 615 // as the state server addresses change. We should only need one of 616 // these in a consolidated agent. 617 apiAddressUpdaterName: ifNotMigrating(apiaddressupdater.Manifold(apiaddressupdater.ManifoldConfig{ 618 AgentName: agentName, 619 APICallerName: apiCallerName, 620 })), 621 622 fanConfigurerName: ifNotMigrating(fanconfigurer.Manifold(fanconfigurer.ManifoldConfig{ 623 APICallerName: apiCallerName, 624 Clock: config.Clock, 625 })), 626 627 // The machiner Worker will wait for the identified machine to become 628 // Dying and make it Dead; or until the machine becomes Dead by other 629 // means. This worker needs to be launched after fanconfigurer 630 // so that it reports interfaces created by it. 631 machinerName: ifNotMigrating(machiner.Manifold(machiner.ManifoldConfig{ 632 AgentName: agentName, 633 APICallerName: apiCallerName, 634 FanConfigurerName: fanConfigurerName, 635 })), 636 637 // The log sender is a leaf worker that sends log messages to some 638 // API server, when configured so to do. We should only need one of 639 // these in a consolidated agent. 640 // 641 // NOTE: the LogSource will buffer a large number of messages as an upgrade 642 // runs; it currently seems better to fill the buffer and send when stable, 643 // optimising for stable controller upgrades rather than up-to-the-moment 644 // observable normal-machine upgrades. 645 logSenderName: ifNotMigrating(logsender.Manifold(logsender.ManifoldConfig{ 646 APICallerName: apiCallerName, 647 LogSource: config.LogSource, 648 })), 649 650 // The deployer worker is primary for deploying and recalling unit 651 // agents, according to changes in a set of state units; and for the 652 // final removal of its agents' units from state when they are no 653 // longer needed. 654 deployerName: ifNotMigrating(deployer.Manifold(deployer.ManifoldConfig{ 655 NewDeployContext: config.NewDeployContext, 656 AgentName: agentName, 657 APICallerName: apiCallerName, 658 })), 659 660 authenticationWorkerName: ifNotMigrating(authenticationworker.Manifold(authenticationworker.ManifoldConfig{ 661 AgentName: agentName, 662 APICallerName: apiCallerName, 663 })), 664 665 // The storageProvisioner worker manages provisioning 666 // (deprovisioning), and attachment (detachment) of first-class 667 // volumes and filesystems. 668 storageProvisionerName: ifNotMigrating(ifCredentialValid(storageprovisioner.MachineManifold(storageprovisioner.MachineManifoldConfig{ 669 AgentName: agentName, 670 APICallerName: apiCallerName, 671 Clock: config.Clock, 672 NewCredentialValidatorFacade: common.NewCredentialInvalidatorFacade, 673 }))), 674 675 resumerName: ifNotMigrating(resumer.Manifold(resumer.ManifoldConfig{ 676 AgentName: agentName, 677 APICallerName: apiCallerName, 678 Clock: config.Clock, 679 Interval: time.Minute, 680 NewFacade: resumer.NewFacade, 681 NewWorker: resumer.NewWorker, 682 })), 683 684 identityFileWriterName: ifNotMigrating(identityfilewriter.Manifold(identityfilewriter.ManifoldConfig{ 685 AgentName: agentName, 686 APICallerName: apiCallerName, 687 })), 688 689 toolsVersionCheckerName: ifNotMigrating(toolsversionchecker.Manifold(toolsversionchecker.ManifoldConfig{ 690 AgentName: agentName, 691 APICallerName: apiCallerName, 692 })), 693 694 machineActionName: ifNotMigrating(machineactions.Manifold(machineactions.ManifoldConfig{ 695 AgentName: agentName, 696 APICallerName: apiCallerName, 697 NewFacade: machineactions.NewFacade, 698 NewWorker: machineactions.NewMachineActionsWorker, 699 })), 700 701 hostKeyReporterName: ifNotMigrating(hostkeyreporter.Manifold(hostkeyreporter.ManifoldConfig{ 702 AgentName: agentName, 703 APICallerName: apiCallerName, 704 RootDir: config.RootDir, 705 NewFacade: hostkeyreporter.NewFacade, 706 NewWorker: hostkeyreporter.NewWorker, 707 })), 708 709 externalControllerUpdaterName: ifNotMigrating(ifPrimaryController(externalcontrollerupdater.Manifold( 710 externalcontrollerupdater.ManifoldConfig{ 711 APICallerName: apiCallerName, 712 NewExternalControllerWatcherClient: newExternalControllerWatcherClient, 713 }, 714 ))), 715 716 logPrunerName: ifNotMigrating(ifPrimaryController(dblogpruner.Manifold( 717 dblogpruner.ManifoldConfig{ 718 ClockName: clockName, 719 StateName: stateName, 720 PruneInterval: config.LogPruneInterval, 721 NewWorker: dblogpruner.NewWorker, 722 }, 723 ))), 724 725 txnPrunerName: ifNotMigrating(ifPrimaryController(txnpruner.Manifold( 726 txnpruner.ManifoldConfig{ 727 ClockName: clockName, 728 StateName: stateName, 729 PruneInterval: config.TransactionPruneInterval, 730 NewWorker: txnpruner.New, 731 }, 732 ))), 733 734 httpServerArgsName: httpserverargs.Manifold(httpserverargs.ManifoldConfig{ 735 ClockName: clockName, 736 ControllerPortName: controllerPortName, 737 StateName: stateName, 738 NewStateAuthenticator: httpserverargs.NewStateAuthenticator, 739 }), 740 741 // TODO Juju 3.0: the controller port worker is only needed while 742 // the controller port is a mutable controller config value. 743 // When we hit 3.0 we should make controller-port a required 744 // and unmutable value. 745 controllerPortName: controllerport.Manifold(controllerport.ManifoldConfig{ 746 AgentName: agentName, 747 HubName: centralHubName, 748 StateName: stateName, 749 Logger: loggo.GetLogger("juju.worker.controllerport"), 750 UpdateControllerAPIPort: config.UpdateControllerAPIPort, 751 GetControllerConfig: controllerport.GetControllerConfig, 752 NewWorker: controllerport.NewWorker, 753 }), 754 755 httpServerName: httpserver.Manifold(httpserver.ManifoldConfig{ 756 CertWatcherName: certificateWatcherName, 757 HubName: centralHubName, 758 StateName: stateName, 759 MuxName: httpServerArgsName, 760 APIServerName: apiServerName, 761 RaftTransportName: raftTransportName, 762 PrometheusRegisterer: config.PrometheusRegisterer, 763 AgentName: config.AgentName, 764 Clock: config.Clock, 765 MuxShutdownWait: config.MuxShutdownWait, 766 LogDir: agentConfig.LogDir(), 767 GetControllerConfig: httpserver.GetControllerConfig, 768 NewTLSConfig: httpserver.NewTLSConfig, 769 NewWorker: httpserver.NewWorkerShim, 770 }), 771 772 apiServerName: apiserver.Manifold(apiserver.ManifoldConfig{ 773 AgentName: agentName, 774 AuthenticatorName: httpServerArgsName, 775 ClockName: clockName, 776 StateName: stateName, 777 ModelCacheName: modelCacheName, 778 MuxName: httpServerArgsName, 779 LeaseManagerName: leaseManagerName, 780 UpgradeGateName: upgradeStepsGateName, 781 RestoreStatusName: restoreWatcherName, 782 AuditConfigUpdaterName: auditConfigUpdaterName, 783 // Synthetic dependency - if raft-transport bounces we 784 // need to bounce api-server too, otherwise http-server 785 // can't shutdown properly. 786 RaftTransportName: raftTransportName, 787 788 PrometheusRegisterer: config.PrometheusRegisterer, 789 RegisterIntrospectionHTTPHandlers: config.RegisterIntrospectionHTTPHandlers, 790 Hub: config.CentralHub, 791 Presence: config.PresenceRecorder, 792 NewWorker: apiserver.NewWorker, 793 NewMetricsCollector: apiserver.NewMetricsCollector, 794 }), 795 796 modelWorkerManagerName: ifFullyUpgraded(modelworkermanager.Manifold(modelworkermanager.ManifoldConfig{ 797 StateName: stateName, 798 NewWorker: modelworkermanager.New, 799 NewModelWorker: config.NewModelWorker, 800 })), 801 802 peergrouperName: ifFullyUpgraded(peergrouper.Manifold(peergrouper.ManifoldConfig{ 803 AgentName: agentName, 804 ClockName: clockName, 805 ControllerPortName: controllerPortName, 806 StateName: stateName, 807 Hub: config.CentralHub, 808 NewWorker: peergrouper.New, 809 ControllerSupportsSpaces: config.ControllerSupportsSpaces, 810 })), 811 812 restoreWatcherName: restorewatcher.Manifold(restorewatcher.ManifoldConfig{ 813 StateName: stateName, 814 NewWorker: restorewatcher.NewWorker, 815 }), 816 817 certificateUpdaterName: ifFullyUpgraded(certupdater.Manifold(certupdater.ManifoldConfig{ 818 AgentName: agentName, 819 StateName: stateName, 820 NewWorker: certupdater.NewCertificateUpdater, 821 NewMachineAddressWatcher: certupdater.NewMachineAddressWatcher, 822 })), 823 824 auditConfigUpdaterName: ifController(auditconfigupdater.Manifold(auditconfigupdater.ManifoldConfig{ 825 AgentName: agentName, 826 StateName: stateName, 827 NewWorker: auditconfigupdater.New, 828 })), 829 830 raftTransportName: ifController(rafttransport.Manifold(rafttransport.ManifoldConfig{ 831 ClockName: clockName, 832 AgentName: agentName, 833 AuthenticatorName: httpServerArgsName, 834 HubName: centralHubName, 835 MuxName: httpServerArgsName, 836 DialConn: rafttransport.DialConn, 837 NewWorker: rafttransport.NewWorker, 838 Path: "/raft", 839 })), 840 841 raftName: ifFullyUpgraded(raft.Manifold(raft.ManifoldConfig{ 842 ClockName: clockName, 843 AgentName: agentName, 844 TransportName: raftTransportName, 845 FSM: leaseFSM, 846 Logger: loggo.GetLogger("juju.worker.raft"), 847 PrometheusRegisterer: config.PrometheusRegisterer, 848 NewWorker: raft.NewWorker, 849 })), 850 851 raftFlagName: raftflag.Manifold(raftflag.ManifoldConfig{ 852 RaftName: raftName, 853 NewWorker: raftflag.NewWorker, 854 }), 855 856 // The raft clusterer can only run on the raft leader, since 857 // it makes configuration updates based on changes in API 858 // server details. 859 raftClustererName: ifRaftLeader(raftclusterer.Manifold(raftclusterer.ManifoldConfig{ 860 RaftName: raftName, 861 CentralHubName: centralHubName, 862 NewWorker: raftclusterer.NewWorker, 863 })), 864 865 raftBackstopName: raftbackstop.Manifold(raftbackstop.ManifoldConfig{ 866 RaftName: raftName, 867 CentralHubName: centralHubName, 868 AgentName: agentName, 869 Logger: loggo.GetLogger("juju.worker.raft.raftbackstop"), 870 NewWorker: raftbackstop.NewWorker, 871 }), 872 873 // The raft forwarder accepts FSM commands from the hub and 874 // applies them to the raft leader. 875 raftForwarderName: ifRaftLeader(raftforwarder.Manifold(raftforwarder.ManifoldConfig{ 876 AgentName: agentName, 877 RaftName: raftName, 878 StateName: stateName, 879 CentralHubName: centralHubName, 880 RequestTopic: leaseRequestTopic, 881 Logger: loggo.GetLogger("juju.worker.raft.raftforwarder"), 882 NewWorker: raftforwarder.NewWorker, 883 NewTarget: raftforwarder.NewTarget, 884 })), 885 886 // The global lease manager tracks lease information in the raft 887 // cluster rather than in mongo. 888 leaseManagerName: ifController(leasemanager.Manifold(leasemanager.ManifoldConfig{ 889 AgentName: agentName, 890 ClockName: clockName, 891 CentralHubName: centralHubName, 892 StateName: stateName, 893 FSM: leaseFSM, 894 RequestTopic: leaseRequestTopic, 895 Logger: loggo.GetLogger("juju.worker.lease.raft"), 896 PrometheusRegisterer: config.PrometheusRegisterer, 897 NewWorker: leasemanager.NewWorker, 898 NewStore: leasemanager.NewStore, 899 })), 900 901 validCredentialFlagName: credentialvalidator.Manifold(credentialvalidator.ManifoldConfig{ 902 APICallerName: apiCallerName, 903 NewFacade: credentialvalidator.NewFacade, 904 NewWorker: credentialvalidator.NewWorker, 905 }), 906 907 legacyLeasesFlagName: ifController(featureflag.Manifold(featureflag.ManifoldConfig{ 908 StateName: stateName, 909 FlagName: feature.LegacyLeases, 910 Logger: loggo.GetLogger("juju.worker.legacyleasesenabled"), 911 NewWorker: featureflag.NewWorker, 912 })), 913 } 914 915 manifolds[upgradeSeriesWorkerName] = ifNotMigrating(upgradeseries.Manifold(upgradeseries.ManifoldConfig{ 916 AgentName: agentName, 917 APICallerName: apiCallerName, 918 Logger: loggo.GetLogger("juju.worker.upgradeseries"), 919 NewFacade: upgradeseries.NewFacade, 920 NewWorker: upgradeseries.NewWorker, 921 })) 922 923 return manifolds 924 } 925 926 func clockManifold(clock clock.Clock) dependency.Manifold { 927 return dependency.Manifold{ 928 Start: func(_ dependency.Context) (worker.Worker, error) { 929 return engine.NewValueWorker(clock) 930 }, 931 Output: engine.ValueWorkerOutput, 932 } 933 } 934 935 var ifFullyUpgraded = engine.Housing{ 936 Flags: []string{ 937 upgradeStepsFlagName, 938 upgradeCheckFlagName, 939 }, 940 }.Decorate 941 942 var ifNotMigrating = engine.Housing{ 943 Flags: []string{ 944 migrationInactiveFlagName, 945 }, 946 Occupy: migrationFortressName, 947 }.Decorate 948 949 var ifPrimaryController = engine.Housing{ 950 Flags: []string{ 951 isPrimaryControllerFlagName, 952 }, 953 }.Decorate 954 955 var ifController = engine.Housing{ 956 Flags: []string{ 957 isControllerFlagName, 958 }, 959 }.Decorate 960 961 var ifRaftLeader = engine.Housing{ 962 Flags: []string{ 963 raftFlagName, 964 }, 965 }.Decorate 966 967 var ifCredentialValid = engine.Housing{ 968 Flags: []string{ 969 validCredentialFlagName, 970 }, 971 }.Decorate 972 973 var ifLegacyLeasesEnabled = engine.Housing{ 974 Flags: []string{ 975 legacyLeasesFlagName, 976 }, 977 }.Decorate 978 979 const ( 980 agentName = "agent" 981 terminationName = "termination-signal-handler" 982 stateConfigWatcherName = "state-config-watcher" 983 controllerName = "controller" 984 controllerPortName = "controller-port" 985 stateName = "state" 986 apiCallerName = "api-caller" 987 apiConfigWatcherName = "api-config-watcher" 988 centralHubName = "central-hub" 989 presenceName = "presence" 990 pubSubName = "pubsub-forwarder" 991 clockName = "clock" 992 993 upgraderName = "upgrader" 994 upgradeStepsName = "upgrade-steps-runner" 995 upgradeStepsGateName = "upgrade-steps-gate" 996 upgradeStepsFlagName = "upgrade-steps-flag" 997 upgradeCheckGateName = "upgrade-check-gate" 998 upgradeCheckFlagName = "upgrade-check-flag" 999 1000 migrationFortressName = "migration-fortress" 1001 migrationInactiveFlagName = "migration-inactive-flag" 1002 migrationMinionName = "migration-minion" 1003 1004 servingInfoSetterName = "serving-info-setter" 1005 apiWorkersName = "unconverted-api-workers" 1006 rebootName = "reboot-executor" 1007 loggingConfigUpdaterName = "logging-config-updater" 1008 diskManagerName = "disk-manager" 1009 proxyConfigUpdater = "proxy-config-updater" 1010 apiAddressUpdaterName = "api-address-updater" 1011 machinerName = "machiner" 1012 logSenderName = "log-sender" 1013 deployerName = "unit-agent-deployer" 1014 authenticationWorkerName = "ssh-authkeys-updater" 1015 storageProvisionerName = "storage-provisioner" 1016 resumerName = "mgo-txn-resumer" 1017 identityFileWriterName = "ssh-identity-writer" 1018 toolsVersionCheckerName = "tools-version-checker" 1019 machineActionName = "machine-action-runner" 1020 hostKeyReporterName = "host-key-reporter" 1021 fanConfigurerName = "fan-configurer" 1022 externalControllerUpdaterName = "external-controller-updater" 1023 globalClockUpdaterName = "global-clock-updater" 1024 leaseClockUpdaterName = "lease-clock-updater" 1025 isPrimaryControllerFlagName = "is-primary-controller-flag" 1026 isControllerFlagName = "is-controller-flag" 1027 logPrunerName = "log-pruner" 1028 txnPrunerName = "transaction-pruner" 1029 certificateWatcherName = "certificate-watcher" 1030 modelCacheName = "model-cache" 1031 modelWorkerManagerName = "model-worker-manager" 1032 peergrouperName = "peer-grouper" 1033 restoreWatcherName = "restore-watcher" 1034 certificateUpdaterName = "certificate-updater" 1035 auditConfigUpdaterName = "audit-config-updater" 1036 leaseManagerName = "lease-manager" 1037 legacyLeasesFlagName = "legacy-leases-flag" 1038 1039 upgradeSeriesEnabledName = "upgrade-series-enabled" 1040 upgradeSeriesWorkerName = "upgrade-series" 1041 1042 httpServerName = "http-server" 1043 httpServerArgsName = "http-server-args" 1044 apiServerName = "api-server" 1045 1046 raftTransportName = "raft-transport" 1047 raftName = "raft" 1048 raftClustererName = "raft-clusterer" 1049 raftFlagName = "raft-leader-flag" 1050 raftBackstopName = "raft-backstop" 1051 raftForwarderName = "raft-forwarder" 1052 1053 validCredentialFlagName = "valid-credential-flag" 1054 )