Skip to content

Commit

Permalink
Merge pull request #295 from yast/dbus-activation
Browse files Browse the repository at this point in the history
Use D-Bus activation instead of explicit service starting
  • Loading branch information
mvidner committed Nov 11, 2022
2 parents 9e39a41 + 6ab05e7 commit 7e67366
Show file tree
Hide file tree
Showing 12 changed files with 106 additions and 16 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,11 @@ $ make devel-install
$ cd -
~~~

* Start the services: beware that D-Installer must run as root (like YaST does) to do hardware probing, partition the disks, install the software and so on.

* Start the services:
* beware that D-Installer must run as root (like YaST does) to do
hardware probing, partition the disks, install the software and so on.
* Note that `setup.sh` sets up D-Bus activation so starting manually is
only needed when you prefer to see the log output upfront.
~~~
$ cd service
$ sudo bundle exec bin/d-installer
Expand Down
2 changes: 1 addition & 1 deletion service/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
root = true

# 2 space indentation
[*.rb]
[{*.rb,bin/d-installer}]
indent_style = space
indent_size = 2
53 changes: 45 additions & 8 deletions service/bin/d-installer
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,27 @@
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)

require "rubygems"
require "bundler/setup"
# find Gemfile when D-Bus activates a git checkout
Dir.chdir(__dir__) do
require "bundler/setup"
end
require "dinstaller/dbus/service_runner"

# Set up a {Logger} suitable either for terminal (started manually)
# or syslog (D-Bus activated)
# @return [Logger]
def logger_for(name)
if $stdout.tty?
formatter = Logger::Formatter.new # the default
else
# going via syslog which will provide time and progname already
formatter = ->(severity, _time, _progname, msg) { "#{severity}: #{msg}\n" }
$stdout.sync = true
end

Logger.new($stdout, progname: name.to_s, formatter: formatter)
end

# Runs the service with the given name
#
# @param name [Symbol] Service name
Expand All @@ -38,32 +56,51 @@ def start_service(name)
module_y2dir = File.expand_path("../lib/dinstaller/dbus/y2dir/#{name}", __dir__)
ENV["Y2DIR"] = "#{module_y2dir}:#{general_y2dir}"

logger = Logger.new($stdout, progname: name.to_s)
service_runner = DInstaller::DBus::ServiceRunner.new(name, logger: logger)
service_runner = DInstaller::DBus::ServiceRunner.new(name, logger: logger_for(name))
service_runner.run
end

ORDERED_SERVICES = [:questions, :language, :software, :storage, :users, :manager].freeze

# Starts all the services
# Normally the services are started by D-Bus activation.
# This starts all the services sequentially without relying on that.
# This is useful during development to have their log output on the terminal,
# not mixed with other syslog/journal messages.
# The downside is relying on an arbitrary delay, and a manually maintained ordering.
#
# @return [Array<Integer>] PIDs
# @return [void]
# @see ORDERED_SERVICES
def start_all_services
ORDERED_SERVICES.map do |name|
puts "Starting #{name}:"
fork { exec("#{__FILE__} #{name}") }
# TODO: implement a better mechanism to check whether the service is running
sleep(1)
sleep(7)
end
end

if ARGV.empty?
pids = start_all_services
start_all_services
Signal.trap("SIGINT") do
puts "Stopping all services..."
exit
end
Process.wait
elsif ["-h", "--help"].include?(ARGV[0])
me = $PROGRAM_NAME
puts "Usage:"
puts "#{me} -h|--help"
puts "#{me} -s|--status"
puts "#{me} -k|--kill"
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'"
elsif ["-k", "--kill"].include?(ARGV[0])
system "pkill -f bin/d-installer.[a-z]"
else
name = ARGV[0]
Signal.trap("SIGINT") do
Expand Down
3 changes: 3 additions & 0 deletions service/package/gem2rpm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@
# ## used by gem2rpm
:post_install: |-
install -D -m 0644 %{buildroot}%{gem_base}/gems/%{mod_full_name}/share/dbus.conf %{buildroot}%{_datadir}/dbus-1/system.d/org.opensuse.DInstaller.conf
install --directory %{buildroot}%{_datadir}/dbus-1/system-services
install -m 0644 --target-directory=%{buildroot}%{_datadir}/dbus-1/system-services %{buildroot}%{gem_base}/gems/%{mod_full_name}/share/org.opensuse.DInstaller*.service
install -D -m 0644 %{buildroot}%{gem_base}/gems/%{mod_full_name}/share/systemd.service %{buildroot}%{_unitdir}/d-installer.service
install -D -m 0644 %{buildroot}%{gem_base}/gems/%{mod_full_name}/etc/d-installer.yaml %{buildroot}%{_sysconfdir}/d-installer.yaml
# ## used by gem_packages
:main:
:filelist: "%{_datadir}/dbus-1/system.d/org.opensuse.DInstaller.conf\n
%{_datadir}/dbus-1/system-services/org.opensuse.DInstaller*.service\n
%{_unitdir}/d-installer.service\n
%{_sysconfdir}/d-installer.yaml\n"
4 changes: 4 additions & 0 deletions service/share/org.opensuse.DInstaller.Language.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[D-BUS Service]
Name=org.opensuse.DInstaller.Language
Exec=/usr/bin/d-installer language
User=root
4 changes: 4 additions & 0 deletions service/share/org.opensuse.DInstaller.Questions.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[D-BUS Service]
Name=org.opensuse.DInstaller.Questions
Exec=/usr/bin/d-installer questions
User=root
4 changes: 4 additions & 0 deletions service/share/org.opensuse.DInstaller.Software.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[D-BUS Service]
Name=org.opensuse.DInstaller.Software
Exec=/usr/bin/d-installer software
User=root
4 changes: 4 additions & 0 deletions service/share/org.opensuse.DInstaller.Storage.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[D-BUS Service]
Name=org.opensuse.DInstaller.Storage
Exec=/usr/bin/d-installer storage
User=root
4 changes: 4 additions & 0 deletions service/share/org.opensuse.DInstaller.Users.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[D-BUS Service]
Name=org.opensuse.DInstaller.Users
Exec=/usr/bin/d-installer users
User=root
5 changes: 5 additions & 0 deletions service/share/org.opensuse.DInstaller.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[D-BUS Service]
Name=org.opensuse.DInstaller
Exec=/usr/bin/d-installer manager
User=root
SystemdService=d-installer.service
2 changes: 1 addition & 1 deletion service/share/systemd.service
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ After=network-online.target
[Service]
Type=dbus
BusName=org.opensuse.DInstaller
ExecStart=/usr/bin/d-installer
ExecStart=/usr/bin/d-installer manager
User=root
TimeoutStopSec=5

Expand Down
30 changes: 26 additions & 4 deletions setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,36 @@ sudo zypper --non-interactive install gcc gcc-c++ make openssl-devel ruby-devel

sudo systemctl start cockpit

# Like "sed -e $1 < $2 > $3" but $3 is a system file owned by root
sudosed() {
echo "$2 -> $3"
sed -e "$1" "$2" | sudo tee "$3" > /dev/null
}

# set up the d-installer service
sudo cp service/share/dbus.conf /usr/share/dbus-1/system.d/org.opensuse.DInstaller.conf
MYDIR=$(realpath $(dirname $0))
sudo cp -v $MYDIR/service/share/dbus.conf /usr/share/dbus-1/system.d/org.opensuse.DInstaller.conf
(
# D-Bus service activation
cd $MYDIR/service/share
DBUSDIR=/usr/share/dbus-1/system-services
for SVC in org.opensuse.DInstaller*.service; do
sudosed "s@\(Exec\)=/usr/bin/@\1=$MYDIR/service/bin/@" $SVC $DBUSDIR/$SVC
done
sudosed "s@\(ExecStart\)=/usr/bin/@\1=$MYDIR/service/bin/@" \
systemd.service /usr/lib/systemd/system/d-installer.service
sudo systemctl daemon-reload
)
cd service; bundle config set --local path 'vendor/bundle'; bundle install; cd -

# set up the web UI
cd web; make devel-install; cd -
sudo ln -s `pwd`/web/dist /usr/share/cockpit/d-installer
sudo ln -snf `pwd`/web/dist /usr/share/cockpit/d-installer

# Start the installer
echo -e "\nStart the d-installer service:\n cd service; sudo bundle exec bin/d-installer\n"
echo -e "Visit http://localhost:9090/cockpit/@localhost/d-installer/index.html"
echo
echo "D-Bus will start the services, see journalctl for their logs."
echo "To start the services manually, logging to the terminal:"
echo " cd service; sudo bundle exec bin/d-installer"
echo
echo "Visit http://localhost:9090/cockpit/@localhost/d-installer/index.html"

0 comments on commit 7e67366

Please sign in to comment.