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
6f48466
[service] Use a separate D-Bus server
imobachgs Dec 29, 2022
a90d3c1
[service] Stop the D-Bus server on "d-installer -k"
imobachgs Dec 29, 2022
6c5de31
[service] Use the own D-Bus server
imobachgs Dec 29, 2022
18a9590
[cli] Update Gemfile.lock
imobachgs Dec 29, 2022
d8c9e05
[web] Connect to the D-Installer D-Bus server
imobachgs Dec 30, 2022
3fd005f
[service] Fix several documentation issues
imobachgs Jan 3, 2023
cbbf944
[service] Remove the START_CMD constant
imobachgs Jan 3, 2023
36970b7
[service] Fix the path to the D-Bus configuration file
imobachgs Jan 3, 2023
c8e358d
[service] Fix and document the D-Bus configuration
imobachgs Jan 3, 2023
3eff53b
[service] Write the D-Bus address to a file
imobachgs Jan 9, 2023
0277449
[web] Read the D-Bus address from /run/d-installer
imobachgs Jan 9, 2023
4b97d02
[service] Fix D-Bus permissions
imobachgs Jan 9, 2023
3fbe599
[service]
imobachgs Jan 9, 2023
7446abf
[service] Improve d-installer -s and -k handling
imobachgs Jan 9, 2023
ca49315
Merge branch 'master' into use-own-bus
imobachgs Jan 9, 2023
a199091
[service] Avoid running the D-Bus servers on tests
imobachgs Jan 9, 2023
77def21
Merge branch 'master' into use-own-bus
imobachgs Jan 9, 2023
e9d2897
[service] createClient receives the address
imobachgs Jan 10, 2023
c7fdcf5
[web] Make ESLint happy
imobachgs Jan 10, 2023
3eafc10
[doc] Mention that D-Installer uses a dedicated D-Bus server
imobachgs Jan 10, 2023
3070588
[service] Adjust the D-Bus configuration file paths
imobachgs Jan 10, 2023
47d0f73
Update the changes files
imobachgs Jan 10, 2023
6f41e60
[service] Fix D-Bus activation
imobachgs Jan 10, 2023
0a8b4ae
[service] Move some logic from bin/d-installer to ServerManager
imobachgs Jan 10, 2023
8dddfd3
[service] Make RuboCop happy
imobachgs Jan 10, 2023
144c60c
Update from code review
imobachgs Jan 11, 2023
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
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ SUSE is working on its next generation operating system called ALP (Adaptable Li

## Architecture

This project is designed as a service-client system, using D-Bus for process communication.
This project is designed as a service-client system, using a dedicated D-Bus server for process
communication.

![Architecture](./doc/images/architecture.png)

Expand Down Expand Up @@ -109,8 +110,8 @@ $ sudo zypper in gcc gcc-c++ make openssl-devel ruby-devel augeas-devel npm cock
* Setup the D-Installer services:

~~~
$ sudo cp service/share/dbus.conf /usr/share/dbus-1/system.d/org.opensuse.DInstaller.conf
$ cd service;
$ sudo cp service/share/dbus.conf /usr/share/dbus-1/d-installer.conf
$ cd service
$ bundle config set --local path 'vendor/bundle';
$ bundle install
$ cd -
Expand Down
7 changes: 5 additions & 2 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ task package: [] do
end
end

SERVICES_DIR = "/usr/share/dbus-1/d-installer-services"

# support for patching by the yupdate script,
# only when running in the inst-sys or live medium
if File.exist?("/.packages.initrd") || `mount`.match?(/^[\w]+ on \/ type overlay/)
Expand All @@ -97,8 +99,9 @@ if File.exist?("/.packages.initrd") || `mount`.match?(/^[\w]+ on \/ type overlay
sh "gem install --local --force --no-format-exec --no-doc --build-root #{destdir.shellescape} d-installer-*.gem"

# update the DBus configuration files
sh "cp share/org.opensuse.DInstaller*.service /usr/share/dbus-1/system-services"
sh "cp share/dbus.conf /usr/share/dbus-1/system.d/org.opensuse.DInstaller.conf"
FileUtils.mkdir_p(SERVICES_DIR)
sh "cp share/org.opensuse.DInstaller*.service #{SERVICES_DIR}"
sh "cp share/dbus.conf /usr/share/dbus-1/d-installer.conf"

# update the systemd service file
source_file = "share/systemd.service"
Expand Down
13 changes: 12 additions & 1 deletion service/bin/d-installer
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Dir.chdir(__dir__) do
require "bundler/setup"
end
require "dinstaller/dbus/service_runner"
require "dinstaller/dbus/server_manager"

# Set up a {Logger} suitable either for terminal (started manually)
# or syslog (D-Bus activated)
Expand Down Expand Up @@ -80,6 +81,8 @@ def start_all_services
end
end

dbus_server_manager = DInstaller::DBus::ServerManager.new

if ARGV.empty?
start_all_services
Signal.trap("SIGINT") do
Expand All @@ -93,17 +96,25 @@ elsif ["-h", "--help"].include?(ARGV[0])
puts "#{me} -h|--help"
puts "#{me} -s|--status"
puts "#{me} -k|--kill"
puts "#{me} -d|--daemon"
puts "#{me} #{ORDERED_SERVICES.sort.join("|")}"
elsif ["-s", "--status"].include?(ARGV[0])
# The .[a-z] ensures matching the forked processes
# which can be distinguished by having a non-option argument
system "pgrep -fl bin/d-installer.[a-z]"
# busctl is prettier but will find nothing until the service files are installed,
# hence the pgrep above
system "busctl | grep -E '^NAME|DInstaller'"
system "busctl --address #{dbus_server_manager.address} | grep -E '^NAME|DInstaller'"
elsif ["-k", "--kill"].include?(ARGV[0])
system "pkill -f bin/d-installer.[a-z]"
# stop the d-bus daemon
dbus_server_manager.stop_server
elsif ["-d", "--daemon"].include?(ARGV[0])
# start the D-Bus server
pid = dbus_server_manager.find_or_start_server
puts pid
else
dbus_server_manager.find_or_start_server
name = ARGV[0]
Signal.trap("SIGINT") do
puts "Stopping #{name} service..."
Expand Down
54 changes: 54 additions & 0 deletions service/lib/dinstaller/dbus/bus.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# frozen_string_literal: true

# Copyright (c) [2022] 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 LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "dbus"
require "dinstaller/dbus/server_manager"

module DInstaller
module DBus
# Represents the D-Installer bus, a distinct one from the system and session buses.
class Bus < ::DBus::Connection
class << self
# Returns the current D-Bus connection
#
# @return [Bus] D-Bus connection
def current
return @current if @current

dbus_manager = ServerManager.new
dbus_manager.find_or_start_server
@current = new(dbus_manager.address)
end

def reset
@current = nil
end
end

# @param address [String] a connectable address
# @see https://dbus.freedesktop.org/doc/dbus-specification.html#addresses
def initialize(address)
super(address)
send_hello
end
end
end
end
3 changes: 2 additions & 1 deletion service/lib/dinstaller/dbus/clients/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
# find current contact information at www.suse.com.

require "dbus"
require "dinstaller/dbus/bus"
require "abstract_method"

module DInstaller
Expand Down Expand Up @@ -63,7 +64,7 @@ def on_properties_change(dbus_object, &block)
end

def bus
@bus ||= ::DBus::SystemBus.instance
@bus ||= Bus.current
end
end
end
Expand Down
3 changes: 2 additions & 1 deletion service/lib/dinstaller/dbus/language_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
# find current contact information at www.suse.com.

require "dbus"
require "dinstaller/dbus/bus"
require "dinstaller/dbus/language"
require "dinstaller/language"

Expand All @@ -45,7 +46,7 @@ class LanguageService
# @param logger [Logger]
def initialize(_config, logger = nil)
@logger = logger || Logger.new($stdout)
@bus = ::DBus::SystemBus.instance
@bus = Bus.current
end

# Exports the installer object through the D-Bus service
Expand Down
3 changes: 2 additions & 1 deletion service/lib/dinstaller/dbus/manager_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
require "dbus"
require "dinstaller/manager"
require "dinstaller/cockpit_manager"
require "dinstaller/dbus/bus"
require "dinstaller/dbus/manager"
require "dinstaller/dbus/storage/proposal"

Expand Down Expand Up @@ -54,7 +55,7 @@ def initialize(config, logger = nil)
@config = config
@manager = DInstaller::Manager.new(config, logger)
@logger = logger || Logger.new($stdout)
@bus = ::DBus::SystemBus.instance
@bus = Bus.current
end

# Initializes and exports the D-Bus API
Expand Down
3 changes: 2 additions & 1 deletion service/lib/dinstaller/dbus/questions_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
# find current contact information at www.suse.com.

require "dbus"
require "dinstaller/dbus/bus"
require "dinstaller/dbus/questions"
require "dinstaller/questions_manager"

Expand All @@ -42,7 +43,7 @@ class QuestionsService
# @param logger [Logger]
def initialize(_config, logger = nil)
@logger = logger || Logger.new($stdout)
@bus = ::DBus::SystemBus.instance
@bus = Bus.current
@backend ||= DInstaller::QuestionsManager.new(logger)
end

Expand Down
135 changes: 135 additions & 0 deletions service/lib/dinstaller/dbus/server_manager.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# frozen_string_literal: true

# Copyright (c) [2022] 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 LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "cheetah"
require "fileutils"

module DInstaller
module DBus
# This class takes care of setting up the D-Installer D-Bus server
#
# @example Find the current server or start a new if it is not running
# manager = DBusManager.new
# manager.find_or_start_server
class ServerManager
# @return [String] Default run directory path
DEFAULT_RUN_DIRECTORY = "/run/d-installer"
private_constant :DEFAULT_RUN_DIRECTORY

attr_reader :run_directory

def initialize(run_directory: DEFAULT_RUN_DIRECTORY)
@run_directory = run_directory
end

# Finds the current D-Bus server or starts a new one
#
# @return [Integer,nil] PID of the server process or nil if it
# was not possible to start a new one
def find_or_start_server
find_server || start_server
end

# Starts a D-Bus server
#
# @return [Integer,nil] PID of the new server. Returns nil if it failed to start
# the server.
def start_server
FileUtils.mkdir_p(run_directory)

output = Cheetah.run(
"/usr/bin/dbus-daemon",
"--config-file", config_file,
"--address", address,
"--fork", "--systemd-activation",
"--print-pid",
stdout: :capture
)
File.write(address_file, address)
pid = output.strip
File.write(pid_file, pid)
pid.to_i
rescue Cheetah::ExecutionFailed => e
puts "Could not start the DBus daemon: #{e.message}"
nil
end

# Gets the PID of the running server
#
# @return [Integer,nil] PID of the process if it exists, nil otherwise.
def find_server
return nil unless File.exist?(pid_file)

pid = File.read(pid_file).to_i
return nil if pid.zero?

begin
Process.getpgid(pid)
pid
rescue Errno::ESRCH # the process is not found
nil
end
end

# Stops the running server
def stop_server
pid = find_server
return unless pid

Process.kill("KILL", pid.to_i)
Copy link
Contributor

Choose a reason for hiding this comment

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

NP: note that usually preferred way for killing is something like SIGTERM wait 5 seconds and then SIGKILL if it does not help. Here you do not allow process to finish anything.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. Let's postpone this change a bit, anyway.

end

# Returns the D-Bus address
#
# @return [String]
def address
@address ||= "unix:path=#{File.join(run_directory, "bus")}"
end

private

# Returns the path to the configuration file
#
# It prefers a local configuration under `share/dbus.conf`. Otherwise, it falls back to a
# system-wide location.
def config_file
file = File.join(Dir.pwd, "share", "dbus.conf")
return file if File.exist?(file)

"/usr/share/dbus-1/d-installer.conf"
end

# Returns the path to the file containing the PID
#
# @return [String]
def pid_file
@pid_file ||= File.join(run_directory, "bus.pid")
end

# Returns the path to the file containing the D-Bus address
#
# @return [String]
def address_file
@address_file ||= File.join(run_directory, "bus.address")
end
end
end
end
3 changes: 2 additions & 1 deletion service/lib/dinstaller/dbus/software_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
# find current contact information at www.suse.com.

require "dbus"
require "dinstaller/dbus/bus"
require "dinstaller/dbus/software"
require "dinstaller/software"

Expand All @@ -42,7 +43,7 @@ class SoftwareService
# @param logger [Logger]
def initialize(config, logger = nil)
@logger = logger || Logger.new($stdout)
@bus = ::DBus::SystemBus.instance
@bus = Bus.current
@backend = DInstaller::Software::Manager.new(config, logger)
@backend.on_progress_change { dispatch }
end
Expand Down
3 changes: 2 additions & 1 deletion service/lib/dinstaller/dbus/storage_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
# find current contact information at www.suse.com.

require "dbus"
require "dinstaller/dbus/bus"
require "dinstaller/dbus/storage"
require "dinstaller/storage"

Expand All @@ -42,7 +43,7 @@ class StorageService
# @param logger [Logger]
def initialize(config, logger = nil)
@logger = logger || Logger.new($stdout)
@bus = ::DBus::SystemBus.instance
@bus = Bus.current
@backend = DInstaller::Storage::Manager.new(config, logger)
@backend.on_progress_change { dispatch }
end
Expand Down
3 changes: 2 additions & 1 deletion service/lib/dinstaller/dbus/users_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
# find current contact information at www.suse.com.

require "dbus"
require "dinstaller/dbus/bus"
require "dinstaller/dbus/users"
require "dinstaller/users"

Expand All @@ -45,7 +46,7 @@ class UsersService
# @param logger [Logger]
def initialize(_config, logger = nil)
@logger = logger || Logger.new($stdout)
@bus = ::DBus::SystemBus.instance
@bus = Bus.current
end

# Exports the installer object through the D-Bus service
Expand Down
Loading