Skip to content

Commit

Permalink
restart YaST after upgrading the packages (bnc#942080)
Browse files Browse the repository at this point in the history
to avoid using the old (removed) files
  • Loading branch information
lslezak committed Aug 18, 2015
1 parent e50803c commit a831996
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 3 deletions.
6 changes: 6 additions & 0 deletions package/yast2-migration.changes
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Tue Aug 18 07:58:27 UTC 2015 - lslezak@suse.cz

- restart YaST after upgrading the packages to avoid using the old
(removed) files (bnc#942080)

-------------------------------------------------------------------
Fri Aug 14 07:37:00 UTC 2015 - lslezak@suse.cz

Expand Down
23 changes: 21 additions & 2 deletions src/lib/migration/main_workflow.rb
Expand Up @@ -27,6 +27,7 @@
Yast.import "Report"

require "migration/finish_dialog"
require "migration/restarter"

module Migration
# The goal of the class is to provide main single entry point to start
Expand Down Expand Up @@ -67,7 +68,11 @@ def run
private

WORKFLOW_SEQUENCE = {
"ws_start" => "create_backup",
"ws_start" => "start",
"start" => {
start: "create_backup",
restart: "finish_dialog"
},
"create_backup" => {
next: "repositories"
},
Expand All @@ -83,7 +88,10 @@ def run
next: "perform_update"
},
"perform_update" => {
next: "finish_dialog"
next: "restart_yast"
},
"restart_yast" => {
next: :next
},
"finish_dialog" => {
abort: :abort,
Expand All @@ -96,12 +104,14 @@ def run

def aliases
{
"start" => ->() { start },
"create_backup" => ->() { create_backup },
"create_snapshot" => ->() { create_snapshot },
"restore" => ->() { restore_state },
"perform_update" => ->() { perform_update },
"proposals" => ->() { proposals },
"repositories" => ->() { repositories },
"restart_yast" => ->() { restart_yast },
"finish_dialog" => ->() { finish_dialog }
}
end
Expand Down Expand Up @@ -187,5 +197,14 @@ def finish_dialog

ret
end

def start
Restarter.instance.restarted ? :restart : :start
end

def restart_yast
Restarter.instance.restart_yast
:next
end
end
end
41 changes: 41 additions & 0 deletions src/lib/migration/restarter.rb
@@ -0,0 +1,41 @@

require "yast"

require "singleton"

module Migration
# this class handles restarting the YaST module during online migration
class Restarter
include Singleton

Yast.import "Installation"
Yast.import "Directory"

RESTART_FILE = Yast::Installation.restart_file
# the generic restart file is removed by the yast script before starting
# YaST again, we need an extra file to distinguish restart and full start
MIGRATION_RESTART = Yast::Directory.vardir + "/migration_restarted"

attr_reader :restarted

# read the restart flag and remove it immediately to avoid
# possible restart loop
def initialize
@restarted = File.exist?(MIGRATION_RESTART)

clear_restart
end

# set the restart flag
def restart_yast
File.write(RESTART_FILE, "")
File.write(MIGRATION_RESTART, "")
end

# clear the set restart flags
def clear_restart
File.unlink(RESTART_FILE) if File.exist?(RESTART_FILE)
File.unlink(MIGRATION_RESTART) if File.exist?(MIGRATION_RESTART)
end
end
end
1 change: 0 additions & 1 deletion test/finish_dialog_test.rb
Expand Up @@ -75,6 +75,5 @@
expect(subject.run).to eq(:next)
expect(subject.reboot).to eq(false)
end

end
end
6 changes: 6 additions & 0 deletions test/main_workflow_test.rb
Expand Up @@ -21,6 +21,7 @@
require_relative "test_helper"

require "migration/main_workflow"
require "migration/restarter"

describe Migration::MainWorkflow do
describe ".run" do
Expand Down Expand Up @@ -49,6 +50,9 @@ def mock_client(name, res)
# simulate snapper failure (to have a better code coverage)
allow(Yast::Report).to receive(:Error).with(/Failed to create filesystem snapshot/)

allow(File).to receive(:write).with(Migration::Restarter::MIGRATION_RESTART, "")
allow(File).to receive(:write).with(Migration::Restarter::RESTART_FILE, "")

allow_any_instance_of(Migration::FinishDialog).to receive(:run).and_return(:next)
allow_any_instance_of(Migration::FinishDialog).to receive(:reboot).and_return(false)
end
Expand All @@ -75,6 +79,7 @@ def mock_client(name, res)

it "reboots the system at the end when requested" do
allow_any_instance_of(Migration::FinishDialog).to receive(:reboot).and_return(true)
allow_any_instance_of(Migration::Restarter).to receive(:restarted).and_return(true)

expect(Yast::SCR).to receive(:Execute).with(bash_path,
Migration::MainWorkflow::REBOOT_COMMAND).and_return(cmd_success)
Expand All @@ -84,6 +89,7 @@ def mock_client(name, res)

it "reports an error when reboot fails" do
allow_any_instance_of(Migration::FinishDialog).to receive(:reboot).and_return(true)
allow_any_instance_of(Migration::Restarter).to receive(:restarted).and_return(true)

expect(Yast::SCR).to receive(:Execute).with(bash_path,
Migration::MainWorkflow::REBOOT_COMMAND).and_return(cmd_fail)
Expand Down
76 changes: 76 additions & 0 deletions test/restarter_test.rb
@@ -0,0 +1,76 @@
# ------------------------------------------------------------------------------
# Copyright (c) 2015 SUSE LLC, All Rights Reserved.
#
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, contact SUSE LLC.
#
# To contact SUSE about this file by physical or electronic mail, you may find
# current contact information at www.suse.com.
# ------------------------------------------------------------------------------

require_relative "test_helper"

require "migration/restarter"

describe Migration::Restarter do
# create a new anonymous instance for each test to avoid test dependencies
# see http://stackoverflow.com/a/26172556/633234
subject { Class.new(Migration::Restarter).instance }

describe "#restarted" do
before do
allow(File).to receive(:exist?).with(Migration::Restarter::RESTART_FILE)
.and_return(false)
end

context "restart flag set" do
before do
expect(File).to receive(:exist?).with(Migration::Restarter::MIGRATION_RESTART)
.twice.and_return(true)
end

it "removes the restart flag and returns true" do
expect(File).to receive(:unlink).with(Migration::Restarter::MIGRATION_RESTART)
expect(subject.restarted).to eq(true)
end
end

context "restart flag not set" do
before do
expect(File).to receive(:exist?).with(Migration::Restarter::MIGRATION_RESTART)
.twice.and_return(false)
end

it "returns false" do
expect(File).to_not receive(:unlink).with(Migration::Restarter::MIGRATION_RESTART)
expect(subject.restarted).to eq(false)
end
end
end

describe "#restart_yast" do
before do
allow(File).to receive(:exist?).with(Migration::Restarter::MIGRATION_RESTART)
.and_return(false)
allow(File).to receive(:exist?).with(Migration::Restarter::RESTART_FILE)
.and_return(false)
end

it "set the restart flags" do
expect(File).to receive(:write).with(Migration::Restarter::RESTART_FILE, "")
expect(File).to receive(:write).with(Migration::Restarter::MIGRATION_RESTART, "")

subject.restart_yast
end
end
end

0 comments on commit a831996

Please sign in to comment.