github.com/david-imola/snapd@v0.0.0-20210611180407-2de8ddeece6d/overlord/overlord_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016-2017 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package overlord_test 21 22 import ( 23 "encoding/json" 24 "errors" 25 "fmt" 26 "io/ioutil" 27 "os" 28 "path/filepath" 29 "syscall" 30 "testing" 31 "time" 32 33 . "gopkg.in/check.v1" 34 "gopkg.in/tomb.v2" 35 36 "github.com/snapcore/snapd/dirs" 37 "github.com/snapcore/snapd/osutil" 38 "github.com/snapcore/snapd/overlord" 39 "github.com/snapcore/snapd/overlord/auth" 40 "github.com/snapcore/snapd/overlord/devicestate/devicestatetest" 41 "github.com/snapcore/snapd/overlord/hookstate" 42 "github.com/snapcore/snapd/overlord/ifacestate" 43 "github.com/snapcore/snapd/overlord/patch" 44 "github.com/snapcore/snapd/overlord/snapstate" 45 "github.com/snapcore/snapd/overlord/state" 46 "github.com/snapcore/snapd/snap" 47 "github.com/snapcore/snapd/snapdenv" 48 "github.com/snapcore/snapd/snapdtool" 49 "github.com/snapcore/snapd/store" 50 "github.com/snapcore/snapd/testutil" 51 "github.com/snapcore/snapd/timings" 52 ) 53 54 func TestOverlord(t *testing.T) { TestingT(t) } 55 56 type overlordSuite struct { 57 testutil.BaseTest 58 } 59 60 var _ = Suite(&overlordSuite{}) 61 62 type ticker struct { 63 tickerChannel chan time.Time 64 } 65 66 func (w *ticker) tick(n int) { 67 for i := 0; i < n; i++ { 68 w.tickerChannel <- time.Now() 69 } 70 } 71 72 func fakePruneTicker() (w *ticker, restore func()) { 73 w = &ticker{ 74 tickerChannel: make(chan time.Time), 75 } 76 restore = overlord.MockPruneTicker(func(t *time.Ticker) <-chan time.Time { 77 return w.tickerChannel 78 }) 79 return w, restore 80 } 81 82 func (ovs *overlordSuite) SetUpTest(c *C) { 83 tmpdir := c.MkDir() 84 dirs.SetRootDir(tmpdir) 85 ovs.AddCleanup(func() { dirs.SetRootDir("") }) 86 ovs.AddCleanup(osutil.MockMountInfo("")) 87 88 dirs.SnapStateFile = filepath.Join(tmpdir, "test.json") 89 snapstate.CanAutoRefresh = nil 90 ovs.AddCleanup(func() { ifacestate.MockSecurityBackends(nil) }) 91 } 92 93 func (ovs *overlordSuite) TestNew(c *C) { 94 restore := patch.Mock(42, 2, nil) 95 defer restore() 96 97 var configstateInitCalled bool 98 overlord.MockConfigstateInit(func(*state.State, *hookstate.HookManager) error { 99 configstateInitCalled = true 100 return nil 101 }) 102 103 o, err := overlord.New(nil) 104 c.Assert(err, IsNil) 105 c.Check(o, NotNil) 106 107 c.Check(o.StateEngine(), NotNil) 108 c.Check(o.TaskRunner(), NotNil) 109 c.Check(o.SnapManager(), NotNil) 110 c.Check(o.ServiceManager(), NotNil) 111 c.Check(o.AssertManager(), NotNil) 112 c.Check(o.InterfaceManager(), NotNil) 113 c.Check(o.HookManager(), NotNil) 114 c.Check(o.DeviceManager(), NotNil) 115 c.Check(o.CommandManager(), NotNil) 116 c.Check(o.SnapshotManager(), NotNil) 117 c.Check(configstateInitCalled, Equals, true) 118 119 o.InterfaceManager().DisableUDevMonitor() 120 121 s := o.State() 122 c.Check(s, NotNil) 123 c.Check(o.Engine().State(), Equals, s) 124 125 s.Lock() 126 defer s.Unlock() 127 var patchLevel, patchSublevel int 128 s.Get("patch-level", &patchLevel) 129 c.Check(patchLevel, Equals, 42) 130 s.Get("patch-sublevel", &patchSublevel) 131 c.Check(patchSublevel, Equals, 2) 132 var refreshPrivacyKey string 133 s.Get("refresh-privacy-key", &refreshPrivacyKey) 134 c.Check(refreshPrivacyKey, HasLen, 16) 135 136 // store is setup 137 sto := snapstate.Store(s, nil) 138 c.Check(sto, FitsTypeOf, &store.Store{}) 139 c.Check(sto.(*store.Store).CacheDownloads(), Equals, 5) 140 } 141 142 func (ovs *overlordSuite) TestNewStore(c *C) { 143 // this is a shallow test, the deep testing happens in the 144 // remodeling tests in managers_test.go 145 o, err := overlord.New(nil) 146 c.Assert(err, IsNil) 147 148 devBE := o.DeviceManager().StoreContextBackend() 149 150 sto := o.NewStore(devBE) 151 c.Check(sto, FitsTypeOf, &store.Store{}) 152 c.Check(sto.(*store.Store).CacheDownloads(), Equals, 5) 153 } 154 155 func (ovs *overlordSuite) TestNewWithGoodState(c *C) { 156 // ensure we don't write state load timing in the state on really 157 // slow architectures (e.g. risc-v) 158 oldDurationThreshold := timings.DurationThreshold 159 timings.DurationThreshold = time.Second * 30 160 defer func() { timings.DurationThreshold = oldDurationThreshold }() 161 162 fakeState := []byte(fmt.Sprintf(`{"data":{"patch-level":%d,"patch-sublevel":%d,"patch-sublevel-last-version":%q,"some":"data","refresh-privacy-key":"0123456789ABCDEF"},"changes":null,"tasks":null,"last-change-id":0,"last-task-id":0,"last-lane-id":0}`, patch.Level, patch.Sublevel, snapdtool.Version)) 163 err := ioutil.WriteFile(dirs.SnapStateFile, fakeState, 0600) 164 c.Assert(err, IsNil) 165 166 o, err := overlord.New(nil) 167 c.Assert(err, IsNil) 168 169 state := o.State() 170 c.Assert(err, IsNil) 171 state.Lock() 172 defer state.Unlock() 173 174 d, err := state.MarshalJSON() 175 c.Assert(err, IsNil) 176 177 var got, expected map[string]interface{} 178 err = json.Unmarshal(d, &got) 179 c.Assert(err, IsNil) 180 err = json.Unmarshal(fakeState, &expected) 181 c.Assert(err, IsNil) 182 183 data, _ := got["data"].(map[string]interface{}) 184 c.Assert(data, NotNil) 185 186 c.Check(got, DeepEquals, expected) 187 } 188 189 func (ovs *overlordSuite) TestNewWithStateSnapmgrUpdate(c *C) { 190 fakeState := []byte(fmt.Sprintf(`{"data":{"patch-level":%d,"some":"data"},"changes":null,"tasks":null,"last-change-id":0,"last-task-id":0,"last-lane-id":0}`, patch.Level)) 191 err := ioutil.WriteFile(dirs.SnapStateFile, fakeState, 0600) 192 c.Assert(err, IsNil) 193 194 o, err := overlord.New(nil) 195 c.Assert(err, IsNil) 196 197 state := o.State() 198 c.Assert(err, IsNil) 199 state.Lock() 200 defer state.Unlock() 201 202 var refreshPrivacyKey string 203 state.Get("refresh-privacy-key", &refreshPrivacyKey) 204 c.Check(refreshPrivacyKey, HasLen, 16) 205 } 206 207 func (ovs *overlordSuite) TestNewWithInvalidState(c *C) { 208 fakeState := []byte(``) 209 err := ioutil.WriteFile(dirs.SnapStateFile, fakeState, 0600) 210 c.Assert(err, IsNil) 211 212 _, err = overlord.New(nil) 213 c.Assert(err, ErrorMatches, "cannot read state: EOF") 214 } 215 216 func (ovs *overlordSuite) TestNewWithPatches(c *C) { 217 p := func(s *state.State) error { 218 s.Set("patched", true) 219 return nil 220 } 221 sp := func(s *state.State) error { 222 s.Set("patched2", true) 223 return nil 224 } 225 patch.Mock(1, 1, map[int][]patch.PatchFunc{1: {p, sp}}) 226 227 fakeState := []byte(`{"data":{"patch-level":0, "patch-sublevel":0}}`) 228 err := ioutil.WriteFile(dirs.SnapStateFile, fakeState, 0600) 229 c.Assert(err, IsNil) 230 231 o, err := overlord.New(nil) 232 c.Assert(err, IsNil) 233 234 state := o.State() 235 c.Assert(err, IsNil) 236 state.Lock() 237 defer state.Unlock() 238 239 var level int 240 err = state.Get("patch-level", &level) 241 c.Assert(err, IsNil) 242 c.Check(level, Equals, 1) 243 244 var sublevel int 245 c.Assert(state.Get("patch-sublevel", &sublevel), IsNil) 246 c.Check(sublevel, Equals, 1) 247 248 var b bool 249 err = state.Get("patched", &b) 250 c.Assert(err, IsNil) 251 c.Check(b, Equals, true) 252 253 c.Assert(state.Get("patched2", &b), IsNil) 254 c.Check(b, Equals, true) 255 } 256 257 func (ovs *overlordSuite) TestNewFailedConfigstate(c *C) { 258 restore := patch.Mock(42, 2, nil) 259 defer restore() 260 261 var configstateInitCalled bool 262 restore = overlord.MockConfigstateInit(func(*state.State, *hookstate.HookManager) error { 263 configstateInitCalled = true 264 return fmt.Errorf("bad bad") 265 }) 266 defer restore() 267 268 o, err := overlord.New(nil) 269 c.Assert(err, ErrorMatches, "bad bad") 270 c.Check(o, IsNil) 271 c.Check(configstateInitCalled, Equals, true) 272 } 273 274 type witnessManager struct { 275 state *state.State 276 expectedEnsure int 277 ensureCalled chan struct{} 278 ensureCallback func(s *state.State) error 279 startedUp int 280 } 281 282 func (wm *witnessManager) StartUp() error { 283 wm.startedUp++ 284 return nil 285 } 286 287 func (wm *witnessManager) Ensure() error { 288 if wm.expectedEnsure--; wm.expectedEnsure == 0 { 289 close(wm.ensureCalled) 290 return nil 291 } 292 if wm.ensureCallback != nil { 293 return wm.ensureCallback(wm.state) 294 } 295 return nil 296 } 297 298 // markSeeded flags the state under the overlord as seeded to avoid running the seeding code in these tests 299 func markSeeded(o *overlord.Overlord) { 300 st := o.State() 301 st.Lock() 302 st.Set("seeded", true) 303 devicestatetest.SetDevice(st, &auth.DeviceState{ 304 Brand: "canonical", 305 Model: "pc", 306 Serial: "serialserial", 307 }) 308 st.Unlock() 309 } 310 311 func (ovs *overlordSuite) TestTrivialRunAndStop(c *C) { 312 o, err := overlord.New(nil) 313 c.Assert(err, IsNil) 314 315 markSeeded(o) 316 // make sure we don't try to talk to the store 317 snapstate.CanAutoRefresh = nil 318 319 err = o.StartUp() 320 c.Assert(err, IsNil) 321 322 o.Loop() 323 324 err = o.Stop() 325 c.Assert(err, IsNil) 326 } 327 328 func (ovs *overlordSuite) TestUnknownTasks(c *C) { 329 o, err := overlord.New(nil) 330 c.Assert(err, IsNil) 331 o.InterfaceManager().DisableUDevMonitor() 332 333 markSeeded(o) 334 // make sure we don't try to talk to the store 335 snapstate.CanAutoRefresh = nil 336 337 // unknown tasks are ignored and succeed 338 st := o.State() 339 st.Lock() 340 defer st.Unlock() 341 t := st.NewTask("unknown", "...") 342 chg := st.NewChange("change-w-unknown", "...") 343 chg.AddTask(t) 344 345 st.Unlock() 346 err = o.Settle(1 * time.Second) 347 st.Lock() 348 c.Assert(err, IsNil) 349 350 c.Check(chg.Status(), Equals, state.DoneStatus) 351 } 352 353 func (ovs *overlordSuite) TestEnsureLoopRunAndStop(c *C) { 354 restoreIntv := overlord.MockEnsureInterval(10 * time.Millisecond) 355 defer restoreIntv() 356 o := overlord.Mock() 357 358 witness := &witnessManager{ 359 state: o.State(), 360 expectedEnsure: 3, 361 ensureCalled: make(chan struct{}), 362 } 363 o.AddManager(witness) 364 365 err := o.StartUp() 366 c.Assert(err, IsNil) 367 368 o.Loop() 369 defer o.Stop() 370 371 t0 := time.Now() 372 select { 373 case <-witness.ensureCalled: 374 case <-time.After(2 * time.Second): 375 c.Fatal("Ensure calls not happening") 376 } 377 c.Check(time.Since(t0) >= 10*time.Millisecond, Equals, true) 378 379 err = o.Stop() 380 c.Assert(err, IsNil) 381 382 c.Check(witness.startedUp, Equals, 1) 383 } 384 385 func (ovs *overlordSuite) TestEnsureLoopMediatedEnsureBeforeImmediate(c *C) { 386 restoreIntv := overlord.MockEnsureInterval(10 * time.Minute) 387 defer restoreIntv() 388 o := overlord.Mock() 389 390 ensure := func(s *state.State) error { 391 s.EnsureBefore(0) 392 return nil 393 } 394 395 witness := &witnessManager{ 396 state: o.State(), 397 expectedEnsure: 2, 398 ensureCalled: make(chan struct{}), 399 ensureCallback: ensure, 400 } 401 o.AddManager(witness) 402 403 c.Assert(o.StartUp(), IsNil) 404 405 o.Loop() 406 defer o.Stop() 407 408 select { 409 case <-witness.ensureCalled: 410 case <-time.After(2 * time.Second): 411 c.Fatal("Ensure calls not happening") 412 } 413 } 414 415 func (ovs *overlordSuite) TestEnsureLoopMediatedEnsureBefore(c *C) { 416 restoreIntv := overlord.MockEnsureInterval(10 * time.Minute) 417 defer restoreIntv() 418 o := overlord.Mock() 419 420 ensure := func(s *state.State) error { 421 s.EnsureBefore(10 * time.Millisecond) 422 return nil 423 } 424 425 witness := &witnessManager{ 426 state: o.State(), 427 expectedEnsure: 2, 428 ensureCalled: make(chan struct{}), 429 ensureCallback: ensure, 430 } 431 o.AddManager(witness) 432 433 c.Assert(o.StartUp(), IsNil) 434 435 o.Loop() 436 defer o.Stop() 437 438 select { 439 case <-witness.ensureCalled: 440 case <-time.After(2 * time.Second): 441 c.Fatal("Ensure calls not happening") 442 } 443 } 444 445 func (ovs *overlordSuite) TestEnsureBeforeSleepy(c *C) { 446 restoreIntv := overlord.MockEnsureInterval(10 * time.Minute) 447 defer restoreIntv() 448 o := overlord.Mock() 449 450 ensure := func(s *state.State) error { 451 overlord.MockEnsureNext(o, time.Now().Add(-10*time.Hour)) 452 s.EnsureBefore(0) 453 return nil 454 } 455 456 witness := &witnessManager{ 457 state: o.State(), 458 expectedEnsure: 2, 459 ensureCalled: make(chan struct{}), 460 ensureCallback: ensure, 461 } 462 o.AddManager(witness) 463 464 c.Assert(o.StartUp(), IsNil) 465 466 o.Loop() 467 defer o.Stop() 468 469 select { 470 case <-witness.ensureCalled: 471 case <-time.After(2 * time.Second): 472 c.Fatal("Ensure calls not happening") 473 } 474 } 475 476 func (ovs *overlordSuite) TestEnsureBeforeLater(c *C) { 477 restoreIntv := overlord.MockEnsureInterval(10 * time.Minute) 478 defer restoreIntv() 479 o := overlord.Mock() 480 481 ensure := func(s *state.State) error { 482 overlord.MockEnsureNext(o, time.Now().Add(-10*time.Hour)) 483 s.EnsureBefore(time.Second * 5) 484 return nil 485 } 486 487 witness := &witnessManager{ 488 state: o.State(), 489 expectedEnsure: 2, 490 ensureCalled: make(chan struct{}), 491 ensureCallback: ensure, 492 } 493 o.AddManager(witness) 494 495 c.Assert(o.StartUp(), IsNil) 496 497 o.Loop() 498 defer o.Stop() 499 500 select { 501 case <-witness.ensureCalled: 502 case <-time.After(2 * time.Second): 503 c.Fatal("Ensure calls not happening") 504 } 505 } 506 507 func (ovs *overlordSuite) TestEnsureLoopMediatedEnsureBeforeOutsideEnsure(c *C) { 508 restoreIntv := overlord.MockEnsureInterval(10 * time.Minute) 509 defer restoreIntv() 510 o := overlord.Mock() 511 512 ch := make(chan struct{}) 513 ensure := func(s *state.State) error { 514 close(ch) 515 return nil 516 } 517 518 witness := &witnessManager{ 519 state: o.State(), 520 expectedEnsure: 2, 521 ensureCalled: make(chan struct{}), 522 ensureCallback: ensure, 523 } 524 o.AddManager(witness) 525 526 c.Assert(o.StartUp(), IsNil) 527 528 o.Loop() 529 defer o.Stop() 530 531 select { 532 case <-ch: 533 case <-time.After(2 * time.Second): 534 c.Fatal("Ensure calls not happening") 535 } 536 537 o.State().EnsureBefore(0) 538 539 select { 540 case <-witness.ensureCalled: 541 case <-time.After(2 * time.Second): 542 c.Fatal("Ensure calls not happening") 543 } 544 } 545 546 func (ovs *overlordSuite) TestEnsureLoopPrune(c *C) { 547 restoreIntv := overlord.MockPruneInterval(200*time.Millisecond, 1000*time.Millisecond, 1000*time.Millisecond) 548 defer restoreIntv() 549 o := overlord.Mock() 550 551 st := o.State() 552 st.Lock() 553 t1 := st.NewTask("foo", "...") 554 chg1 := st.NewChange("abort", "...") 555 chg1.AddTask(t1) 556 chg2 := st.NewChange("prune", "...") 557 chg2.SetStatus(state.DoneStatus) 558 t0 := chg2.ReadyTime() 559 st.Unlock() 560 561 // observe the loop cycles to detect when prune should have happened 562 pruneHappened := make(chan struct{}) 563 cycles := -1 564 waitForPrune := func(_ *state.State) error { 565 if cycles == -1 { 566 if time.Since(t0) > 1000*time.Millisecond { 567 cycles = 2 // wait a couple more loop cycles 568 } 569 return nil 570 } 571 if cycles > 0 { 572 cycles-- 573 if cycles == 0 { 574 close(pruneHappened) 575 } 576 } 577 return nil 578 } 579 witness := &witnessManager{ 580 ensureCallback: waitForPrune, 581 } 582 o.AddManager(witness) 583 584 c.Assert(o.StartUp(), IsNil) 585 586 o.Loop() 587 588 select { 589 case <-pruneHappened: 590 case <-time.After(2 * time.Second): 591 c.Fatal("Pruning should have happened by now") 592 } 593 594 err := o.Stop() 595 c.Assert(err, IsNil) 596 597 st.Lock() 598 defer st.Unlock() 599 600 c.Assert(st.Change(chg1.ID()), Equals, chg1) 601 c.Assert(st.Change(chg2.ID()), IsNil) 602 603 c.Assert(t1.Status(), Equals, state.HoldStatus) 604 } 605 606 func (ovs *overlordSuite) TestEnsureLoopPruneRunsMultipleTimes(c *C) { 607 restoreIntv := overlord.MockPruneInterval(100*time.Millisecond, 5*time.Millisecond, 1*time.Hour) 608 defer restoreIntv() 609 o := overlord.Mock() 610 611 // create two changes, one that can be pruned now, one in progress 612 st := o.State() 613 st.Lock() 614 t1 := st.NewTask("foo", "...") 615 chg1 := st.NewChange("pruneNow", "...") 616 chg1.AddTask(t1) 617 t1.SetStatus(state.DoneStatus) 618 t2 := st.NewTask("foo", "...") 619 chg2 := st.NewChange("pruneNext", "...") 620 chg2.AddTask(t2) 621 t2.SetStatus(state.DoStatus) 622 c.Check(st.Changes(), HasLen, 2) 623 st.Unlock() 624 625 w, restoreTicker := fakePruneTicker() 626 defer restoreTicker() 627 628 // start the loop that runs the prune ticker 629 o.Loop() 630 631 // this needs to be more than pruneWait=5ms mocked above 632 time.Sleep(10 * time.Millisecond) 633 w.tick(2) 634 635 st.Lock() 636 c.Check(st.Changes(), HasLen, 1) 637 chg2.SetStatus(state.DoneStatus) 638 st.Unlock() 639 640 // this needs to be more than pruneWait=5ms mocked above 641 time.Sleep(10 * time.Millisecond) 642 // tick twice for extra Ensure 643 w.tick(2) 644 645 st.Lock() 646 c.Check(st.Changes(), HasLen, 0) 647 st.Unlock() 648 649 // cleanup loop ticker 650 err := o.Stop() 651 c.Assert(err, IsNil) 652 } 653 654 func (ovs *overlordSuite) TestOverlordStartUpSetsStartOfOperation(c *C) { 655 restoreIntv := overlord.MockPruneInterval(100*time.Millisecond, 1000*time.Millisecond, 1*time.Hour) 656 defer restoreIntv() 657 658 // use real overlord, we need device manager to be there 659 o, err := overlord.New(nil) 660 c.Assert(err, IsNil) 661 662 st := o.State() 663 st.Lock() 664 defer st.Unlock() 665 666 // sanity check, not set 667 var opTime time.Time 668 c.Assert(st.Get("start-of-operation-time", &opTime), Equals, state.ErrNoState) 669 st.Unlock() 670 671 c.Assert(o.StartUp(), IsNil) 672 673 st.Lock() 674 c.Assert(st.Get("start-of-operation-time", &opTime), IsNil) 675 } 676 677 func (ovs *overlordSuite) TestEnsureLoopPruneDoesntAbortShortlyAfterStartOfOperation(c *C) { 678 w, restoreTicker := fakePruneTicker() 679 defer restoreTicker() 680 681 // use real overlord, we need device manager to be there 682 o, err := overlord.New(nil) 683 c.Assert(err, IsNil) 684 685 markSeeded(o) 686 687 // avoid immediate transition to Done due to unknown kind 688 o.TaskRunner().AddHandler("bar", func(t *state.Task, _ *tomb.Tomb) error { 689 return &state.Retry{} 690 }, nil) 691 692 st := o.State() 693 st.Lock() 694 695 // start of operation time is 50min ago, this is less then abort limit 696 opTime := time.Now().Add(-50 * time.Minute) 697 st.Set("start-of-operation-time", opTime) 698 699 // spawn time one month ago 700 spawnTime := time.Now().AddDate(0, -1, 0) 701 restoreTimeNow := state.MockTime(spawnTime) 702 703 t := st.NewTask("bar", "...") 704 chg := st.NewChange("other-change", "...") 705 chg.AddTask(t) 706 707 restoreTimeNow() 708 709 // sanity 710 c.Check(st.Changes(), HasLen, 1) 711 712 st.Unlock() 713 c.Assert(o.StartUp(), IsNil) 714 715 // start the loop that runs the prune ticker 716 o.Loop() 717 w.tick(2) 718 719 c.Assert(o.Stop(), IsNil) 720 721 st.Lock() 722 defer st.Unlock() 723 c.Assert(st.Changes(), HasLen, 1) 724 c.Check(chg.Status(), Equals, state.DoingStatus) 725 } 726 727 func (ovs *overlordSuite) TestEnsureLoopPruneAbortsOld(c *C) { 728 // Ensure interval is not relevant for this test 729 restoreEnsureIntv := overlord.MockEnsureInterval(10 * time.Hour) 730 defer restoreEnsureIntv() 731 732 w, restoreTicker := fakePruneTicker() 733 defer restoreTicker() 734 735 // use real overlord, we need device manager to be there 736 o, err := overlord.New(nil) 737 c.Assert(err, IsNil) 738 739 // avoid immediate transition to Done due to having unknown kind 740 o.TaskRunner().AddHandler("bar", func(t *state.Task, _ *tomb.Tomb) error { 741 return &state.Retry{} 742 }, nil) 743 744 markSeeded(o) 745 746 st := o.State() 747 st.Lock() 748 749 // start of operation time is a year ago 750 opTime := time.Now().AddDate(-1, 0, 0) 751 st.Set("start-of-operation-time", opTime) 752 753 st.Unlock() 754 c.Assert(o.StartUp(), IsNil) 755 st.Lock() 756 757 // spawn time one month ago 758 spawnTime := time.Now().AddDate(0, -1, 0) 759 restoreTimeNow := state.MockTime(spawnTime) 760 t := st.NewTask("bar", "...") 761 chg := st.NewChange("other-change", "...") 762 chg.AddTask(t) 763 764 restoreTimeNow() 765 766 // sanity 767 c.Check(st.Changes(), HasLen, 1) 768 st.Unlock() 769 770 // start the loop that runs the prune ticker 771 o.Loop() 772 w.tick(2) 773 774 c.Assert(o.Stop(), IsNil) 775 776 st.Lock() 777 defer st.Unlock() 778 779 // sanity 780 op, err := o.DeviceManager().StartOfOperationTime() 781 c.Assert(err, IsNil) 782 c.Check(op.Equal(opTime), Equals, true) 783 784 c.Assert(st.Changes(), HasLen, 1) 785 // change was aborted 786 c.Check(chg.Status(), Equals, state.HoldStatus) 787 } 788 789 func (ovs *overlordSuite) TestEnsureLoopNoPruneWhenPreseed(c *C) { 790 w, restoreTicker := fakePruneTicker() 791 defer restoreTicker() 792 793 restore := snapdenv.MockPreseeding(true) 794 defer restore() 795 796 restorePreseedExitWithErr := overlord.MockPreseedExitWithError(func(err error) {}) 797 defer restorePreseedExitWithErr() 798 799 o, err := overlord.New(nil) 800 c.Assert(err, IsNil) 801 markSeeded(o) 802 803 // avoid immediate transition to Done due to unknown kind 804 o.TaskRunner().AddHandler("bar", func(t *state.Task, _ *tomb.Tomb) error { 805 return &state.Retry{} 806 }, nil) 807 808 // sanity 809 _, err = o.DeviceManager().StartOfOperationTime() 810 c.Assert(err, ErrorMatches, `internal error: unexpected call to StartOfOperationTime in preseed mode`) 811 812 c.Assert(o.StartUp(), IsNil) 813 814 st := o.State() 815 st.Lock() 816 817 // spawn time one month ago 818 spawnTime := time.Now().AddDate(0, -1, 0) 819 restoreTimeNow := state.MockTime(spawnTime) 820 t := st.NewTask("bar", "...") 821 chg := st.NewChange("change", "...") 822 chg.AddTask(t) 823 restoreTimeNow() 824 825 st.Unlock() 826 // start the loop that runs the prune ticker 827 o.Loop() 828 w.tick(2) 829 830 c.Assert(o.Stop(), IsNil) 831 832 st.Lock() 833 defer st.Unlock() 834 835 var opTime time.Time 836 c.Assert(st.Get("start-of-operation-time", &opTime), Equals, state.ErrNoState) 837 c.Check(chg.Status(), Equals, state.DoingStatus) 838 } 839 840 func (ovs *overlordSuite) TestCheckpoint(c *C) { 841 oldUmask := syscall.Umask(0) 842 defer syscall.Umask(oldUmask) 843 844 o, err := overlord.New(nil) 845 c.Assert(err, IsNil) 846 847 s := o.State() 848 s.Lock() 849 s.Set("mark", 1) 850 s.Unlock() 851 852 st, err := os.Stat(dirs.SnapStateFile) 853 c.Assert(err, IsNil) 854 c.Assert(st.Mode(), Equals, os.FileMode(0600)) 855 856 c.Check(dirs.SnapStateFile, testutil.FileContains, `"mark":1`) 857 } 858 859 type sampleManager struct { 860 ensureCallback func() 861 } 862 863 func newSampleManager(s *state.State, runner *state.TaskRunner) *sampleManager { 864 sm := &sampleManager{} 865 866 runner.AddHandler("runMgr1", func(t *state.Task, _ *tomb.Tomb) error { 867 s := t.State() 868 s.Lock() 869 defer s.Unlock() 870 s.Set("runMgr1Mark", 1) 871 return nil 872 }, nil) 873 runner.AddHandler("runMgr2", func(t *state.Task, _ *tomb.Tomb) error { 874 s := t.State() 875 s.Lock() 876 defer s.Unlock() 877 s.Set("runMgr2Mark", 1) 878 return nil 879 }, nil) 880 runner.AddHandler("runMgrEnsureBefore", func(t *state.Task, _ *tomb.Tomb) error { 881 s := t.State() 882 s.Lock() 883 defer s.Unlock() 884 s.EnsureBefore(20 * time.Millisecond) 885 return nil 886 }, nil) 887 runner.AddHandler("runMgrForever", func(t *state.Task, _ *tomb.Tomb) error { 888 s := t.State() 889 s.Lock() 890 defer s.Unlock() 891 s.EnsureBefore(20 * time.Millisecond) 892 return &state.Retry{} 893 }, nil) 894 runner.AddHandler("runMgrWCleanup", func(t *state.Task, _ *tomb.Tomb) error { 895 s := t.State() 896 s.Lock() 897 defer s.Unlock() 898 s.Set("runMgrWCleanupMark", 1) 899 return nil 900 }, nil) 901 runner.AddCleanup("runMgrWCleanup", func(t *state.Task, _ *tomb.Tomb) error { 902 s := t.State() 903 s.Lock() 904 defer s.Unlock() 905 s.Set("runMgrWCleanupCleanedUp", 1) 906 return nil 907 }) 908 909 return sm 910 } 911 912 func (sm *sampleManager) Ensure() error { 913 if sm.ensureCallback != nil { 914 sm.ensureCallback() 915 } 916 return nil 917 } 918 919 func (ovs *overlordSuite) TestTrivialSettle(c *C) { 920 restoreIntv := overlord.MockEnsureInterval(1 * time.Minute) 921 defer restoreIntv() 922 o := overlord.Mock() 923 924 s := o.State() 925 sm1 := newSampleManager(s, o.TaskRunner()) 926 o.AddManager(sm1) 927 o.AddManager(o.TaskRunner()) 928 929 defer o.Engine().Stop() 930 931 s.Lock() 932 defer s.Unlock() 933 934 chg := s.NewChange("chg", "...") 935 t1 := s.NewTask("runMgr1", "1...") 936 chg.AddTask(t1) 937 938 s.Unlock() 939 o.Settle(5 * time.Second) 940 s.Lock() 941 c.Check(t1.Status(), Equals, state.DoneStatus) 942 943 var v int 944 err := s.Get("runMgr1Mark", &v) 945 c.Check(err, IsNil) 946 } 947 948 func (ovs *overlordSuite) TestSettleNotConverging(c *C) { 949 restoreIntv := overlord.MockEnsureInterval(1 * time.Minute) 950 defer restoreIntv() 951 o := overlord.Mock() 952 953 s := o.State() 954 sm1 := newSampleManager(s, o.TaskRunner()) 955 o.AddManager(sm1) 956 o.AddManager(o.TaskRunner()) 957 958 defer o.Engine().Stop() 959 960 s.Lock() 961 defer s.Unlock() 962 963 chg := s.NewChange("chg", "...") 964 t1 := s.NewTask("runMgrForever", "1...") 965 chg.AddTask(t1) 966 967 s.Unlock() 968 err := o.Settle(250 * time.Millisecond) 969 s.Lock() 970 971 c.Check(err, ErrorMatches, `Settle is not converging`) 972 973 } 974 975 func (ovs *overlordSuite) TestSettleChain(c *C) { 976 restoreIntv := overlord.MockEnsureInterval(1 * time.Minute) 977 defer restoreIntv() 978 o := overlord.Mock() 979 980 s := o.State() 981 sm1 := newSampleManager(s, o.TaskRunner()) 982 o.AddManager(sm1) 983 o.AddManager(o.TaskRunner()) 984 985 defer o.Engine().Stop() 986 987 s.Lock() 988 defer s.Unlock() 989 990 chg := s.NewChange("chg", "...") 991 t1 := s.NewTask("runMgr1", "1...") 992 t2 := s.NewTask("runMgr2", "2...") 993 t2.WaitFor(t1) 994 chg.AddAll(state.NewTaskSet(t1, t2)) 995 996 s.Unlock() 997 o.Settle(5 * time.Second) 998 s.Lock() 999 c.Check(t1.Status(), Equals, state.DoneStatus) 1000 c.Check(t2.Status(), Equals, state.DoneStatus) 1001 1002 var v int 1003 err := s.Get("runMgr1Mark", &v) 1004 c.Check(err, IsNil) 1005 err = s.Get("runMgr2Mark", &v) 1006 c.Check(err, IsNil) 1007 } 1008 1009 func (ovs *overlordSuite) TestSettleChainWCleanup(c *C) { 1010 restoreIntv := overlord.MockEnsureInterval(1 * time.Minute) 1011 defer restoreIntv() 1012 o := overlord.Mock() 1013 1014 s := o.State() 1015 sm1 := newSampleManager(s, o.TaskRunner()) 1016 o.AddManager(sm1) 1017 o.AddManager(o.TaskRunner()) 1018 1019 defer o.Engine().Stop() 1020 1021 s.Lock() 1022 defer s.Unlock() 1023 1024 chg := s.NewChange("chg", "...") 1025 t1 := s.NewTask("runMgrWCleanup", "1...") 1026 t2 := s.NewTask("runMgr2", "2...") 1027 t2.WaitFor(t1) 1028 chg.AddAll(state.NewTaskSet(t1, t2)) 1029 1030 s.Unlock() 1031 o.Settle(5 * time.Second) 1032 s.Lock() 1033 c.Check(t1.Status(), Equals, state.DoneStatus) 1034 c.Check(t2.Status(), Equals, state.DoneStatus) 1035 1036 var v int 1037 err := s.Get("runMgrWCleanupMark", &v) 1038 c.Check(err, IsNil) 1039 err = s.Get("runMgr2Mark", &v) 1040 c.Check(err, IsNil) 1041 1042 err = s.Get("runMgrWCleanupCleanedUp", &v) 1043 c.Check(err, IsNil) 1044 } 1045 1046 func (ovs *overlordSuite) TestSettleExplicitEnsureBefore(c *C) { 1047 restoreIntv := overlord.MockEnsureInterval(1 * time.Minute) 1048 defer restoreIntv() 1049 o := overlord.Mock() 1050 1051 s := o.State() 1052 sm1 := newSampleManager(s, o.TaskRunner()) 1053 sm1.ensureCallback = func() { 1054 s.Lock() 1055 defer s.Unlock() 1056 v := 0 1057 s.Get("ensureCount", &v) 1058 s.Set("ensureCount", v+1) 1059 } 1060 1061 o.AddManager(sm1) 1062 o.AddManager(o.TaskRunner()) 1063 1064 defer o.Engine().Stop() 1065 1066 s.Lock() 1067 defer s.Unlock() 1068 1069 chg := s.NewChange("chg", "...") 1070 t := s.NewTask("runMgrEnsureBefore", "...") 1071 chg.AddTask(t) 1072 1073 s.Unlock() 1074 o.Settle(5 * time.Second) 1075 s.Lock() 1076 c.Check(t.Status(), Equals, state.DoneStatus) 1077 1078 var v int 1079 err := s.Get("ensureCount", &v) 1080 c.Check(err, IsNil) 1081 c.Check(v, Equals, 2) 1082 } 1083 1084 func (ovs *overlordSuite) TestEnsureErrorWhenPreseeding(c *C) { 1085 restore := snapdenv.MockPreseeding(true) 1086 defer restore() 1087 1088 restoreIntv := overlord.MockEnsureInterval(1 * time.Millisecond) 1089 defer restoreIntv() 1090 1091 var errorCallbackError error 1092 restoreExitWithErr := overlord.MockPreseedExitWithError(func(err error) { 1093 errorCallbackError = err 1094 }) 1095 defer restoreExitWithErr() 1096 1097 o, err := overlord.New(nil) 1098 c.Assert(err, IsNil) 1099 markSeeded(o) 1100 1101 err = o.StartUp() 1102 c.Assert(err, IsNil) 1103 1104 o.TaskRunner().AddHandler("bar", func(t *state.Task, _ *tomb.Tomb) error { 1105 return fmt.Errorf("bar error") 1106 }, nil) 1107 1108 s := o.State() 1109 s.Lock() 1110 defer s.Unlock() 1111 1112 chg := s.NewChange("chg", "...") 1113 t := s.NewTask("bar", "...") 1114 chg.AddTask(t) 1115 1116 s.Unlock() 1117 o.Loop() 1118 time.Sleep(1 * time.Second) 1119 o.Stop() 1120 1121 s.Lock() 1122 c.Check(t.Status(), Equals, state.ErrorStatus) 1123 c.Check(errorCallbackError, ErrorMatches, "bar error") 1124 } 1125 1126 func (ovs *overlordSuite) TestRequestRestartNoHandler(c *C) { 1127 o, err := overlord.New(nil) 1128 c.Assert(err, IsNil) 1129 1130 o.State().RequestRestart(state.RestartDaemon) 1131 } 1132 1133 type testRestartBehavior struct { 1134 restartRequested state.RestartType 1135 rebootState string 1136 rebootVerifiedErr error 1137 } 1138 1139 func (rb *testRestartBehavior) HandleRestart(t state.RestartType) { 1140 rb.restartRequested = t 1141 } 1142 1143 func (rb *testRestartBehavior) RebootAsExpected(_ *state.State) error { 1144 rb.rebootState = "as-expected" 1145 return rb.rebootVerifiedErr 1146 } 1147 1148 func (rb *testRestartBehavior) RebootDidNotHappen(_ *state.State) error { 1149 rb.rebootState = "did-not-happen" 1150 return rb.rebootVerifiedErr 1151 } 1152 1153 func (ovs *overlordSuite) TestRequestRestartHandler(c *C) { 1154 rb := &testRestartBehavior{} 1155 1156 o, err := overlord.New(rb) 1157 c.Assert(err, IsNil) 1158 1159 o.State().RequestRestart(state.RestartDaemon) 1160 1161 c.Check(rb.restartRequested, Equals, state.RestartDaemon) 1162 } 1163 1164 func (ovs *overlordSuite) TestVerifyRebootNoPendingReboot(c *C) { 1165 fakeState := []byte(fmt.Sprintf(`{"data":{"patch-level":%d,"patch-sublevel":%d,"some":"data","refresh-privacy-key":"0123456789ABCDEF"},"changes":null,"tasks":null,"last-change-id":0,"last-task-id":0,"last-lane-id":0}`, patch.Level, patch.Sublevel)) 1166 err := ioutil.WriteFile(dirs.SnapStateFile, fakeState, 0600) 1167 c.Assert(err, IsNil) 1168 1169 rb := &testRestartBehavior{} 1170 1171 _, err = overlord.New(rb) 1172 c.Assert(err, IsNil) 1173 1174 c.Check(rb.rebootState, Equals, "as-expected") 1175 } 1176 1177 func (ovs *overlordSuite) TestVerifyRebootOK(c *C) { 1178 fakeState := []byte(fmt.Sprintf(`{"data":{"patch-level":%d,"patch-sublevel":%d,"some":"data","refresh-privacy-key":"0123456789ABCDEF","system-restart-from-boot-id":%q},"changes":null,"tasks":null,"last-change-id":0,"last-task-id":0,"last-lane-id":0}`, patch.Level, patch.Sublevel, "boot-id-prev")) 1179 err := ioutil.WriteFile(dirs.SnapStateFile, fakeState, 0600) 1180 c.Assert(err, IsNil) 1181 1182 rb := &testRestartBehavior{} 1183 1184 _, err = overlord.New(rb) 1185 c.Assert(err, IsNil) 1186 1187 c.Check(rb.rebootState, Equals, "as-expected") 1188 } 1189 1190 func (ovs *overlordSuite) TestVerifyRebootOKButError(c *C) { 1191 fakeState := []byte(fmt.Sprintf(`{"data":{"patch-level":%d,"patch-sublevel":%d,"some":"data","refresh-privacy-key":"0123456789ABCDEF","system-restart-from-boot-id":%q},"changes":null,"tasks":null,"last-change-id":0,"last-task-id":0,"last-lane-id":0}`, patch.Level, patch.Sublevel, "boot-id-prev")) 1192 err := ioutil.WriteFile(dirs.SnapStateFile, fakeState, 0600) 1193 c.Assert(err, IsNil) 1194 1195 e := errors.New("boom") 1196 rb := &testRestartBehavior{rebootVerifiedErr: e} 1197 1198 _, err = overlord.New(rb) 1199 c.Assert(err, Equals, e) 1200 1201 c.Check(rb.rebootState, Equals, "as-expected") 1202 } 1203 1204 func (ovs *overlordSuite) TestVerifyRebootDidNotHappen(c *C) { 1205 curBootID, err := osutil.BootID() 1206 c.Assert(err, IsNil) 1207 1208 fakeState := []byte(fmt.Sprintf(`{"data":{"patch-level":%d,"patch-sublevel":%d,"some":"data","refresh-privacy-key":"0123456789ABCDEF","system-restart-from-boot-id":%q},"changes":null,"tasks":null,"last-change-id":0,"last-task-id":0,"last-lane-id":0}`, patch.Level, patch.Sublevel, curBootID)) 1209 err = ioutil.WriteFile(dirs.SnapStateFile, fakeState, 0600) 1210 c.Assert(err, IsNil) 1211 1212 rb := &testRestartBehavior{} 1213 1214 _, err = overlord.New(rb) 1215 c.Assert(err, IsNil) 1216 1217 c.Check(rb.rebootState, Equals, "did-not-happen") 1218 } 1219 1220 func (ovs *overlordSuite) TestVerifyRebootDidNotHappenError(c *C) { 1221 curBootID, err := osutil.BootID() 1222 c.Assert(err, IsNil) 1223 1224 fakeState := []byte(fmt.Sprintf(`{"data":{"patch-level":%d,"patch-sublevel":%d,"some":"data","refresh-privacy-key":"0123456789ABCDEF","system-restart-from-boot-id":%q},"changes":null,"tasks":null,"last-change-id":0,"last-task-id":0,"last-lane-id":0}`, patch.Level, patch.Sublevel, curBootID)) 1225 err = ioutil.WriteFile(dirs.SnapStateFile, fakeState, 0600) 1226 c.Assert(err, IsNil) 1227 1228 e := errors.New("boom") 1229 rb := &testRestartBehavior{rebootVerifiedErr: e} 1230 1231 _, err = overlord.New(rb) 1232 c.Assert(err, Equals, e) 1233 1234 c.Check(rb.rebootState, Equals, "did-not-happen") 1235 } 1236 1237 func (ovs *overlordSuite) TestOverlordCanStandby(c *C) { 1238 restoreIntv := overlord.MockEnsureInterval(10 * time.Millisecond) 1239 defer restoreIntv() 1240 o := overlord.Mock() 1241 witness := &witnessManager{ 1242 state: o.State(), 1243 expectedEnsure: 3, 1244 ensureCalled: make(chan struct{}), 1245 } 1246 o.AddManager(witness) 1247 1248 c.Assert(o.StartUp(), IsNil) 1249 1250 // can only standby after loop ran once 1251 c.Assert(o.CanStandby(), Equals, false) 1252 1253 o.Loop() 1254 defer o.Stop() 1255 1256 select { 1257 case <-witness.ensureCalled: 1258 case <-time.After(2 * time.Second): 1259 c.Fatal("Ensure calls not happening") 1260 } 1261 1262 c.Assert(o.CanStandby(), Equals, true) 1263 } 1264 1265 func (ovs *overlordSuite) TestStartupTimeout(c *C) { 1266 o, err := overlord.New(nil) 1267 c.Assert(err, IsNil) 1268 1269 to, _, err := o.StartupTimeout() 1270 c.Assert(err, IsNil) 1271 c.Check(to, Equals, 30*time.Second) 1272 1273 st := o.State() 1274 st.Lock() 1275 defer st.Unlock() 1276 1277 // have two snaps 1278 snapstate.Set(st, "core18", &snapstate.SnapState{ 1279 Active: true, 1280 Sequence: []*snap.SideInfo{ 1281 {RealName: "core18", Revision: snap.R(1)}, 1282 }, 1283 Current: snap.R(1), 1284 SnapType: "base", 1285 }) 1286 snapstate.Set(st, "foo", &snapstate.SnapState{ 1287 Active: true, 1288 Sequence: []*snap.SideInfo{ 1289 {RealName: "foo", Revision: snap.R(1)}, 1290 }, 1291 Current: snap.R(1), 1292 SnapType: "app", 1293 }) 1294 1295 st.Unlock() 1296 to, reasoning, err := o.StartupTimeout() 1297 st.Lock() 1298 c.Assert(err, IsNil) 1299 1300 c.Check(to, Equals, (30+5+5)*time.Second) 1301 c.Check(reasoning, Equals, "pessimistic estimate of 30s plus 5s per snap") 1302 }