Skip to content

Commit

Permalink
Merge be04ea0 into 5de7596
Browse files Browse the repository at this point in the history
  • Loading branch information
lslezak committed Aug 14, 2015
2 parents 5de7596 + be04ea0 commit d4f08d3
Show file tree
Hide file tree
Showing 7 changed files with 283 additions and 6 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
/.yardoc
/coverage
*.bz2
*.pot
7 changes: 7 additions & 0 deletions package/yast2-migration.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
-------------------------------------------------------------------
Thu Aug 13 13:50:14 UTC 2015 - lslezak@suse.cz

- display a finish dialog at the very end, suggest rebooting the
machine to activate the changes (new kernel, ...) (bsc#941625)
- 3.1.3

-------------------------------------------------------------------
Wed Aug 5 12:08:53 UTC 2015 - lslezak@suse.cz

Expand Down
2 changes: 1 addition & 1 deletion package/yast2-migration.spec
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@


Name: yast2-migration
Version: 3.1.2
Version: 3.1.3
Release: 0

BuildRoot: %{_tmppath}/%{name}-%{version}-build
Expand Down
122 changes: 122 additions & 0 deletions src/lib/migration/finish_dialog.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# ------------------------------------------------------------------------------
# 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 "yast"

module Migration
# Display the "finished" dialog, allow rebooting the machine
class FinishDialog
include Yast::Logger
include Yast::I18n
include Yast::UIShortcuts

Yast.import "UI"
Yast.import "Wizard"
Yast.import "Popup"
Yast.import "Label"

attr_accessor :reboot

# constructor
def initialize
textdomain "migration"

@reboot = false
end

# display and run the dialog
# @return [Symbol] user input
def run
Yast::Wizard.SetContents(
# TRANSLATORS: dialog title
_("Migration Finished"),
dialog_content,
help,
# going back is not possible
false,
true
)

Yast::Wizard.SetNextButton(:next, Yast::Label.FinishButton)

loop do
ret = Yast::UI.UserInput

if ret == :next && reboot?
# TRANSLATORS: popup message, restart can be canceled by the [Cancel] button
if Yast::Popup.ContinueCancel(_("The system will be restarted in one minute\n" \
"after closing this YaST module."))

store_values
else
next
end
end

return ret if [:next, :back, :cancel, :abort].include?(ret)
end
end

private

def help
# TRANSLATORS: a short help text (the details are directly in the dialog)
_("<p><b>Finish</b> will close the migration and you should restart " \
"the system as soon as possible.</b>")
end

# the main dialog content
# @return [Yast::Term] UI term
def dialog_content
VBox(
VSpacing(1),
RichText(Id(:details), Opt(:vstretch), message),
VSpacing(1),
# TRANSLATORS: check button label, if checked the system will be rebooted
CheckBox(Id(:reboot), _("Restart the System"), reboot),
VSpacing(1)
)
end

def message
# TRANSLATORS: The final congratulation displayed at the end of migration,
# in RichText format, %s = URL link to the SUSE home page
_("<h2>Congratulations!</h2><br>
<p>You have just successfully finished the on-line migration.<br>
The system has been upgraded, it should be restarted
as soon as possible to activate the changes.</p>
<p>Please visit us at %s.</p>
<br>
<p>Have a lot of fun!</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Your SUSE Development Team</p>") % "http://www.suse.com"
end

# store the current UI values
def store_values
self.reboot = reboot?
log.info "Reboot flag: #{reboot}"
end

def reboot?
Yast::UI.QueryWidget(:reboot, :Value)
end
end
end
42 changes: 40 additions & 2 deletions src/lib/migration/main_workflow.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
Yast.import "Update"
Yast.import "Report"

require "migration/finish_dialog"

module Migration
# The goal of the class is to provide main single entry point to start
# migration work-flow. It is UI oriented sequence.
Expand All @@ -36,10 +38,15 @@ class MainWorkflow

FIND_CONFIG_CMD = "/usr/bin/snapper --no-dbus list-configs | " \
"grep \"^root \" >/dev/null"

CREATE_SNAPSHOT_CMD = "/usr/bin/snapper create --type=%{snapshot_type} " \
"--cleanup-algorithm=number --print-number " \
"--description=\"%{description}\""

# reboot command: reboot in one minute to give the user a chance to finish YaST
# and log out, the reboot can be canceled by "shutdown -c" command if needed
REBOOT_COMMAND = "shutdown --reboot +1"

def self.run
workflow = new
workflow.run
Expand All @@ -48,7 +55,13 @@ def self.run
def run
textdomain "migration"
Yast::Mode.SetMode("update")
Yast::Sequencer.Run(aliases, WORKFLOW_SEQUENCE)

begin
Yast::Wizard.CreateDialog
Yast::Sequencer.Run(aliases, WORKFLOW_SEQUENCE)
ensure
Yast::Wizard.CloseDialog
end
end

private
Expand All @@ -70,6 +83,10 @@ def run
next: "perform_update"
},
"perform_update" => {
next: "finish_dialog"
},
"finish_dialog" => {
abort: :abort,
next: :next
},
"restore" => {
Expand All @@ -84,7 +101,8 @@ def aliases
"restore" => ->() { restore_state },
"perform_update" => ->() { perform_update },
"proposals" => ->() { proposals },
"repositories" => ->() { repositories }
"repositories" => ->() { repositories },
"finish_dialog" => ->() { finish_dialog }
}
end

Expand Down Expand Up @@ -149,5 +167,25 @@ def perform_snapshot
log.error "Snapshot could not be created: #{cmd} returned: #{out}"
Yast::Report.Error(_("Failed to create filesystem snapshot."))
end

# display the finish dialog and optionally reboot the system
# @return [Symbol] UI user input
def finish_dialog
dialog = Migration::FinishDialog.new
ret = dialog.run

if ret == :next && dialog.reboot
log.info "Rebooting the system in one minute..."

out = Yast::SCR.Execute(Yast::Path.new(".target.bash_output"), REBOOT_COMMAND)
if out["exit"] != 0
log.error "Reboot could not be scheduled: #{REBOOT_COMMAND} returned: #{out}"
Yast::Report.Error(_("Failed to schedule the system restart,\n" \
"restart the system manually."))
end
end

ret
end
end
end
80 changes: 80 additions & 0 deletions test/finish_dialog_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# ------------------------------------------------------------------------------
# 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"

describe Migration::FinishDialog do
describe ".run" do
it "displays the finish message" do
# check the displayed content
expect(Yast::Wizard).to receive(:SetContents) do |_title, content, _help, _back, _next|
richtext = content.nested_find do |t|
t.respond_to?(:value) && t.value == :RichText &&
t.params[2].match(/Congratulations!/)
end

expect(richtext).to_not eq(nil)
end

# user pressed the "Abort" button
allow(Yast::UI).to receive(:UserInput).and_return(:abort)
subject.run
end

it "when aborted reboot flag is not set and return :abort" do
# check the displayed content
allow(Yast::Wizard).to receive(:SetContents)

# user pressed the "Abort" button
expect(Yast::UI).to receive(:UserInput).and_return(:abort)

expect(subject.run).to eq(:abort)
expect(subject.reboot).to eq(false)
end

it "displays a confirmation when reboot is requested" do
allow(Yast::Wizard).to receive(:SetContents)

# user pressed the "Next" button
expect(Yast::UI).to receive(:UserInput).and_return(:next)
allow(Yast::UI).to receive(:QueryWidget).with(:reboot, :Value).and_return(true)

expect(Yast::Popup).to receive(:ContinueCancel).and_return(true)

expect(subject.run).to eq(:next)
expect(subject.reboot).to eq(true)
end

it "goes back when reboot is rejected" do
allow(Yast::Wizard).to receive(:SetContents)

# user pressed the "Next" button
allow(Yast::UI).to receive(:UserInput).and_return(:next)
# reboot is disabled at the second attempt
allow(Yast::UI).to receive(:QueryWidget).with(:reboot, :Value).and_return(true, false)

expect(Yast::Popup).to receive(:ContinueCancel).and_return(false)

expect(subject.run).to eq(:next)
expect(subject.reboot).to eq(false)
end

end
end
35 changes: 32 additions & 3 deletions test/main_workflow_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@

describe Migration::MainWorkflow do
describe ".run" do
let(:cmd_success) { { "exit" => 0 } }
let(:cmd_fail) { { "exit" => 1 } }
let(:bash_path) { Yast::Path.new(".target.bash_output") }

def mock_client(name, res)
allow(Yast::WFM).to receive(:CallFunction).with(*name).and_return(res)
end
Expand All @@ -35,12 +39,18 @@ def mock_client(name, res)
mock_client("inst_kickoff", :next)
mock_client("inst_rpmcopy", :next)

cmd_success = { "exit" => 0 }
cmd_fail = { "exit" => 1 }
allow(Yast::Update).to receive(:clean_backup)
allow(Yast::Update).to receive(:create_backup)
allow(Yast::Update).to receive(:restore_backup)
allow(Yast::SCR).to receive(:Execute).and_return(cmd_success, cmd_fail)

allow(Yast::SCR).to receive(:Execute).with(bash_path, /snapper .*list-configs/)
.and_return(cmd_success)
allow(Yast::SCR).to receive(:Execute).with(bash_path, /snapper create/).and_return(cmd_fail)
# simulate snapper failure (to have a better code coverage)
allow(Yast::Report).to receive(:Error).with(/Failed to create filesystem snapshot/)

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

it "pass workflow sequence to Yast sequencer" do
Expand All @@ -62,5 +72,24 @@ def mock_client(name, res)

expect(::Migration::MainWorkflow.run).to eq :abort
end

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

expect(Yast::SCR).to receive(:Execute).with(bash_path,
Migration::MainWorkflow::REBOOT_COMMAND).and_return(cmd_success)

expect(::Migration::MainWorkflow.run).to eq :next
end

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

expect(Yast::SCR).to receive(:Execute).with(bash_path,
Migration::MainWorkflow::REBOOT_COMMAND).and_return(cmd_fail)
expect(Yast::Report).to receive(:Error).with(/Failed to schedule the system restart/)

expect(::Migration::MainWorkflow.run).to eq :next
end
end
end

0 comments on commit d4f08d3

Please sign in to comment.