Compare commits

..

No commits in common. "rawhide" and "f28" have entirely different histories.

7 changed files with 32 additions and 613 deletions

3
README.md Normal file
View file

@ -0,0 +1,3 @@
# resalloc
Client/Server application for managing (expensive) resources

View file

@ -1,37 +0,0 @@
#! /bin/sh
# Prepare rawhide branch, review the list of branches below and then execute this
# script.
main=main
branches="$main epel8 epel9 f41 f42"
exit_handler ()
{
git checkout $main
}
trap exit_handler EXIT
set -e
set -x
koji hello
tasks=
for branch in $branches; do
if test $branch != $main; then
git checkout "$branch"
git merge $main
fi
git push
tasks="${tasks}`fedpkg build --nowait | grep 'Created task' | cut -d: -f2`"
done
if test -n "$tasks"; then
koji watch-task $tasks
fi
set -- $branches
git checkout $1
fedpkg update

View file

@ -1,15 +0,0 @@
[Unit]
Description=Start self-stending agent-like resources using Resalloc
After=syslog.target network.target auditd.service
[Service]
Type=simple
User=resalloc
Group=resalloc
ExecStart=/usr/bin/resalloc-agent-spawner
# we don't want to kill background action processors (daemoncontext)
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target

View file

@ -4,8 +4,7 @@ After=network.target
[Service]
Type=simple
Restart=always
RestartSec=5
User=resalloc
Group=resalloc

View file

@ -2,19 +2,8 @@
%global sysuser resalloc
%global sysgroup %sysuser
%global _homedir %_sharedstatedir/%{name}server
%global agent_user resalloc-agent-spawner
%global agent_group %agent_user
%global create_user_group() \
getent group "%1" >/dev/null || groupadd -r "%1" \
getent passwd "%1" >/dev/null || \\\
useradd -r -g "%2" -G "%2" -s "%3" \\\
-c "%1 service user" "%1" \\\
-d "%4"
%global _logdir %_var/log/%{name}server
%global _homedir %_sharedstatedir/%{name}server
%global sum Resource allocator for expensive resources
%global desc \
@ -25,7 +14,7 @@ the purposes of CI/CD tasks.
%bcond_without check
%if 0%{?fedora} || 0%{?rhel} > 7 || 0%{?is_opensuse}
%if 0%{?fedora} || 0%{?rhel} > 7
%bcond_with python2
%bcond_without python3
%else
@ -33,59 +22,34 @@ the purposes of CI/CD tasks.
%bcond_with python3
%endif
# Modern distributions (using RPM v4.19+; for example, Fedora 39+) do not
# require the %%pre scriptlet for creating users/groups because the sysusers
# feature is now built directly into RPM. Simply including the sysusers
# `mock.conf` file in a package payload is sufficient to leverage this feature.
# However, for older distributions that lack this capability, we still define
# the %%pre scriptlet.
%if (0%{?rhel} && 0%{?rhel} < 10) || (0%{?mageia} && 0%{?mageia} < 10) || (0%{?suse_version} && 0%{?suse_version} < 1660)
%bcond_without sysusers_compat
%else
%bcond_with sysusers_compat
%endif
%global default_python %{?with_python3:python3}%{!?with_python3:python2}
%global default_sitelib %{?with_python3:%python3_sitelib}%{!?with_python3:%python_sitelib}
Name: %srcname
Summary: %sum - client tooling
Version: 5.11
Release: 4%{?dist}
License: GPL-2.0-or-later
Version: 2.3
Release: 3%{?dist}
License: GPLv2+
URL: https://github.com/praiskup/resalloc
BuildArch: noarch
BuildRequires: make
BuildRequires: postgresql-server
%if %{with python3}
BuildRequires: python3-alembic
BuildRequires: python3-argparse-manpage
BuildRequires: python3-devel
BuildRequires: python3-psycopg2
BuildRequires: python3-pytest
BuildRequires: python3-pytest-cov
BuildRequires: python3-setuptools
BuildRequires: python3-six
BuildRequires: python3-sqlalchemy
%if 0%{?is_opensuse}
BuildRequires: python3-PyYAML
BuildRequires: cron
%else
BuildRequires: python3-yaml
%endif
%endif
%if %{with python2}
BuildRequires: python-alembic
BuildRequires: python2-argparse-manpage
BuildRequires: python2-devel
BuildRequires: python-psycopg2
BuildRequires: python2-mock
BuildRequires: python2-pytest
BuildRequires: python2-pytest-cov
BuildRequires: python2-setuptools
BuildRequires: python2-six
BuildRequires: python-sqlalchemy
@ -94,18 +58,11 @@ BuildRequires: python-yaml
Requires: %default_python-%srcname = %version-%release
%if %{with sysusers_compat}
Requires(pre): shadow-utils
%endif
Source0: https://github.com/praiskup/%name/releases/download/v%version/%name-%version.tar.gz
Source1: resalloc.service
Source5: resalloc-agent-spawner.service
Source2: logrotate
Source3: merge-hook-logs
Source4: cron.hourly
# GPL-2.0-or-later too
Source6: https://raw.githubusercontent.com/praiskup/wait-for-ssh/main/wait-for-ssh
Source0: https://github.com/praiskup/%name/releases/download/v%version/%name-%version.tar.gz
Source1: resalloc.service
Source2: logrotate
Source3: merge-hook-logs
Source4: cron.hourly
%description
%desc
@ -116,10 +73,9 @@ The %name package provides the client-side tooling.
%package server
Summary: %sum - server part
Requires: crontabs
Requires: logrotate
Requires: crontabs
Requires: logrotate
Requires: %default_python-%srcname = %version-%release
Requires: %srcname-helpers = %version-%release
%if %{with python3}
Requires: python3-alembic
Requires: python3-six
@ -132,6 +88,7 @@ Requires: python-sqlalchemy
Requires: python-yaml
%endif
Requires(pre): /usr/sbin/useradd
%description server
%desc
@ -139,55 +96,6 @@ The %name-server package provides the resalloc server, and
some tooling for resalloc administrators.
%package helpers
Summary: %sum - helper/library scripts
%description helpers
%desc
Helper and library-like scripts for external Resalloc plugins like resalloc-aws,
resalloc-openstack, etc.
%if %{with python3}
%package webui
Summary: %sum - webui part
%if %{with python3}
Requires: %default_python-%srcname = %version-%release
Requires: %name-server
Requires: python3-flask
Recommends: %name-selinux
%endif
%description webui
%desc
The %name-webui package provides the resalloc webui,
it shows page with information about resalloc resources.
%endif
%if %{with python3}
%package agent-spawner
Summary: %sum - daemon starting agent-like resources
Requires: python3-copr-common >= 0.23
Requires: python3-daemon
Requires: python3-redis
Requires: python3-resalloc = %version-%release
Requires: python3-setproctitle
%description agent-spawner
%desc
Agent Spawner maintains sets resources (agents) of certain kind and in certain
number, according to given configuration. Typical Resalloc resource is
completely dummy, fully controlled from the outside. With agent-like resources
this is different such resources are self-standing, they take care of
themselves, perhaps interacting/competing with each other. The only thing that
agent-spawner needs to do is to control the ideal number of them.
%endif
%if %{with python3}
%package -n python3-%srcname
Summary: %sum - Python 3 client library
@ -212,69 +120,28 @@ to the resalloc server.
%endif
%package selinux
Summary: SELinux module for %{name}
# Requires(post): policycoreutils-python
BuildRequires: selinux-policy-devel
%{?selinux_requires}
%description selinux
%desc
%post selinux
semanage fcontext -a -t httpd_sys_script_exec_t \
%_var/www/cgi-%{name} 2>/dev/null || :
restorecon -R %_var/www/cgi-%{name} || :
%prep
%autosetup -p1 -n %name-%version
%if %{without python3}
rm -r resalloc_agent_spawner
%endif
# Create sysusers.d config files
cat >resalloc.sysusers.conf <<EOF
u resalloc - '%sysuser service user' %_homedir /bin/bash
m resalloc %sysgroup
EOF
cat >resalloc-agent-spawner.sysusers.conf <<EOF
u resalloc-agent-spawner - '%agent_user service user' - -
m resalloc-agent-spawner %agent_group
EOF
%setup -q
%build
%if %{with python2}
python=%__python2
%py2_build
%else
%py3_build
python=%__python3
%endif
sed "1c#! $python" %SOURCE6 > %{name}-wait-for-ssh
%install
%if %{with python2}
%py2_install
rm -r %buildroot%python2_sitelib/%{name}webui
%else
%py3_install
install -d -m 755 %buildroot%_datadir/%{name}webui
cp -r %{name}webui/templates %buildroot%_datadir/%{name}webui/
cp -r %{name}webui/static %buildroot%_datadir/%{name}webui/
install -d -m 755 %buildroot%_var/www/
install -p -m 755 %{name}webui/cgi-resalloc %buildroot%_var/www/cgi-%{name}
%endif
mkdir -p %buildroot%_unitdir
mkdir -p %buildroot%_logdir
install -p -m 644 %SOURCE1 %buildroot%_unitdir
%if %{with python3}
install -p -m 644 %SOURCE5 %buildroot%_unitdir
%endif
install -d -m 700 %buildroot%_homedir
install -d -m 700 %buildroot%_sysconfdir/logrotate.d
install -p -m 644 %SOURCE2 %buildroot%_sysconfdir/logrotate.d/resalloc-server
@ -283,15 +150,6 @@ install -d -m 755 %buildroot/%_libexecdir
install -p -m 755 %SOURCE3 %buildroot/%_libexecdir/%name-merge-hook-logs
install -d %buildroot%_sysconfdir/cron.hourly
install -p -m 755 %SOURCE4 %buildroot%_sysconfdir/cron.hourly/resalloc
install -p -m 755 %name-wait-for-ssh %buildroot%_bindir/%name-wait-for-ssh
%if %{without python3}
rm %buildroot%_bindir/%name-agent-*
rm %buildroot%_sysconfdir/resalloc-agent-spawner/config.yaml
%endif
install -m0644 -D resalloc.sysusers.conf %{buildroot}%{_sysusersdir}/resalloc.conf
install -m0644 -D resalloc-agent-spawner.sysusers.conf %{buildroot}%{_sysusersdir}/resalloc-agent-spawner.conf
%if %{with check}
@ -308,10 +166,15 @@ make check TEST_PYTHONS="python3"
ln -s "%{default_sitelib}/%{name}server" %buildroot%_homedir/project
%if %{with sysusers_compat}
%pre server
%create_user_group %sysuser %sysgroup /bin/bash %_homedir
%endif
user=%sysuser
group=%sysgroup
getent group "$user" >/dev/null || groupadd -r "$group"
getent passwd "$user" >/dev/null || \
useradd -r -g "$group" -G "$group" -s /bin/bash \
-c "resalloc server's user" "$user" \
-d "%_homedir"
%post server
%systemd_post resalloc.service
@ -320,32 +183,16 @@ ln -s "%{default_sitelib}/%{name}server" %buildroot%_homedir/project
%systemd_postun_with_restart resalloc.service
%if %{with python3}
%if %{with sysusers_compat}
%pre agent-spawner
%create_user_group %agent_user %agent_group /bin/false /
%endif
%post agent-spawner
%systemd_post resalloc-agent-spawner.service
%postun agent-spawner
%systemd_postun_with_restart resalloc-agent-spawner.service
%endif
%global doc_files NEWS README.md
%files
%doc %doc_files
%license COPYING
%doc README
%{_bindir}/%{name}
%_mandir/man1/%{name}.1*
%if %{with python3}
%files -n python3-%srcname
%doc %doc_files
%doc README
%license COPYING
%{python3_sitelib}/%{name}
%{python3_sitelib}/%{name}-*.egg-info
@ -354,7 +201,7 @@ ln -s "%{default_sitelib}/%{name}server" %buildroot%_homedir/project
%if %{with python2}
%files -n python2-%srcname
%doc %doc_files
%doc README
%license COPYING
%{python2_sitelib}/%{name}
%{python2_sitelib}/%{name}-*.egg-info
@ -362,12 +209,12 @@ ln -s "%{default_sitelib}/%{name}server" %buildroot%_homedir/project
%files server
%doc %doc_files
%doc README
%license COPYING
%{default_sitelib}/%{name}server
%{_bindir}/%{name}-server
%{_bindir}/%{name}-maint
%attr(0750, %sysuser, %sysgroup) %dir %{_sysconfdir}/%{name}server
%attr(0700, %sysuser, %sysgroup) %dir %{_sysconfdir}/%{name}server
%config(noreplace) %{_sysconfdir}/%{name}server/*
%_unitdir/resalloc.service
%attr(0700, %sysuser, %sysgroup) %dir %_logdir
@ -377,226 +224,9 @@ ln -s "%{default_sitelib}/%{name}server" %buildroot%_homedir/project
%config %_sysconfdir/logrotate.d/resalloc-server
%_libexecdir/resalloc-merge-hook-logs
%config %attr(0755, root, root) %{_sysconfdir}/cron.hourly/resalloc
%{_sysusersdir}/resalloc.conf
%files helpers
%doc %doc_files
%license COPYING
%{_bindir}/%{name}-check-vm-ip
%{_bindir}/%{name}-wait-for-ssh
%if %{with python3}
%files agent-spawner
%_bindir/resalloc-agent*
%{default_sitelib}/%{name}_agent_spawner
%_unitdir/resalloc-agent-spawner.service
%config(noreplace) %_sysconfdir/resalloc-agent-spawner
%{_sysusersdir}/resalloc-agent-spawner.conf
%files webui
%doc %doc_files
%license COPYING
%{default_sitelib}/%{name}webui/
%_datadir/%{name}webui/
%_var/www/cgi-%{name}
%endif
%files selinux
%changelog
* Fri Sep 19 2025 Python Maint <python-maint@redhat.com> - 5.11-4
- Rebuilt for Python 3.14.0rc3 bytecode
* Fri Aug 15 2025 Python Maint <python-maint@redhat.com> - 5.11-3
- Rebuilt for Python 3.14.0rc2 bytecode
* Fri Jul 25 2025 Fedora Release Engineering <releng@fedoraproject.org> - 5.11-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild
* Mon Jul 21 2025 Pavel Raiskup <praiskup@redhat.com> - 5.11-1
- new upstream release, don't keep cleanup processes indefinitely:
https://github.com/praiskup/resalloc/releases/tag/v5.11
* Thu Jun 12 2025 Pavel Raiskup <praiskup@redhat.com> - 5.10-1
- new upstream release, packages use RPM built-in sysusers support:
https://github.com/praiskup/resalloc/releases/tag/v5.10
* Thu Jun 05 2025 Python Maint <python-maint@redhat.com> - 5.9-2
- Rebuilt for Python 3.14
* Sat Jan 18 2025 Pavel Raiskup <praiskup@redhat.com> - 5.9-1
- New upstream release https://github.com/praiskup/resalloc/releases/tag/v5.9
* Thu Jan 16 2025 Jakub Kadlcik <frostyx@email.cz> - 5.8-1
- New upstream release https://github.com/praiskup/resalloc/releases/tag/v5.8
* Fri Jan 10 2025 Jakub Kadlcik <frostyx@email.cz> - 5.7-1
- New upstream release https://github.com/praiskup/resalloc/releases/tag/v5.7
* Mon Oct 07 2024 Pavel Raiskup <praiskup@redhat.com> - 5.6-1
- New upstream release https://github.com/praiskup/resalloc/releases/tag/v5.6
* Fri Jul 19 2024 Fedora Release Engineering <releng@fedoraproject.org> - 5.5-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild
* Sun Jun 09 2024 Python Maint <python-maint@redhat.com> - 5.5-2
- Rebuilt for Python 3.13
* Wed Apr 24 2024 Pavel Raiskup <praiskup@redhat.com> - 5.5-1
- New upstream release https://github.com/praiskup/resalloc/releases/tag/v5.5
* Fri Mar 15 2024 Pavel Raiskup <praiskup@redhat.com> - 5.4-1
- New upstream release https://github.com/praiskup/resalloc/releases/tag/v5.4
* Wed Feb 28 2024 Pavel Raiskup <praiskup@redhat.com> - 5.3-1
- New upstream release https://github.com/praiskup/resalloc/releases/tag/v5.3
* Wed Feb 28 2024 Pavel Raiskup <praiskup@redhat.com> - 5.2-1
- New upstream release https://github.com/praiskup/resalloc/releases/tag/v5.2
* Fri Jan 26 2024 Fedora Release Engineering <releng@fedoraproject.org> - 5.1-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Mon Jan 22 2024 Fedora Release Engineering <releng@fedoraproject.org> - 5.1-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Mon Nov 06 2023 Pavel Raiskup <praiskup@redhat.com> - 5.1-1
- new upstream release https://github.com/praiskup/resalloc/releases/tag/v5.1
* Fri Aug 11 2023 Pavel Raiskup <praiskup@redhat.com> - 5.0-1
- new upstream release https://github.com/praiskup/resalloc/releases/tag/v5.0
* Fri Jul 21 2023 Fedora Release Engineering <releng@fedoraproject.org> - 4.9-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
* Tue Jul 04 2023 Python Maint <python-maint@redhat.com> - 4.9-3
- Rebuilt for Python 3.12
* Mon Jan 30 2023 Miro Hrončok <mhroncok@redhat.com> - 4.9-2
- Rebuilt to change Python shebangs to /usr/bin/python3.6 on EPEL 8
* Mon Jan 23 2023 Pavel Raiskup <praiskup@redhat.com> - 4.9-1
- new upstream release https://github.com/praiskup/resalloc/releases/tag/v4.9
* Fri Jan 20 2023 Fedora Release Engineering <releng@fedoraproject.org> - 4.8-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
* Fri Sep 23 2022 Pavel Raiskup <praiskup@redhat.com> - 4.8-1
- new upstream release:
https://github.com/praiskup/resalloc/releases/tag/v4.8
* Tue Sep 20 2022 Pavel Raiskup <praiskup@redhat.com> - 4.7-1
- new upstream release:
https://github.com/praiskup/resalloc/releases/tag/v4.7
* Sat Jul 23 2022 Fedora Release Engineering <releng@fedoraproject.org> - 4.6-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
* Wed Jun 29 2022 Jakub Kadlcik <frostyx@email.cz> - 4.6-2
- Add resalloc-selinux subpackage
* Wed Jun 29 2022 Jakub Kadlcik <frostyx@email.cz> - 4.6-1
- New upstream version:
https://github.com/praiskup/resalloc/releases/tag/v4.6
* Thu Jun 23 2022 Pavel Raiskup <praiskup@redhat.com> - 4.5-1
- New upstream version:
https://github.com/praiskup/resalloc/releases/tag/v4.5
* Wed Jun 22 2022 Jakub Kadlcik <python-maint@redhat.com> - 4.4-1
- New upstream version:
https://github.com/praiskup/resalloc/releases/tag/v4.4
* Tue Jun 14 2022 Python Maint <python-maint@redhat.com> - 4.3-2
- Rebuilt for Python 3.11
* Thu Jan 20 2022 Pavel Raiskup <praiskup@redhat.com> - 4.3-1
- new upstream release:
https://github.com/praiskup/resalloc/releases/tag/v4.3
* Thu Jan 20 2022 Pavel Raiskup <praiskup@redhat.com> - 4.2-1
- new upstream release:
https://github.com/praiskup/resalloc/releases/tag/v4.2
* Tue Aug 24 2021 Pavel Raiskup <praiskup@redhat.com> - 4.1-1
- bugfix release, with prioritized released resources again
* Mon Aug 23 2021 Pavel Raiskup <praiskup@redhat.com> - 4-1
- new release, with tag-priority
* Fri Jul 23 2021 Fedora Release Engineering <releng@fedoraproject.org> - 3.7-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild
* Tue Jun 22 2021 Pavel Raiskup <praiskup@redhat.com> - 3.7-1
- new upstream release, see NEWS file
* Wed Jun 09 2021 Pavel Raiskup <praiskup@redhat.com> - 3.6-1
- rebase to a new version having DB performance fixes
* Fri Jun 04 2021 Python Maint <python-maint@redhat.com> - 3.4-3
- Rebuilt for Python 3.10
* Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 3.4-2
- Rebuilt for updated systemd-rpm-macros
See https://pagure.io/fesco/issue/2583.
* Fri Feb 19 2021 Silvie Chlupova <schlupov@redhat.com> - 3.4-1
- New upstream release v3.4
* Wed Jan 27 2021 Fedora Release Engineering <releng@fedoraproject.org> - 3.3-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
* Wed Jul 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 3.3-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Thu Jun 25 2020 Pavel Raiskup <praiskup@redhat.com> - 3.3-1
- new release, mostly fixing one bug causing traceback on too-long stdout output
from AllocWorker script
* Tue Jun 02 2020 Pavel Raiskup <praiskup@redhat.com> - 3.2-1
- new configuration option cmd_release - command to be run before we mark the
resource as reusable again
- after server restart, schedule all inconsistent resources to be terminated
(mitigates issue#41)
- systemd service is restarted upon failure (just in case)
* Tue May 26 2020 Miro Hrončok <mhroncok@redhat.com> - 3.1-2
- Rebuilt for Python 3.9
* Tue May 26 2020 Pavel Raiskup <praiskup@redhat.com> - 3.1-1
- new version v3.1, improved resource checker
* Tue May 26 2020 Miro Hrončok <mhroncok@redhat.com> - 3.0-2
- Rebuilt for Python 3.9
* Sun May 17 2020 Pavel Raiskup <praiskup@redhat.com> - 3.0-1
- new 3.0 version - new possibility to re-use resources, and client requests can
survive server restarts
* Thu Jan 30 2020 Fedora Release Engineering <releng@fedoraproject.org> - 2.6-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Thu Oct 03 2019 Miro Hrončok <mhroncok@redhat.com> - 2.6-3
- Rebuilt for Python 3.8.0rc1 (#1748018)
* Mon Aug 19 2019 Miro Hrončok <mhroncok@redhat.com> - 2.6-2
- Rebuilt for Python 3.8
* Fri Aug 02 2019 Pavel Raiskup <praiskup@redhat.com> - 2.6-1
- don't assign resources to closed tickets
* Fri Jul 26 2019 Fedora Release Engineering <releng@fedoraproject.org> - 2.5-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Thu Jun 13 2019 Pavel Raiskup <praiskup@redhat.com> - 2.5-1
- thread safety - don't change os.environ
* Tue Jun 11 2019 Pavel Raiskup <praiskup@redhat.com> - 2.4-1
- fix improperly handled thread communication
* Fri May 10 2019 Pavel Raiskup <praiskup@redhat.com> - 2.3-3
- drop mkhomedir requires leftover
- configure logrotate to compress rotated logs

View file

@ -1 +1 @@
SHA512 (resalloc-5.11.tar.gz) = 73becebe671a59912006eb4b227c10f6ac7be91a91e94cff470ac6bb32eb4447ec905b1d151c5eeb54fdc6c2a6179f9b7d606bcf25c3f9caeb63bde171759ac3
SHA512 (resalloc-2.3.tar.gz) = ea158b59e1cc2e74d7915436d9ae111c05c5ae5541f09fe4fada6325e67fce4ac2d5d8ab45adc7d1e5323e4b1338b30da76c2b88126f38109c9580f5c5a91482

View file

@ -1,161 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (C) 2017 Pavel Raiskup
#
# This program accepts one argument IP or HOSTNAME. First try to connect to the
# HOSTNAME as 'root' user. If cloud-init scripts instruct us to use different
# user than 'root', switch to that user and check again. In the end, print the
# successful username on stdout.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from re import compile as re_compile
import sys
from os import devnull
from threading import Thread, Event
from argparse import ArgumentParser
from subprocess import Popen, PIPE
import logging
handler = logging.StreamHandler()
log = logging.getLogger()
log.setLevel(logging.INFO)
log.addHandler(handler)
# create console handler and set level to debug
ssh = [
'ssh',
'-o', 'StrictHostKeyChecking=no',
'-o', 'UserKnownHostsFile=/dev/null',
'-o', 'PasswordAuthentication=no',
'-o', 'ConnectTimeout=10',
]
expected_output = 'foobar'
inner_cmd = 'echo ' + expected_output
class Checker(Thread):
user = 'root'
daemon = True
user_re = '[a-zA-Z0-9_.][a-zA-Z0-9_.-]*[$]?'
re_clouduser = re_compile('Please login as the user "({0})"'.format(user_re))
event = Event()
def loop(self):
cmd = ssh + [
'{0}@{1}'.format(self.user, self.args.host),
inner_cmd,
]
with open(devnull, 'w') as drop:
log.debug('executing: ' + ' '.join(cmd))
self.child = Popen(cmd, stdout=PIPE, stderr=drop)
(stdout, _) = self.child.communicate()
exp = (expected_output + '\n').encode('ascii')
if self.child.returncode == 0 and stdout == exp:
if self.args.print_user:
print(self.user)
return True
if self.args.cloud_user:
match = self.re_clouduser.search(str(stdout))
if match:
self.user = match.group(1)
log.info('cloud user switched to ' + self.user)
return False
def run(self):
while True:
if self.loop():
# Success!
break
if self.event.wait(1):
log.debug("stopping per kill event")
break
def kill(self):
self.event.set()
# Best effort kill.
try:
self.child.kill()
except:
pass
self.join()
parser = ArgumentParser(
description="Wait till the host's ssh becomes responsive.")
parser.add_argument('host', help='hostname or IP')
parser.add_argument('--timeout',
help='seconds to wait before failure, default=indefinitely',
default=None, type=float)
parser.add_argument('--check-cloud-user', action='store_true', default=False,
dest='cloud_user',
help='if cloud-init disallows "root" login, try to detect the cloud ' \
+'user and use that')
parser.add_argument('--print-user', action='store_true', default=False,
dest='print_user',
help='print the username which succeeded to connect on stdout')
parser.add_argument('--log', default=False,
dest='log_verbosity',
help='set the threshold for logging, e.g. debug, info, error, ...')
def main():
sleep_period = 1.0
args = parser.parse_args()
if args.log_verbosity:
log.setLevel(logging.getLevelName(args.log_verbosity.upper()))
def timeouted():
if args.timeout is None:
return False
log.debug("wait {0}s, remains {1}s".format(sleep_period, args.timeout))
args.timeout -= sleep_period
return args.timeout <= 0
checker = Checker()
checker.args = args
checker.start()
try:
# threading.join() is not Ctrl-C interruptable :( in python2, so we need
# this ugly infinite loop.
# https://stackoverflow.com/questions/25676835/signal-handling-in-multi-threaded-python
while True:
checker.join(sleep_period)
if not checker.is_alive():
# Success!
return 0
if timeouted():
log.error("timeout!")
checker.kill()
return 1
except KeyboardInterrupt:
log.error("interrupt by user")
checker.kill()
return 1
if __name__ == "__main__":
sys.exit(main())