The Wombelix Post - Uyunihttps://dominik.wombacher.cc/2022-12-22T00:00:00+01:00Why Open Source matter, experience of my last contribution to Uyuni2022-12-22T00:00:00+01:002022-12-22T00:00:00+01:00Dominik Wombachertag:dominik.wombacher.cc,2022-12-22:/posts/why-open-source-matter-experience-of-my-last-contribution-to-uyuni.html<!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>After being guest at <a class="reference external" href="https://dominik.wombacher.cc/posts/guest-at-emiel-broks-friday-ketchup.html">Friday Ketchup with Emiel Brok</a>,
I had to think about my last contribution to Uyuni.</p>
<p>It’s a great example how even something small can have ... <a class="read-more" href="/posts/why-open-source-matter-experience-of-my-last-contribution-to-uyuni.html"> [read more]</a></p><!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>After being guest at <a class="reference external" href="https://dominik.wombacher.cc/posts/guest-at-emiel-broks-friday-ketchup.html">Friday Ketchup with Emiel Brok</a>,
I had to think about my last contribution to Uyuni.</p>
<p>It’s a great example how even something small can have an impact and even if you can’t finish it on your own,
you might be able to lead the way so other can, and will, pick your work up.</p>
<p>Back in May I wanted to further improve my Java skills, I tend to check some open source projects in such a case,
that way I do something useful ;) I was skimming through the Uyuni Issues on GitHub to see if there is anything
interesting I could work on. I found the Issue
<a class="reference external" href="https://github.com/uyuni-project/uyuni/issues/5343">complete set of parameters with smtp host, port, user and password for SUSE Manager</a>
(Archive: <a class="reference external" href="https://archive.today/2022.12.23-214324/https://github.com/uyuni-project/uyuni/issues/5343">[1]</a>).</p>
<p>So far you could define an SMTP Server which Uyuni / SUMA will use to send out Notifications, but it wasn’t possible
to configure a port other then 25 or to authenticate with a username and password. It was obvious that this is
actually an important feature, most companies get rid of open SMTP relays.</p>
<p>I started to work on it and came up with a working, let’s call it <a class="reference external" href="https://github.com/uyuni-project/uyuni/pull/5466">proof of concept</a>
(Archive: <a class="reference external" href="https://archive.today/2022.12.23-214517/https://github.com/uyuni-project/uyuni/pull/5466">[1]</a>).
It wasn’t the most elegant solution and still WIP, but it did the job already in my test environment. Unfortunately
a lot of other things came up and during the next months I wasn’t able to find time to further work on the feature.</p>
<p>In September one of the Uyuni Maintainer <a class="reference external" href="https://github.com/uyuni-project/uyuni/pull/5886">used my code, further brushed it up and merged it</a>
(Archive: <a class="reference external" href="https://archive.today/2022.12.23-214530/https://github.com/uyuni-project/uyuni/pull/5886">[1]</a>)
so it became a feature in the next Uyuni release.</p>
<p>THIS is in my opinion the most important part, THIS is one example why Open Source matters, a feature request was reported,
I was interested to work on it, started with something but even though I couldn’t finish it, someone else found it useful,
took it from there and completed it.</p>
<p>I would like to encourage everyone who’s interested in contributing to open source projects: Just do it! Start with something,
give it a try, share and publish your results, further improve it if you can or let other from the community help you.</p>
<p>And last but not least, you don’t need coding skills to contribute, trust me, every project has a ton of non-code
related things that could use some improvement and help :)</p>
First time Speaker @ SUSECON Digital 2022 about SUSE Manager as a Service2022-05-27T00:00:00+02:002022-05-27T00:00:00+02:00Dominik Wombachertag:dominik.wombacher.cc,2022-05-27:/posts/first_time_speaker_at_susecon_digital_2022_june_7th_till_9th.html<!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>In the Session
<a class="reference external" href="https://susecon.com/sessions.html?#/session/1649177024584001TPU9">SUSE Manager as a Service: Infrastructure & Patch Management made easy [POV-1236]</a>
(Archive: <a class="reference external" href="https://archive.today/2022.05.28-114148/https://susecon.com/sessions.html?%23/session/1649177024584001TPU9">[1]</a>)
on Thursday, Jun 9, from 2:00 PM - 2:30 PM CEST, I will ... <a class="read-more" href="/posts/first_time_speaker_at_susecon_digital_2022_june_7th_till_9th.html"> [read more]</a></p><!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>In the Session
<a class="reference external" href="https://susecon.com/sessions.html?#/session/1649177024584001TPU9">SUSE Manager as a Service: Infrastructure & Patch Management made easy [POV-1236]</a>
(Archive: <a class="reference external" href="https://archive.today/2022.05.28-114148/https://susecon.com/sessions.html?%23/session/1649177024584001TPU9">[1]</a>)
on Thursday, Jun 9, from 2:00 PM - 2:30 PM CEST, I will talk about my vision to provide Managed Services based on SUSE Manager.
It will be my first time as Speaker, but hopefully not the last time ;)</p>
<p>It's still time to <a class="reference external" href="https://reg.rainfocus.com/flow/suse/susecon22/registration/login">register for free</a>,
there are a lot of other interesting <a class="reference external" href="https://susecon.com/sessions.html">sessions</a> to watch during the SUSECON Digital 2022..</p>
<p>My Employer NTT Germany is going to launch a managed service offering,
details about the various options will also be part of that Session.</p>
<p>The Interest and Support from SUSE and NTT Germany is amazing, I'm thrilled about this opportunity and
looking forward to build and operate the solution together with my Team.</p>
<p>I already wrote a few times about SUSE Manager and the Upstream Open Source Project Uyuni,
my contributions, development and troubleshooting.</p>
<p>It's not a secret that I really enjoy hacking Uyuni in my free time, the fact that this is
something I can also do as part of my Job now is just great :)</p>
<p>You may wonder why all Contributions are related to Uyuni? Due to the strict
<a class="reference external" href="https://links.imagerelay.com/cdn/3404/ql/5ef7f48c5eea4293b0c836f4dd184885/suse_open_source_policy.pdf">Upstream first</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20220121053948/https://links.imagerelay.com/cdn/3404/ql/5ef7f48c5eea4293b0c836f4dd184885/suse_open_source_policy.pdf">[1]</a>,
<a class="reference external" href="https://archive.today/2022.05.28-131831/https://links.imagerelay.com/cdn/3404/ql/5ef7f48c5eea4293b0c836f4dd184885/suse_open_source_policy.pdf">[2]</a>)
Policy from SUSE, which is a really good thing, fixes and new features always go from Uyuni to SUSE Manager.</p>
How changing '<' to '>=' introduced a weird and hard to track bug2022-03-22T00:00:00+01:002022-03-22T00:00:00+01:00Dominik Wombachertag:dominik.wombacher.cc,2022-03-22:/posts/how_changing_less-than_to_greater-equal_introduced_a_weird_and_hard_to_track_bug.html<!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>After upgrading to <a class="reference external" href="https://www.uyuni-project.org">Uyuni 2022.2</a> I wasn't able to sync openSUSE Leap 15.3
and Oracle Linux 8 repositories anymore, the configured HTTP Proxy was ignored. Multiple people reported ... <a class="read-more" href="/posts/how_changing_less-than_to_greater-equal_introduced_a_weird_and_hard_to_track_bug.html"> [read more]</a></p><!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>After upgrading to <a class="reference external" href="https://www.uyuni-project.org">Uyuni 2022.2</a> I wasn't able to sync openSUSE Leap 15.3
and Oracle Linux 8 repositories anymore, the configured HTTP Proxy was ignored. Multiple people reported similar issues:
<a class="reference external" href="https://github.com/uyuni-project/uyuni/issues/4932">#4932</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20220322220517/https://github.com/uyuni-project/uyuni/issues/4932">[1]</a>,
<a class="reference external" href="https://archive.today/2022.03.22-220522/https://github.com/uyuni-project/uyuni/issues/4932">[2]</a>),
<a class="reference external" href="https://github.com/uyuni-project/uyuni/issues/4850">#4850</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20220322220540/https://github.com/uyuni-project/uyuni/issues/4850">[1]</a>,
<a class="reference external" href="https://archive.today/2022.03.22-220553/https://github.com/uyuni-project/uyuni/issues/4850">[2]</a>),
<a class="reference external" href="https://github.com/uyuni-project/uyuni/issues/4826">#4826</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20220322220605/https://github.com/uyuni-project/uyuni/issues/4826">[1]</a>,
<a class="reference external" href="https://archive.today/2022.03.22-220613/https://github.com/uyuni-project/uyuni/issues/4826">[2]</a>).</p>
<p>During multiple troubleshooting sessions I learned a lot about
the Python Codebase and the reposync tool.</p>
<p>It took my quite a while to track down the Issue to the <code>urlgrabber</code> package.</p>
<p>What happened? Method <code>find_proxy</code> in <code>urlgrabber.grabber.URLGrabberOptions</code>
will identify the proxy server that should be used based on the provided URL Scheme.</p>
<p>Let's assume <code>server.satellite.http_proxy</code> in <code>/etc/rhn/rhn.conf</code> is set to <code>http://10.11.12.13:80</code>.</p>
<pre class="code python literal-block">
<span class="pygments-o">>>></span> <span class="pygments-kn">from</span> <span class="pygments-nn">urlgrabber.grabber</span> <span class="pygments-kn">import</span> <span class="pygments-n">URLGrabberOptions</span><span class="pygments-w">
</span><span class="pygments-o">>>></span> <span class="pygments-n">opts</span> <span class="pygments-o">=</span> <span class="pygments-n">URLGrabberOptions</span><span class="pygments-p">(</span><span class="pygments-n">proxy</span><span class="pygments-o">=</span><span class="pygments-kc">None</span><span class="pygments-p">,</span> <span class="pygments-n">proxies</span><span class="pygments-o">=</span><span class="pygments-p">{</span><span class="pygments-s1">'http'</span><span class="pygments-p">:</span> <span class="pygments-s1">'http://10.11.12.13:80'</span><span class="pygments-p">,</span> <span class="pygments-s1">'https'</span><span class="pygments-p">:</span> <span class="pygments-s1">'http://10.11.12.13:80'</span><span class="pygments-p">,</span> <span class="pygments-s1">'ftp'</span><span class="pygments-p">:</span> <span class="pygments-s1">'http://10.11.12.13:80'</span><span class="pygments-p">})</span><span class="pygments-w">
</span><span class="pygments-o">>>></span> <span class="pygments-n">opts</span><span class="pygments-o">.</span><span class="pygments-n">find_proxy</span><span class="pygments-p">(</span><span class="pygments-sa">b</span><span class="pygments-s1">'http://test.example.com'</span><span class="pygments-p">,</span> <span class="pygments-sa">b</span><span class="pygments-s1">'http'</span><span class="pygments-p">)</span><span class="pygments-w">
</span>
</pre>
<p>That's the simplified version of the relevant Code, a Instance of <code>URLGrabberOptions</code> contains a list of proxies,
one per URL Scheme, the method <code>find_proxy</code> is used to choose the right proxy from <code>opts.proxies</code>
based on two parameter, <code>url</code> and <code>scheme</code>, both are passed as type <code>bytes</code>.</p>
<p>The expected result, <code>opts.proxy</code> contains the value <code>http://10.11.12.13:80</code> from type <code>str</code>,
actual result, <code>None</code>.</p>
<p>The package <code>urlgrabber</code> is quite old and not that actively maintained.
Python 3 support was added in Version 4, the last release is from October 2019.</p>
<p>It looks like that the above issues, that proxy is None, comes from an inconsistent bytes / string conversion.
If you pass the scheme as string instead bytes, you get the expected result:</p>
<pre class="code python literal-block">
<span class="pygments-o">>>></span> <span class="pygments-kn">from</span> <span class="pygments-nn">urlgrabber.grabber</span> <span class="pygments-kn">import</span> <span class="pygments-n">URLGrabberOptions</span><span class="pygments-w">
</span><span class="pygments-o">>>></span> <span class="pygments-n">opts</span> <span class="pygments-o">=</span> <span class="pygments-n">URLGrabberOptions</span><span class="pygments-p">(</span><span class="pygments-n">proxy</span><span class="pygments-o">=</span><span class="pygments-kc">None</span><span class="pygments-p">,</span> <span class="pygments-n">proxies</span><span class="pygments-o">=</span><span class="pygments-p">{</span><span class="pygments-s1">'http'</span><span class="pygments-p">:</span> <span class="pygments-s1">'http://10.11.12.13:80'</span><span class="pygments-p">,</span> <span class="pygments-s1">'https'</span><span class="pygments-p">:</span> <span class="pygments-s1">'http://10.11.12.13:80'</span><span class="pygments-p">,</span> <span class="pygments-s1">'ftp'</span><span class="pygments-p">:</span> <span class="pygments-s1">'http://10.11.12.13:80'</span><span class="pygments-p">})</span><span class="pygments-w">
</span><span class="pygments-o">>>></span> <span class="pygments-n">opts</span><span class="pygments-o">.</span><span class="pygments-n">find_proxy</span><span class="pygments-p">(</span><span class="pygments-sa">b</span><span class="pygments-s1">'http://test.example.com'</span><span class="pygments-p">,</span> <span class="pygments-s1">'http'</span><span class="pygments-p">)</span><span class="pygments-w">
</span><span class="pygments-o">>>></span> <span class="pygments-n">opts</span><span class="pygments-o">.</span><span class="pygments-n">proxy</span><span class="pygments-w">
</span><span class="pygments-s1">'http://10.11.12.13:80'</span><span class="pygments-w">
</span>
</pre>
<p>To get the Sync of openSUSE Leap 15.3 and Oracle Linux 8 Repositories working again
through a http proxy, a small change was already sufficient:</p>
<pre class="code diff literal-block">
<span class="pygments-gh">diff --git a/backend/satellite_tools/download.py b/backend/satellite_tools/download.py</span><span class="pygments-w">
</span><span class="pygments-gh">index 3d064e5c6ce..3b7a02d5176 100644</span><span class="pygments-w">
</span><span class="pygments-gd">--- a/backend/satellite_tools/download.py</span><span class="pygments-w">
</span><span class="pygments-gi">+++ b/backend/satellite_tools/download.py</span><span class="pygments-w">
</span><span class="pygments-gu">@@ -114,7 +114,7 @@ def __init__(self, url, filename, opts, curl_cache, parent):</span><span class="pygments-w">
</span> self.parent = parent<span class="pygments-w">
</span> (url, parts) = opts.urlparser.parse(url, opts)<span class="pygments-w">
</span> (scheme, host, path, parm, query, frag) = parts<span class="pygments-w">
</span><span class="pygments-gd">- opts.find_proxy(url, scheme)</span><span class="pygments-w">
</span><span class="pygments-gi">+ opts.find_proxy(url, scheme.decode("utf-8"))</span><span class="pygments-w">
</span> super().__init__(url, filename, opts)<span class="pygments-w">
</span> def _do_open(self):<span class="pygments-w">
</span>
</pre>
<p>Pull Request <a class="reference external" href="https://github.com/uyuni-project/uyuni/pull/4953">#4953</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20220322220636/https://github.com/uyuni-project/uyuni/pull/4953">[1]</a>,
<a class="reference external" href="https://archive.today/2022.03.22-220654/https://github.com/uyuni-project/uyuni/pull/4953">[2]</a>)
was accepted and merged, unfortunately a few user still reported issues, especially related to CentOS 7 this time.</p>
<p>After a quick check, I had the impression that syncing EL8 based Distributions like Oracle Linux 8
share the same Code as EL7 based Distributions like CentOS 7.
More or less right, but due to things like <em>mirrorlist</em>, there are some additional steps and further
calls of <code>urlgrabber</code> split across the reposync code.</p>
<p>I had to find another way to fix it without touching multiple files and methods.
So I gave some hacky <a class="reference external" href="https://en.wikipedia.org/wiki/Monkey_patch">Monkey Patching</a> a try.
First I reverted the previous workaround:</p>
<pre class="code diff literal-block">
<span class="pygments-gh">diff --git a/python/spacewalk/satellite_tools/download.py b/python/spacewalk/satellite_tools/download.py</span><span class="pygments-w">
</span><span class="pygments-gh">index 3b7a02d5176..3d064e5c6ce 100644</span><span class="pygments-w">
</span><span class="pygments-gd">--- a/python/spacewalk/satellite_tools/download.py</span><span class="pygments-w">
</span><span class="pygments-gi">+++ b/python/spacewalk/satellite_tools/download.py</span><span class="pygments-w">
</span><span class="pygments-gu">@@ -114,7 +114,7 @@ def __init__(self, url, filename, opts, curl_cache, parent):</span><span class="pygments-w">
</span> self.parent = parent<span class="pygments-w">
</span> (url, parts) = opts.urlparser.parse(url, opts)<span class="pygments-w">
</span> (scheme, host, path, parm, query, frag) = parts<span class="pygments-w">
</span><span class="pygments-gd">- opts.find_proxy(url, scheme.decode("utf-8"))</span><span class="pygments-w">
</span><span class="pygments-gi">+ opts.find_proxy(url, scheme)</span><span class="pygments-w">
</span> super().__init__(url, filename, opts)<span class="pygments-w">
</span> def _do_open(self):<span class="pygments-w">
</span>
</pre>
<p>Then I created a new <code>find_proxy</code> method, which just triggers the original one
but performs the bytes to string conversion. The magic happens in the two lines after
the method, <code>urlgrabber_find_proxy</code> becomes the method from <code>urlgrabber</code>
and my own version replaces the original one. That way it doesn't matter where in
<code>yum_src.py</code> anything related to <code>urlgrabber</code> will be triggered, scheme
will always be converted to a string a the proxy set as configured and expected.</p>
<pre class="code diff literal-block">
<span class="pygments-gh">diff --git a/python/spacewalk/satellite_tools/repo_plugins/yum_src.py b/python/spacewalk/satellite_tools/repo_plugins/yum_src.py</span><span class="pygments-w">
</span><span class="pygments-gh">index 85013cfb36a..39f36be61e5 100644</span><span class="pygments-w">
</span><span class="pygments-gd">--- a/python/spacewalk/satellite_tools/repo_plugins/yum_src.py</span><span class="pygments-w">
</span><span class="pygments-gi">+++ b/python/spacewalk/satellite_tools/repo_plugins/yum_src.py</span><span class="pygments-w">
</span><span class="pygments-gu">@@ -80,6 +80,17 @@</span><span class="pygments-w">
</span>APACHE_USER = 'wwwrun'<span class="pygments-w">
</span>APACHE_GROUP = 'www'<span class="pygments-w">
</span><span class="pygments-gi">+</span><span class="pygments-w">
</span><span class="pygments-gi">+# Monkey Patch 'urlgrabber.grabber' method 'find_proxy' to enforce type string for variable 'scheme'</span><span class="pygments-w">
</span><span class="pygments-gi">+# Workaround due to wrong byte/string handling in 'urlgrabber' package</span><span class="pygments-w">
</span><span class="pygments-gi">+# Required by reposync to connect through http_proxy as configured</span><span class="pygments-w">
</span><span class="pygments-gi">+def find_proxy(self, url, scheme):</span><span class="pygments-w">
</span><span class="pygments-gi">+ urlgrabber_find_proxy(self, url, scheme.decode('utf-8'))</span><span class="pygments-w">
</span><span class="pygments-gi">+</span><span class="pygments-w">
</span><span class="pygments-gi">+urlgrabber_find_proxy = urlgrabber.grabber.URLGrabberOptions.find_proxy</span><span class="pygments-w">
</span><span class="pygments-gi">+urlgrabber.grabber.URLGrabberOptions.find_proxy = find_proxy</span><span class="pygments-w">
</span><span class="pygments-gi">+</span><span class="pygments-w">
</span><span class="pygments-gi">+</span><span class="pygments-w">
</span>class ZyppoSync:<span class="pygments-w">
</span> """<span class="pygments-w">
</span> This class prepares a environment for running Zypper inside a dedicated reposync root<span class="pygments-w">
</span>
</pre>
<p>There is a <a class="reference external" href="https://github.com/rpm-software-management/urlgrabber/issues/33">Issue</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20220322220711/https://github.com/rpm-software-management/urlgrabber/issues/33">[1]</a>,
<a class="reference external" href="https://archive.today/2022.03.22-220733/https://github.com/rpm-software-management/urlgrabber/issues/33">[2]</a>)
in the urlgrabber repository, until that's fixed, it looks like that a
workaround in the Uyuni / reposync Codebase will be required.</p>
<p>I created a new <a class="reference external" href="https://github.com/uyuni-project/uyuni/pull/5051">Pull Request</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20220322220814/https://github.com/uyuni-project/uyuni/pull/5051">[1]</a>,
<a class="reference external" href="https://archive.today/2022.03.22-220809/https://github.com/uyuni-project/uyuni/pull/5051">[2]</a>)
in the Uyuni Project based on the above described fix, let's see if anyone comes
up with a more elegant solution or if the guys are happy with that one and agree to merge it.</p>
<p>Based on my tests, by syncing <em>openSUSE Leap 15.3</em>, <em>Oracle Linux 8</em>, <em>CentOS 7</em> and <em>Ubuntu 20.04</em> repositories,
it should finally resolve all, so far known, Issues related to reposync and HTTP Proxy.</p>
<p>And what had all this to do with a change of '<' to '>='?</p>
<p>In PR <a class="reference external" href="https://github.com/uyuni-project/uyuni/pull/4604">#4604</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20220322220815/https://github.com/uyuni-project/uyuni/pull/4604">[1]</a>,
<a class="reference external" href="https://archive.today/2022.03.22-220831/https://github.com/uyuni-project/uyuni/pull/4604">[2]</a>)
the version was bumped, changing <code>python3-urlgrabber < 4</code> to
<code>python3-urlgrabber >= 4</code> caused all that trouble and lot of issues
where syncing repositories behind a http proxy was just not possible anymore.</p>
Setup Uyuni Development Environment with focus on Java and IntelliJ2022-03-09T00:00:00+01:002022-05-18T00:00:00+02:00Dominik Wombachertag:dominik.wombacher.cc,2022-03-09:/posts/setup_uyuni_development_environment_with_focus_on_java_and_intellij.html<!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>Hacking Uyuni, either to troubleshoot and fix bugs or to contribute new features / improvements
is something I do since quite a while already, at least whenever I find some time ... <a class="read-more" href="/posts/setup_uyuni_development_environment_with_focus_on_java_and_intellij.html"> [read more]</a></p><!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>Hacking Uyuni, either to troubleshoot and fix bugs or to contribute new features / improvements
is something I do since quite a while already, at least whenever I find some time.
Getting started wasn't that easy, there are a lot of resources available but sometimes there are outdated,
too focused on SUSE employees instead community contributors or just didn't fully answered my questions.</p>
<p>So I want to share my experiences to Setup a Development Environment for Uyuni,
with focus on the Java Codebase, on a openSUSE Tumbleweed System by using sumaform and IntelliJ IDEA.</p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#resources" id="toc-entry-1">Resources</a></li>
<li><a class="reference internal" href="#sumaform" id="toc-entry-2">sumaform</a></li>
<li><a class="reference internal" href="#install-packages" id="toc-entry-3">Install Packages</a></li>
<li><a class="reference internal" href="#clone-git-repo-and-prepare-files-folders" id="toc-entry-4">Clone git repo and prepare files / folders</a></li>
<li><a class="reference internal" href="#configure-intellij-idea" id="toc-entry-5">Configure IntelliJ IDEA</a><ul>
<li><a class="reference internal" href="#enable-automatic-building" id="toc-entry-6">Enable automatic building</a></li>
<li><a class="reference internal" href="#configure-code-style" id="toc-entry-7">Configure Code Style</a></li>
<li><a class="reference internal" href="#remote-debugging" id="toc-entry-8">Remote Debugging</a></li>
<li><a class="reference internal" href="#ivy-integration" id="toc-entry-9">Ivy integration</a></li>
<li><a class="reference internal" href="#checkstyle-integration" id="toc-entry-10">CheckStyle integration</a></li>
<li><a class="reference internal" href="#avoid-checkstyle-violations" id="toc-entry-11">Avoid CheckStyle violations</a><ul>
<li><a class="reference internal" href="#enabling-automatic-import-completion" id="toc-entry-12">enabling automatic import completion</a></li>
<li><a class="reference internal" href="#disabling-star-imports" id="toc-entry-13">disabling "star imports"</a></li>
<li><a class="reference internal" href="#wrapping-and-braces" id="toc-entry-14">wrapping and braces</a></li>
</ul>
</li>
<li><a class="reference internal" href="#faster-deployments-via-manager-build-xml" id="toc-entry-15">Faster deployments via manager-build.xml</a></li>
<li><a class="reference internal" href="#configure-junit-tests" id="toc-entry-16">Configure JUnit tests</a></li>
</ul>
</li>
<li><a class="reference internal" href="#deploying-java-code-or-css" id="toc-entry-17">Deploying Java code or CSS</a></li>
<li><a class="reference internal" href="#contribute" id="toc-entry-18">Contribute</a></li>
</ul>
</div>
<hr class="docutils" />
<div class="section" id="resources">
<h2><a class="toc-backref" href="#toc-entry-1">Resources</a></h2>
<p>You can find a lot of information in the <a class="reference external" href="https://github.com/uyuni-project/uyuni/wiki/">Uyuni Wiki</a> and a
great <a class="reference external" href="http://bosdonnat.fr/slides/openSUSEAsiaSummit19/">Presentation</a>
(<a class="reference external" href="https://web.archive.org/web/20211001151412/http://bosdonnat.fr/slides/openSUSEAsiaSummit19/">Archive</a>,
<a class="reference external" href="https://github.com/cbosdo/openSUSEAsia19-uyuni-dev">Source</a>) from <a class="reference external" href="http://bosdonnat.fr">Cédric Bosdonnat</a>.</p>
</div>
<div class="section" id="sumaform">
<h2><a class="toc-backref" href="#toc-entry-2">sumaform</a></h2>
<p>See my Post <a class="reference external" href="https://dominik.wombacher.cc/posts/uyuni_test_environment_with_sumaform_on_local_libvirt_host_opensuse_tumbleweed.html">Uyuni Test Environment with sumaform on local libvirt host (openSUSE Tumbleweed)</a></p>
<p>There are <a class="reference external" href="https://github.com/uyuni-project/uyuni/wiki/Development-Environment-Alternative-Instructions">Alternative Instructions</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20220309214954/https://github.com/uyuni-project/uyuni/wiki/Development-Environment-Alternative-Instructions">[1]</a>,
<a class="reference external" href="https://archive.today/2022.03.09-214849/https://github.com/uyuni-project/uyuni/wiki/Development-Environment-Alternative-Instructions">[2]</a>)
available in case using sumaform isn't possible or not intended.</p>
</div>
<div class="section" id="install-packages">
<h2><a class="toc-backref" href="#toc-entry-3">Install Packages</a></h2>
<p>Add the <em>systemsmanagement:Uyuni:Utils</em> repository, especially for <em>obs-to-maven</em>, and install the necessary packages.</p>
<p>Manually:</p>
<pre class="code text literal-block">
sudo zypper addrepo obs://systemsmanagement:Uyuni:Utils systemsmanagement:uyuni:utils
sudo zypper in java-11-openjdk-devel openssh rsync apache-ivy ant ant-junit servletapi5 cpio obs-to-maven tito yarn
</pre>
<p>Ansible snippet:</p>
<pre class="code yaml literal-block">
<span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-nt">name</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">Import systemsmanagement:/Uyuni:/Utils RPM Key</span><span class="pygments-w">
</span><span class="pygments-nt">rpm_key</span><span class="pygments-p">:</span><span class="pygments-w">
</span><span class="pygments-nt">key</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">https://download.opensuse.org/repositories/systemsmanagement:/Uyuni:/Utils/openSUSE_Tumbleweed/repodata/repomd.xml.key</span><span class="pygments-w">
</span><span class="pygments-nt">state</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">present</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-nt">name</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">Add systemsmanagement:/Uyuni:/Utils RPM Repository</span><span class="pygments-w">
</span><span class="pygments-nt">community.general.zypper_repository</span><span class="pygments-p">:</span><span class="pygments-w">
</span><span class="pygments-nt">name</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">systemsmanagement_uyuni_utils</span><span class="pygments-w">
</span><span class="pygments-nt">description</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">Several utilities to develop, build or release Uyuni (openSUSE_Tumbleweed)</span><span class="pygments-w">
</span><span class="pygments-nt">repo</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">https://download.opensuse.org/repositories/systemsmanagement:/Uyuni:/Utils/openSUSE_Tumbleweed/</span><span class="pygments-w">
</span><span class="pygments-nt">priority</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">95</span><span class="pygments-w">
</span><span class="pygments-nt">state</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">present</span><span class="pygments-w">
</span><span class="pygments-nt">ignore_errors</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">true</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-nt">name</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">Package Installation (Uyuni Development)</span><span class="pygments-w">
</span><span class="pygments-nt">community.general.zypper</span><span class="pygments-p">:</span><span class="pygments-w">
</span><span class="pygments-nt">name</span><span class="pygments-p">:</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">java-11-openjdk-devel</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">openssh</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">rsync</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">apache-ivy</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">ant</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">ant-junit</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">servletapi5</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">obs-to-maven</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">tito</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">yarn</span><span class="pygments-w">
</span><span class="pygments-nt">allow_vendor_change</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">true</span><span class="pygments-w">
</span><span class="pygments-nt">force_resolution</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">true</span><span class="pygments-w">
</span><span class="pygments-nt">force</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">true</span><span class="pygments-w">
</span><span class="pygments-nt">state</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">latest</span><span class="pygments-w">
</span>
</pre>
</div>
<div class="section" id="clone-git-repo-and-prepare-files-folders">
<h2><a class="toc-backref" href="#toc-entry-4">Clone git repo and prepare files / folders</a></h2>
<p>Fork the <a class="reference external" href="https://github.com/uyuni-project/uyuni">Uyuni Repository</a> and clone it.
I will use the placeholder <code><path_to_uyuni></code> a lot, which refers to the local path of your cloned uyuni fork.</p>
<p>Let's start with some files and folders which are required at a later point for unittest and deployment.</p>
<p>Create the folders <em>/usr/share/rhn/config-defaults</em>, <em>/var/log/rhn</em> and <em>/srv/susemanager</em>, owner and group should match with your user account.</p>
<p>Ansible snippet:</p>
<pre class="code yaml literal-block">
<span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-nt">name</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">Create Folders for Uyuni Development Unittests and Build</span><span class="pygments-w">
</span><span class="pygments-nt">file</span><span class="pygments-p">:</span><span class="pygments-w">
</span><span class="pygments-nt">path</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-s">"{{</span><span class="pygments-nv"> </span><span class="pygments-s">item</span><span class="pygments-nv"> </span><span class="pygments-s">}}"</span><span class="pygments-w">
</span><span class="pygments-nt">state</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">directory</span><span class="pygments-w">
</span><span class="pygments-nt">owner</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">wombelix</span><span class="pygments-w">
</span><span class="pygments-nt">group</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">users</span><span class="pygments-w">
</span><span class="pygments-nt">loop</span><span class="pygments-p">:</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">/usr/share/rhn/config-defaults</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">/var/log/rhn</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">/srv/susemanager</span><span class="pygments-w">
</span>
</pre>
<p>Create a <em>rhn.conf</em> used by JUnit:</p>
<pre class="code text literal-block">
cp <path_to_uyuni_root>/java/buildconf/test/rhn.conf.postgresql-example <path_to_uyuni_root>/java/buildconf/test/rhn.conf
</pre>
<p>Get / update java libraries and dependencies:</p>
<pre class="code text literal-block">
cd <path_to_uyuni_root>/java
ant -f manager-build.xml ivy
</pre>
<p>Compile branding jar for the first time:</p>
<pre class="code text literal-block">
cd <path_to_uyuni_root>/java
ant -f manager-build.xml refresh-branding-jar
</pre>
</div>
<div class="section" id="configure-intellij-idea">
<h2><a class="toc-backref" href="#toc-entry-5">Configure IntelliJ IDEA</a></h2>
<p>I will focus on IntelliJ IDEA but can also use
<a class="reference external" href="https://github.com/uyuni-project/uyuni/wiki/Eclipse-specific-development-instructions">Eclipse</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20220309215457/https://github.com/uyuni-project/uyuni/wiki/Eclipse-specific-development-instructions">[1]</a>,
<a class="reference external" href="https://archive.today/2022.03.09-215319/https://github.com/uyuni-project/uyuni/wiki/Eclipse-specific-development-instructions">[2]</a>)
or <a class="reference external" href="https://github.com/uyuni-project/uyuni/wiki/VS-Code-specific-development-instructions">VSCode</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20220309215449/https://github.com/uyuni-project/uyuni/wiki/VS-Code-specific-development-instructions">[1]</a>,
<a class="reference external" href="https://archive.today/2022.03.09-215515/https://github.com/uyuni-project/uyuni/wiki/VS-Code-specific-development-instructions">[2]</a>), if you want.</p>
<p>The following Steps are heavily based on
<a class="reference external" href="https://github.com/uyuni-project/uyuni/wiki/IntelliJ-IDEA-specific-development-instructions">IntelliJ IDEA specific development instructions</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20220309215526/https://github.com/uyuni-project/uyuni/wiki/IntelliJ-IDEA-specific-development-instructions">[1]</a>,
<a class="reference external" href="https://archive.today/2022.03.09-215715/https://github.com/uyuni-project/uyuni/wiki/IntelliJ-IDEA-specific-development-instructions">[2]</a>)
and <a class="reference external" href="https://github.com/uyuni-project/uyuni/wiki/Java-Development-Environment">Java Development Environment</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20220309215601/https://github.com/uyuni-project/uyuni/wiki/Java-Development-Environment">[1]</a>,
<a class="reference external" href="https://archive.today/2022.03.09-215915/https://github.com/uyuni-project/uyuni/wiki/Java-Development-Environment">[2]</a>)
with some adjustments, additional information and tested on IntelliJ IDEA Ultimate 2022.1 EAP.</p>
<p>The JetBrain Toolbox is in my opinion the easiest way to install and update IntelliJ.
If you installed it manually, please check the documentation where / how you can configure the <em>vmoptions</em>.</p>
<p><strong>Toolbox App > three dots next to "IntelliJ IDEA" > Settings > Configuration > Java Virtual Machine options "Edit..."</strong></p>
<blockquote>
Replace <code>-Xmx2048m</code> with <code>-Xmx4G</code></blockquote>
<p>Source:
<a class="reference external" href="https://intellij-support.jetbrains.com/hc/en-us/articles/206544869-Configuring-JVM-options-and-platform-properties">https://intellij-support.jetbrains.com</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20211213213449/https://intellij-support.jetbrains.com/hc/en-us/articles/206544869-Configuring-JVM-options-and-platform-properties">[1]</a>,
<a class="reference external" href="https://archive.today/2022.03.09-220705/https://intellij-support.jetbrains.com/hc/en-us/articles/206544869-Configuring-JVM-options-and-platform-properties">[2]</a>)</p>
<p>Afterwards start IntelliJ IDEA to proceed with the actual configuration.</p>
<p><strong>File > New > Project from existing Source</strong></p>
<blockquote>
<div class="line-block">
<div class="line">Select <path_to_uyuni_root></div>
<div class="line">Create Project from existing Source</div>
<div class="line">Accept the project format defaults</div>
<div class="line">Also accept auto discovered source directories</div>
<div class="line">From the Libraries list, uncheck all items</div>
<div class="line">From the Modules list, only check the items corresponding to the following directories:</div>
</div>
<blockquote>
<div class="line-block">
<div class="line"><code>uyuni/java/code</code> (change the name to code)</div>
<div class="line"><code>uyuni/branding/java/code</code> (change the name to branding)</div>
</div>
</blockquote>
<div class="line-block">
<div class="line">Select a Java 11 runtime e.g. the previously installed openJDK</div>
<div class="line">Ultimate Edition: Unselect eventually found frameworks</div>
</div>
</blockquote>
<div class="section" id="enable-automatic-building">
<h3><a class="toc-backref" href="#toc-entry-6">Enable automatic building</a></h3>
<p><strong>File > Settings... > Build, Execution, Deployment > Compiler and select "Build project automatically"</strong></p>
</div>
<div class="section" id="configure-code-style">
<h3><a class="toc-backref" href="#toc-entry-7">Configure Code Style</a></h3>
<p><strong>File > Settings... > Editor > Code Style > Java > Imports</strong></p>
<blockquote>
Click on the cog / settings icon next to the "Scheme: Default" field at the top, then "Import Scheme", "IntelliJ IDEA code style XML" and select the <code><path_to_uyuni_root>/java/conf/intellij-codestyle.xml</code> file.</blockquote>
</div>
<div class="section" id="remote-debugging">
<h3><a class="toc-backref" href="#toc-entry-8">Remote Debugging</a></h3>
<p><strong>Run > Edit Configurations... > + sign</strong></p>
<blockquote>
<div class="line-block">
<div class="line">Accept all defaults, except from Host and Port, configure them based on the service you want to debug.</div>
<div class="line">8000 for Tomcat, 8001 for Taskomatic, 8002 for Search (defaults if deployed with sumaform)</div>
</div>
</blockquote>
<p>Further reading: <a class="reference external" href="https://www.jetbrains.com/help/idea/debugging-code.html#general-procedure">IntelliJ IDEA Debugging Guide</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20220218091806/https://www.jetbrains.com/help/idea/debugging-code.html">[1]</a>,
<a class="reference external" href="https://archive.today/2022.03.09-220232/https://www.jetbrains.com/help/idea/debugging-code.html%23general-procedure">[2]</a>)</p>
</div>
<div class="section" id="ivy-integration">
<h3><a class="toc-backref" href="#toc-entry-9">Ivy integration</a></h3>
<p><strong>File > Settings... > Plugins > Browse repositories... > search for "IvyIDEA" > Install the Ivy plugin</strong></p>
<blockquote>
Restart IntelliJ IDEA (if asked) to activate the plugin</blockquote>
<p><strong>File > Project Structure... > Modules -> right click on code > + sign > click on "ivyIDEA" to enable the plugin for the project</strong></p>
<blockquote>
<div class="line-block">
<div class="line">Click on folder icon at the right side to select the Ivy configuration path: <code><path_to_uyuni_root>/java/buildconf/ivy/ivy-suse.xml</code></div>
<div class="line">Check "Use module specific ivy settings"</div>
<div class="line">Click on folder icon at the right side to select the Ivy configuration path: <code><path_to_uyuni_root>/java/buildconf/ivy/ivyconf.xml</code></div>
</div>
</blockquote>
<p><strong>Tools > IvyIDEA > "Resolve for all modules" to get updated Ivy dependencies</strong></p>
<p><em>Note: When switching branches that have different dependencies (notably, major versions) you have to:</em></p>
<blockquote>
<div class="line-block">
<div class="line">Tools > IvyIDEA > Remove all resolved libraries</div>
<div class="line">Tools > IvyIDEA > Resolve for all modules</div>
<div class="line">Build > Rebuild project</div>
</div>
</blockquote>
</div>
<div class="section" id="checkstyle-integration">
<h3><a class="toc-backref" href="#toc-entry-10">CheckStyle integration</a></h3>
<p><strong>File > Settings... > Plugins > Browse repositories... > search for "CheckStyle" -> Install the CheckStyle IDEA plugin</strong></p>
<blockquote>
Restart IntelliJ IDEA to activate the plugin</blockquote>
<p><strong>File > Settings... > Tools > Checkstyle</strong></p>
<blockquote>
<div class="line-block">
<div class="line">Change the Checkstyle version to the one in <code><path_to_uyuni_root>/java/buildconf/ivy/ivy-suse.xml</code> (currently 8.30)</div>
<div class="line">Click on the + sign next to Configuration File</div>
<div class="line"><br /></div>
<div class="line">Description: Uyuni</div>
<div class="line">Check "Use a local Checkstyle file", select <code><path_to_uyuni_root>/java/buildconf/checkstyle.xml</code></div>
<div class="line">Check "Store relative to project location", click on Next</div>
</div>
<p>Set the following values for properties:</p>
<pre class="code text literal-block">
checkstyle.cache.file: <path_to_uyuni_root>/java/build/checkstyle.cache.src
checkstyle.header.file: <path_to_uyuni_root>/java/buildconf/LICENSE.txt
checkstyle.suppressions.file: <path_to_uyuni_root>/java/buildconf/checkstyle-suppressions.xml
javadoc.lazy: false
javadoc.method.scope: public
javadoc.type.scope: package
javadoc.var.scope: package
</pre>
<p>Click on Finish, mark the file as Active, click on Apply and leave the Settings.</p>
</blockquote>
<p>Afterwards a new mini-tab will appear at the bottom named "CheckStyle".</p>
</div>
<div class="section" id="avoid-checkstyle-violations">
<h3><a class="toc-backref" href="#toc-entry-11">Avoid CheckStyle violations</a></h3>
<p>These are recommended settings, which might already be set as default, that help respecting style guidelines independent of the CheckStyle plugin:</p>
<div class="section" id="enabling-automatic-import-completion">
<h4><a class="toc-backref" href="#toc-entry-12">enabling automatic import completion</a></h4>
<p><strong>File > Settings... > Editor > General > Auto Import</strong></p>
<blockquote>
<div class="line-block">
<div class="line">Set "Insert imports on paste" to "Always"</div>
<div class="line">Select "Add unambiguous imports on the fly" and "Optimize imports on the fly" in the Java Section.</div>
</div>
</blockquote>
</div>
<div class="section" id="disabling-star-imports">
<h4><a class="toc-backref" href="#toc-entry-13">disabling "star imports"</a></h4>
<p><strong>File > Settings... > Editor > Code Style > Java > Imports</strong></p>
<blockquote>
<div class="line-block">
<div class="line">Class count to use import with '*' > 999</div>
<div class="line">Names count to use static import with '*' > 999</div>
</div>
</blockquote>
</div>
<div class="section" id="wrapping-and-braces">
<h4><a class="toc-backref" href="#toc-entry-14">wrapping and braces</a></h4>
<p><strong>File > Settings... > Editor > Code Style > Java > Wrapping and Braces</strong></p>
<blockquote>
<div class="line-block">
<div class="line">Under 'try' statement check 'catch' on new line and 'finally' on new line</div>
<div class="line">Under 'if' statement check 'else' on new line</div>
</div>
</blockquote>
</div>
</div>
<div class="section" id="faster-deployments-via-manager-build-xml">
<h3><a class="toc-backref" href="#toc-entry-15">Faster deployments via manager-build.xml</a></h3>
<p>Change the output directory to enable quick <em>manager-build.xml</em> deploys:</p>
<p><strong>File -> Project Structure... -> Modules -> code -> Paths</strong></p>
<blockquote>
<div class="line-block">
<div class="line-block">
<div class="line">Click on "Use module compile output path" and set:</div>
</div>
<div class="line">"Output path" to <code><path_to_uyuni_root>/java/build/classes</code></div>
<div class="line">"Test output path" to <code><path_to_uyuni_root>/java/build/tests</code></div>
</div>
</blockquote>
<p>Enable usage of precompiled files by adding <code>precompiled=true</code> to <code><path_to_uyuni_root>/java/buildconf/manager-developer-build.properties</code>,
if the file not exist, copy <code><path_to_uyuni_root>/java/buildconf/manager-developer-build.properties.example</code>, rename and edit the new file.</p>
</div>
<div class="section" id="configure-junit-tests">
<h3><a class="toc-backref" href="#toc-entry-16">Configure JUnit tests</a></h3>
<p><strong>File > Project Structure... > Modules > code > Dependencies</strong></p>
<blockquote>
Click the + sign > Module dependency > branding > OK to include branding classes and files in the build</blockquote>
<p><strong>File > Project Structure... -> Modules -> code</strong></p>
<blockquote>
Mark the directory webapp as Resources</blockquote>
<p><strong>Run > Edit Configurations... > + sign > JUnit</strong></p>
<blockquote>
<div class="line-block">
<div class="line">Name: JUnit</div>
<div class="line">Run on: Local machine</div>
<div class="line">Build and run:</div>
</div>
<pre class="code text literal-block">
JRE: Java 11
-cp: -cp code
-ea: -ea -Drhn.config.dir=$MODULE_DIR$/../buildconf/test/ -Dlog4j.threshold=debug
</pre>
<p>Select "All in package" to execute all available Unittests, if you want to limit to a specific class or package adjust the dropdown and filepath accordingly</p>
</blockquote>
<p>To start the JUnit tests, click on <strong>Run > Run</strong>.</p>
<p><em>Important: Start the test database docker container first, otherwise almost all tests will just fail</em></p>
<pre class="code text literal-block">
cd <path_to_uyuni_root>/java
make -f Makefile.docker dockerrun_pg
</pre>
</div>
</div>
<div class="section" id="deploying-java-code-or-css">
<h2><a class="toc-backref" href="#toc-entry-17">Deploying Java code or CSS</a></h2>
<p>If you created a terraform based VM with sumaform, you can easily deploy code:</p>
<ol class="arabic simple">
<li>Run checkstyle</li>
</ol>
<pre class="code text literal-block">
cd <path_to_uyuni_root>/java
ant -f manager-build.xml checkstyle
</pre>
<ol class="arabic simple" start="2">
<li>Deploy</li>
</ol>
<pre class="code text literal-block">
cd <path_to_uyuni_root>/java
ant -f manager-build.xml refresh-branding-jar deploy -Ddeploy.host=uyuni-server.tf.local restart-tomcat restart-taskomatic
</pre>
<p>You can configure the <em>deploy.host</em> in <code><path_to_uyuni_root>/java/buildconf/manager-developer-build.properties</code>
and omit the command line parameter.</p>
</div>
<div class="section" id="contribute">
<h2><a class="toc-backref" href="#toc-entry-18">Contribute</a></h2>
<p><a class="reference external" href="https://www.uyuni-project.org">Uyuni</a> exist since July 2018, the initial release (4.0.0) was based on SUSE Manager 3.2, since
then Uyuni is the Upstream Project of SUSE Manager. SUSE Manager is based on Spacewalk, which was sponsored by Red Hat and
abandoned, so SUSE decided to start a own <a class="reference external" href="https://news.opensuse.org/2018/05/26/uyuni-forking-spacewalk-with-salt-and-containers/">Fork</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20210418110047/https://news.opensuse.org/2018/05/26/uyuni-forking-spacewalk-with-salt-and-containers/">[1]</a>,
<a class="reference external" href="https://archive.today/2022.03.09-211509/https://news.opensuse.org/2018/05/26/uyuni-forking-spacewalk-with-salt-and-containers/">[2]</a>), Uyuni was born.</p>
<p>Still a lot of development comes from SUSE but there is a growing <a class="reference external" href="https://www.uyuni-project.org/pages/contact.html">Community</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20220309221253/https://www.uyuni-project.org/pages/contact.html">[1]</a>,
<a class="reference external" href="https://archive.today/2022.03.09-221014/https://www.uyuni-project.org/pages/contact.html">[2]</a>)
with more and more independent Contributions.</p>
<p>If your dev environment is ready and you want to jump in, but didn't contributed to the Uyuni Project before,
I suggest you take a look at some <a class="reference external" href="https://github.com/uyuni-project/uyuni/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22">Good first Issues</a>.</p>
</div>
Uyuni Test Environment with sumaform on local libvirt host (openSUSE Tumbleweed)2022-03-08T00:00:00+01:002022-03-08T00:00:00+01:00Dominik Wombachertag:dominik.wombacher.cc,2022-03-08:/posts/uyuni_test_environment_with_sumaform_on_local_libvirt_host_opensuse_tumbleweed.html<!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>A convenient way to quickly setup a local Uyuni Instance inclusive Clients, either for Development or Testing, is sumaform.
It supports different backends and provides a ton of options, check ... <a class="read-more" href="/posts/uyuni_test_environment_with_sumaform_on_local_libvirt_host_opensuse_tumbleweed.html"> [read more]</a></p><!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>A convenient way to quickly setup a local Uyuni Instance inclusive Clients, either for Development or Testing, is sumaform.
It supports different backends and provides a ton of options, check it out: <a class="reference external" href="https://github.com/uyuni-project/sumaform">https://github.com/uyuni-project/sumaform</a></p>
<p>I just want to run a Uyuni Server and a few Clients (openSUSE, EL, Debian) on my Laptop so I can verify reported bugs,
try some configs as well as deploy and test changes during development, without investing much time.</p>
<p>Following a overview of the, in my case, relevant steps, examples of my config and some Ansible snippets.</p>
<p><strong>Setup</strong></p>
<pre class="code text literal-block">
sudo zypper addrepo http://download.opensuse.org/repositories/systemsmanagement:/sumaform/openSUSE_Tumbleweed/systemsmanagement:sumaform.repo
sudo zypper install git-core
sudo zypper install --from systemsmanagement_sumaform terraform terraform-provider-libvirt
git clone https://github.com/uyuni-project/sumaform.git
</pre>
<p>Follow the <em>First-time configuration (libvirt)</em> instructions in the
<a class="reference external" href="https://github.com/uyuni-project/sumaform/blob/2082e344b9cdde5c3befb11fc358d80eb50de346/backend_modules/libvirt/README.md">README</a>,
but use the uyuni example file instead: <code>copy main.tf.uyuni.example to main.tf</code></p>
<p><strong>Config & Deployment</strong></p>
<pre class="code text literal-block">
vim main.tf
terraform init
terraform validate
terraform apply
</pre>
<p><strong>My terraform main.cf based on the uyuni example file</strong></p>
<pre class="code shell literal-block">
terraform<span class="pygments-w"> </span><span class="pygments-o">{</span><span class="pygments-w">
</span><span class="pygments-nv">required_version</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-s2">"1.0.10"</span><span class="pygments-w">
</span>required_providers<span class="pygments-w"> </span><span class="pygments-o">{</span><span class="pygments-w">
</span><span class="pygments-nv">libvirt</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-o">{</span><span class="pygments-w">
</span><span class="pygments-nv">version</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-s2">"0.6.3"</span><span class="pygments-w">
</span><span class="pygments-o">}</span><span class="pygments-w">
</span><span class="pygments-o">}</span><span class="pygments-w">
</span><span class="pygments-o">}</span><span class="pygments-w">
</span>provider<span class="pygments-w"> </span><span class="pygments-s2">"libvirt"</span><span class="pygments-w"> </span><span class="pygments-o">{</span><span class="pygments-w">
</span><span class="pygments-o">}</span><span class="pygments-w">
</span>module<span class="pygments-w"> </span><span class="pygments-s2">"base"</span><span class="pygments-w"> </span><span class="pygments-o">{</span><span class="pygments-w">
</span><span class="pygments-nv">cc_username</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-s2">""</span><span class="pygments-w">
</span><span class="pygments-nv">cc_password</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-s2">""</span><span class="pygments-w">
</span><span class="pygments-nv">images</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-o">[</span><span class="pygments-s2">"centos7"</span>,<span class="pygments-w"> </span><span class="pygments-s2">"opensuse153o"</span>,<span class="pygments-w"> </span><span class="pygments-s2">"ubuntu1804"</span><span class="pygments-o">]</span><span class="pygments-w">
</span><span class="pygments-o">}</span><span class="pygments-w">
</span>module<span class="pygments-w"> </span><span class="pygments-s2">"server"</span><span class="pygments-w"> </span><span class="pygments-o">{</span><span class="pygments-w">
</span><span class="pygments-nv">base_configuration</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span>module.base.configuration<span class="pygments-w">
</span><span class="pygments-nv">product_version</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-s2">"uyuni-master"</span><span class="pygments-w">
</span><span class="pygments-nv">name</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-s2">"server"</span><span class="pygments-w">
</span><span class="pygments-nv">image</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-s2">"opensuse153o"</span><span class="pygments-w">
</span><span class="pygments-nv">use_os_released_updates</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-nb">true</span><span class="pygments-w">
</span><span class="pygments-nv">create_first_user</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-nb">false</span><span class="pygments-w">
</span><span class="pygments-nv">auto_accept</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-nb">false</span><span class="pygments-w">
</span><span class="pygments-nv">skip_changelog_import</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-nb">false</span><span class="pygments-w">
</span><span class="pygments-nv">mgr_sync_autologin</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-nb">false</span><span class="pygments-w">
</span><span class="pygments-nv">create_sample_channel</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-nb">false</span><span class="pygments-w">
</span><span class="pygments-nv">create_sample_activation_key</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-nb">false</span><span class="pygments-w">
</span><span class="pygments-nv">create_sample_bootstrap_script</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-nb">false</span><span class="pygments-w">
</span><span class="pygments-nv">publish_private_ssl_key</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-nb">false</span><span class="pygments-w">
</span><span class="pygments-nv">java_debugging</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-nb">true</span><span class="pygments-w">
</span><span class="pygments-nv">provider_settings</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-o">{</span><span class="pygments-w">
</span><span class="pygments-nv">memory</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-m">8192</span><span class="pygments-w">
</span><span class="pygments-nv">vcpu</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-m">4</span><span class="pygments-w">
</span><span class="pygments-o">}</span><span class="pygments-w">
</span><span class="pygments-o">}</span><span class="pygments-w">
</span>module<span class="pygments-w"> </span><span class="pygments-s2">"redhat-minion"</span><span class="pygments-w"> </span><span class="pygments-o">{</span><span class="pygments-w">
</span><span class="pygments-nv">base_configuration</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span>module.base.configuration<span class="pygments-w">
</span><span class="pygments-nv">product_version</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-s2">"uyuni-master"</span><span class="pygments-w">
</span><span class="pygments-nv">name</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-s2">"minion-centos7"</span><span class="pygments-w">
</span><span class="pygments-nv">image</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-s2">"centos7"</span><span class="pygments-w">
</span><span class="pygments-nv">server_configuration</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span>module.server.configuration<span class="pygments-w">
</span><span class="pygments-nv">provider_settings</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-o">{</span><span class="pygments-w">
</span><span class="pygments-nv">memory</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-m">1024</span><span class="pygments-w">
</span><span class="pygments-o">}</span><span class="pygments-w">
</span><span class="pygments-nv">auto_connect_to_master</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-nb">true</span><span class="pygments-w">
</span><span class="pygments-o">}</span><span class="pygments-w">
</span>module<span class="pygments-w"> </span><span class="pygments-s2">"debian-minion"</span><span class="pygments-w"> </span><span class="pygments-o">{</span><span class="pygments-w">
</span><span class="pygments-nv">base_configuration</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span>module.base.configuration<span class="pygments-w">
</span><span class="pygments-nv">product_version</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-s2">"uyuni-master"</span><span class="pygments-w">
</span><span class="pygments-nv">name</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-s2">"minion-ubuntu1804"</span><span class="pygments-w">
</span><span class="pygments-nv">image</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-s2">"ubuntu1804"</span><span class="pygments-w">
</span><span class="pygments-nv">server_configuration</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span>module.server.configuration<span class="pygments-w">
</span><span class="pygments-nv">provider_settings</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-o">{</span><span class="pygments-w">
</span><span class="pygments-nv">memory</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-m">1024</span><span class="pygments-w">
</span><span class="pygments-o">}</span><span class="pygments-w">
</span><span class="pygments-nv">auto_connect_to_master</span><span class="pygments-w"> </span><span class="pygments-o">=</span><span class="pygments-w"> </span><span class="pygments-nb">true</span><span class="pygments-w">
</span><span class="pygments-o">}</span><span class="pygments-w">
</span>
</pre>
<p><strong>Ansible Snippets for the Setup steps</strong></p>
<pre class="code yaml literal-block">
<span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-nt">name</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">Import systemsmanagement:/sumaform RPM Key</span><span class="pygments-w">
</span><span class="pygments-nt">rpm_key</span><span class="pygments-p">:</span><span class="pygments-w">
</span><span class="pygments-nt">key</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">https://download.opensuse.org/repositories/systemsmanagement:/sumaform/openSUSE_Tumbleweed/repodata/repomd.xml.key</span><span class="pygments-w">
</span><span class="pygments-nt">state</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">present</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-nt">name</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">Add systemsmanagement:/sumaform RPM Repository</span><span class="pygments-w">
</span><span class="pygments-nt">community.general.zypper_repository</span><span class="pygments-p">:</span><span class="pygments-w">
</span><span class="pygments-nt">name</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">systemsmanagement_sumaform</span><span class="pygments-w">
</span><span class="pygments-nt">description</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">Using Terraform to create a SUSE Manager test environment (openSUSE_Tumbleweed)</span><span class="pygments-w">
</span><span class="pygments-nt">repo</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">https://download.opensuse.org/repositories/systemsmanagement:/sumaform/openSUSE_Tumbleweed/</span><span class="pygments-w">
</span><span class="pygments-nt">priority</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">90</span><span class="pygments-w">
</span><span class="pygments-nt">state</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">present</span><span class="pygments-w">
</span><span class="pygments-nt">ignore_errors</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">true</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-nt">name</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">Package Installation (Uyuni Development - sumaform)</span><span class="pygments-w">
</span><span class="pygments-nt">community.general.zypper</span><span class="pygments-p">:</span><span class="pygments-w">
</span><span class="pygments-nt">name</span><span class="pygments-p">:</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">terraform</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">terraform-provider-libvirt</span><span class="pygments-w">
</span><span class="pygments-p-Indicator">-</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">git-core</span><span class="pygments-w">
</span><span class="pygments-nt">allow_vendor_change</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">true</span><span class="pygments-w">
</span><span class="pygments-nt">force_resolution</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">true</span><span class="pygments-w">
</span><span class="pygments-nt">force</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">true</span><span class="pygments-w">
</span><span class="pygments-nt">state</span><span class="pygments-p">:</span><span class="pygments-w"> </span><span class="pygments-l-Scalar-Plain">latest</span><span class="pygments-w">
</span>
</pre>
SUSE Manager / Uyuni - Upcoming feature: Salt Bundle (venv-salt-minion)2021-09-11T00:00:00+02:002021-09-11T00:00:00+02:00Dominik Wombachertag:dominik.wombacher.cc,2021-09-11:/posts/suse-manager-uyuni-upcoming-feature-salt-bundle-venv-salt-minion.html<!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>I want to share what I already could find about it, how it seem to work, it's going to be implemented and what issues / challenges it's going to address / resolve ... <a class="read-more" href="/posts/suse-manager-uyuni-upcoming-feature-salt-bundle-venv-salt-minion.html"> [read more]</a></p><!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>I want to share what I already could find about it, how it seem to work, it's going to be implemented and what issues / challenges it's going to address / resolve.</p>
<div class="section" id="background">
<h2>Background</h2>
<p>Salt is more or less the heart of SUSE Manager / Uyuni, handling all configuration and communication with the registered systems and replaced the Traditional Client, which is still supported and around but new features only are developed for Salt.</p>
<p>That said, Salt has it's strength compared to Solutions like Ansible in the Master <> Minion Architecture, where Salt-Minions listening on a zeroMQ Bus for Messages/Actions send by the Master.</p>
<p>So compared to pure SSH connections, that's very fast and scales pretty well. But it requires an installed Salt-Minion on the Client which need to be connected to the SUSE Manager.</p>
<p>Let's assume you already use Salt somehow in your Environment and all your Server are connected to a Salt Master already, which is not SUSE Manager / Uyuni, then you can only use <em>SSH-Push</em> (Salt-SSH) to register them to SUMA / Uyuni.</p>
<p>So far it's not possible to have multiple Minions running on a Client connected to different Salt-Master, at least not in combination with SUSE Manager / Uyuni.</p>
<p>At work there are roughly 200 Server connected via SSH-Push because we can't change the existing Salt-Minion Setup, which leads to lot of issues. Even though SUSE is really committed to help, as stated earlier, SSH-Push just doesn't scale well...</p>
</div>
<div class="section" id="future">
<h2>Future?</h2>
<p>There is a new feature on the horizon, which wasn't really communicated our announced yet: <strong>Salt Bundle aka venv-salt-minion</strong></p>
<p>SUSE describes it as <em>"Virtual environment jail for Salt"</em> and <em>"salt-minion in a bundled package"</em>.</p>
<p>So it's a package which contains a Salt-Minion including all dependencies in a own Python Virtual Environment and therefore doesn't affect any Salt Package that might already be installed on a System.</p>
<p>It's still in active development and my opinion is, that it will probably not officially arrive as stable in SUSE Manager before Version 4.3 (Summer 2022).</p>
</div>
<div class="section" id="implementation">
<h2>Implementation</h2>
<p>There are two parts:</p>
<blockquote>
<ul class="simple">
<li>The actual venv-salt-minion package, which provides a Salt-Minion that could be connected to most likely every Salt-Master and doesn't necessary require Uyuni or SUSE Manager</li>
<li>The Uyuni / SUSE Manager specific changes, mostly related to Salt States / Formulas as well as mgr_bootstrap components.</li>
</ul>
</blockquote>
<div class="section" id="package-on-obs">
<h3>Package on OBS</h3>
<p>Main Project: <a class="reference external" href="https://build.opensuse.org/package/show/systemsmanagement:saltstack:bundle/venv-salt-minion">https://build.opensuse.org/package/show/systemsmanagement:saltstack:bundle/venv-salt-minion</a></p>
<p>Results of pre-build Packages for various Distributions: <a class="reference external" href="https://build.opensuse.org/search?search_text=systemsmanagement%3Asaltstack%3Abundle">https://build.opensuse.org/search?search_text=systemsmanagement%3Asaltstack%3Abundle</a></p>
<p>Almost the whole Implementation is handled in the spec file, it takes all dependencies, creates a venv, prepares configs, systemd unit files and build a self containing rpm or deb package: <a class="reference external" href="https://build.opensuse.org/package/view_file/systemsmanagement:saltstack:bundle/venv-salt-minion/venv-salt-minion.spec">https://build.opensuse.org/package/view_file/systemsmanagement:saltstack:bundle/venv-salt-minion/venv-salt-minion.spec</a></p>
</div>
<div class="section" id="uyuni-suse-manager">
<h3>Uyuni / SUSE Manager</h3>
<p>Based on Issues and Pull Requests from the Uyuni Project (<a class="reference external" href="https://github.com/uyuni-project/uyuni">https://github.com/uyuni-project/uyuni</a>) Development is at least ongoing and some progress visible in public since March 2021.</p>
<p>Related PRs:</p>
<blockquote>
<ul class="simple">
<li><a class="reference external" href="https://github.com/uyuni-project/uyuni/pull/3645">https://github.com/uyuni-project/uyuni/pull/3645</a></li>
<li><a class="reference external" href="https://github.com/uyuni-project/uyuni/pull/3895">https://github.com/uyuni-project/uyuni/pull/3895</a></li>
<li><a class="reference external" href="https://github.com/uyuni-project/uyuni/pull/4065">https://github.com/uyuni-project/uyuni/pull/4065</a></li>
</ul>
</blockquote>
<p>Based on comments in the Source (<a class="reference external" href="https://github.com/uyuni-project/uyuni/pull/3895/files">https://github.com/uyuni-project/uyuni/pull/3895/files</a>) it looks like that, sooner or later, venv-salt-minion might be the preferred way to bootstrap a new System with Salt-Minion.</p>
<p>The adjustments in the Salt States are related to identify the correct name (either "salt-minion" or "venv-salt-minion") as well as the paths to binaries and configs because, obviously, they differ depending if package salt-minion or venv-salt-minion was installed.</p>
<p>In Uyuni <em>venv-salt-minion</em> is already available in a early testing stage for a few Distributions and the overall approach looks very promising.</p>
</div>
</div>
SUSE Manager / Uyuni - Database Backup with "smdba" fails on symlink2021-08-31T00:00:00+02:002021-08-31T00:00:00+02:00Dominik Wombachertag:dominik.wombacher.cc,2021-08-31:/posts/suse-manager-uyuni-database-backup-with-smdba-fails-on-symlink.html<!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>I performed a Upgrade of our SUSE Manager Instance at work to Version 4.2 and in parallel adjusted the disk layout a bit.</p>
<p>The exact details about all the ... <a class="read-more" href="/posts/suse-manager-uyuni-database-backup-with-smdba-fails-on-symlink.html"> [read more]</a></p><!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>I performed a Upgrade of our SUSE Manager Instance at work to Version 4.2 and in parallel adjusted the disk layout a bit.</p>
<p>The exact details about all the changes are not that interesting, more the fact which issue I faced after changing <em>/var/spacewalk/db-backup</em> to be a symlink into a sub-folder of a new mountpoint.</p>
<p>Backups are created and handled by the smdba tool, which performs an Owner and Permission check as soon a Backup was started.
The path is defined by the argument "--backup-dir", default as mentioned in the official docs is <em>/var/spacewalk/db-backup</em>, but as of today it doesn't follow symlinks.</p>
<p>So what happens: It will check the owner and permissions of the symlink instead the target folder.
Due to the limitations that chmod can't be performed on symlinks, it stays 777, smdba will always fail when comparing with <em>/var/lib/pgsql/data</em>.</p>
<p>To solve this issue and make smdba symlink aware, some small adjustments on the code of <em>/usr/lib/python3.6/site-packages/smdba/postgresqlgate.py</em> are required.</p>
<p>I created a <a class="reference external" href="https://github.com/SUSE/smdba/issues/51">GitHub Issue</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20210928140221/https://github.com/SUSE/smdba/issues/51">[1]</a>,
<a class="reference external" href="https://archive.today/2021.09.28-140140/https://github.com/SUSE/smdba/issues/51">[2]</a>)
to report my findings and discuss a solution.</p>
<p>Based on the feedback and suggestions from Victor and Michael, I created a <a class="reference external" href="https://github.com/SUSE/smdba/pull/52">Pull Request</a> to get the fix hopefully included in a future release :)</p>
<pre class="code diff literal-block">
<span class="pygments-gh">diff --git a/src/smdba/postgresqlgate.py b/src/smdba/postgresqlgate.py</span><span class="pygments-w">
</span><span class="pygments-gh">index 5bcb86e..e28b8f2 100644</span><span class="pygments-w">
</span><span class="pygments-gd">--- a/src/smdba/postgresqlgate.py</span><span class="pygments-w">
</span><span class="pygments-gi">+++ b/src/smdba/postgresqlgate.py</span><span class="pygments-w">
</span><span class="pygments-gu">@@ -767,6 +767,11 @@ def do_backup_hot(self, *opts: str, **args: str) -> None: # pylint: disable=W06</span><span class="pygments-w">
</span> if 'enable' in args.keys():<span class="pygments-w">
</span> # Check destination only in case user is enabling the backup<span class="pygments-w">
</span> if args.get('enable') == 'on':<span class="pygments-w">
</span><span class="pygments-gi">+ # Save original value in temporary variable to re-assign after Permission Check</span><span class="pygments-w">
</span><span class="pygments-gi">+ args_backup_dir_orig = args['backup-dir']</span><span class="pygments-w">
</span><span class="pygments-gi">+ # If backup-dir is Symlink, use target instead</span><span class="pygments-w">
</span><span class="pygments-gi">+ while os.path.islink(args['backup-dir']):</span><span class="pygments-w">
</span><span class="pygments-gi">+ args['backup-dir'] = os.readlink(args_backup_dir_orig)</span><span class="pygments-w">
</span> # Same owner?<span class="pygments-w">
</span> if os.lstat(args['backup-dir']).st_uid != os.lstat(self.config['pcnf_pg_data']).st_uid \<span class="pygments-w">
</span> or os.lstat(args['backup-dir']).st_gid != os.lstat(self.config['pcnf_pg_data']).st_gid:<span class="pygments-w">
</span><span class="pygments-gu">@@ -777,6 +782,8 @@ def do_backup_hot(self, *opts: str, **args: str) -> None: # pylint: disable=W06</span><span class="pygments-w">
</span> if oct(os.lstat(args['backup-dir']).st_mode & 0o777) != oct(os.lstat(self.config['pcnf_pg_data']).st_mode & 0o777):<span class="pygments-w">
</span> raise GateException("The \"%s\" directory must have the same permissions as \"%s\" directory."<span class="pygments-w">
</span> % (args['backup-dir'], self.config['pcnf_pg_data']))<span class="pygments-w">
</span><span class="pygments-gi">+ # Avoid issues at a later point due to different paths by setting original value</span><span class="pygments-w">
</span><span class="pygments-gi">+ args['backup-dir'] = args_backup_dir_orig</span><span class="pygments-w">
</span> self._perform_enable_backups(**args)<span class="pygments-w">
</span> if 'source' in args.keys():<span class="pygments-w">
</span>
</pre>
<p>I know that I could also use a different path in the "--backup-dir" argument, which already points to the new location.
But in my opinion it's helpful to stick with paths that are mentioned in the official documentation when there are multiple administrators.</p>
<p>Doesn't matter how good your internal KB is, in case of an issues or when new people takeover, project / vendor guides mostly have a higher precedence.</p>
<p>Also supporting Symlinks avoid that configured backup cronjobs silently failing in case someone has the idea to move the folder away and configure a symlink, like me ;)</p>
First Contribution to the Uyuni Project aka SUSE Manager2021-03-24T00:00:00+01:002021-03-24T00:00:00+01:00Dominik Wombachertag:dominik.wombacher.cc,2021-03-24:/posts/first-contribution-to-the-uyuni-project-aka-suse-manager.html<!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>I'm using a lot of Open Source Software and always benefited from the work of the community.
So whenever possible I try to contribute and give something back.</p>
<p>As mentioned ... <a class="read-more" href="/posts/first-contribution-to-the-uyuni-project-aka-suse-manager.html"> [read more]</a></p><!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>I'm using a lot of Open Source Software and always benefited from the work of the community.
So whenever possible I try to contribute and give something back.</p>
<p>As mentioned in other Posts, I'm using SUSE Manager at work, the commercial Product of the Upstream
Open Source Project <a class="reference external" href="https://www.uyuni-project.org">Uyuni</a>, which is a fork of <a class="reference external" href="https://spacewalkproject.github.io">Spacewalk</a>
that <a class="reference external" href="https://www.suse.com/c/were-back-to-earth-and-the-earth-is-flat-welcome-uyuni/">SUSE introduced 2018</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20200421061926/https://www.suse.com/c/were-back-to-earth-and-the-earth-is-flat-welcome-uyuni/">[1]</a>,
<a class="reference external" href="https://archive.today/2021.03.24-213548/https://www.suse.com/c/were-back-to-earth-and-the-earth-is-flat-welcome-uyuni/">[2]</a>).</p>
<p>So I decided it's time to look for a <a class="reference external" href="https://github.com/uyuni-project/uyuni/labels/good%20first%20issue">good-first-issue</a>
and support the Uyuni Project as well. I'm still improving my Java Skills,
so I thought some adjustments on the <a class="reference external" href="https://github.com/uyuni-project/uyuni/issues/1354">Setup Bash Script</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20210324212349/https://github.com/uyuni-project/uyuni/issues/1354">[1]</a>,
<a class="reference external" href="https://archive.today/2021.03.24-212400/https://github.com/uyuni-project/uyuni/issues/1354">[2]</a>)
might be the right thing to start with.</p>
<p>The Task was to get the product name from a default config file and use this value
instead the hardcoded occurrences of <strong>SUSE Manager</strong> for user visible output.</p>
<p>Today my <a class="reference external" href="https://github.com/uyuni-project/uyuni/pull/3460">pull request</a>
(Archive: <a class="reference external" href="https://web.archive.org/web/20210324212223/https://github.com/uyuni-project/uyuni/pull/3460">[1]</a>,
<a class="reference external" href="https://archive.today/2021.03.24-212223/https://github.com/uyuni-project/uyuni/pull/3460">[2]</a>)
was accepted and merged in the Main branch :)</p>
SUSE Manager / Uyuni - Salt SSH Push: Thin package corrupted2021-03-02T00:00:00+01:002021-03-02T00:00:00+01:00Dominik Wombachertag:dominik.wombacher.cc,2021-03-02:/posts/suse-manager-uyuni-salt-ssh-push-thin-package-corrupted.html<!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>At work we had issues with almost all Salt-SSH / SSH-Push connected Clients for months due to an unhandled exception <code>ImportError: No module named 'salt.exceptions'</code> that occurred regularly. It took ... <a class="read-more" href="/posts/suse-manager-uyuni-salt-ssh-push-thin-package-corrupted.html"> [read more]</a></p><!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>At work we had issues with almost all Salt-SSH / SSH-Push connected Clients for months due to an unhandled exception <code>ImportError: No module named 'salt.exceptions'</code> that occurred regularly. It took me a lot of time to track the issue down together with SUSE so I want to share my Experience.</p>
<div class="section" id="error">
<h2>Error</h2>
<pre class="code text literal-block">
[...]
"stderr": "Traceback (most recent call last):\n File
\"/var/tmp/.user_a567dc_salt/salt-call\", line 26, in \n from
salt.scripts import salt_call\n File
\"/var/tmp/.user_a567dc_salt/pyall/salt/scripts.py\", line 21, in \n
from salt.exceptions import SaltSystemExit, SaltClientError,
SaltReqTimeoutError\nImportError: No module named 'salt.exceptions'"
[...]
</pre>
</div>
<div class="section" id="background">
<h2>Background</h2>
<p>Normally Salt is using an Agent (Salt-Minion) but also supports an Agentless approach called Salt-SSH.
A package (<em>"thin.tgz"</em>), which contains all python code and files that Salt need to run Jobs on a server, will be uploaded and extracted to <strong>/var/tmp/.<user>_<id>_salt/</strong> on the target Server.
The "<em>id</em>" is related to the used Salt Version, the "<em>user</em>" is the one configured on the Salt Master - in our Case SUSE Manager - which has full sudo permissions and is allowed to login via SSH on the target.</p>
<p>Everytime Salt connect to run a Job, some checks will performed to verify that state of the thin package:</p>
<ul class="simple">
<li>Does the Folder for the specified user with the matching id exist in <em>/var/tmp/</em></li>
<li>Is the file <em>"code-checksum"</em> available and does the containing checksum matches with the thin.tgz package on the Salt Master</li>
</ul>
<p>As long both checks are successful, the Salt Master will _not_ upload a new <em>thin.tgz</em> - that's important to understand.</p>
</div>
<div class="section" id="troubleshooting">
<h2>Troubleshooting</h2>
<p>First it was totally unclear were the issue was coming from, it could occur with every job type, on different server at a different time.
The thin package was always corrupted at some point what caused the unhandled exception.
The Workaround was to manually delete the whole folder of the Salt thin package on the target Server so the Salt Master uploaded a fresh copy next time.</p>
<p>SUSE helped to go through tons of logs and to visualize a timeline were I could see that the issue seem to occur every 7 days.</p>
<p>Further investigation confirmed, in this case the problem was self-made. Someone from the Team configured systemd to automatically cleanup the tmp folder on a lot of server and neither tested nor documented it well.
Removing the thin package folder wouldn't be a problem, it would be just newly uploaded, as long it's done right but it wasn't.</p>
<pre class="code text literal-block">
/etc/tmpfiles.d/clean_tmp.conf
D /tmp 1777 root root 7d
D /var/tmp 1777 root root 7d
</pre>
<p>The tmpfiles config removed only files and folder owned by user <em>root</em>, but a few files, like "<em>code-checksum</em>", of the thin package folder are owned by salt.
So every 7 days almost all files were removed and therefore corrupted Salt thin, but the Salt Master found the folder and the "<em>code-checksum</em>" file with the correct hash and thought the thin state is healthy.</p>
</div>
<div class="section" id="solution">
<h2>Solution</h2>
<p>At the end I just removed the custom tmpfiles config and once again the thin folder manually on all affected server.</p>
<p>For us there wasn't much benefit in deleting the thin package weekly and generate high load and consume bandwith to re-upload it. In case you prefer the regular cleanup of your tmp folders, just ensure that the whole thin folder and all files are covered and either removed ore kept untouched by your ruleset.</p>
<p>Even though it was a human error and not directly related to SUSE Manager / Uyuni or Salt it demonstrated how fragile such components can be.
From a technical point of view I understand why there are just a few checks and validation of the hash in a file.
Doing that for the whole folder content on every job run would horrible slow and increase the load.
But as we can see, it comes with a price and can be affected by something you wouldn't expect.</p>
</div>
SUSE Manager / Uyuni - Valid PTR Record required for SSH-Push Clients2021-02-23T00:00:00+01:002021-02-23T00:00:00+01:00Dominik Wombachertag:dominik.wombacher.cc,2021-02-23:/posts/suse-manager-uyuni-valid-ptr-required-for-ssh-push.html<!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>I'm responsible for a <a class="reference external" href="https://www.suse.com/products/suse-manager/">SUSE Manager</a> Installation, the commercial product
based on <a class="reference external" href="https://www.uyuni-project.org">Uyuni</a>, with almost 900 connected Server.</p>
<p>The recommend connection method is using a Salt Minion, but SSH-Push - based ... <a class="read-more" href="/posts/suse-manager-uyuni-valid-ptr-required-for-ssh-push.html"> [read more]</a></p><!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher <dominik@wombacher.cc> -->
<!-- -->
<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<p>I'm responsible for a <a class="reference external" href="https://www.suse.com/products/suse-manager/">SUSE Manager</a> Installation, the commercial product
based on <a class="reference external" href="https://www.uyuni-project.org">Uyuni</a>, with almost 900 connected Server.</p>
<p>The recommend connection method is using a Salt Minion, but SSH-Push - based on Salt-SSH - is the agentless alternative.
In our Environment, something around 200 Server using this connection type, because there is already a Salt Minion running,
attached to a different Salt Master.</p>
<div class="section" id="problem">
<h2>Problem</h2>
<p>During the last weeks we faced some issues were the <strong>salt-api</strong> service is going to crash due to an unhandled exception from time to time.</p>
<p>Investigation together with SUSE is still ongoing but so far it seems like, that under rare conditions, a Server with connection method
SSH-Push and without valid PTR DNS Record can indeed raise an Exception in the Salt Codebase.</p>
</div>
<div class="section" id="background">
<h2>Background</h2>
<p>Function <code>ip_to_host</code> located in <strong>/usr/lib/python3.6/site-packages/salt/utils/network.py</strong> is passing the FQDN to Python built-in Function
<code>socket.gethostbyaddr</code>. This will raise an Exception, handled by <code>ip_to_host</code> which then return <code>None</code> (Normally that should be a Hostname).</p>
<p>Based on the return value, a new Minion Job for Server <code>None</code> will be started and end up in an <strong>unhandled Exception</strong> that cause salt-api
to crash as shown in the following error message (Debug Mode need to be enabled for <em>Salt</em> as well <em>Taskomatic</em>):</p>
<p><em>/var/log/salt/api_error</em></p>
<pre class="code text literal-block">
Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/salt/netapi/rest_cherrypy/app.py", line 860, in hypermedia_handler
ret = cherrypy.serving.request._hypermedia_inner_handler(*args, **kwargs)
File "/usr/lib/python3.6/site-packages/cherrypy/_cpdispatch.py", line 54, in __call__
return self.callable(*self.args, **self.kwargs)
File "/usr/lib/python3.6/site-packages/salt/netapi/rest_cherrypy/app.py", line 2140, in POST
'return': list(self.exec_lowstate()),
File "/usr/lib/python3.6/site-packages/salt/netapi/rest_cherrypy/app.py", line 1187, in exec_lowstate
ret = self.api.run(chunk)
File "/usr/lib/python3.6/site-packages/salt/netapi/__init__.py", line 152, in run
return l_fun(*f_call.get('args', ()), **f_call.get('kwargs', {}))
File "/usr/lib/python3.6/site-packages/salt/netapi/__init__.py", line 218, in ssh
return ssh_client.cmd_sync(kwargs)
File "/usr/lib/python3.6/site-packages/salt/client/ssh/client.py", line 159, in cmd_sync
**kwargs)
File "/usr/lib/python3.6/site-packages/salt/client/ssh/client.py", line 123, in cmd
for ret in ssh.run_iter(jid=kwargs.get('jid', None)):
File "/usr/lib/python3.6/site-packages/salt/client/ssh/__init__.py", line 696, in run_iter
self.cache_job(jid, host, ret[host], fun)
File "/usr/lib/python3.6/site-packages/salt/client/ssh/__init__.py", line 720, in cache_job
'fun': fun})
File "/usr/lib/python3.6/site-packages/salt/returners/local_cache.py", line 147, in returner
hn_dir = os.path.join(jid_dir, load['id'])
File "/usr/lib64/python3.6/posixpath.py", line 94, in join
genericpath._check_arg_types('join', a, *p)
File "/usr/lib64/python3.6/genericpath.py", line 149, in _check_arg_types
(funcname, s.__class__.__name__)) from None
TypeError: join() argument must be str or bytes, not 'NoneType'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/cherrypy/_cprequest.py", line 638, in respond
self._do_respond(path_info)
File "/usr/lib/python3.6/site-packages/cherrypy/_cprequest.py", line 697, in _do_respond
response.body = self.handler()
File "/usr/lib/python3.6/site-packages/cherrypy/lib/encoding.py", line 219, in __call__
self.body = self.oldhandler(*args, **kwargs)
File "/usr/lib/python3.6/site-packages/salt/netapi/rest_cherrypy/app.py", line 894, in hypermedia_handler
if cherrypy.config['debug']
File "/usr/lib64/python3.6/traceback.py", line 167, in format_exc
return "".join(format_exception(*sys.exc_info(), limit=limit, chain=chain))
File "/usr/lib64/python3.6/traceback.py", line 121, in format_exception
type(value), value, tb, limit=limit).format(chain=chain))
File "/usr/lib64/python3.6/traceback.py", line 498, in __init__
_seen=_seen)
File "/usr/lib64/python3.6/traceback.py", line 509, in __init__
capture_locals=capture_locals)
File "/usr/lib64/python3.6/traceback.py", line 338, in extract
if limit >= 0:
TypeError: '>=' not supported between instances of 'TypeError' and 'int'
</pre>
<p><em>/var/log/salt/api</em></p>
<pre class="code text literal-block">
[...]
2021-02-08 01:08:01,229 [salt.utils.network:239 ][DEBUG ][38989] salt.utils.network.ip_to_host('server.example.com') failed: [Errno 0] Resolver Error 0 (no error)
[...]
2021-02-08 01:08:02,801 [salt.loaded.int.returner.local_cache:252 ][DEBUG ][38989] Adding minions for job 20210208000802780236: [None]
[...]
2021-02-08 01:08:02,839 [salt.utils.process:767 ][ERROR ][5340] An un-handled exception from the multiprocessing process 'Process-1:335' was caught:
[...]
2021-02-08 01:08:02,916 [salt.client.ssh :644 ][ERROR ][38989] Target 'None' did not return any data, probably due to an error.
2021-02-08 01:08:02,917 [salt.loaded.int.netapi.rest_cherrypy.app:887 ][DEBUG ][38989] Error while processing request for: /run
</pre>
<p><em>/var/log/rhn/rhn_taskomatic_daemon.log</em></p>
<pre class="code text literal-block">
2021-02-08 01:08:02,976 [Thread-70313] ERROR com.redhat.rhn.taskomatic.task.SSHPush - com.suse.salt.netapi.
exception.SaltException: Response code: 500
java.lang.RuntimeException: com.suse.salt.netapi.exception.SaltException: Response code: 500
at com.suse.manager.webui.services.impl.SaltService.callSync(SaltService.java:235)
at com.suse.manager.webui.services.impl.SaltService.ping(SaltService.java:244)
at com.redhat.rhn.taskomatic.task.sshpush.SSHPushWorkerSalt.performCheckin(SSHPushWorkerSalt.java:337)
at com.redhat.rhn.taskomatic.task.sshpush.SSHPushWorkerSalt.lambda$run$0(SSHPushWorkerSalt.java:122)
at java.base/java.util.Optional.ifPresent(Optional.java:183)
at com.redhat.rhn.taskomatic.task.sshpush.SSHPushWorkerSalt.run(SSHPushWorkerSalt.java:110)
at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(PooledExecutor.java:732)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: com.suse.salt.netapi.exception.SaltException: Response code: 500
at com.suse.salt.netapi.client.impl.HttpAsyncClientImpl.createSaltException(HttpAsyncClientImpl.java:
145)
at com.suse.salt.netapi.client.impl.HttpAsyncClientImpl.access$000(HttpAsyncClientImpl.java:27)
at com.suse.salt.netapi.client.impl.HttpAsyncClientImpl$1.completed(HttpAsyncClientImpl.java:121)
at com.suse.salt.netapi.client.impl.HttpAsyncClientImpl$1.completed(HttpAsyncClientImpl.java:101)
at org.apache.http.concurrent.BasicFuture.completed(BasicFuture.java:123)
at org.apache.http.impl.nio.client.DefaultClientExchangeHandlerImpl.responseCompleted
(DefaultClientExchangeHandlerImpl.java:181)
at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.processResponse(HttpAsyncRequestExecutor.java:
442)
at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.inputReady(HttpAsyncRequestExecutor.java:332)
at org.apache.http.impl.nio.DefaultNHttpClientConnection.consumeInput(DefaultNHttpClientConnection.java:
265)
at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:81)
at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:39)
at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:121)
at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:162)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:337)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:276)
at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run
(AbstractMultiworkerIOReactor.java:588)
... 1 more
</pre>
<p>You can quickly check, with two Python based commands, if the reverse lookup is working for a given FQDN.
In this Example we assume the FQDN is <strong>server.example.com</strong> and the assigned IP Address is <strong>10.11.12.13</strong>:</p>
<pre class="code text literal-block">
python3 -c 'import socket; print(socket.gethostbyaddr("server.example.com"))'
python3 -c 'import socket; print(socket.getaddrinfo("server.example.com", 0, 0, 0, 0))'
</pre>
<p>In case everything is fine, both should return something similar as the following:</p>
<pre class="code text literal-block">
('server.example.com', [], ['10.11.12.13'])
[(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('10.11.12.13', 0)),
(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_DGRAM: 2>, 17, '', ('10.11.12.13', 0)),
(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_RAW: 3>, 0, '', ('10.11.12.13', 0))]
</pre>
<p>Further reading regarding <em>gethostbyaddr</em>: <a class="reference external" href="https://docs.python.org/3/library/socket.html#socket.gethostbyaddr">https://docs.python.org/3/library/socket.html#socket.gethostbyaddr</a></p>
</div>
<div class="section" id="solution">
<h2>Solution</h2>
<p>I expect that SUSE is going to include a Patch in future SUSE Manager and Uyuni releases were a Server will probably skipped
if there is no valid PTR Record. So you should double check in your Environment, that all Systems connected via SSH-Push / Salt-SSH
have the necessary DNS Records and can be resolved by their FQDN as well IP Address to avoid potential issues.</p>
</div>