foursixnine's lair2024-01-25T21:36:22+00:00https://foursixnine.io/Testing kernels with sporadic issues until heisenbug shows in openQA2024-01-25T00:00:00+00:00https://foursixnine.io//blog/linux/tech/qualityassurance/openqa/2024/01/25/testingkernelswithsporadicissuesuntilheisenbugshowsinopenqa<p>This is a follow up to my previous post about <a href="/blog/linux/tech/qualityassurance/2021/06/18/How-to-test-things-with-openQA-without-running-your-own-instance">How to test things with openQA without running your own instance</a>, so you might want to read that first.</p>
<p>Now, while hunting for <a href="https://bugzilla.suse.com/show_bug.cgi?id=1219073">bsc#1219073</a> which is quite sporadic, and took quite some time to show up often enough so that
became noticeable and traceable, once stars aligned and managed to find a way to get a higher failure rate,
I wanted to have a way for me and for the developer to test the kernel with the different patches to help with the bisecting
and ease the process of finding the culprit and finding a solution for it.</p>
<p>I came with a fairly simple solution, using the <code class="language-plaintext highlighter-rouge">--repeat</code> parameter of the openqa-cli tool, and a simple shell script to run it:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="sb">```</span>bash
<span class="nv">$ </span><span class="nb">cat</span> ~/Downloads/trigger-kernel-openqa-mdadm.sh
<span class="c"># the kernel repo must be the one without https; tests don't have the kernel CA installed</span>
<span class="nv">KERNEL</span><span class="o">=</span><span class="s2">"KOTD_REPO=http://download.opensuse.org/repositories/Kernel:/linux-next/standard/"</span>
<span class="nv">REPEAT</span><span class="o">=</span><span class="s2">"--repeat 100"</span> <span class="c"># using 100 by default</span>
<span class="nv">JOBS</span><span class="o">=</span><span class="s2">"https://openqa.your.instan.ce/tests/13311283 https://openqa.your.instan.ce/tests/13311263 https://openqa.your.instan.ce/tests/13311276 https://openqa.your.instan.ce/tests/13311278"</span>
<span class="nv">BUILD</span><span class="o">=</span><span class="s2">"bsc1219073"</span>
<span class="k">for </span>JOB <span class="k">in</span> <span class="nv">$JOBS</span><span class="p">;</span> <span class="k">do
</span>openqa-clone-job <span class="nt">--within-instance</span> <span class="nv">$JOB</span> <span class="nv">CASEDIR</span><span class="o">=</span>https://github.com/foursixnine/os-autoinst-distri-opensuse.git#tellmewhy <span class="k">${</span><span class="nv">REPEAT</span><span class="k">}</span> <span class="se">\</span>
<span class="nv">_GROUP</span><span class="o">=</span>DEVELOPERS <span class="k">${</span><span class="nv">KERNEL</span><span class="k">}</span> <span class="nv">BUILD</span><span class="o">=</span><span class="k">${</span><span class="nv">BUILD</span><span class="k">}</span> <span class="nv">FORCE_SERIAL_TERMINAL</span><span class="o">=</span>1<span class="se">\</span>
<span class="nv">TEST</span><span class="o">=</span><span class="s2">"</span><span class="k">${</span><span class="nv">BUILD</span><span class="k">}</span><span class="s2">_checkmdadm"</span> <span class="nv">YAML_SCHEDULE</span><span class="o">=</span>schedule/qam/QR/15-SP5/textmode/textmode-skip-registration-extra.yaml <span class="nv">INSTALLONLY</span><span class="o">=</span>0 <span class="nv">DESKTOP</span><span class="o">=</span>textmode<span class="se">\</span>
|& <span class="nb">tee </span>jobs-launched.list<span class="p">;</span>
<span class="k">done</span><span class="p">;</span>
</code></pre></div></div>
<p>There are few things to note here:</p>
<ul>
<li>the kernel repo must be the one without https; tests don’t have the CA installed by default.</li>
<li>the <code class="language-plaintext highlighter-rouge">--repeat</code> parameter is set to 100 by default, but can be changed to whatever number is desired.</li>
<li>the <code class="language-plaintext highlighter-rouge">JOBS</code> variable contains the list of jobs to clone and run, having all supported architecures is recommended (at least for this case)</li>
<li>the <code class="language-plaintext highlighter-rouge">BUILD</code> variable can be anything, but it’s recommended to use the bug number or something that makes sense.</li>
<li>the <code class="language-plaintext highlighter-rouge">TEST</code> variable is used to set the name of the test as it will show in the test overview page, you can use <code class="language-plaintext highlighter-rouge">TEST+=foo</code> if you want to append text instead of overriding it, the <code class="language-plaintext highlighter-rouge">--repeat</code> parameter, will append a number incrementally to your test, see <a href="https://github.com/os-autoinst/openQA/pull/5331">os-autoinst/openQA#5331</a> for more details.</li>
<li>the <code class="language-plaintext highlighter-rouge">YAML_SCHEDULE</code> variable is used to set the yaml schedule to use, there are other ways to modify the schedule, but in this case I want to perform a full installation</li>
</ul>
<h3 id="running-the-script">Running the script</h3>
<ul>
<li>Ensure you can run at least the openQA client; if you need API keys, see post linked at the beginning of this post</li>
<li>replace the kernel repo with your branch in line 5</li>
<li>run the script <code class="language-plaintext highlighter-rouge">$ bash trigger-kernel-openqa-mdadm.sh</code> and you should get the following, times the <code class="language-plaintext highlighter-rouge">--repeat</code> if you modified it</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1 job has been created:
- sle-15-SP5-Full-QR-x86_64-Build134.5-skip_registration+workaround_modules@64bit -> https://openqa.your.instan.ce/tests/13345270
</code></pre></div></div>
<p>Each URL, will be a job triggered in openQA, depending on the load and amount of jobs, you might need to wait quite a bit (some users can help moving the priority of these jobs so it executes faster)</p>
<h2 id="the-review-stuff">The review stuff:</h2>
<h3 id="looking-at-the-results">Looking at the results</h3>
<ul>
<li>Go to https://openqa.your.instan.ce/tests/overview?distri=sle&build=bsc1219073&version=15-SP5 or from any job from the list above click on <code class="language-plaintext highlighter-rouge">Job groups</code> menu at the top, and select <code class="language-plaintext highlighter-rouge">Build bsc1219073</code></li>
<li>Click on “Filter”</li>
<li>type the name of the test module to filter in the field <em>Module name</em>, e.g <code class="language-plaintext highlighter-rouge">mdadm</code>, and select the desired result of such test module e.g <code class="language-plaintext highlighter-rouge">failed</code> (you can also type, and select multiple result types)</li>
<li>Click Apply</li>
<li>The overall summary of the build overview page, will provide you with enough information to calculate the pass/fail rate.</li>
</ul>
<p>A rule of thumb: anything above 5% is bad, but you need to also understand your sample size + the setup you’re using; YMMV.</p>
<h3 id="aint-nobody-got-time-to-wait">Ain’t nobody got time to wait</h3>
<p>The script will generate a file called: <code class="language-plaintext highlighter-rouge">jobs-launched.list</code>, in case you absolutely need to change the priority of the jobs, set it to 45, so it runs higher than default priority, which is 50
<code class="language-plaintext highlighter-rouge">cat jobs-launched.list | grep https | sed -E 's/^.*->\s.*tests\///' | xargs -r -I {} bash -c "openqa-cli api --osd -X POST jobs/{}/prio prio=45; sleep 1"</code></p>
<h2 id="the-magic">The magic</h2>
<p>The actual magic is in the schedule, so right after booting the system and setting it up, before running the mdadm test, I inserted the <code class="language-plaintext highlighter-rouge">update_kernel</code> module, which will add the kernel repo specified by KOTD_REPO, and install the kernel from there, reboot the system, and leave the system ready for the actual test,
however I had to add very small changes:</p>
<div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">---
</span> tests/kernel/update_kernel.pm | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/kernel/update_kernel.pm b/tests/kernel/update_kernel.pm
<span class="gh">index 1d6312bee0dc..048da593f68f 100644
</span><span class="gd">--- a/tests/kernel/update_kernel.pm
</span><span class="gi">+++ b/tests/kernel/update_kernel.pm
</span><span class="p">@@ -398,7 +398,7 @@</span> sub boot_to_console {
sub run {
my $self = shift;
<span class="gd">- if ((is_ipmi && get_var('LTP_BAREMETAL')) || is_transactional) {
</span><span class="gi">+ if ((is_ipmi && get_var('LTP_BAREMETAL')) || is_transactional || get_var('FORCE_SERIAL_TERMINAL')) {
</span> # System is already booted after installation, just switch terminal
select_serial_terminal;
} else {
<span class="p">@@ -476,7 +476,7 @@</span> sub run {
reboot_on_changes;
} elsif (!get_var('KGRAFT')) {
power_action('reboot', textmode => 1);
<span class="gd">- $self->wait_boot if get_var('LTP_BAREMETAL');
</span><span class="gi">+ $self->wait_boot if (get_var('FORCE_SERIAL_TERMINAL') || get_var('LTP_BAREMETAL'));
</span> }
}
</code></pre></div></div>
<p>Likely I’ll make a new pull request to have this in the test distribution, but for now this is good enough to help kernel developers
to do some self-service and trigger their own openQA tests, that have many more tests (hopefully in parallel) and faster than if there
was a person doing all of this manually.</p>
<p>Special thanks to the QE Kernel team, who do the amazing job of thinking of some scenarios like this, because they save a lot
of time.</p>
Deactivating copilot for password managers like pass2024-01-05T00:00:00+00:00https://foursixnine.io//blog/copilot/tinfoil/security/nvim/2024/01/05/Deactivating-copilot-for-password-managers-like-pass<p>If you’re using <a href="https://github.com/copilot">copilot</a> and by luck also use <a href="https://www.passwordstore.org/">pass</a> to manage
your passwords, you will find that the default configuration, or rather the configuration where you want copilot enabled
everywhere, basically creates a risk for your precious passwords… As Copilot will be enabled by default, on text files.</p>
<p><img src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExMWZ5aXozcnJvMmRmZ2xra2trY3M4c2Nub2lzbjh4dXIwdHVjZDA2ZSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/G1ifnX4d5tYFACktp9/giphy.gif" alt="My dataaa!" /></p>
<p>So here’s the snippet I use:</p>
<div class="language-lua highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">-- initialize copilot</span>
<span class="kd">local</span> <span class="n">copilot</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">"zbirenbaum/copilot.lua"</span><span class="p">,</span>
<span class="s2">"ofseed/copilot-status.nvim"</span><span class="p">,</span>
<span class="n">cmd</span> <span class="o">=</span> <span class="s2">"Copilot"</span><span class="p">,</span>
<span class="n">build</span> <span class="o">=</span> <span class="s2">":Copilot auth"</span><span class="p">,</span>
<span class="n">event</span> <span class="o">=</span> <span class="s2">"InsertEnter"</span><span class="p">,</span>
<span class="n">opts</span> <span class="o">=</span> <span class="p">{</span>
<span class="n">filetypes</span> <span class="o">=</span> <span class="p">{</span>
<span class="n">sh</span> <span class="o">=</span> <span class="k">function</span><span class="p">()</span>
<span class="k">if</span> <span class="nb">string.match</span><span class="p">(</span><span class="n">vim</span><span class="p">.</span><span class="n">fs</span><span class="p">.</span><span class="n">basename</span><span class="p">(</span><span class="n">vim</span><span class="p">.</span><span class="n">api</span><span class="p">.</span><span class="n">nvim_buf_get_name</span><span class="p">(</span><span class="mi">0</span><span class="p">)),</span> <span class="s2">"^%.env.*"</span><span class="p">)</span> <span class="k">then</span>
<span class="c1">-- disable for .env files</span>
<span class="k">return</span> <span class="kc">false</span>
<span class="k">end</span>
<span class="k">return</span> <span class="kc">true</span>
<span class="k">end</span><span class="p">,</span>
<span class="n">text</span> <span class="o">=</span> <span class="k">function</span><span class="p">()</span>
<span class="k">if</span>
<span class="n">vim</span><span class="p">.</span><span class="n">has_key</span><span class="p">(</span><span class="n">vim</span><span class="p">.</span><span class="n">environ</span><span class="p">(),</span> <span class="s2">"GIT_CEILING_DIRECTORIES"</span><span class="p">)</span> <span class="ow">or</span> <span class="n">vim</span><span class="p">.</span><span class="n">has_key</span><span class="p">(</span><span class="n">vim</span><span class="p">.</span><span class="n">environ</span><span class="p">(),</span> <span class="s2">"PASS_VERSION"</span><span class="p">)</span>
<span class="k">then</span>
<span class="c1">-- disable for .env files</span>
<span class="k">return</span> <span class="kc">false</span>
<span class="k">end</span>
<span class="k">return</span> <span class="kc">true</span>
<span class="k">end</span><span class="p">,</span>
<span class="p">},</span>
<span class="p">},</span>
<span class="p">}</span>
</code></pre></div></div>
<p>I should eventually add this too to my dotfiles… Once I have the time to do so.</p>
<p><img src="/assets/images/if-i-had-dotfiles.jpg" alt="My dotfiles would be here, if I updated them" /></p>
Extracting postfix journal logs for fun, profit and unbanning2023-11-02T00:00:00+00:00https://foursixnine.io//blog/linux/perl/postfix/2023/11/02/Extracting-postfix-journal-logs-for-fun,-profit-and-unbanning<h1 id="from-journal-to-json">From journal to .json</h1>
<p>In order to convert from your journal log to json, so it is easily parseable, <a href="https://jqlang.github.io/jq/">jq</a> offers an option
that allows you to run a filter, only until the end of the file:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Instead of running the filter for each JSON object in the input, read the entire input stream into a large array and
run the filter just once.
</code></pre></div></div>
<p>This allows you to save the file directly, ready to be processed by your favorite tools, here’s what I used:</p>
<p><code class="language-plaintext highlighter-rouge">journalctl -u postfix.service --since yesterday -g "denied" --output json | jq -s "." > data/log.json</code></p>
<h2 id="enter-perl">Enter Perl</h2>
<p>Now, because I’ve been using Perl for <code class="language-plaintext highlighter-rouge">${deity}</code> knows how long (I wrote my first Perl script at the end of the 90’s),
naturally, is my language of choice for quick things where my knowledge of <code class="language-plaintext highlighter-rouge">bash</code> isn’t going to cut it:</p>
<p>First I want to load my file, I’m going to rely on <a href="https://docs.mojolicious.org/Mojo">Mojo</a>, specifically
<code class="language-plaintext highlighter-rouge">Mojo::Collection</code> and <code class="language-plaintext highlighter-rouge">Mojo::JSON</code> for this as I’m familiar with both, also, if I wan’t to dig a bit into what’s inside
my collections, I can always do:</p>
<div class="language-perl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">use</span> <span class="nn">Mojo::</span><span class="nv">Util</span> <span class="sx">qw(dumper)</span><span class="p">;</span>
<span class="nv">say</span> <span class="nv">dumper</span> <span class="nv">$collection</span><span class="o">-></span><span class="nv">to_array</span><span class="p">;</span>
</code></pre></div></div>
<p>But I digress, back to business</p>
<h3 id="the-real-stuff">The real stuff</h3>
<p>This piece of code filters for me, what it reads from a file (I’m doing <code class="language-plaintext highlighter-rouge">$_= path(shift);</code> for convenience)</p>
<div class="language-perl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">my</span> <span class="nv">$file</span> <span class="o">=</span> <span class="nn">Mojo::</span><span class="nv">Collection</span><span class="o">-></span><span class="k">new</span><span class="p">(</span><span class="nv">decode_json</span><span class="p">(</span><span class="vg">$_</span><span class="o">-></span><span class="nv">slurp</span><span class="p">))</span><span class="o">-></span><span class="nv">flatten</span><span class="p">;</span>
<span class="sr">//</span> <span class="nv">Filter</span> <span class="nv">using</span> <span class="nn">Mojo::Collection::</span><span class="nv">grep</span> <span class="nv">to</span> <span class="nv">have</span> <span class="nv">a</span> <span class="k">new</span> <span class="nv">collection</span> <span class="nv">with</span> <span class="nv">the</span> <span class="nv">data</span> <span class="nv">I</span><span class="p">'</span><span class="s1">m interested in
my $filtered = $file->grep(sub{
$_->{MESSAGE} =~ /denied/
});
</span></code></pre></div></div>
<p>Now that I have the elements on a single array (of course, if I’m looking at a file over a gigabyte, likely I’d look into
putting this inside some sort of database, PostgreSQL for instance, has excellent Json support), it’s time to do something
with it:</p>
<div class="language-perl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="sr">//</span> <span class="nv">get</span> <span class="nv">anything</span> <span class="nv">that</span> <span class="nv">looks</span> <span class="nv">like</span> <span class="nv">a</span> <span class="nv">hostname</span> <span class="nv">before</span><span class="p">,</span> <span class="ow">and</span> <span class="nv">get</span> <span class="nv">the</span> <span class="nv">ip</span> <span class="nv">address</span>
<span class="sr">//</span> <span class="nv">example:</span> <span class="nv">NOQUEUE:</span> <span class="nv">reject:</span> <span class="nv">RCPT</span> <span class="nv">from</span> <span class="nv">ns2</span><span class="o">.</span><span class="nv">pads</span><span class="o">.</span><span class="nv">ufrj</span><span class="o">.</span><span class="nv">br</span><span class="p">[</span><span class="mf">146.164.48.5</span><span class="p">]:</span> <span class="mi">554</span> <span class="mf">5.7.1</span> <span class="o"><</span><span class="nv">relaytest@antispam</span><span class="o">-</span><span class="nv">ufrj</span><span class="o">.</span><span class="nv">pads</span><span class="o">.</span><span class="nv">ufrj</span><span class="o">.</span><span class="nv">br</span><span class="o">></span><span class="p">:</span>
<span class="sr">//</span> <span class="nv">I</span> <span class="nv">want</span> <span class="nv">to</span> <span class="nv">have</span> <span class="nv">ethe</span> <span class="nv">IP</span> <span class="nv">in</span> <span class="nv">a</span> <span class="nv">named</span> <span class="nv">group</span> <span class="nv">so</span> <span class="nv">I</span> <span class="nv">can</span> <span class="nv">later</span> <span class="nv">reference</span> <span class="nv">it</span> <span class="nv">with</span> <span class="p">`</span><span class="sb">$+{'IP'}</span><span class="p">`</span>
<span class="k">my</span> <span class="nv">$regexp</span> <span class="o">=</span> <span class="sx">qr{(.*[a-zA-Z0-9-._]+)\[(?<IP>.*)\]>?:.*}</span><span class="p">;</span>
</code></pre></div></div>
<p>Ideally (and for the future) I might want to filter in a different way, and capture different things, but you get the idea
however today, we only want to know which ip addresses were rejected while testing our changes in our postfix’s configuration</p>
<div class="language-perl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$filtered</span><span class="o">-></span><span class="nb">each</span><span class="p">(</span><span class="nv">sub</span><span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="vg">$_</span><span class="o">-></span><span class="p">{'</span><span class="s1">MESSAGE</span><span class="p">'}</span> <span class="o">=~</span> <span class="sr">/$regexp/</span> <span class="p">){</span>
<span class="nv">say</span> <span class="p">"</span><span class="s2">bash ./unban </span><span class="p">"</span><span class="o">.</span><span class="vg">$+</span><span class="p">{'</span><span class="s1">IP</span><span class="p">'};</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nb">warn</span> <span class="p">"</span><span class="s2">CANNOT GET IP: </span><span class="p">"</span><span class="o">.</span><span class="vg">$_</span><span class="o">-></span><span class="p">{"</span><span class="s2">MESSAGE</span><span class="p">"};</span>
<span class="p">}</span>
<span class="p">});</span>
</code></pre></div></div>
<p>I have another script that does the unban, but for now I’m ok with copy&pasting :)</p>
<p>The full script is at <a href="https://github.com/foursixnine/stunning-octo-chainsaw/blob/master/postfix-logparser/logparser.pl">foursixnine/stunning-octo-chainsaw</a>
pull requests are welcome, and maybe in the future I move this to its own thing, but for now, that’s all folks.</p>
<p><img src="https://imgs.xkcd.com/comics/regular_expressions.png" alt="Regular Expressions" /></p>
In case your zsh completion is broken on OSX with homebrew2022-07-13T00:00:00+00:00https://foursixnine.io//blog/osx/homebrew/zsh/2022/07/13/In-case-your-zsh-completion-is-broken-on-OSX-with-homebrew<p>Happens that I spent today (Finally) a good few hours trying to figure out why my autocompletion was broken on my new shiny MacBook Pro M1 Pro…</p>
<p>despite Homebrew’s <code class="language-plaintext highlighter-rouge">brew doctor</code> giving me the All OK.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>foursixnine@pakhet ~ % brew doctor
Your system is ready to brew.
</code></pre></div></div>
<p>turns out that it was just the shell:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>foursixnine@pakhet ~ % echo $FPATH
/opt/homebrew/share/zsh-completions:/usr/local/share/zsh/site-functions:/usr/share/zsh/site-functions:/usr/share/zsh/5.8.1/functions
</code></pre></div></div>
<p>My user’s shell is still being set to osx’s 5.8.1 zsh…</p>
<p>So after hours of searching on the internet to no avail, and scratching my head, I came back to my initial idea of just switching the shell::</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo "export PATH=/opt/homebrew/bin:$PATH" >> ~/.zshenv
sudo sh -c "echo $(which zsh) >> /etc/shells"
chsh -s $(which zsh)
</code></pre></div></div>
Interoperabilidad de Obsidian con Linux, iOS y OSX2022-04-18T00:00:00+00:00https://foursixnine.io//blog/linux/tech/espa%C3%B1ol/2022/04/18/Interoperabilidad-de-Obsidian-con-Linux,-iOS-y-OSX<p>Hace tiempo en el grupo de Developers Ve en el mundo, preguntaba si alguien había utilizado Obsidian. Considerándome un power user de Evernote, sé lo que necesito, y en los años que llevo buscando una alternativa que funcione en linux, tenia el problema de que muy pocas realmente funcionan bien o siquiera tienen soporte para linux.</p>
<p>Decidí irme por <a href="https://obsidian.md/">Obsidian</a>, luego de considerar Notion y otras herramientas principalmente por los plugins, que tiene <a href="https://es.wikipedia.org/wiki/Zettelkasten">Zettelkasten</a> como feature, esta pensado con las siguientes otras razones:</p>
<ul>
<li>Es perfecto para <a href="https://es.wikipedia.org/wiki/Zettelkasten">Zettelkasten</a> y para construir un segundo cerebro (<a href="https://robingeuens.com/blog/build-a-second-brain-obsidian">Building a Second Brain</a>), y tiene un sistema de tags simple, pero poderoso.</li>
<li>Soporte para Markdown <em>by default</em>.</li>
<li>Los archivos están en mis dispositivos, no en la nube <em>by design</em>.</li>
<li>Puedo elegir alternativas de respaldo, control de versiones y redundancia.</li>
<li>Soporte para <a href="obsidian://show-plugin?id=obsidian-kanban">Kanban Boards</a>.</li>
<li>Soporte para <a href="https://github.com/lynchjames/obsidian-day-planner">Day Planners</a>.</li>
<li>Soporte para <a href="obsidian://show-plugin?id=nldates-obsidian">Natural Language Dates</a> para cosas <em>like</em>: <code class="language-plaintext highlighter-rouge">@today</code>, <code class="language-plaintext highlighter-rouge">@tomorrow</code>.</li>
<li>La interfaz es exactamente lo que me encanta de Sublime que es lo que había estado utilizando para tomar notas, junto a la aplicación de notas del teléfono y notas via el correo.</li>
<li>Tiene un VIM mode :D.</li>
<li>El <a href="https://trello.com/b/Psqfqp7I/obsidian-roadmap">roadmap</a> promete.</li>
</ul>
<p><img src="/assets/images/zettelkasten.png" alt="zettelkasten" /></p>
<p>Revisando varias cosas, y realmente investigando un poco, llegue al siguiente workflow:</p>
<ul>
<li>Logre construir el workflow que hace lo que necesito:
<ul>
<li>Vault en git en mi VPS, en una instancia propia de gitea, la data es mia.</li>
<li>En Linux:
<ul>
<li>El manejo de las distintas <em>Vaults</em> (Bóvedas) seria por <strong>git</strong> directamente.
<ul>
<li><a href="nextcloud.com">Nextcloud</a> como mecanismo de backup redundante en el <a href="https://www.truenas.com/truenas-mini">NAS</a> en casa via <em>scsi</em> en un rpi.</li>
<li>A mediano, o largo plazo:
<ul>
<li>La solución de NAS podría ser FreeNAS, TrueNAS o Synology</li>
<li>VPS como gateway, utilizando vpn con wireguard para mantener todo en una red privada.</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>En <em>OSX</em>:
<ul>
<li>Seria igual que en <em>linux</em>, por <strong>git</strong> pero con la diferencia de que las bóvedas estarían alojadas en una carpeta en <em>iCloud</em>.</li>
<li>La llave ssh con permiso de escritura en el repo seria importada al <em>keystore</em> (<code class="language-plaintext highlighter-rouge">ssh-add -K</code>), para que no de problemas a la hora de pedir contraseñas.</li>
<li>Queda pendiente revisar como hacer con las firmas de los commits con GPG, o <em>maybe</em> usando <a href="https://github.com/github/feedback/discussions/7744">ssh para firmar commits</a></li>
</ul>
</li>
<li>En <em>IOS</em>, los vaults se estarían abriendo via <em>iCloud</em>, dejando por fuera el manejo con git, mientras se agrega el soporte en para <a href="https://github.com/denolehov/obsidian-git/issues/57">ios/mobile en obsidian-git</a>.</li>
</ul>
</li>
</ul>
<p><img src="https://media.giphy.com/media/l0IylOPCNkiqOgMyA/giphy-downsized.gif" alt="Conspiracy" /></p>
<p>En un tiempo revisare este post, y actualizare seguramente a mi nuevo workflow… o hare una vista en retrospectiva de que pudo salir mejor, etc, sin embargo creo que la primera tarea que hare, sera escribir un plugin para poderlo integrar con la creación de posts de este blog, y utilizar el grafo de tags, que por ahora… se ve así:</p>
<p><img src="/assets/images/blog_tag_cloud.png" alt="tag cloud" /></p>
Remove file from the last commit in git2022-02-11T00:00:00+00:00https://foursixnine.io//blog/tech/linux/git/2022/02/11/Remove-file-from-the-last-commit-in-git<ul>
<li>So, you want to remove that pesky file from your last commit?</li>
<li>By accident (naturally, as you and me are perfect beings) a file was commited and it should have not?</li>
<li>The cat went over the keyboard and now there’s an extra file in your commit?</li>
</ul>
<p>If the answer to any of the above is yes, here’s how to do it without pain (Tanking into account, that you want to do
that on the last commit; If you need to do it in the middle of a rebase, see the previous post or combine this trick
with a rebase (edit a commit with a rebase…).</p>
<p><code class="language-plaintext highlighter-rouge">git restore --source=HEAD^ pesky.file</code></p>
<p>You can always checkout the file again, or use some witchcraft extracted from <code class="language-plaintext highlighter-rouge">man git-restore</code> to do it all at once</p>
<p>This is blatantly stolen from: https://devconnected.com/how-to-remove-files-from-git-commit/ but also <code class="language-plaintext highlighter-rouge">man git</code>
could get you there too, given enough reading.</p>
So you want to recover and old git branch because it has been overwritten?2021-09-17T00:00:00+00:00https://foursixnine.io//blog/linux/tech/git/2021/09/17/So-you-want-to-recover-and-old-git-branch-because-it-has-been-overwritten?<h2 id="so-you-just-broke-that-pr-youve-been-working-on-for-months">So you just broke that PR you’ve been working on for months?</h2>
<p>One day, you find yourself force pushing over your already existing Pull request/branch, because like me, you like to
reuse funny names:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git fetch origin
git checkout tellmewhy #already exists and has a pull request still open, but you didn't know
git reset --hard origin/master
# hack hack hack
git commit $files
git push -f nameofmyremote
</code></pre></div></div>
<p><img src="https://giphy.com/media/panic-P4133zeloooHm/giphy.gif" alt="panic" /></p>
<h2 id="panic">Panic!</h2>
<p>Here’s when you realize that You’ve done something wrong, very very wrong, because github will throw the message:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Error creating pull request: Unprocessable Entity (HTTP 422)
A pull request already exists for foursixnine:tellmewhy.
</code></pre></div></div>
<p>So, you already broke your old PR with a completely unrelated change,</p>
<p><img src="https://giphy.com/media/cjWY3shtuKyfX5VeB1/giphy.gif" alt="what do you do?" /></p>
<h2 id="dont-panic">Don’t panic</h2>
<p><img src="https://media.giphy.com/media/MEM0K35P4iC70rCNSo/giphy.gif" alt="don't panic" /></p>
<p>If you happen to know what’s the previous commit id, you can always pick it up again (go to github.com/pulls for instance and look for the PR with the branch),
AND, AND, AAANDDDD, ABSOLUTELY ANDDDD, you haven’t ran <code class="language-plaintext highlighter-rouge">git gc</code>.</p>
<p>In my case:</p>
<p><strong>@foursixnine foursixnine force-pushed the tellmewhy branch from 9e86f3a to **9714c93** 2 months ago</strong></p>
<p>All there’s to do is:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git checkout $commit
# even better:
git checkout tellmewhy # old branch with new commits that are unrelated/overwritten over the old ones
git checkout -b tellmewhyagain # your new copy, open your pr from here
git push tellmewhyagain # now all is "safe" in the cloud
git checkout tellmewhy # Let's bring the dead back to life
git reset --hard 9714c93
git push -f tellmewhy
</code></pre></div></div>
<p>And this is it, you’ve brought the dead back to life</p>
<p><img src="https://media.giphy.com/media/l2YWAOJso1n136fM4/giphy.gif" alt="" /></p>
How to test things with openQA without running your own instance2021-06-18T00:00:00+00:00https://foursixnine.io//blog/linux/tech/qualityassurance/2021/06/18/How-to-test-things-with-openQA-without-running-your-own-instance<h1 id="wait-what">Wait what?</h1>
<p>Yes, there are couple of ways for you, the user, the contributor, the amazing human being who wants to improve the software that is used by
millions, to write automated tests and have bots doing all the work for you, once you’ve signed a binding contract with the blood of an unicorn,
and have obtained api keys for our public https://openqa.opensuse.org instance.</p>
<p>For now I will leave out the details on how to get those, but will rather point you to the #factory irc channel (or dischord), where you can get
in touch with current admins, whom will be able to guide you better in the process.</p>
<h2 id="i-have-the-keys">I have the keys</h2>
<p>You should get operator keys and they would look like this (more or less):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[openqa.opensuse.org]
key = 45ABCEB4562ACB04
secret = 4BA0003086C4CB95
</code></pre></div></div>
<p><img src="https://media.giphy.com/media/uIGHPjEfdc0Ni/giphy.gif" alt="Multipass" /></p>
<h2 id="now-lets-do-this">Now let’s do this</h2>
<p>I will assume that you’re using openSUSE Tumbleweed, instructions are similar for Leap, but if you’re looking for something more esoteric, check the
<a href="https://open.qa/docs/#bootstrapping">bootstraping guide</a></p>
<p>Bring up a terminal or your favorite package manager, and install <code class="language-plaintext highlighter-rouge">openQA-client</code>, it will pull almost everything you will need</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>zypper in openQA-client
</code></pre></div></div>
<p>Once we’re here, we’ve gotta clone the git repo from the tests being ran in openqa.opensuse.org, to do that let’s go to a directory; let’s call it
Skynet and create it in our user’s home. My user’s home is <code class="language-plaintext highlighter-rouge">/home/foursixnine</code> \o/ and use <code class="language-plaintext highlighter-rouge">git</code> to clone the test repository:
<code class="language-plaintext highlighter-rouge">https://github.com/os-autoinst/os-autoinst-distri-opensuse/</code>.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd $HOME
mkdir Skynet
cd Skynet
git clone https://github.com/os-autoinst/os-autoinst-distri-opensuse/
</code></pre></div></div>
<p>Now since we already cloned the test distribution, and also got the openQA client installed, all there is to do is:</p>
<p>1 - Hacking & Commiting
2 - Scheduling a test run</p>
<p>At this point we can do #1 fairly easy, but #2 needs a bit of a push (no pun intended), this is where we will need the API keys that we requested,
in the beginning.</p>
<p>We will rely for now, on <code class="language-plaintext highlighter-rouge">openqa-clone-custom-git-refspec</code> which reads configuration parameters from “$OPENQA_CONFIG/client.conf”, “~/.config/openqa/client.conf”
and “/etc/openqa/client.conf” (you can run openqa-cli –help to get more detailed info on this), for now open up your favorite editor and let’s create the directories
and files we’ll need</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir ~/.config/openqa
$EDITOR ~/.config/openqa/client.conf
</code></pre></div></div>
<p>And paste the API keys you already have, you you will be able to post and create jobs on the public instance!</p>
<h2 id="lets-get-hacking">Let’s get hacking</h2>
<p><img src="https://media.giphy.com/media/115BJle6N2Av0A/giphy.gif" alt="Hacker!" /></p>
<p>This part is pretty straightforward once you’ve looked at $HOME/Skynet/os-autoinst-distri-opensuse.</p>
<p>For this round, let’s say we want to also test chrome, in incognito mode. By looking at chrome’s help we know that the <code class="language-plaintext highlighter-rouge">--incognito</code> is a thing</p>
<p>So let’s go to where all the tests are, edit, commit and push our changes</p>
<p>Remember to set up your fork, however if you want to make your life easier use <code class="language-plaintext highlighter-rouge">hub</code> you can find it in the repos too!</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd $HOME/Skynet/os-autoinst-distri-opensuse
vim tests/x11/chrome.pm
git commit -m "Message goes here" tests/x11/chrome.pm
git push $REMOTE
openqa-clone-custom-git-refspec \
https://github.com/foursixnine/os-autoinst-distri-opensuse/tree/test_incognito_in_chrome \
https://openqa.opensuse.org/tests/1792294 \
SCHEDULE=tests/installation/bootloader_start,tests/boot/boot_to_desktop,tests/console/consoletest_setup,tests/x11/chrome \
BUILD=0 \
TEST=openQA-WORKSHOP-ALL-CAPS
</code></pre></div></div>
<p>In the end you will end up with an URL https://openqa.opensuse.org/t1793764, and you will get emails from travis if something is going wrong</p>
<p><a href="https://asciinema.org/a/EplIHYg4UYHKh1MW2q553sPth"><img src="https://asciinema.org/a/EplIHYg4UYHKh1MW2q553sPth.svg" alt="asciicast" /></a></p>
How to edit stuff that you've already commited to git? (And squash as a bonus)2021-05-04T00:00:00+00:00https://foursixnine.io//blog/tech/linux/git/2021/05/04/How-to-edit-stuff-that-you've-already-commited-to-git?<p>So, you’re in the middle of a review, and have couple of commits but one of the comments is asking you to modify a line
that belongs to second to last, or even the first commit in your list, and you’re not willing to do:</p>
<p><code class="language-plaintext highlighter-rouge">git commit -m "Add fixes from the review" $file</code></p>
<p>Or you simply don’t know, and have no idea what <code class="language-plaintext highlighter-rouge">squash</code> or <code class="language-plaintext highlighter-rouge">rebase</code> means?, well I won’t explain <code class="language-plaintext highlighter-rouge">squash</code> today, but I
will explain <code class="language-plaintext highlighter-rouge">rebase</code></p>
<p><img src="https://media.giphy.com/media/O8FdP4NKLFKcU/giphy.gif" alt="DON'T PANIC" /></p>
<p>See how I do it, and also how do I screw up!</p>
<p><a href="https://asciinema.org/a/bUdcrFZRRAzCHQk2EyG7ru9mA"><img src="https://asciinema.org/a/bUdcrFZRRAzCHQk2EyG7ru9mA.svg" alt="asciicast" /></a></p>
<p>It all boils down to making sure that you <strong>trust</strong> git, and hope that things are small enough so that if you lose the
stash, you can always rewrite it.</p>
<p>So in the end, for me it was:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git fetch origin
git rebase -i origin/master # if your branch is not clean, git will complain and stop
git stash # because my branch was not clean, and my desired change was already done
git rebase -i origin/master # now, let's do a rebase
# edit desired commits, for this add the edit (or an e) before the commit
# save and quit vim ([esc]+[:][x] or [esc]+[:][w][q], or your editor, if you're using something else
git stash pop # because I already had my change
$HACK # if you get conflicts or if you want to modify more
# be careful here, if you rewrite history too much
# you will end up in Back to the Future II
# Luckly you can do git rebase --abort
git commit --amend $files #(alternatively, git add $files first then git commit --amend
git rebase --continue
git push -f # I think you will need to add remote+branch, git will remind you
# go on with your life
</code></pre></div></div>
<p>Note: A squash is gonna put all of the commits together, just make sure that there’s an order:</p>
<h2 id="i-lied-heres-a-very-quick-and-dirty-squash-guide">I lied, here’s a very quick and dirty squash guide</h2>
<ul>
<li>pick COMMIT1</li>
<li>pick COMMIT2</li>
<li>squash COMMIT3 # (Git will combine this commit, with the one above iir, so COMMIT2+COMMIT3 and git will ask you for a new commit message)</li>
</ul>
<p><img src="https://media.giphy.com/media/11CCn8sSFSm2kg/giphy.gif" alt="I lied" /></p>
Perl binaries are mismatched - the revenge of the lazy person2021-02-09T00:00:00+00:00https://foursixnine.io//blog/linux/perl/2021/02/09/Perl-binaries-are-mismatched---the-revenge-of-the-lazy-person<h1 id="the-uninvited-eldrich-terror">The uninvited eldrich terror</h1>
<p>You use <a href="https://metacpan.org/pod/local::lib">local::lib</a>, and the pain unfolds: A shell is started, and you find a dreaded:</p>
<div class="language-perl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">Cwd</span><span class="o">.</span><span class="nv">c:</span> <span class="nv">loadable</span> <span class="nv">library</span> <span class="ow">and</span> <span class="nv">perl</span> <span class="nv">binaries</span> <span class="nv">are</span> <span class="nv">mismatched</span> <span class="p">(</span><span class="nv">got</span> <span class="nv">handshake</span> <span class="nv">key</span> <span class="mh">0xdb00080</span><span class="p">,</span> <span class="nv">needed</span> <span class="mh">0xdb80080</span><span class="p">)</span>
</code></pre></div></div>
<p><img src="https://media.giphy.com/media/CiJGnsh7wWXv2/giphy.gif" alt="Pennywise, because I could not find the right gif, from the Uninvited, of Sabrina's netflix" /></p>
<p>Which means: that the module (Cwd in this case) is not compatible (Because it’s an <a href="http://modernperlbooks.com/mt/2009/05/perl-5-and-binary-compatibility.html">XS module</a>)
with your current version of perl, installed on your system: Likely it was compiled for a previous version, leadin to those <a href="https://rt.perl.org/Public/Bug/Display.html?id=133440">binaries mismatching</a></p>
<h2 id="dont-panic">Don’t panic!</h2>
<p>I <a href="/blog/2019/01/21/perl-binaries-are-mismatched.html">wrote about this</a> however, I left out how to get to the point where you have already an usable Perl again?</p>
<h2 id="the-light">The light</h2>
<p>Instead of downloading local::lib from git as I used to do… this time I decided to do it on a much simpler way: use <code class="language-plaintext highlighter-rouge">perl-local-lib</code> from my distribution, and let it do the magic, I mean
that’s why I run <a href="https://get.opensuse.org">openSUSE Tumbleweed</a></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> zypper in perl-local-lib
rm -rf perl5-old || echo "First time eh?"
mv perl5 perl5-old
perl -MCPAN -Mlocal::lib -e 'CPAN::install(App::cpanminus)'
cpanm App::MigrateModules
perl-migrate-modules --from ~/perl5-old/lib/perl5 /usr/bin/perl
</code></pre></div></div>
<p>Et voilà, ma chérie!</p>
<p><img src="https://media.giphy.com/media/xT5LMDi8H2A1FtLlpC/giphy.gif" alt="It's alive!" /></p>
Cron do not send me empty emails2021-01-26T00:00:00+00:00https://foursixnine.io//blog/linux/2021/01/26/Cron-do-not-send-me-empty-emails<p>Just in case, if you’ve ever wondered how to stop <code class="language-plaintext highlighter-rouge">cron</code> from sending empty emails, a quick look at <code class="language-plaintext highlighter-rouge">man mail</code> will give
you the answer you’re looking for (if you know what you’re searching for):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> -E
If an outgoing message does not contain any text in its first or only message part, do not send it but discard it silently,
effectively setting the skipemptybody variable at program startup. This is useful for sending messages from scripts started
by cron(8).
</code></pre></div></div>
<p>I got this after visiting couple of forums, and some threads at stack exchange, however <a href="https://stackoverflow.com/a/14656511">this one</a> nailed it</p>
<p>So all you need to do is, fire up that <code class="language-plaintext highlighter-rouge">crontab -e</code> and make your script run every five minutes, without fear of the noise</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>*/5 * * * * /usr/local/bin/only-talk-if-there-are-errors-script |& mail -E -r $(hostname)@opensuse.org -s "[CRON][monitoring] foo bar $(date --iso-8601='minutes')" do-not-spam-me@example.com
</code></pre></div></div>
<p><em>Et voilà, ma chérie!</em>
<img src="https://media.giphy.com/media/xT5LMDi8H2A1FtLlpC/giphy.gif" alt="It's alive!" /></p>
Quick and dirty ipmitool tutorial2021-01-19T00:00:00+00:00https://foursixnine.io//blog/2021/01/19/Quick-and-dirty-ipmitool-tutorial<h1 id="because-i-always-forget">Because I always forget</h1>
<h2 id="to-reboot-a-supermicro-server">To reboot a SUPERMICRO server:</h2>
<p>Just remember that the default user/password might still be ADMIN/ADMIN :)</p>
<p>ipmitool -I lanplus -H $HOST -U USER -P PASSWORD power cycle</p>
<h2 id="to-connect-to--the-serial-console">To connect to the serial console</h2>
<p>ipmitool -I lanplus -H $HOST -U USER -P PASSWORD sol activate</p>
Ext4 filesystem has no space left on device? You liar!2020-09-15T00:00:00+00:00https://foursixnine.io//blog/linux/tech/filesystems/2020/09/15/Ext4-filesystem-has-no-space-left-on-device?-You-liar!<p><img src="https://imgs.xkcd.com/comics/disk_usage.png" alt="Disk usage" /></p>
<p>So, you wake up one day, and find that one of your programs, starts to complainig about “No space left on device”:</p>
<p>Next thing (Obviously, duh?) is to see what happened, so you fire up <code class="language-plaintext highlighter-rouge">du -h /tmp</code> right?:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ du -h /tmp
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/zkvm1-root 6.2G 4.6G 1.3G 79% /
</code></pre></div></div>
<p><img src="https://media.giphy.com/media/SVgKToBLI6S6DUye1Y/giphy.gif" alt="Well, yes, but no, ok? ok, ok!" /></p>
<p>Wait, what? there’s space there! How can it be? In all my years of experience (+15!), I’ve never seen such thing!</p>
<p>Gods must be crazy!? or is it a 2020 thing?</p>
<p><img src="https://media.giphy.com/media/VcWnY3R6YWVtC/giphy.gif" alt="I disagree with you" /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ touch /tmp
touch: cannot touch ‘/tmp/test’: No space left on device
</code></pre></div></div>
<p><img src="https://media.giphy.com/media/ToMjGpJ1lQiQarAftaU/giphy.gif" alt="Wait, what? not even a small empty file?" />
<img src="https://media.giphy.com/media/XdIOEZTt6dL7zTYWIo/giphy.gif" alt="Ok..." /></p>
<p>After shamelessly googling/duckducking/searching, I ended up at https://blog.merovius.de/2013/10/20/ext4-mysterious-no-space-left-on.html
but alas, that was not my problem, although… perhaps too many files?, let’s check with <code class="language-plaintext highlighter-rouge">du -i</code> this time:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ du -i /tmp
`Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/zkvm1-root 417792 417792 0 100% /
</code></pre></div></div>
<p><img src="https://media.giphy.com/media/xT1R9Up1IZR6AtWdKE/giphy.gif" alt="Of course!" /></p>
<p>Because I’m super smart <del>I’m not</del>, I now <strong>know</strong> where my problem is, too many files!, time to start fixing this…</p>
<p>After few minutes of deleting files, moving things around, bind mounting things, I landed with the actual root cause:</p>
<p>Tons of messages waiting in <a href="https://www.ibm.com/support/pages/varspoolclientmqueue-keeps-filling-and-causes-var-filesystem-usage-exceeded-threshold">/var/spool/clientmqueue</a> to be processed,
I decided to delete some, after all, I don’t care about this system’s mails… so <code class="language-plaintext highlighter-rouge">find /var/spool/clientmqueue -type f -delete</code> does the job, and allows me to have tab completion again! YAY!.</p>
<p>However, because deleting files blindly is never a good solution, I ended up in the link from above, the solution was quite simple:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ systemctl enable --now sendmail
</code></pre></div></div>
<p><img src="https://media.giphy.com/media/W35DnRbN4oDHIAApdk/giphy.gif" alt="Smart idea!" /></p>
<p>After a while, <code class="language-plaintext highlighter-rouge">root</code> user started to receive system mail, and I could delete them afterwards :)</p>
<p>In the end, very simple solution (In my case!) rather than formatting or transfering all the data to a second drive, formatting & playing with inode size and stuff…</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/zkvm1-root 417792 92955 324837 23% /
</code></pre></div></div>
<p><em>Et voilà, ma chérie!</em>
<img src="https://media.giphy.com/media/xT5LMDi8H2A1FtLlpC/giphy.gif" alt="It's alive!" /></p>
<p>This is a very long post, just to say:</p>
<p>ext4 no space left on device can mean: You have no space left, or you don’t have more room to store your files.</p>
Using python virtualenv inside vscode2020-06-14T00:00:00+00:00https://foursixnine.io//blog/2020/06/14/Using-python-virtualenv-inside-vscode<h2 id="quick-and-dirty">Quick and dirty</h2>
<ul>
<li>Install python3-virtualenvwrapper (via pip or via package manager)</li>
<li>Export a workon directory: <code class="language-plaintext highlighter-rouge">export WORKON_HOME=/home/foursixnine/Projects/python-virtualenv</code></li>
<li><code class="language-plaintext highlighter-rouge">source virtualenvwrapper</code></li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>foursixnine@deimos:~/Projects> source virtualenvwrapper
virtualenvwrapper.user_scripts creating /home/foursixnine/Projects/python-virtualenv/premkproject
...
virtualenvwrapper.user_scripts creating /home/foursixnine/Projects/python-virtualenv/get_env_details
</code></pre></div></div>
<ul>
<li>mkvirtualenv newenv</li>
</ul>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>foursixnine@deimos:~/Projects> mkvirtualenv newenv
created virtual environment CPython3.8.3.final.0-64 <span class="k">in </span>115ms
creator CPython3Posix<span class="o">(</span><span class="nv">dest</span><span class="o">=</span>/home/foursixnine/Projects/python-virtualenv/newenv, <span class="nv">clear</span><span class="o">=</span>False, <span class="nv">global</span><span class="o">=</span>False<span class="o">)</span>
seeder FromAppData<span class="o">(</span><span class="nv">download</span><span class="o">=</span>False, <span class="nv">pip</span><span class="o">=</span>latest, <span class="nv">setuptools</span><span class="o">=</span>latest, <span class="nv">wheel</span><span class="o">=</span>latest, <span class="nv">via</span><span class="o">=</span>copy, <span class="nv">app_data_dir</span><span class="o">=</span>/home/foursixnine/.local/share/virtualenv/seed-app-data/v1.0.1<span class="o">)</span>
activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator
virtualenvwrapper.user_scripts creating /home/foursixnine/Projects/python-virtualenv/newenv/bin/predeactivate
...
virtualenvwrapper.user_scripts creating /home/foursixnine/Projects/python-virtualenv/newenv/bin/get_env_details
</code></pre></div></div>
<ul>
<li>By this point, you’re already inside <code class="language-plaintext highlighter-rouge">newenv</code>:</li>
</ul>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">(</span>newenv<span class="o">)</span> foursixnine@deimos:~/Projects>
</code></pre></div></div>
<ul>
<li>You can create multiple virtual environments and switch among them using <code class="language-plaintext highlighter-rouge">workon $env</code> so long as you have sourced <code class="language-plaintext highlighter-rouge">virtualenvwrapper</code> and your <code class="language-plaintext highlighter-rouge">$WORKON_HOME</code> is properly defined.</li>
</ul>
<h2 id="real-business">Real business</h2>
<ul>
<li>Now, if you want to use vscode, remember that you will need to define properly <code class="language-plaintext highlighter-rouge">python.PythonPath</code> for your workspace/project (I’m new to this, don’t hang me in a public square ok?), in this case, my env is called linkedinlearningaiml</li>
</ul>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="nl">"python.pythonPath"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/home/foursixnine/Projects/python-virtualenv/linkedinlearningaiml/bin/python"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>Now your python code will be executed within the context of your virtual environment, so you can get down to serious (or not at all) python development, without screweing up your host or polluting the dependencies and stuff.</p>
<p>PS: Since wanted to be able to run standalone python files, I also needed to change a bit my launch.json (Maybe this is not needed?)</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w"> </span><span class="nl">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0.2.0"</span><span class="err">,</span><span class="w">
</span><span class="nl">"configurations"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="p">{</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Python: Current File"</span><span class="p">,</span><span class="w">
</span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"python"</span><span class="p">,</span><span class="w">
</span><span class="nl">"request"</span><span class="p">:</span><span class="w"> </span><span class="s2">"launch"</span><span class="p">,</span><span class="w">
</span><span class="nl">"program"</span><span class="p">:</span><span class="w"> </span><span class="s2">"${file}"</span><span class="p">,</span><span class="w">
</span><span class="nl">"console"</span><span class="p">:</span><span class="w"> </span><span class="s2">"integratedTerminal"</span><span class="p">,</span><span class="w">
</span><span class="nl">"cwd"</span><span class="p">:</span><span class="w"> </span><span class="s2">"${fileDirname}"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>And off you go, how to use python virtualenv inside vscode</p>
<p><em>Et voilà, ma chérie!</em>
<img src="https://media.giphy.com/media/xT5LMDi8H2A1FtLlpC/giphy.gif" alt="It's alive!" /></p>
Looking for exceptions with awk2020-05-21T00:00:00+00:00https://foursixnine.io//blog/linux/tech/2020/05/21/Looking-for-exceptions-with-awk<p>Sometimes you just need to search using awk or want to use plain bash to search for an exception in a log file, it’s
hard to go into google, stack overflow, duck duck go, or any other place to do a search, and find nothing, or at least
a solution that fits your needs.</p>
<p>In my case, I wanted to know where a package was generating a conflict <a href="https://github.com/os-autoinst/os-autoinst-distri-opensuse/pull/10259/files#diff-141f4b5a48eaecb0c631a0de23e41a51R503">for a friend</a>, and ended up scratching my head,
because I didn’t want to write yet another domain specific function to use on the test framework of openQA, and I’m
very stubborn, I ended up with the following solution</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>journalctl -k | awk 'BEGIN {print "Error - ",NR; group=0}
/ACPI BIOS Error \(bug\)/,/ACPI Error: AE_NOT_FOUND/{ print group"|",
$0; if ($0 ~ /ACPI Error: AE_NOT_FOUND,/ ){ print "EOL"; group++ };
}'
</code></pre></div></div>
<p>This is short for:</p>
<ul>
<li>Define <code class="language-plaintext highlighter-rouge">$START_PATTERN as /ACPI BIOS Error \(bug\)/,</code> and <code class="language-plaintext highlighter-rouge">$END_PATTERN as /ACPI Error: AE_NOT_FOUND/</code></li>
<li>Look for <code class="language-plaintext highlighter-rouge">$START_PATTERN</code></li>
<li>Look for <code class="language-plaintext highlighter-rouge">$END_PATTERN</code></li>
<li>If you find <code class="language-plaintext highlighter-rouge">$END_PATTERN</code> add an <code class="language-plaintext highlighter-rouge">EOL</code> marker (that is not needed, since the group variable will be incremented)</li>
</ul>
<p>And there you go: How to search for exceptions in logs, of course it could be more complicated, because you can have nested
cases and whatnot, but for now, this does exactly what I need:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>EOL
10| May 20 12:38:36 deimos kernel: ACPI BIOS Error (bug): Could not resolve symbol [\_SB.PCI0.LPCB.HEC.CHRG], AE_NOT_FOUND (20200110/psargs-330)
10| May 20 12:38:36 deimos kernel: ACPI Error: Aborting method \PNOT due to previous error (AE_NOT_FOUND) (20200110/psparse-529)
10| May 20 12:38:36 deimos kernel: ACPI Error: Aborting method \_SB.AC._PSR due to previous error (AE_NOT_FOUND) (20200110/psparse-529)
10| May 20 12:38:36 deimos kernel: ACPI Error: AE_NOT_FOUND, Error reading AC Adapter state (20200110/ac-115)
EOL
11| May 20 12:39:12 deimos kernel: ACPI BIOS Error (bug): Could not resolve symbol [\_SB.PCI0.LPCB.HEC.CHRG], AE_NOT_FOUND (20200110/psargs-330)
11| May 20 12:39:12 deimos kernel: ACPI Error: Aborting method \PNOT due to previous error (AE_NOT_FOUND) (20200110/psparse-529)
11| May 20 12:39:12 deimos kernel: ACPI Error: Aborting method \_SB.AC._PSR due to previous error (AE_NOT_FOUND) (20200110/psparse-529)
11| May 20 12:39:12 deimos kernel: ACPI Error: AE_NOT_FOUND, Error reading AC Adapter state (20200110/ac-115)
EOL
12| May 20 13:37:41 deimos kernel: ACPI BIOS Error (bug): Could not resolve symbol [\_SB.PCI0.LPCB.HEC.CHRG], AE_NOT_FOUND (20200110/psargs-330)
12| May 20 13:37:41 deimos kernel: ACPI Error: Aborting method \PNOT due to previous error (AE_NOT_FOUND) (20200110/psparse-529)
12| May 20 13:37:41 deimos kernel: ACPI Error: Aborting method \_SB.AC._PSR due to previous error (AE_NOT_FOUND) (20200110/psparse-529)
12| May 20 13:37:41 deimos kernel: ACPI Error: AE_NOT_FOUND, Error reading AC Adapter state (20200110/ac-115)
EOL
</code></pre></div></div>
<p>So I could later write some code that looks per string, separates the string using the pipe <code class="language-plaintext highlighter-rouge">|</code> discards the group id, and adds that record to an array
of arrays or hashes: <code class="language-plaintext highlighter-rouge">[ {group: id, errors: [error string .. error string] ]</code></p>
How to import a gpg key on zypper (openSUSE)2020-05-07T00:00:00+00:00https://foursixnine.io//blog/linux/tech/2020/05/07/How-to-import-a-gpg-key-on-zypper-(openSUSE)<p>For some odd reason, I couldn’t find quickly (2 mins in the manpage and some others on DuckDuckGo) a way to import a
GPG key.</p>
<p><img src="https://media.giphy.com/media/L3pfVwbsJbrk4/giphy.gif" alt="" /></p>
<p>Just because one of the repos gives this ugly message:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Repository vscode does not define additional 'gpgkey=' URLs.
Warning: File 'repomd.xml' from repository 'vscode' is signed with an unknown key 'EB3E94ADBE1229CF'.
Note: Signing data enables the recipient to verify that no modifications occurred after the data
were signed. Accepting data with no, wrong or unknown signature can lead to a corrupted system
and in extreme cases even to a system compromise.
Note: File 'repomd.xml' is the repositories master index file. It ensures the integrity of the
whole repo.
Warning: We can't verify that no one meddled with this file, so it might not be trustworthy
anymore! You should not continue unless you know it's safe.
</code></pre></div></div>
<p>I know you can use <code class="language-plaintext highlighter-rouge">zypper ar --gpg-auto-import-keys</code>, but I didn’t do it when I added it (and I’m too lazy to remove
the repo and add it again, just to see if it works)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rpm --import https://packages.microsoft.com/keys/microsoft.asc
zypper ref
</code></pre></div></div>
Roundcube smtp (250) authentication failed2019-09-27T00:00:00+00:00https://foursixnine.io//blog/2019/09/27/Roundcube-smtp-(250)-authentication-failed<p>So, say you find yourself, somehow having the following error in the roundcube logs:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[27-Sep-2019 12:44:48 +0000]: <f930f680> PHP Error: SMTP server does not support authentication (POST /?_task=mail&_unlock=loading1569588324419&_framed=1&_lang=es&_action=send)
[27-Sep-2019 12:44:48 +0000]: <f930f680> SMTP Error: Authentication failure: SMTP server does not support authentication (Code: ) in /roundcube/program/lib/Roundcube/rcube.php on line 1674 (POST /correo/?_task=mail&_unlock=loading 1569588324419&_framed=1&_lang=es&_action=send)
</code></pre></div></div>
<p>You have tried everything, but still can’t seem to be able to send email from roundcube, you keep getting this annoying
“SMTP (250) authentication failed” notification, every time you click “Send”.</p>
<p>Well… Make sure that your server is connecting to the right place. It took me a while to realize that roundcube was
trying to connect to localhost, but somehow the authentication mechanism stopped working (it was before upgrading).</p>
<p>Since I don’t really want to debug too much today (it’s friday after all), and because my configuration/use case is
over ssl/tls, the solution to the probem was simply:</p>
<p><code class="language-plaintext highlighter-rouge">$config['smtp_server'] = 'tls://services.host.co';</code></p>
<p>Et voilà, ma chérie!</p>
<p><img src="https://media.giphy.com/media/xT5LMDi8H2A1FtLlpC/giphy.gif" alt="It's alive!" /></p>
When find can't find2019-08-27T00:00:00+00:00https://foursixnine.io//blog/tech/2019/08/27/When-find-can't-find<p>If you happen to be using <a href="http://man7.org/linux/man-pages/man1/find.1.html">gnu find</a> in the deadly combination with
a directory that is a symlink (you just don’t know that yet), you will find face the hard truth that running:</p>
<p><code class="language-plaintext highlighter-rouge">find /path/to/directory -type f</code></p>
<p>Will return <em>zero</em>, <strong>nada</strong>, <em>nichts</em>, <del>meiyou</del>, which is annoying.</p>
<p><img src="https://media.giphy.com/media/clupdT5vHL9GifMlnC/giphy.gif" alt="where is it!" /></p>
<p>this will make you question your life decisions, and your knowledge on tools that you use daily, only to find out that
the directory is actually a symlink :).</p>
<p>So next time you find yourself using <code class="language-plaintext highlighter-rouge">find</code> and it returns nothing, but you are sure that your syntax is correct and get
no errors, try adding the <code class="language-plaintext highlighter-rouge">--fowllow</code> or use the <code class="language-plaintext highlighter-rouge">-L</code></p>
<p>` find -L /path/to/directory/with/symlink -type f`</p>
<p>This will do what you want :)</p>
<p><img src="https://media.giphy.com/media/1FnPDkhFZDgoU/giphy.gif" alt="Here is it!" /></p>
Permission denied for hugepages in QEMU without libvirt2019-06-18T00:00:00+00:00https://foursixnine.io//blog/2019/06/18/Permission-denied-for-hugepages-in-QEMU-without-libvirt<p>So, say you’re running qemu, and decided to use hugepages, nice isn’t it? helps with performace and stuff, however
a wild wall appears!</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> QEMU: qemu-system-aarch64: can't open backing store /dev/hugepages/ for guest RAM: Permission denied
</code></pre></div></div>
<p>This basically means that you’re using the amazing <em>-mem-path /dev/hugepages</em>, and that QEMU running as an unprivileged user can’t
write there… This is how it looked for me:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -u _openqa-worker qemu-system-aarch64 -device virtio-gpu-pci -m 4094 -machine virt,gic-version=host -cpu host \
-mem-prealloc -mem-path /dev/hugepages -serial mon:stdio -enable-kvm -no-shutdown -vnc :102,share=force-shared \
-cdrom openSUSE-Tumbleweed-DVD-aarch64-Snapshot20190607-Media.iso \
-pflash flash0.img -pflash flash1.img -drive if=none,file=opensuse-Tumbleweed-aarch64-20190607-gnome-x11@aarch64.qcow2,id=hd0 \
-device virtio-blk-device,drive=hd0
</code></pre></div></div>
<p>The machine tries to start, but utimately I get that dreadful message.
You can simply do a chmod to the directory, use an udev rule, and get away with it, it’s quick and does the job but also
there are few options to solve this using libvirt, however if you’re not using <a href="https://linux.die.net/man/8/hugeadm">hugeadm</a>
to manage those pools and let the operating system take care of it, likely the operating system will take care of this for you,
so you can look to <code class="language-plaintext highlighter-rouge">/usr/lib/systemd/system/dev-hugepages.mount</code>, since trying to add an udev rule failed for a colleague of mine,
I decided to use the systemd approach, ending up with the following:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
[Unit]
Description=Systemd service to fix hugepages + qemu ram problems.
After=dev-hugepages.mount
[Service]
Type=simple
ExecStart=/usr/bin/chmod o+w /dev/hugepages/
[Install]
WantedBy=multi-user.target
</code></pre></div></div>
Table to json with jq and awk2019-05-08T00:00:00+00:00https://foursixnine.io//blog/2019/05/08/Table-to-json<h2 id="the-problem">The problem</h2>
<p>Say you have a table that looks like this:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>AGGREGATE_NEEDED 1
ARCH x86_64
BASE_TEST_ISSUES NUMBER
BUILD :NUMBER:PACKAGE
DISTRI DISTRIBUTION
FLAVOR Server-DVD-Incidents-Install
INCIDENT_ID 99999
</code></pre></div></div>
<p>It’s just that it contains about 78 or more entries. Of course for a very skilled engineer or a person with
a lot of tricks under the hood, this might be a very trivial task in vim or something like this, I guess that
with a couple of replaces here and there, you’d get somewhere; but I’m not skilled, other than at eating.</p>
<h2 id="the-solution">The Solution</h2>
<p>So I took my Key Value table saved it to a file and after googling a bit, now I’m more versed into awk :D:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> cat FILE.txt | \
awk 'BEGIN { print "{" } \
{ printf "\"%s\":\"%s\",", $1,$2} \
END { print "\"MANUALLY_GENERATED_ISO_POST\":1 }" }'
| jq > x86_64-ready.json'"}'
</code></pre></div></div>
<p>I guess this could have been done easier and prettier, but fits my need and might save you too at some point.
Just make sure you have <code class="language-plaintext highlighter-rouge">jq</code> installed ok?</p>
About Perl and mismatched binaries2019-01-21T00:00:00+00:00https://foursixnine.io//blog/2019/01/21/perl-binaries-are-mismatched<h1 id="the-horror">The horror</h1>
<p>You happen to update your system (In my case, I use Tumbleweed or Gentoo) and there’s new version of Perl,
at some point there’s the realization that you’re using <a href="https://metacpan.org/pod/local::lib">local::lib</a>, and
the pain unfolds: A shell is started, and you find a dreaded:</p>
<div class="language-perl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">Cwd</span><span class="o">.</span><span class="nv">c:</span> <span class="nv">loadable</span> <span class="nv">library</span> <span class="ow">and</span> <span class="nv">perl</span> <span class="nv">binaries</span> <span class="nv">are</span> <span class="nv">mismatched</span> <span class="p">(</span><span class="nv">got</span> <span class="nv">handshake</span> <span class="nv">key</span> <span class="mh">0xdb00080</span><span class="p">,</span> <span class="nv">needed</span> <span class="mh">0xdb80080</span><span class="p">)</span>
</code></pre></div></div>
<p>Which means: that the module (Cwd in this case) is not compatible (Because it’s an <a href="http://modernperlbooks.com/mt/2009/05/perl-5-and-binary-compatibility.html">XS module</a>)
with your current version of perl, installed on your system: Likely it was compiled for a previous version, leadin to those <a href="https://rt.perl.org/Public/Bug/Display.html?id=133440">binaries mismatching</a></p>
<h2 id="dont-panic">Don’t panic!</h2>
<p>In the past, I used to reinstall my full local::lib directory, however after hanging out and asking few questions on #toolchain on irc.perl.org, I got to write (or rather hack, an ugly hack) a
quick perl script to walk the <a href="https://github.com/foursixnine/stunning-octo-chainsaw/blob/master/ll-walker.pl">local::lib</a> packages that were installed already, only looking at the specified
directory… it worked well, gave me the list of what I needed so I could reinstall later, however Grinnz pointed me to his <a href="https://bit.ly/2CwLXvb">perl-migrate-modules</a> script, to which after chatting a bit,
he added the <code class="language-plaintext highlighter-rouge">from</code> switch, which allows people to reinstall all the modules that were present in an old local::lib directory:</p>
<h2 id="the-light">The light</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Migrate modules from an old (inactive) local::lib directory
$ perl-migrate-modules --from ~/perl5-old/lib/perl5 /usr/bin/perl
</code></pre></div></div>
<p>Hope you find it useful :)</p>
Open Build Service- Contributing on a project2019-01-21T00:00:00+00:00https://foursixnine.io//blog/2019/01/21/Open-Build-Service-Contributing-on-a-project<p>Here at SUSE we heavily use <a href="http://openbuildservice.org">Open Build Service</a>,
and often while collaborating on a project (In my case, <a href="https://openqa.opensuse.org">openQA</a>) one has to add a new package
as a dependency from time to time, or has to do a backport for an older SLE or openSUSE Leap release</p>
<p>It boils down to the following steps, in this case I wanted to change the project to build against
SUSE:SLE-12-SPX:Update instead of SUSE:SLE-12-SPX:GM which is a <a href="https://en.opensuse.org/openSUSE:Build_Service_supported_build_targets">build target</a> that will get the updates while the GM doesn’t,
all this, because I wanted to add openvswitch to the project, so that we could use new features in our openQA deployments.</p>
<p>To do this, after setting up the obs account, it boils down to:</p>
<p>1- Branch your project
2- <a href="https://en.opensuse.org/openSUSE:Build_Service_Concept_project_linking">Link</a> your packages
2- Modify the project metadata if needed
3- Modify the project config if errors related to multiple choices appear (PostgreSQL will be there for sure!)
4- Grab a cup of coffee/tea/water and do <a href="https://en.opensuse.org/openSUSE:Build_Service_Tips_and_Tricks">some reading</a> while waiting for the build</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Branch the project</span>
osc branch devel:openQA:SLE-12
<span class="c"># Link the new package</span>
osc linkpac openSUSE:Factory openvswitch
<span class="c"># More and more packages will say that their dependencies cannot be resolved, this is</span>
<span class="c"># you might spend some time here adding bunch of dependencies :)</span>
osc linkpac openSUSE:Factory dpdk devel:openQA:SLE-12
osc linkpac openSUSE:Factory python-six devel:openQA:SLE-12
</code></pre></div></div>
<p>By this point you might get error messages on the webUI stating that:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$a_package: have choice for $conflicting_package needed by $a_package: $options
</code></pre></div></div>
<p>As an example, it might happen that you see postgres-server there, having
postgres96-server and postgres94-server as <code class="language-plaintext highlighter-rouge">$options</code>, you’ve got to choose
your destiny!.</p>
<p>When you find this, it’s time to edit the project configuration:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Since
osc meta prjconf devel:openQA:SLE-12 -e
# An editor will open and you will be able to change stuff
# Remember that you need write permissions on the project!
...
Prefer: postgresql96-devel
Prefer: postgresql96-server
Prefer: python-dateutil
...
</code></pre></div></div>
<p>Modify the project metadata to use :Updates instead of :GM, and change architectures
if you need to do so.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code># same as before: An editor will open, and you will be able to edit stuff
osc meta prjconf devel:openQA:SLE-12 -e
<span class="nt"><repository</span> <span class="na">name=</span><span class="s">"SLE_12_SP4"</span><span class="nt">></span>
<span class="nt"><path</span> <span class="na">project=</span><span class="s">"SUSE:SLE-12-SP4:Update"</span> <span class="na">repository=</span><span class="s">"standard"</span><span class="nt">/></span>
<span class="nt"><arch></span>x86_64<span class="nt"></arch></span>
<span class="nt"><arch></span>aarch64<span class="nt"></arch></span>
<span class="nt"><arch></span>ppc64le<span class="nt"></arch></span>
<span class="nt"></repository></span>
</code></pre></div></div>
<p>After this, a project rebuild will take place, sit down and give some more reading :)</p>
gentoo eix-update failure2018-11-04T00:00:00+00:00https://foursixnine.io//blog/2018/11/04/gentoo-eix-update-failure<h2 id="summary">Summary</h2>
<p>If you are having the following error on your Gentoo system:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Can't open the database file '/var/cache/eix/portage.eix' for writing (mode = 'wb')
</code></pre></div></div>
<p>Don’t waste your time, simply the /var/cache/eix directory is not present and/or writeable by the eix/portage use</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir -p /var/cache/eix
chmod +w /var/cache/eix*
</code></pre></div></div>
<p>Basic story is that eix will drop privileges to portage user when ran as root.</p>
Setting up postfix, dovecot and sieve2018-10-26T00:00:00+00:00https://foursixnine.io//blog/2018/10/26/postfix-dovecot-sieve<h1 id="the-horror">The horror</h1>
<p>While trying to set up my mail system, I ran into multiple tutorials to figure
out what was the best way to avoid multiple error messages, mainly because you,
like me (you silly human!), simply copy and pasted random stuff from stack
overflow, and tutorials in howtoforge and places like that…</p>
<h2 id="the-mistakes">The mistakes</h2>
<p>You tried something like this</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>spamassassin unix - n n - - pipe flags=DROhu user=vmail argv=/usr/bin/spamc -e /usr/lib/dovecot/deliver -f ${sender} -d ${user}@${nexthop}
</code></pre></div></div>
<p>or this:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mailbox_transport = lmtp:unix:private/lmtp
virtual_transport = lmtp:unix:private/lmtp
</code></pre></div></div>
<h2 id="the-pain">The pain</h2>
<p>so you ended up with something that looks similar to this:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Oct 24 01:13:24 nergal postfix/pipe[10207]: fatal: get_service_attr: unknown username: vmail
Oct 24 01:13:25 nergal postfix/master[10104]: warning: process /usr/lib/postfix/bin//pipe pid 10207 exit status 1
Oct 24 01:13:25 nergal postfix/qmgr[10106]: warning: private/spamassassin socket: malformed response
Oct 24 01:13:25 nergal postfix/master[10104]: warning: /usr/lib/postfix/bin//pipe: bad command startup -- throttling
Oct 24 01:13:25 nergal postfix/qmgr[10106]: warning: transport spamassassin failure -- see a previous warning/fatal/panic logfile record for the problem description
</code></pre></div></div>
<h2 id="resignation">Resignation</h2>
<p>So what worked for me was to leave the service in the master.cf as I had it working…</p>
<p>and simply add to master.cf</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>spamassassin unix - n n - - pipe flags=R user=app argv=/usr/bin/spamc -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}
</code></pre></div></div>
<p>and in the main.cf</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mailbox_command = /usr/lib/dovecot/deliver
</code></pre></div></div>
<h2 id="the-light">The light</h2>
<p>Sieve filtering started to work after these changes :)</p>
<ul>
<li>Check <a href="https://www.vultr.com/docs/simple-mailserver-postfix-dovecot-sieve-centos-7">This article</a>
that gave me that life saving line</li>
</ul>
Visa, Venezuela, Prorroga2018-10-23T00:00:00+00:00https://foursixnine.io//blog/venezuela/2018/10/23/prorroga-venezolana<h1 id="como-renovar-visa-como-venezolano-con-prorroga-y-no-morir-en-el-intento">Como renovar visa como Venezolano con prorroga y no morir en el intento</h1>
<p>Si llegaste hasta este lugar, es porque eres posiblemente Venezolano, y estas en la penosa necesidad de necesitar una prorroga,
pero tambien debes renovar tu visa de residente sea en el pais que estes.</p>
<p>Ya que no encontre informacion clara de el proceso, aca dejo los pasos que tuve que seguir en Alemania:</p>
<ol>
<li>Solicitar la prorroga en la pagina de Saime, y pagar el monto.</li>
<li>Mientras llega la prorroga, llama a la embajada de Venezuela que te corresponde y solicita una constancia de tramite de prorroga.</li>
<li>Comunicate con la autoridad de migracion de el pais donde necesites renovar tu visa, y solicita la extension de tu visa, asegurate de entregar la constancia de que estas tramitando tu prorroga.</li>
<li>En el transcurso del tiempo entre que solicitas la cita para extender tu visa, y el momento de la cita, puede ser que la prorroga te llegue, aparecete en la cita con tu flamante prorroga, si esta no llega, te otorgaran un permiso temporal, mientras te llega la prorroga, una vez que te llegue, dirigete al paso 3.</li>
<li>Disfrute de dos años mas de estancia :)</li>
</ol>
<h2 id="cuanto-tiempo-toma">Cuanto tiempo toma?</h2>
<p>Entropia. No estoy seguro de cuanto tiempo toma, hay personas a las que le toma un par de meses, y a otros les toma 3-6 meses… asi que a esperar.</p>
<h2 id="no-se-como-solicitar-la-prorroga">No se como solicitar la prorroga!</h2>
<p>Una explicacion flash: Una vez que ingreses con tu usuario y contraseña en la pagina de saime:</p>
<ol>
<li>Situate en la opcion “En el extranjero” - <img src="/assets/images/prorroga/prorroga-1.jpg" alt="Paso 1" /></li>
<li>Mueve el mouse (Horizontalmente funciona bastante bien) hacia la opcion: “Obtencion de prorroga de pasaporte electronico” <img src="/assets/images/prorroga/prorroga-2.jpg" alt="paso 2" /></li>
<li>Luego de ver un anuncio sobre la prorroa, deberias poder ver esto: <img src="/assets/images/prorroga/prorroga-3.jpg" alt="paso 3" /></li>
<li>En caso de que los pasos arriba mencionados no funcionen, una vez que logres ingresar a la web de saime con tu usuario y contraseña, puedes intentar esta url directamente: https://tramites.saime.gob.ve/index.php?r=inicio/inicio/prorrogaconsular</li>
</ol>
<p>Si tienes alguna duda, puedes escribirme a @foursixnine en instagram o en twitter, o en ‘i+blog @ foursixnine <em>punto</em> io’</p>
Merge two git repositories2018-07-11T00:00:00+00:00https://foursixnine.io//blog/tech/2018/07/11/git-without-history<p>I just followed this <a href="https://medium.com/@spences10/git-allow-unrelated-histories-a39a3814b981">medium post</a>, but long story short:</p>
<p>Check out the origin/master branch and make sure my local master, is equal to
origin, then push it to my fork (I seldomly do git pull on master).</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> git fetch origin
git checkout master
git reset <span class="nt">--hard</span> origin/master
git push foursixnine
</code></pre></div></div>
<p>I needed to add the remote that belongs to a complete different repository:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> git remote add acarvajal gitlab@myhost:acarvajal/openqa-monitoring.git
git fetch acarvajal
git checkout <span class="nt">-b</span> merge-monitoring
git merge acarvajal/master <span class="nt">--allow-unrelated-histories</span>
</code></pre></div></div>
<p>Tadam! my changes are there!</p>
<p>Since I want everything inside a specific directory:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">mkdir </span>openqa/monitoring
git <span class="nb">mv</span> <span class="k">${</span><span class="nv">allmyfiles</span><span class="k">}</span> openqa/monitoring/
</code></pre></div></div>
<p>Since the unrelated repository had a README.md file, I need to make sure that
both of them make it into the cut, the one from my original repo, and the other
from the new unrelated repo:</p>
<p>Following command means: checkout README.md from acarvajal/master.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> git checkout acarvajal/master <span class="nt">--</span> README.md
git <span class="nb">mv </span>README.md openqa/monitoring/
</code></pre></div></div>
<p>Following command means: checkout README.md from origin/master.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> git checkout origin/master <span class="nt">--</span> README.md
</code></pre></div></div>
<p>Commit changes, push to my fork and open pull request :)</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> git commit
git push foursixnine
</code></pre></div></div>
Insomnia2009-08-29T00:00:00+00:00https://foursixnine.io//blog/2009/08/29/Insomnia<p><img src="https://imgs.xkcd.com/comics/insomnia.png" alt="Insomnia from XKCD" /></p>