Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ TODO: use a url shortener
To build and run this software you need a few tools. To install them on openSUSE
Tumbleweed just type:

$ sudo zypper in gcc gcc-c++ make openssl-devel ruby-devel npm
$ sudo zypper in gcc gcc-c++ make openssl-devel ruby-devel augeas-devel npm

## yastd

Expand Down
2 changes: 1 addition & 1 deletion deploy.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#! /bin/sh
sudo zypper --non-interactive install gcc gcc-c++ make openssl-devel ruby-devel npm git || exit 1
sudo zypper --non-interactive install gcc gcc-c++ make openssl-devel ruby-devel npm git augeas-devel || exit 1

git clone https://github.com/yast/the-installer || exit 1
cd the-installer
Expand Down
1 change: 1 addition & 0 deletions yastd-proxy/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ gem "sinatra"
gem "sinatra-cors"
gem "ruby-dbus", require: "dbus"
gem "thin"
gem "rexml" # ruby3 has it as separate gem
2 changes: 1 addition & 1 deletion yastd/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ source "https://rubygems.org"

gem "rake"
gem "ruby-dbus"
gem "rexml" # dependency of dbus
gem "eventmachine"
gem "nokogiri"

# Required by YaST
gem "cheetah"
Expand Down
4 changes: 3 additions & 1 deletion yastd/lib/yast2/dbus/installer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ def initialize(installer, logger, *args)
self.StatusChanged(status.id)
end

installer.dbus_obj = self

super(*args)
end

Expand Down Expand Up @@ -170,7 +172,7 @@ def initialize(installer, logger, *args)
# - total_substeps: total count of smaller steps done as part of big step. Can be 0, which means no substeps defined
# - current_substep: current substep. Always in range of 0..total_substeps
dbus_signal :Progress,
"message:s, total_steps:t, current_step: t, total_substeps: t, current_substep: t"
"message:s, total_steps:t, current_step:t, total_substeps:t, current_substep:t"
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,70 @@
# YaST specific code lives under this namespace
module Yast2
# This class represents the installer status
class Progress
def initialize(dbus_obj)
class InstallationProgress
KNOWN_STEPS = 3 # keep it in sync with installer.rb
def initialize(dbus_obj, logger: nil)
@dbus_obj = dbus_obj
@logger = logger
@total_pkgs = 0
@remaining_pkgs = 0
end

def partitioning(&block)
report(
# TODO: localization
"Partitioning target disk", 0
)
block.call(self)
report(
# TODO: localization
"Partitioning finished", 1
)
end

def package_installation(&block)
report(
# TODO: localization
"Starting to install packages", 1
)
block.call(self)
report(
# TODO: localization
"Package installation finished", 2
)
end

def bootloader_installation(&block)
report(
# TODO: localization
"Starting to deploy bootloader", 2
)
block.call(self)
report(
# TODO: localization
"Installation finished", 3
)
end

def packages_to_install=(value)
@total_pkgs = @remaining_pkgs = value
end

def package_installed
@remaining_pkgs -= 1
@dbus_obj&.report_progress(
report(
# TODO: localization
"Installing packages (#{@remaining_pkgs} remains)",
1, 0, @total_pkgs, @total_pkgs - @remaining_pkgs
1, substeps: @total_pkgs, current_substep: @total_pkgs - @remaining_pkgs
)
end

private

def report(title, step, substeps: 0, current_substep: 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not making it public and use it directly in the installer.rb?

I mean,

...

def install
  ...
  Yast::Installation.destdir = "/mnt"
  # Imaging we have a collection of steps or so where partitioning could be...
  # 
  # class Partitioning < InstallationStep
  #   def start_label
  #     _("Partitioning target disk")
  #   end
  # 
  #   def perform
  #     Yast::WFM.CallFunction("inst_prepdisk", [])
  #   end
  #  
  #   ...
  steps = [partitioning, package_installation, bootloader_installation]

  # So...

  progress = InstallationProgress.new(@dbus_obj, steps.size, logger: logger)
  
  steps.each_with_index |step, index| do
    progress.report(step.start_label, index)
    step.perform
    progress.report(step.end_label, index + 1)
  end

  ...
end

...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, I am still not sure whose responsibility it is. Also progress needs to know about number of steps so it can report it. So question is who owns responsibility for proper messaging. Still not sure what would be the best solution

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also progress needs to know about number of steps so it can report it

Right. That's why I put the "steps.size" in the InstallationProgress constructor. To tell it the number of steps when creating it, instead of having an internal constant that must be in sync with the installer.rb.

Anyway, let's continue playing around. Thank you!

@logger&.info title
@dbus_obj&.Progress(
title, KNOWN_STEPS, step, substeps, current_substep
)
end
end
Expand Down
41 changes: 26 additions & 15 deletions yastd/lib/yast2/installer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
require "y2storage"
require "yast2/installer_status"
require "yast2/software"
require "yast2/progress"
require "yast2/installation_progress"
require "bootloader/proposal_client"
require "bootloader/finish_client"
require "dbus"
Expand Down Expand Up @@ -63,7 +63,6 @@ def initialize(logger: nil)
@status = InstallerStatus::IDLE
@logger = logger || Logger.new(STDOUT)
@software = Software.new(@logger)
@progress = Progress.new(nil) # TODO: fix passing progress
# Set stage to initial, so it will act as installer for some cases like
# proposing installer instead of reading current one
Yast::Stage.Set("initial")
Expand All @@ -86,9 +85,8 @@ def options
def probe
change_status(InstallerStatus::PROBING)
probe_languages
@software.probe
@software.propose
probe_storage
@software.probe
true
rescue StandardError => e
logger.error "Probing error: #{e.inspect}"
Expand Down Expand Up @@ -120,20 +118,29 @@ def storage_proposal
end

def install
Yast::Installation.destdir = "/mnt"
logger.info "Installing(partitioning)"
change_status(InstallerStatus::PARTITIONING)
Yast::WFM.CallFunction("inst_prepdisk", [])
# Install software
logger.info "Installing(installing software)"
change_status(InstallerStatus::INSTALLING)
@software.install(@progress)
# Install bootloader
logger.info "Installing(bootloader)"
Yast::Installation.destdir = "/mnt"
# lets propose it here to be sure that software proposal reflects product selection
# FIXME: maybe repropose after product selection change?
# first make bootloader proposal to be sure that required packages is installed
proposal = ::Bootloader::ProposalClient.new.make_proposal({})
logger.info "Bootloader proposal #{proposal.inspect}"
::Bootloader::FinishClient.new.write
logger.info "Installing(finished)"
@software.propose

progress = InstallationProgress.new(@dbus_obj, logger: logger)
progress.partitioning do |_|
Yast::WFM.CallFunction("inst_prepdisk", [])
end
progress.package_installation do |progr|
# call inst bootloader to get properly initialized bootloader
# sysconfig before package installation
Yast::WFM.CallFunction("inst_bootloader", [])
@software.install(progr)
end
progress.bootloader_installation do |_|
Yast::WFM.SCROpen("chroot=#{Yast::Installation.destdir}:scr", false)
::Bootloader::FinishClient.new.write
end
change_status(InstallerStatus::IDLE)
end

Expand All @@ -146,6 +153,10 @@ def on_status_change(&block)
@on_status_change = block
end

def dbus_obj=(obj)
@dbus_obj = obj
end

private

def change_status(new_status)
Expand Down
33 changes: 27 additions & 6 deletions yastd/lib/yast2/software.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

Yast.import "Pkg"
Yast.import "PackageInstallation"
Yast.import "Stage"

# YaST specific code lives under this namespace
module Yast2
Expand All @@ -46,19 +47,38 @@ def select_product(name)

def probe
logger.info "Probing software"
# as we use liveDVD with normal like ENV, lets temporary switch to normal to use its repos
Yast::Stage.Set("normal")
Yast::Pkg.TargetInitialize("/")
Yast::Pkg.TargetLoad
Yast::Pkg.SourceRestore
Yast::Pkg.SourceLoad
@products = Y2Packager::Product.all
end

def propose
@product = @products.first&.name
proposal = Yast::Packages.Proposal(force_reset = true, reinit = false, _simple = true)
@logger.info "proposal #{proposal["raw_proposal"]}"
Yast::Stage.Set("initial")

raise "No Product Available" unless @product
end

Yast::Packages.Proposal(force_reset = true, reinit = true, _simple = true)
def propose
Yast::Pkg.TargetInitialize(Yast::Installation.destdir)
Yast::Pkg.TargetLoad
selected_product = @products.find { |p| p.name == @product }
selected_product.select
@logger.info "selected product #{selected_product.inspect}"

# as we use liveDVD with normal like ENV, lets temporary switch to normal to use its repos
Yast::Stage.Set("normal")
# FIXME: workaround to have at least reasonable proposal
Yast::PackagesProposal.AddResolvables("the-installer", :pattern, ["base", "enhanced_base"])
proposal = Yast::Packages.Proposal(force_reset = false, reinit = false, _simple = true)
@logger.info "proposal #{proposal["raw_proposal"]}"
res = Yast::Pkg.PkgSolve(unused = true)
@logger.info "solver run #{res.inspect}"

Yast::Stage.Set("initial")
# do not return proposal hash, so intentional nil here
nil
end
Expand All @@ -69,13 +89,14 @@ def install(progress)
PackageCallbacks.setup(progress)

# TODO: error handling
Yast::Pkg.TargetInitialize(Yast::Installation.destdir)
commit_result = Yast::PackageInstallation.Commit({})

if commit_result.nil? || commit_result.empty?
log.error("Commit failed")
@logger.error("Commit failed")
raise Yast::Pkg.LastError
end

@logger.info "Commit result #{commit_result}"
end

private
Expand Down