<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Igmar&#39;s tech talk</title>
		<link>https://www.palsenberg.com/</link>
		<description>Recent content on Igmar&#39;s tech talk</description>
		<generator>Hugo 0.151.0 -- gohugo.io</generator>
		<language>en-us</language>
		<copyright>Igmar Palsenberg</copyright>
		<lastBuildDate>Fri, 24 Oct 2025 15:20:09 +0200</lastBuildDate>
		<atom:link href="https://www.palsenberg.com/index.xml" rel="self" type="application/rss+xml" />
		<item>
			<title>Sigasi cli in CICD</title>
			<link>https://www.palsenberg.com/2025/10/24/sigasi-cli-in-cicd/</link>
			<pubDate>Fri, 24 Oct 2025 15:20:09 +0200</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2025/10/24/sigasi-cli-in-cicd/</guid>
			<description>&lt;p&gt;If you happen to have a license of &lt;a href=&#34;https://www.sigasi.com/solutions/&#34;&gt;SVH Enterprise Edition&lt;/a&gt;, or like me, have a trial license, you also can use the CLI features of SVH.&lt;/p&gt;
&lt;p&gt;A few things on the CLI. As of the 2025.3 release, the CLI is part of the VSCode extension, but by default, it ends up in a bit unconvenient location :&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/.config/Code/User/globalStorage/sigasi.sigasi-visual-hdl/cli/sigasi-cli&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;for me. You will need to add that to your path (or better, symlink it in &lt;code&gt;$HOME/bin&lt;/code&gt;. I prefer a manual CLI installation.
On a build agent, you will need the separate installation anyway, else it will require a headless VSCode installation, and that is way harder then a download + unzip of the sigasi-cli installation.&lt;/p&gt;
&lt;p&gt;The separate download is available &lt;a href=&#34;https://www.sigasi.com/downloads/&#34;&gt;here&lt;/a&gt;. To install it, unzip it into a location of preference, and make sure the directory is in your &lt;code&gt;PATH&lt;/code&gt; variable, so calling &lt;code&gt;sigasi-cli&lt;/code&gt; actually works.
The CLI is a licensed feature, so you need to set &lt;code&gt;SIGASI_LM_LICENSE_FILE&lt;/code&gt; to the correct location of the license file, and make sure the user calling &lt;code&gt;sigasi-cli&lt;/code&gt; has access to both the installed CLI, as well as the specified license file.&lt;/p&gt;
&lt;p&gt;First, let me explain the value of the Sigasi CLI : it allows for automation of operations that are otherwise not easy to do outside of VSCode, and it can be used to safeguard project quality in your CICD pipeline.
If you are a software developer, the IDE and CICD pipeline safeguard certain aspects of your project. If you happen to code in Go for example, most IDE&amp;rsquo;s already call &lt;code&gt;go fmt&lt;/code&gt; on your Go files.&lt;/p&gt;
&lt;h1 id=&#34;code-formatting&#34;&gt;Code formatting&lt;/h1&gt;
&lt;p&gt;If you use CICD and work with Go projects, you can use a &lt;a href=&#34;https://github.com/golang/go/blob/release-branch.go1.1/misc/git/pre-commit&#34;&gt;pre-commit hook&lt;/a&gt; to automatically reject commits that contain unformatted code.&lt;/p&gt;
&lt;p&gt;Why would you want that in the first place ? Well, different whitespace settings in IDE&amp;rsquo;s can cause very long diffs in version control. It takes focus away from engineers from things that really matter : Functional changes.&lt;/p&gt;
&lt;p&gt;Lets give an example. First, a piece of (badly) formatted VHDL code&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-vhdl&#34; data-lang=&#34;vhdl&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;library&lt;/span&gt; IEEE;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;use&lt;/span&gt; IEEE.std_logic_1164.&lt;span style=&#34;color:#66d9ef&#34;&gt;all&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;entity&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;and_gate&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;port&lt;/span&gt; ( a &lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;std_logic&lt;/span&gt;; b &lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;std_logic&lt;/span&gt;; y &lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;std_logic&lt;/span&gt;); &lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;entity&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;and_gate&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;architecture&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;rtl&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;of&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;and_gate&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;begin&lt;/span&gt; y &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;=&lt;/span&gt; a &lt;span style=&#34;color:#66d9ef&#34;&gt;and&lt;/span&gt; b; &lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;architecture&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;rtl&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, both the entity, as wel as the architecture declaration are one liners. Syntactically, it is correct, the parser will have no issue with it, and the resulting netlist will be a correct one.&lt;/p&gt;
&lt;p&gt;Is it easy to read (image a 1000 line file) : Probably not, at least, not for me.&lt;/p&gt;
&lt;p&gt;So, lets try to fix that :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sigasi-cli format --align --keywords&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;lowercase --spaces-for-tabs --vhdl-version &lt;span style=&#34;color:#ae81ff&#34;&gt;2008&lt;/span&gt; bad_example.vhd --out&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;formatted.vhd
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;which will result in&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-vhdl&#34; data-lang=&#34;vhdl&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;library&lt;/span&gt; IEEE;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;use&lt;/span&gt; IEEE.std_logic_1164.&lt;span style=&#34;color:#66d9ef&#34;&gt;all&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;entity&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;and_gate&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;port&lt;/span&gt;(a &lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;std_logic&lt;/span&gt;; b &lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;std_logic&lt;/span&gt;; y &lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;out&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;std_logic&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;entity&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;and_gate&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;architecture&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;rtl&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;of&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;and_gate&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;begin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    y &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;=&lt;/span&gt; a &lt;span style=&#34;color:#66d9ef&#34;&gt;and&lt;/span&gt; b;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;architecture&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;rtl&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Unfortunately, the formatted lacks verilog support, as well as configuration options for the formatted. For verilog, there is &lt;code&gt;verible-verilog-format&lt;/code&gt; which works well, as has configuration options for determining how it formats. Downside : Another tool to install in the CICD agent.&lt;/p&gt;
&lt;p&gt;So, why does this matter ? If you are a lonely designer like I am, probably not. If you are part of a team, it matter a lot. Looking at the example above, both are valid VHDL files. If one developer uses one version, and another developer uses the other, and it ends up in version control, the diff will look like&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;--- bad.vhd     2025-10-11 18:55:41.282057461 +0100
+++ good.vhd    2025-10-11 18:55:47.554132357 +0100
@@ -1,6 +1,11 @@
 library IEEE;
 use IEEE.std_logic_1164.all;
 
-entity and_gate is port ( a : in  std_logic; b : in  std_logic; y : out std_logic); end entity and_gate;
+entity and_gate is
+    port(a : in std_logic; b : in std_logic; y : out std_logic);
+end entity and_gate;
 
-architecture rtl of and_gate is begin y &amp;lt;= a and b; end architecture rtl;
+architecture rtl of and_gate is
+begin
+    y &amp;lt;= a and b;
+end architecture rtl;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Are there ways to limit the impact of whitespace ? Sure. Do you want to use it : No. Desigers should focus on the design, not on how the code is formatted, or if code conventions are lived after. That is what we have IDE&amp;rsquo;s for.&lt;/p&gt;
&lt;h1 id=&#34;style-validation&#34;&gt;Style validation&lt;/h1&gt;
&lt;p&gt;Sigasi SVH has options to set requirements for a coding style to be used. Do you want all input ports to start with &lt;code&gt;i_&lt;/code&gt; ? You can configure that in SVH.
The same applies to many other options related to verilog / VHDL coding styles. You can flag violation of the requirements on info, warning and error level.&lt;/p&gt;
&lt;p&gt;Setting the style validation option in a project level will result in a file being writtin in the .settings directory in the project.
Those files can be added in version control.&lt;/p&gt;
&lt;p&gt;Doing a &lt;code&gt;sigasi-cli verify .&lt;/code&gt; from the CICD pipeline on the checked-out project will result in the validation being run, and that includes style validation.&lt;/p&gt;
&lt;p&gt;Setting the input port pattern to &lt;code&gt;^xx_.*&lt;/code&gt; will, and using a name that doesn&amp;rsquo;t match will result in validation messages like below.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;rtl/z80/z80_debug.v:10:16: WARNING: Naming convention violation: input port name should match pattern &amp;#39;xx_.*&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this case, its a warning, but you can also set it to ERROR level. Adding this to a pipeline is a next step in making checked in code comply to company guidelines, and reject code that fails to meet the guidelines.&lt;/p&gt;
&lt;p&gt;If you have really big projects, this can help in maintaning a consistent style.&lt;/p&gt;
&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;The above options provide some basic guidelines how to use the Sigasi CLI in your CICD pipeline. It can do all kinds of validation, based on settings that developers set in their IDE.
Doing so helps to keep a project maintainable.&lt;/p&gt;
&lt;p&gt;The tools is agnostic of the actual CICD pipeline used, but since its bound to a flexlm issued license, using a PaaS / SaaS hosted CICD solution will probably not work.
Most solutions will allow to run your own agent, and that does allow to use licensed features.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Running Lattice Diamond on Fedora 42</title>
			<link>https://www.palsenberg.com/2025/10/06/lattice-diamond-on-fedora-42/</link>
			<pubDate>Mon, 06 Oct 2025 10:39:10 +0200</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2025/10/06/lattice-diamond-on-fedora-42/</guid>
			<description>&lt;p&gt;As some of you might know, next to a BsC in computer science, I also have a degree in electronics. I never used to do anything with that long-gone knowledge,
but since a few week backs, I revived an old hobby of mine : Retro computing.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m especially fond of the &lt;a href=&#34;https://en.wikipedia.org/wiki/MSX&#34;&gt;MSX&lt;/a&gt;, which I also own myself. It was also the first computer I get aquited to.&lt;/p&gt;
&lt;p&gt;Going back to that era also mean going back to the time you can create your own hardware, and writing software often meant assembly and in-depth hardware knowledge. There days, most is abstracted away by drivers and high-level interfaces (DirextX, OpenGL), and modern compilers take away most need to learn and use assembly language.&lt;/p&gt;
&lt;p&gt;Doing you own hardware there days is more &amp;rsquo;easy&amp;rsquo; then back in the 80&amp;rsquo;s due to the arrival of FPGA&amp;rsquo;s, which provide you with the means to create complex hardware platforms at a cheap price. Boards with an Lattice ECP5 or Gowin FPGA are very affordable these days (&amp;lt; 100 Euro&amp;rsquo;s&amp;gt;).
Developing for FPGA&amp;rsquo;s is done in either Verilog or VHDL (yes, other HDL&amp;rsquo;s also exist, I know, but those are far from mainstream), two Hardware Description Languages. Looks like a regular programming language (the Verilog language looks like C), but its a descriptive language, which means you don&amp;rsquo;t always get what you want.
Hardware also involved timing and concurrency by default, which both don&amp;rsquo;t play a vital role in software development. Being able to do both makes you a better developer, being it in hardware or in software.&lt;/p&gt;
&lt;p&gt;With FPGA&amp;rsquo;s in most cases come&amp;hellip; vendor tools. In the software world, most is free. In the hardware world, most is priced involving lots of digits. For homebrew development, most vendors (Lattice, Intel, Gowin) provide &amp;lsquo;free&amp;rsquo; versions that are usually limited in features and device support. The paid versions start at approx. 3k USD per year, and that goes up to 100k.&lt;/p&gt;
&lt;p&gt;This blog is about Lattice Diamond, tooling that comes from the vendor and does &lt;a href=&#34;https://www.latticesemi.com/Products/FPGAandCPLD/ECP5&#34;&gt;ECP5 FPGA&lt;/a&gt;&amp;rsquo;s. Without a license, you can use the most common devices.
For hobby stuff, I own 2 devices : A Lenovo T580 and a Dell XPS13, both running Fedora Core 42. The T580 also runs windows because I play games on steam as well.&lt;/p&gt;
&lt;p&gt;So, lets get this thing running.&lt;/p&gt;
&lt;h1 id=&#34;download--installation&#34;&gt;Download &amp;amp; installation&lt;/h1&gt;
&lt;p&gt;Your journey starts at the &lt;a href=&#34;https://www.latticesemi.com/latticediamond&#34;&gt;download site for the Diamond software&lt;/a&gt;. Pick the Linux RPM version (no, that doesn&amp;rsquo;t actually deliver an RPM).&lt;/p&gt;
&lt;p&gt;Create a new empty dir, and unpack the zip file in that directory. You&amp;rsquo;ll find a single file, called &lt;code&gt;&amp;lt;version&amp;gt;_Diamond_lin.run&lt;/code&gt;. Run that binary (as a user, NOT as root), and install it in a proper place. I place all vendor software in &lt;code&gt;/opt&lt;/code&gt;, so the installation ends up in &lt;code&gt;/opt/lscc/diamond/&lt;/code&gt;
You need to manually create the menu item, the program it needs to run is &lt;code&gt;&amp;lt;install_dir&amp;gt;/bin/lin64/diamond&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;the-first-issue--shared-object-version-conflicts&#34;&gt;the first issue : shared object version conflicts&lt;/h2&gt;
&lt;p&gt;If you run it, some things you&amp;rsquo;ll notice (run it from the termimal to start with) : Tons of errors on missing glibc symbols, and some things crash (floorplan editor being one).
This is caused by Diamond using its own set of shared objects, but still depending on some system QT libs. It also relies on the system&amp;rsquo;s libxml2, and that version delivered in a supported OS (RHEL 7, RHEL8) differs from what is there in FC42.&lt;/p&gt;
&lt;p&gt;The embedded SO&amp;rsquo;s are most likely done to prevent issues on somewhat &amp;ldquo;older&amp;rdquo; RHEL versions. For me, this resulted in all kinds of errors because it also uses system provided SO&amp;rsquo;s.
FC 34&amp;rsquo;s libs are in all cases new then what is embedded in the Diamond distribution.&lt;/p&gt;
&lt;p&gt;For the libstdc++ issue, I solved it with a&lt;/p&gt;
&lt;p&gt;&lt;code&gt;find &amp;lt;install_dir&amp;gt; -name &#39;*libstdc++*so*&#39; -print0 | xargs -0 rm&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&#34;the-second-issue--coredumps&#34;&gt;the second issue : coredumps&lt;/h2&gt;
&lt;p&gt;The second issue is that using certain functionality result in a coredump. Opening a project, and selecting Floorplan View results in a crash and a coredump. The backtrace gives :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#0  0x00007f1973cd7388 xmlSAX2Comment (libxml2.so.2 + 0x32388)
#1  0x00007f1958525d7f pr_parse (libbaspr.so + 0x125d7f)
#2  0x00007f19584fe446 _ZN11PR_PREFCNTL15syntax_chk_loadEPKcS1_S1_S1_ (libbaspr.so + 0xfe446)
#3  0x00007f195eeb4d1e _ZN7PrfData8loadDataEv (libcommondata.so.1 + 0xb4d1e)
#4  0x00007f1964d76245 _ZN15PNHeavyDutyTask15loadCommondDataEv (libpnmaindll.so + 0x176245)
#5  0x00007f1964d768e5 _ZN15PNHeavyDutyTask7runTaskEv (libpnmaindll.so + 0x1768e5)
#6  0x00007f1974c8b86c n/a (libQtCore.so.4 + 0x8b86c)
#7  0x00007f197427ff54 start_thread (libc.so.6 + 0x71f54)
#8  0x00007f197430332c __clone3 (libc.so.6 + 0xf532c)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So, it crashes somewhere in libxml.so.2. That SO is however not part of the Diamon distribution, and is taken from the system path. The version that Diamond assumes, and the version that FC42 provides are binary incompatible.&lt;/p&gt;
&lt;p&gt;The only way to fix this is to provide an older version of libxml, and making that specifically available to Diamon. If you install this in the normal system location, you will brick things for sure.&lt;/p&gt;
&lt;p&gt;The recipe that worked for me :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git clone https://github.com/GNOME/libxml2.git
cd libxml2
git checkout v2.10.4
./autogen.sh
./configure --without-python
make
cd .libs
cp -d ibxml2.so.2 libxml2.so.2.10.4 &amp;lt;install_dir&amp;gt;/bin/lin64/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That should repairs the non-working functionality.&lt;/p&gt;
&lt;p&gt;I haven&amp;rsquo;t used all functionality (yet), so there can be other (hidden) issues. I&amp;rsquo;ll update this blog when I encounter and fix an issue.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Autoscaling like a Pro on AWS</title>
			<link>https://www.palsenberg.com/2014/11/05/autoscaling-like-a-pro-on-aws/</link>
			<pubDate>Wed, 05 Nov 2014 22:18:23 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2014/11/05/autoscaling-like-a-pro-on-aws/</guid>
			<description>&lt;p&gt;The Amazon cloud (AWS) is a great place to deploy your application to. It&amp;rsquo;s flexible, cheap, you pay by-the-hour, and it offers great additional services to make your life easier. AWS also offer a great API, with properly written tools, that can act as a complete replacement for the AWS console. If you can manage something from within the console, you can also do the same thing from within the API. I&amp;rsquo;ll cover the AWS tools a later on.&lt;/p&gt;
&lt;p&gt;When it comes to handling a massive amount of traffic, we need to look at a number of component, they we look how that translates into AWS. A few key pointers to dynamically scale your application (I consider a website to be an application) :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Nodes need to be self-contained and stateless. All nodes should be considered equal, so no master or slave nodes. Nodes can also come and go when they please in an auto scaling setup, so if you store data on it, make sure the node is not the only source of data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you manage relational data, split up the reads from the writes. Read-only copies of relational databases on AWS are cheap, and easily setup, and even more important, scale well. All reads go to the slaves (which are read-only), all writes go to the master. As a bonus, RDS slaves can span multiple availability zones (CHECK : cross region ?).&lt;/p&gt;
&lt;p&gt;If possible, make the write action a service. Requests to services can be queued, and you don&amp;rsquo;t have all nodes lurking the master database. It also means you can replace how it works without breaking all the nodes. AWS also offers queues as a service, where queue endpoints can be all over the AWS cloud.&lt;/p&gt;
&lt;p&gt;If possible, store data in a NoSQL database. If data is read-only, it&amp;rsquo;s usually a good candidate. It also means you don&amp;rsquo;t have to deal with ORM layers, which can be a plus (even seen the queries Hibernate generates ?)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cache things. All of it. Really. If it &lt;strong&gt;can&lt;/strong&gt; be cached, cache it. Memory is cheap and fast, disk access is far less fast, and network access is probably even less faster. If you can keep things in memory for even a few minutes, it will keep the response times fast. Also, a look up from memory can&amp;rsquo;t go wrong, which is not something you can say from disk or network access.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use API&amp;rsquo;s for everything, and always assume something can fail. If it fails, handle it well. Generating a &lt;strong&gt;decent&lt;/strong&gt; error message, and notifying OPS is also considered &amp;ldquo;handling well&amp;rdquo;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;elastic-beanstalk&#34;&gt;Elastic Beanstalk&lt;/h2&gt;
&lt;p&gt;One of those service is Elastic Beanstalk, which allows you to deploy applications with the push of a single button on the AWS console. Elastic Beanstalk is basically a top-level front-end for a number of AWS services : Elastic Load Balancing, Auto Scaling, CloudWatch and CloudFront.&lt;/p&gt;
&lt;p&gt;It basically gives you a load balancer, an auto scaling policy, monitoring and a chef-based infrastructure deployment tooling all combined into one service.&lt;/p&gt;
&lt;p&gt;Since it&amp;rsquo;s a generic solution, it is limited to a number of platforms :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;IIS&lt;/li&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;PHP&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Ruby&lt;/li&gt;
&lt;li&gt;Tomcat&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You have limited control over the environment you get, customization is possible with the use of &lt;a href=&#34;http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/customize-containers.html&#34;&gt;.ebextensions&lt;/a&gt;. While it gives you some control, it&amp;rsquo;s not the whole deal, but it will be sufficient for most cases.&lt;/p&gt;
&lt;p&gt;Since we use the &lt;a href=&#34;http://www.playframework.org&#34;&gt;playframework&lt;/a&gt;, the options are limited to either Tomcat or Docker. The Tomcat options doesn&amp;rsquo;t work with our setup (we need apache in front), so, it&amp;rsquo;s down to just one option : Docker.&lt;/p&gt;
&lt;p&gt;Docker on Elastic Beanstalk is run on an instance, with the application run inside a private subnet. So, you have the instance on a private subnet, and the application in the Docker container is run inside a NAT subnet within that container. That&amp;rsquo;s not convenient if you need to handle incoming traffic outside the load-balancer.&lt;/p&gt;
&lt;h1 id=&#34;rolling-code-updates&#34;&gt;Rolling code updates&lt;/h1&gt;
&lt;p&gt;Another show-stopper for me was the fact that it doesn&amp;rsquo;t support rolling code updates. Ideally, you would deploy a new version, it would boot up instances with the new version, wait until they accept traffic, and when they do, you terminate the old instances with the old software version. That way, you would have zero downtime. Unfortunately, Elastic Beanstalk doesn&amp;rsquo;t support that. So, when switching to a new version, it removes all instances with the old version,&lt;/p&gt;
&lt;p&gt;I haven&amp;rsquo;t been able to get this in a workable state. You might end up with a different situation, where it is usable. If it isn&amp;rsquo;t : What&amp;rsquo;s next ?&lt;/p&gt;
&lt;h2 id=&#34;auto-scaling&#34;&gt;Auto scaling&lt;/h2&gt;
&lt;p&gt;Luckily for us, AWS has auto scaling. In short, you group a number of instances (the auto scaling group), and the number of instances in that group is determined by metrics collected from the instances in that group. This doesn&amp;rsquo;t mean absolute numbers but the actions taken based on the metrics result in a number of instances.&lt;/p&gt;
&lt;p&gt;Sounds.. Well. Vague. Let me give you an example.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start a group with 3 instances, and a maximum of 10. Those are absolute values : The group can&amp;rsquo;t drop below 3, and can&amp;rsquo;t go above 10, no matter what happens. You need to provide triggers (alarms in AWS), and an action. Those two things together are called a scaling policy. To make it usable at all, you need to create a policy for scaling up, and a policy for scaling down. So, you start with 3 instances, it gets busy, and the group scales it up by one instance. Then you have 4. If that&amp;rsquo;s not enough, it will add another one, etc. You can add multiple triggers, so that you can handle traffic peaks.&lt;/p&gt;
&lt;h1 id=&#34;scaling-policies&#34;&gt;Scaling policies&lt;/h1&gt;
&lt;p&gt;First, you should determine what the trigger is. You can pick CPU utilization, Disk IO Operation (Disk Ops), Disk bytes read/write and network bytes in/out on EC2 instances. I usually pick the CPU utilization, because that gives me a direct relation with how busy a node is. The more CPU utilization, the busier it is, and the other way around.&lt;/p&gt;
&lt;p&gt;So, you can pick for example 50% average utilization as a trigger, and when that gets trigger, add 1 instance to the auto scaling group. If CPU utilization drops below 30% average, you remove 1 instance for the group.&lt;/p&gt;
&lt;p&gt;Scaling is a delicate operation : You don&amp;rsquo;t want add instances to fast (it will cost money), or remove instances to fast, which will result in a higher load, which can result in a scaling policy kicking. If you create a bad scaling policy, you will have a constant flow of scaling operations, which is a bad thing. To prevent this, AWS has a cooldown period. If a scaling activity occurs, it will wait the number of seconds assigned to the cooldown period before another scaling activity will begin. Effectively, it will suspend scaling activity during that period. During the cooldown, the new instances have the time to settle down. You need to pick that number carefully, which will I cover later on.&lt;/p&gt;
&lt;p&gt;What happens if a scaling activity occurs ? It means launching an instances from a predefined AMI. That AMI, and which instance type, is determined by the Launch configuration. Every scaling group has one launch configuration attached. Normally, when the instance is declared &amp;ldquo;Healthy&amp;rdquo;, the auto scaling group will add it to the ELB, and it will start to accept traffic. Good, assuming your instance is directly capable of handling traffic after it has booted. In many cases, it&amp;rsquo;s not. You can have your application starting up, Tomcat booting, all factors that basically means you can&amp;rsquo;t handle traffic directly after the instance has booted.&lt;/p&gt;
&lt;p&gt;If your instance needs time to &amp;ldquo;warm up&amp;rdquo;, you need to tell the ELB this. This means that the ELB will do periodic checks, and when those check succeed, it will add the instance to the load balancer. As long as the check fails, it will not send traffic to that instance. You can tell the auto scaling group to use the ELB&amp;rsquo;s health check instead of looking at instance healthiness. This will allow your instances to warm up, and accept traffic when they are ready. The auto scaling group will wait a certain amount of time before it starts checking, the &amp;ldquo;Health check grace period&amp;rdquo;. After that, the checks begin. There is one catch : If your instance isn&amp;rsquo;t ready to accept traffic after the grace period, the auto scaling group will consider the instance unhealthy, and replace it.&lt;/p&gt;
&lt;p&gt;Let me rephrase that : &lt;strong&gt;If you instance isn&amp;rsquo;t healthy after the grace period + (Unhealthy Threshold * interval), your instance will be axed and replaced.&lt;/strong&gt; So, pick this value carefully. Very carefully.&lt;/p&gt;
&lt;p&gt;So, at this point we have autoscaling. We need to be able to rollout code without downtime&lt;/p&gt;
&lt;h2 id=&#34;code-rollouts&#34;&gt;Code rollouts&lt;/h2&gt;
&lt;p&gt;You usually want to rollout a new version of your application without bringing it down. You also want to control how this is done, instead of an automated system doing this for you. In my case, I&amp;rsquo;ve decided to use some nice AWS properties to accomplish this :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you attach an ELB to an autoscaling group, it will direct traffic to the ELB to all healthy instances in the autoscaling group&lt;/li&gt;
&lt;li&gt;You can tell the autoscaling group to use the ELB health check, instead of the EC2 health check&lt;/li&gt;
&lt;li&gt;You can attach an ELB to multiple autoscaling groups&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Combining all the above facts, it roughly functions as following :&lt;/p&gt;
&lt;p&gt;Every application has two autoscaling groups: One which hold the current version, with a number of running instance, the other one is a target for the new application (with a new launch configuration), and that has no running instances.&lt;/p&gt;
&lt;p&gt;In pseudo code, it ends up with :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;check_ami_id $ami_id
check_ami_tags $ami_id
determine_app_version $ami_id
find_as_group_name $appname
check_elb_health $asg_current
copy_current_lc $appname $ami $lc_old
assign_lc_to_asg asg_target $lc_new
suspend_asg $asg_current
scale_asg asg_current $asg_target
wait_until_instance_cnt_reached $asg_target $asg_current
wait_until_healthy asg_target $instance_cnt
resume_asg $asg_current
scale_asg_down $asg_current
wait_until_terminated $asg_current
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hey !! This looks like Bash. Well, it actually is. Actual implementation is done in Bash 4, and with some minor work, should also be able to support Bash 3.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve done this for a number of reasons :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I wanted to upscale my Bash knowledge&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s installed by default on all AWS instances we run, and also with a recent enought version&lt;/li&gt;
&lt;li&gt;No external dependencies to worry about : We use tools that are installed by default&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;ll shortly describe each function :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;check_ami_id : this checks if the AMI id is correct. This is just name-only.

check_ami_tags : This checks if the AMI has the correct tag set. It wants a
tag named &amp;#39;autodeploy&amp;#39;, with the application name as it&amp;#39;s value. This
prevents the wrong application ending up on production, because someone
picked the wrong AMI by accident.

determine_app_version: This pick the version tag from the AMI, and display
that.

find_as_group_name: This finds the two auto scaling groups. It needs exactly
2, anything else is considered an error. It finds the two groups by looking
at it tags, where it expects to find a tag named autodeploy, with the name
of the application as value. How the groups are actually named isn&amp;#39;t
relevant. It then fills asg_current and asg_target by looking at how many
instances are running. If both have running instances, it is considered a
fatal error.

check_elb_health: This check the ELB attached to the auto scaling group.
All instances registered on the ELB need to be healthy. If this is not the
case, this is considered a fatal error. We do this to prevent the number of
instances to be determined wrongly, since that number is needed later on to
see if the new auto scale group has scaled up.

copy_current_lc: This copies the launch configuration of the running auto
scaling group to a new one, with the new AMI attached. You can&amp;#39;t edit a
launch configuration, so the only option is to create a new one.

assign_lc_to_asg: Assign the new launch configuration to the target auto
scale group.

suspend_asg: This prevents the auto scaling policies from kicking in. The
scripts depend on the number to be consistent during run time.

scale_asg: Scales up the asg_target to match the asg_current

wait_until_instance_cnt_reached: Waits until the auto scale group reaches a
certain instance count.

wait_until_healthy: Waits until at least instance_cnt in the auto scale group
are healthy (as determined by the ELB)

resume_asg: Resumes the auto scaling policies

scale_asg_down: Scales down the auto scale group to zero

wait_until_terminated: Waits until all instances have terminated
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The scripts use the AWS cli exclusively, together with some standard *NIX tools : readlink, wget, basename, grep, awk, sed The AWS cli is an one size fits all tooling : You can use it to control all aspects of AWS. Most commands offer filtering, and the output format can be switched to either JSON, a table or text.&lt;/p&gt;
&lt;p&gt;text is a tab delimited format, which is ideal as an input for bash, since it operated on tab delimited input by default. While I know that json can also be handled from within bash, it depends on external tooling, or some really ugly workarounds. Since it gives no advantage in this case, I&amp;rsquo;ve chosen the text format.&lt;/p&gt;
&lt;h2 id=&#34;aws-cli&#34;&gt;AWS CLI&lt;/h2&gt;
&lt;p&gt;First, make sure you have it configured. You need to set AWS_ACCESS_KEY and AWS_SECRET_KEY before you can use it. To test, run&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;aws ec2 describe-regions --region=eu-west-1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you get a list of regions : OK, if not, you need to check your setup. The output will look like&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;{
    &amp;#34;Regions&amp;#34;: [
        {
            &amp;#34;Endpoint&amp;#34;: &amp;#34;ec2.eu-central-1.amazonaws.com&amp;#34;,
            &amp;#34;RegionName&amp;#34;: &amp;#34;eu-central-1&amp;#34;
        },
        .....
        {
            &amp;#34;Endpoint&amp;#34;: &amp;#34;ec2.ap-southeast-1.amazonaws.com&amp;#34;,
            &amp;#34;RegionName&amp;#34;: &amp;#34;ap-southeast-1&amp;#34;
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To use the tab separated format use&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;aws ec2 describe-regions --region=eu-west-1 --output=text
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and it will get you&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;REGIONS ec2.eu-central-1.amazonaws.com  eu-central-1
....
REGIONS ec2.ap-southeast-1.amazonaws.com    ap-southeast-1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The same data, different format. The AWS tools contain two important features :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Filtering. Limit the output to match the filter specified&lt;/li&gt;
&lt;li&gt;Query : Limit the output to selected parts&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let me explain both of them to you. Take for example&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;aws ec2 describe-tags --region=eu-west-1 --filters
&amp;#34;Name=resource-id,Values=ami-bcad1234&amp;#34; --output text
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This will display the AMI ami-bcad1234 if that exists, else the output will be empty. You can have multiple of them :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;aws ec2 describe-tags --region=eu-west-1 --filters
&amp;#34;Name=resource-id,Values=ami-bcad1234&amp;#34; &amp;#34;Name=key,Values=autodeploy&amp;#34;
--output text
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Will display AMI ami-bcad1234 of they have a tag with a key named &lt;code&gt;autodeploy&lt;/code&gt;. Matches will only be displayed if both conditions are met. Some command give you tons of output. In most cases, you&amp;rsquo;re not interested in all of them. Getting all of the output makes filtering the desired information harder, and if fields get added or removed in the future, your script might break on them.&lt;/p&gt;
&lt;p&gt;Assume we want to query the load balancer attached to an autoscaling group. We are not interested in the rest, just the name of the autoscaling group. information. To see what you get by default, run&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names
&amp;#34;name of auto scaling group&amp;#34; --region=eu-west-1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pick the right region, and the right name. You&amp;rsquo;ll get a lot of output, but we just want to get the load balancer name from that output. Here is where query comes in. It gives you a way to tell the CLI what you want, and that you are not interested in the rest.&lt;/p&gt;
&lt;p&gt;To just get the ELB name, use&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names
&amp;#34;name of auto scaling group&amp;#34; --query
&amp;#34;AutoScalingGroups[0].LoadBalancerNames[0]&amp;#34; --region=eu-west-1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So, what does this do ? It asks for the first member from the LoadBalancerNames array, and for the first LoadBalancer. You can also ask for multiple values :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names
&amp;#34;name of auto scaling group&amp;#34; --region=eu-west-1 --query
&amp;#34;AutoScalingGroups[*].Instances[*].
{HS:HealthStatus,Id:InstanceId,LS:LifecycleState}&amp;#34; --output text
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This gives you for all members in the AutoScalingGroups array, the Instances member, and the HealthStatus, InstanceId and LifecycleState members. The CLI tools requires you to ID each field.&lt;/p&gt;
&lt;h2 id=&#34;wrapping-it-up&#34;&gt;Wrapping it up&lt;/h2&gt;
&lt;p&gt;Now that we have the autoscaling setup and deploy in place, that leaves us with one thing : The AMI. Or better we need a way to create them. Traditionally, we launch an existing AMI, make the changes we need, and create a new AMI from the modified existing AMI.&lt;/p&gt;
&lt;p&gt;While this works, it&amp;rsquo;s also very time consuming, not to mention error-prone. Luckily, we have a solution for this : &lt;a href=&#34;http://www.packer.io&#34;&gt;packer&lt;/a&gt;. It&amp;rsquo;s a image creation tool on steroids.&lt;/p&gt;
&lt;p&gt;You start out with a template (a JSON file), let the builder create an AMI from the template, using a one or more provisioners. I used two : a list of assets that get uploaded to the instance, and a bunch of shell scripts to do the actual work. While it can use fancy stuff like Ansible, Chef, Puppet and Salt, I personally are way more comfortable with bash, and it&amp;rsquo;s also easier for colleagues to understand.&lt;/p&gt;
&lt;p&gt;In general, I advise for two templates : A base one, with for example a JDK and all need tools, and one for the application. That saves us time since we don&amp;rsquo;t have to install the JDK with every build, and items in the base AMI is pretty much fixed.&lt;/p&gt;
&lt;p&gt;The application AMI handles installation of the application, with the mention base AMI as source. This way, you can build you AMI with a short amount of time, and with a consequent result : You can&amp;rsquo;t forget stuff. It builds it the same time over and over again.&lt;/p&gt;
&lt;p&gt;While we have a complete set now, on my personal TODO list is a git hook, so it builds a new AMI with every tag that get&amp;rsquo;s pushed.&lt;/p&gt;
&lt;h2 id=&#34;questions--comments-&#34;&gt;Questions / comments ?&lt;/h2&gt;
&lt;p&gt;Have any questions / comments ? My contact data is on the bottom of each page. I&amp;rsquo;m also pretty easy to find using Google. Since I&amp;rsquo;m not doing posts frequently, I welcome feedback.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Server side mail filtering</title>
			<link>https://www.palsenberg.com/2013/07/02/server-side-mail-filtering/</link>
			<pubDate>Tue, 02 Jul 2013 13:08:31 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2013/07/02/server-side-mail-filtering/</guid>
			<description>&lt;p&gt;When you get a lot of mail, and go on vacation, you usually pull in all that mail over your expensive roaming 3G connection.&lt;/p&gt;
&lt;p&gt;I use filtering to make sure certain mails end up in the right folder. I usually don&amp;rsquo;t want to read all mails that come from mailinglists. You can use filtering from within your mail client  and that works well. That has one huge disadvantage : Your mail client needs to pull in at least the headers to see if it matches filtering. Not nice if you&amp;rsquo;re for example subscribed to the LKML.&lt;/p&gt;
&lt;p&gt;So.. How do you handle this, without all kinds of mailclient plugins ? The answer : Service side filtering. I use Maildir as my mailbox format, and if you still use mbox : See &lt;a href=&#34;http://www.palsenberg.com/jdi/moving-from-mbox-to-maildir&#34;&gt;this&lt;/a&gt; article to migrate. I use &lt;a href=&#34;http://www.courier-mta.org/maildrop/&#34;&gt;maildrop&lt;/a&gt; as my mail delivery agent, since it has filtering capabilities.&lt;/p&gt;
&lt;p&gt;I assume that you&amp;rsquo;ve told your MTA (Postfix, Sendmail) to use it : If not, you&amp;rsquo;ll end up debugging why it isn&amp;rsquo;t filtered, and at the end, you&amp;rsquo;ll find out it isn&amp;rsquo;t even called.&lt;/p&gt;
&lt;p&gt;When maildrop works, it&amp;rsquo;s time to start filtering. Configuring is done using the .mailfilter file in your homedir, or a .mailfilters directory in your homedir. A small part of the one I&amp;rsquo;m using right now :&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;It&amp;rsquo;s pretty simple : It specifies a logfile (relative starting at our homedir). After them, a regexp, and a action. I wrap the actions in an exception statement, so that if the move fails, we don&amp;rsquo;t bounce to the sender (which in case of a mailinglist, will mos likely result in a unsubscribe). In above examples, it will filter messages from LinkedIn or the OSGi mailinglist.&lt;/p&gt;
&lt;p&gt;Look at the headers to see a common header in messages that belong together. You can&amp;rsquo;t assume things, especially not with mailing lists.&lt;/p&gt;
&lt;p&gt;If you also run SpamAssasin, you can filter on for example on the X-Spam-Status header. Example :&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;Happy filtering !!&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Asterisk for the novice, part 2</title>
			<link>https://www.palsenberg.com/2013/06/29/asterisk-for-the-novice-part-2/</link>
			<pubDate>Sat, 29 Jun 2013 21:15:30 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2013/06/29/asterisk-for-the-novice-part-2/</guid>
			<description>&lt;p&gt;Let&amp;rsquo;s start with the dialplan. I&amp;rsquo;ve put it on github : &lt;a href=&#34;https://gist.github.com/4066527&#34;&gt;extensions.lua&lt;/a&gt;
Yes, it&amp;rsquo;s a beast. It&amp;rsquo;s also the first piece of &lt;a href=&#34;http://www.lua.org&#34;&gt;LUA&lt;/a&gt; I&amp;rsquo;ve even written, so yes, a LUA guru can probably shorten it by half or so.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SQLite database&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Our user list is in a sqlite db. That&amp;rsquo;s also what lines 1 and 4 are about : Adding the LUA extension (line 1) and opening the database (line 4). It&amp;rsquo;s a bit buggy : Sometimes we end up with a locked SQLite database, and all further operations fail. The solution is either a MySQL database, reverting back to textfiles, or fix the locking issue. I haven&amp;rsquo;t fount the cause yet.&lt;/p&gt;
&lt;p&gt;**Context
**&lt;/p&gt;
&lt;p&gt;A context is a group of extensions. In this dialplan, all SIP phones end up in the context sipphones. The incoming ISDN lines are mapped to the bri-incoming context. That means that you can also do nice things with incoming calls, based on the number of the calling party. This script looks up the number using a REST call, and then displays the number on the display of the phone.&lt;/p&gt;
&lt;p&gt;The default context (which is always present), maps to the unauthenticated context (using the include directive), and that just calls a function that drops the call.&lt;/p&gt;
&lt;p&gt;**Initialisation and extensions
**
We define our outgoing interface on line 10 : TRUNK, which is our ISDN BRI card.&lt;/p&gt;
&lt;p&gt;The API key on line 13 is for the interface to our admin interface, which requires a login and cookies, except when using the API, which needs the apikey.&lt;/p&gt;
&lt;p&gt;The actual work is done in the extensions table on line 352 : That maps what extension (read : number) is handled in which context. It also determines for example what happens when you dial 911 (or 112) : You want that to work, even when the extension isn&amp;rsquo;t logged on.&lt;/p&gt;
&lt;p&gt;In short : It maps dialed numbers to action the PBX takes. For example : If you dial #741, you ask the PBX to call e_hotdesk_login(), with the context and extension as arguments.&lt;/p&gt;
&lt;p&gt;It does checking (is the extension enabled, and not already logged in), asks for the PIN, and if that is correct, writes the SIP phone ID to the database, and puts the user on the right queue.&lt;/p&gt;
&lt;p&gt;Logging out is the reverse : Remove from the queue, and remove the SIP phone ID from the database.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dialplan&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The dialplan we now use is sub-optimal : You need to think about the public service, and what mapping the SIP phone uses, and is hardcoded. That might interfere with the dialplan you think up, which get&amp;rsquo;s you into trouble.&lt;/p&gt;
&lt;p&gt;Make sure you get this right : Users get annoyed when the dialplan changes on a regular basis, and you end up with unhappy collegues.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Issues&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Issues I&amp;rsquo;ve ran into :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;No real argument checking of the calls into Asterisk from within Lua. Documentation is a bit scarse, so you need to debug, and have a debug console run at maximum level open while writing the Lua code.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The SQLite DB keeps getting locked, especially when the DB is accessed a lot. No idea how to fix this, or what the real cause is. A good solution would be to use Yaml instead, since the file is mostly read-only anyway.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When doing a transfer, the person doing the tranfer is displayed, instead of the caller. The cause is that Asterisk acts as a intermediate gateway, doing an outgoing call, and then a passthrough between the two connections. It&amp;rsquo;s fixable in theory.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Conslusion : You can do a lot of very nice stuff with Asterisk. I have really touched the real nice goodies yet. Hope I can some day.&lt;/p&gt;
&lt;p&gt;If you cant to discuss : &lt;a href=&#34;http://www.palsenberg.com/about&#34;&gt;contact&lt;/a&gt; me.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Asterisk for the novice</title>
			<link>https://www.palsenberg.com/2012/10/26/asterisk-for-the-novice-2/</link>
			<pubDate>Fri, 26 Oct 2012 13:46:59 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2012/10/26/asterisk-for-the-novice-2/</guid>
			<description>&lt;p&gt;We switched to VOIP : Our old PBX was lacking features, and the prices for phones went sky-high. I purchased an Asterisk EuroISDN card, and some Aastra phones.&lt;/p&gt;
&lt;p&gt;Some lessons I learnt the hard way :&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A GUI&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you installed a GUI, deinstall it. If you have the GUI config and installation in  a backup : remove it from the backup also. Then, print the GUI sources, and shred them. Really, do so. If you have a real problem, and a GUI, and no knowledge of Asterisk, you&amp;rsquo;re totally screwed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The hardware&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;First, make sure Asterisk knows your hardware. dahdi_hardware should give some output. If it doesn&amp;rsquo;t, reinstall the kernel drivers, and make sure that the driver is loaded. I used the .src.rpm for building those, but the instructions at https://wiki.asterisk.org/wiki/display/AST/Building+and+Installing+DAHDI also work.&lt;/p&gt;
&lt;p&gt;Load the kernel drivers : I needed to load wcb4xxp and dahdi.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Asterisk software&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I installed Asterisk 10.6, using a homebrew RPM. No special reason for this version : It was the latest available.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Configurating Asterisk&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;First, I ran dahdi_genconf, that took care of configuring all 4 spans.
My chan_dahdi.conf looks like :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[trunkgroups]

[channels]
; Deprecated, don&#39;t use it
[lines]

echocancel = yes
echotraining = yes
signalling = bri_cpe
callerid = asreceived
context = bri-incoming
group = 1
channel = 1,2
channel = 4,5
dahdichan =&amp;gt; 1,2,4,5
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The SIP phones also need config. This is done in /etc/asterisk/sip.conf :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[jdioffice](!)
type=friend
context=sipphones
host=dynamic
nat=no
dtmfmode=auto
disallow=all
allow=ulaw
allow=g722
allow=g729
qualify=yes
language=nl

[00085D3XXXXX](jdioffice)
secret=mysecret
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This gives us two asterisk contexts : sipphones, and bri-incoming. You need these to tell Asterisk what to when a call comes in or goes uit on a certain context.&lt;/p&gt;
&lt;p&gt;I use a LUA based dialplan : I know how to code, and that gives me an extensions file that is a whole lot better to read then the &amp;rsquo;traditional&amp;rsquo; Asterisk dialplan config.&lt;/p&gt;
&lt;p&gt;Entrypoints are in a table :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;extensions = {
  -- Incoming calls
  [&amp;quot;unauthenticated&amp;quot;] = {
    [&amp;quot;_.&amp;quot;] = e_drop_call
  };

  [&amp;quot;sipphones&amp;quot;] = {
    [&amp;quot;_#NXX&amp;quot;] = e_hotdesk_login,
    [&amp;quot;_#000&amp;quot;] = e_hotdesk_logout,
    [&amp;quot;_0X.&amp;quot;]  = e_outgoing_sip,
    [&amp;quot;_NXX&amp;quot;]  = e_internal_sip,
    [&amp;quot;112&amp;quot;]   = e_outgoing_emergency,
    [&amp;quot;911&amp;quot;]   = e_outgoing_emergency,
    [&amp;quot;_*.&amp;quot;]   = e_dial_custnr,
    [&amp;quot;_**.&amp;quot;]  = e_dial_employee
};

  [&amp;quot;bri-incoming&amp;quot;] = {
    [&amp;quot;_X.&amp;quot;]   = e_incoming
  };

  [&amp;quot;default&amp;quot;] = {
    include = { &amp;quot;unauthenticated&amp;quot; }
  };
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can clearly see the context, and the resulting mapping. All names are actual lua functions, which take a context and extension as a result.&lt;/p&gt;
&lt;p&gt;Next post : More on the dialplan, things I&amp;rsquo;ve run into, and the solutions, if available.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>A new PBX aka playing with Asterisk</title>
			<link>https://www.palsenberg.com/2012/07/03/a-new-pbx-aka-playing-with-asterisk/</link>
			<pubDate>Tue, 03 Jul 2012 12:32:40 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2012/07/03/a-new-pbx-aka-playing-with-asterisk/</guid>
			<description>&lt;p&gt;We started out with 1 employee back in 2001. Now, we have 11. We started out with a Siemens PBX, and one ISDN-2 line. That Siemens has 8 digital ports, and 1 expansion slot. That slot has been taken for a second ISDN-2 port, since customers where getting a busy signal.&lt;/p&gt;
&lt;p&gt;Now, people share a phone. Not something we want. The Siemens PBX is also as extensible and flexible as solid concrete. We had 2 options :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Buy a new PBX from Siemens (Siemens phones only work on a Siemens PBX)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Throw everything out, and start from scratch with a VOIP based solution.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After receiving the offer for the Siemens PBX, recovering from falling of my chair, and being resuscitated by one of my collegues, I decided to start from scratch with a VOIP solution. We soon ended up with :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Asterisk as the software platform&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A &lt;a href=&#34;http://www1.digium.com/en/products/telephony-cards/digital/euro-isdn-bri&#34;&gt;Digium B41oP&lt;/a&gt; 4 port Euro ISDN card&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;http://www.aastra.com/aastra-6757i.htm&#34;&gt;Aastra 6757i&lt;/a&gt; SIP phones&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hardware was quickly ordered. I&amp;rsquo;ve upgraded our old fileserver with extra memory, a new storage array (which needed replacement anyway), and the Digium card. The OS has been manually upgraded from CentOS5 to CentOS6, since installer totally screwed up the upgrade.&lt;/p&gt;
&lt;p&gt;The&amp;rsquo;re no packages for CentOS 6, only for CentOS 5. I needed a shole bunch of non-standard libs :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;libss7&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;libopenr2&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;libpri&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;dahdi&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Downloaded, and packaged them. Asterisk was next : Version 10 wasn&amp;rsquo;t an option, since OpenPBX refuses to work with that. I ended up with &lt;a href=&#34;http://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-1.8.13.0.tar.gz&#34;&gt;1.8.13.0&lt;/a&gt;, since that&amp;rsquo;s an LTS release. Welcome if you don&amp;rsquo;t want to restart you PBX every day or so.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m going to publish the SRPMS and i386 binaries in my RPM repo, no x86_64, sorry. If you want modifications to those RPM&amp;rsquo;s, contact be, and we&amp;rsquo;ll work something out.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>GDB 7.3a and a new elfutils</title>
			<link>https://www.palsenberg.com/2011/09/27/gdb-7-3a-and-a-new-elfutils/</link>
			<pubDate>Tue, 27 Sep 2011 14:14:47 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2011/09/27/gdb-7-3a-and-a-new-elfutils/</guid>
			<description>&lt;p&gt;I just uploaded gdb 7.3a It can be found on my &lt;a href=&#34;http://www.palsenberg.com/rpmrepo/&#34;&gt;RPM repo&lt;/a&gt;. I&amp;rsquo;ve also added new elfutils packages, since these are required by this version of GDB.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Binutils 2.21.1a on CentOS 5.6</title>
			<link>https://www.palsenberg.com/2011/09/23/binutils-2-21-1a-on-centos-5-6/</link>
			<pubDate>Fri, 23 Sep 2011 20:59:51 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2011/09/23/binutils-2-21-1a-on-centos-5-6/</guid>
			<description>&lt;p&gt;I just uploaded binutils.2.21.1a. It can be found on my &lt;a href=&#34;http://www.palsenberg.com/rpmrepo/&#34;&gt;RPM repo&lt;/a&gt;. GDB will be uploaded begin next week. Happy compiling !!!&lt;/p&gt;
</description>
		</item>
		<item>
			<title>GCC 4.6.1 on CentOS 5.6</title>
			<link>https://www.palsenberg.com/2011/09/23/gcc-4-6-1-on-centos-5-6/</link>
			<pubDate>Fri, 23 Sep 2011 15:14:30 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2011/09/23/gcc-4-6-1-on-centos-5-6/</guid>
			<description>&lt;p&gt;I&amp;rsquo;ve just created packages for CentOS 5.6 that replace the default compiler with gcc 4.6.1. That version has some interesting options, so I wanted to use that as my default compiler. It&amp;rsquo;s also more strict, so it&amp;rsquo;s a good check for my own code.&lt;/p&gt;
&lt;p&gt;Packages can be downloaded from my &lt;a href=&#34;http://www.palsenberg.com/rpmrepo/&#34;&gt;RPM repo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Later today I&amp;rsquo;ll upload my binutils and gdb packages.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>VIM 7.3 with Python 2.6 on CentOS 5.x</title>
			<link>https://www.palsenberg.com/2011/09/22/vim-7-3-with-python-2-6-on-centos-5-x/</link>
			<pubDate>Thu, 22 Sep 2011 13:43:33 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2011/09/22/vim-7-3-with-python-2-6-on-centos-5-x/</guid>
			<description>&lt;p&gt;I&amp;rsquo;ve been a OSX user for some time, but my main C development happens on CentOS. OSX has &lt;a href=&#34;http://macromates.com/&#34;&gt;TextMate&lt;/a&gt; as editor, which has snippets : A sort of runtime macro&amp;rsquo;s on steroids. It saves lots of time with common language constructs such as loops.&lt;/p&gt;
&lt;p&gt;Vim has a &lt;a href=&#34;https://launchpad.net/ultisnips&#34;&gt;UltiSnips&lt;/a&gt;, but that has some preconditions : It need vim 7.3 with Python &amp;gt;= 2.6 compiled in. CentOS has neither of them. You can&amp;rsquo;t just upgrade Python on a CentOS machine, since lots of things (yum being one of them) depend on a specific version. So if you overwrite the default version, all hell will brake loose.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve created packages for both Python and Vim (x86 and srpms), available at &lt;a href=&#34;http://www.palsenberg.com/rpmrepo/&#34;&gt;http://www.palsenberg.com/rpmrepo/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Happy VIMming !!!&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Migrating to JIRA 4.4</title>
			<link>https://www.palsenberg.com/2011/09/07/migrating-to-jira-4-4/</link>
			<pubDate>Wed, 07 Sep 2011 09:28:51 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2011/09/07/migrating-to-jira-4-4/</guid>
			<description>&lt;p&gt;Migrating to JIRA 4.4 is now complete. It has&amp;rsquo;t been without hickups however :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;JIRA 4.4 en Fisheye 2.6.0-2.6.3 don&amp;rsquo;t get along when using trusted authentication. You get Seraph errors : Error handling trusted applications authentication attempt:BAD_SIGNATURE&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Make sure the user that is authenticating the application link (and managing the JIRA project) has read errors to Fisheye projects. Else you can&amp;rsquo;t link you repo to the JIRA project.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Make sure you have adequate backups before attempting to upgrade. Without them, it&amp;rsquo;s a one-way ticket of something goes wrong.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Confluence</title>
			<link>https://www.palsenberg.com/2011/08/09/confluence/</link>
			<pubDate>Tue, 09 Aug 2011 12:32:12 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2011/08/09/confluence/</guid>
			<description>&lt;p&gt;I&amp;rsquo;ve installed an milestone of Confluence. I never liked the 3.x editor : Wiki just isn&amp;rsquo;t my thing. Fortunately, the 4.x release has a brand new editor, and it&amp;rsquo;s WYSIWYG. No more fancy tagging, no more thinking on what wikimarkup to use.&lt;/p&gt;
&lt;p&gt;A nice addition is that it also allows macro&amp;rsquo;s to be embedded into that page. I&amp;rsquo;m going to use that to add some information of my own personal projects, like commit history.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Migrating to Atlassian tools</title>
			<link>https://www.palsenberg.com/2011/05/24/migrating-to-atlassian-tools/</link>
			<pubDate>Tue, 24 May 2011 12:14:58 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2011/05/24/migrating-to-atlassian-tools/</guid>
			<description>&lt;p&gt;So.. Finally found to spare time : I&amp;rsquo;ve migrated my old setup to include (most) of the Atlassian tools. I&amp;rsquo;ve got Crowd, JIRA, Confluence, Bamboo and Fisheye up-and-running, with SSO authentication.
Next step is to figure out how to make Bamboo build my C / C++ projects (which use make, not Ant or Maven which are supported native in Bamboo). I also need to look at the testsuite, for which Bamboo assumes it generated JUnit XML reports. At this moment, it doesn&amp;rsquo;t. I&amp;rsquo;ll be opening Confluence spaces for most of my (old) projects soon.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Working with re2c, lessons learned</title>
			<link>https://www.palsenberg.com/2011/05/05/working-with-re2c-lessons-learned/</link>
			<pubDate>Thu, 05 May 2011 13:54:09 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2011/05/05/working-with-re2c-lessons-learned/</guid>
			<description>&lt;p&gt;I&amp;rsquo;ve completed the parser that parses bind9 style config files. The parser itself is based on  the &lt;a href=&#34;http://www.hwaci.com/sw/lemon/lemon.html&#34;&gt;lemon parser generator&lt;/a&gt;,  and the lexer is based on &lt;a href=&#34;http://re2c.org/&#34;&gt;re2c&lt;/a&gt;. While testing and developing the parser, I&amp;rsquo;ve ran into some strange, undocumented issues.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Error checking is practically absent. Bad input results in bad runtime behaviour instead of errors.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Make sure that all input in conditions is handled; Input encountered in states without a matching rule results in the resulting code jumping to a (semi) random rule. Again, this doesn&amp;rsquo;t result in errors.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;RTFM about what regular expressions re2c supports. No error checking what so ever.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Rules with wildcard conditions &lt;!-- raw HTML omitted --&gt;(&amp;lt;*&amp;gt; &amp;lt;regexp&amp;gt;)&lt;!-- raw HTML omitted --&gt; are first processed, above all other rules. A condition with a matching rules overrides the wildcard condition. This is important if you have a match-all condition [^], since that will precede the wildcard condition rule.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you live up to the above undocumented things, re2c make writing lexers as easy as it gets.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Migrating from Xen Citrix to RHEV</title>
			<link>https://www.palsenberg.com/2010/10/28/migrating-from-xen-citrix-to-rhev/</link>
			<pubDate>Thu, 28 Oct 2010 12:53:13 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2010/10/28/migrating-from-xen-citrix-to-rhev/</guid>
			<description>&lt;p&gt;Since I&amp;rsquo;ve got fed-up with all Citrix bugs (operations that het stuck on locks, resumes not working, etc) and the fact that the&amp;rsquo;re probably going to drop Xen in favor of Microsoft Hyper-V we are going to migrate to RedHat RHEV.&lt;/p&gt;
&lt;p&gt;The software installs fine (except for the know issue that you can&amp;rsquo;t register on RHN), but migrating 35 VM&amp;rsquo;s is not something I really like doing. Well, virt-v2v comes to the rescue according to the docs.&lt;/p&gt;
&lt;p&gt;Uhm.. Well&amp;hellip; not exactly. What the docs don&amp;rsquo;t really mention that it depends on a Xen with libvirt on top of that. And that is exactly what Citrix Xen doesn&amp;rsquo;t use. So, only errors, and no migration.&lt;/p&gt;
&lt;p&gt;So.. I&amp;rsquo;m stuck with a manual migration, using or friends dd and netcat. Bah :(&lt;/p&gt;
</description>
		</item>
		<item>
			<title>PHP and the reasons why we consider switching</title>
			<link>https://www.palsenberg.com/2010/09/13/php-and-the-reasons-why-we-consider-switching/</link>
			<pubDate>Mon, 13 Sep 2010 13:28:59 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2010/09/13/php-and-the-reasons-why-we-consider-switching/</guid>
			<description>&lt;p&gt;PHP is a nice language, with numerous advantages :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Easy to learn&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Easy to install and upgrade serverwise&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Interpreted, so no compile and deploy worries&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The disadvantages are starting to annoy me more and more over time :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Zend engine is huge. It&amp;rsquo;s a major memory consumer&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Not all extensions are stable. When it comes to thread safety, there are major problems&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Some language constructs simply suck : __construct(), the 5.3 namespace seperator&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;No type hinting for build-in types (int, string)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;No OO function overloading&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Multibyte support is basically non-existent&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Our current framework (I-Content) is based on PHP4 code, and therefore not object orientated. There are some improvements, but the PHP limitations don&amp;rsquo;t go away.
Our new framework is on it&amp;rsquo;s way, and build using JAVA. The above limitations go away, althrough we get some new disadvantages in return. Time will tell if the switch is really going to happen&amp;hellip;&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Booting a &gt; 2 TB partition using EFI</title>
			<link>https://www.palsenberg.com/2010/08/20/booting-a-2-tb-partition-using-efi/</link>
			<pubDate>Fri, 20 Aug 2010 14:43:52 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2010/08/20/booting-a-2-tb-partition-using-efi/</guid>
			<description>&lt;p&gt;When our new storage server arrived last week, I wanted to skip use EFI t0 boot this system. It requires en EFI capable system, which this Intel server mobo is capable off.&lt;/p&gt;
&lt;p&gt;The CentOS installer doesn&amp;rsquo;t grasp an GPT partition table (needed to enable &amp;gt; 2TB partition tables), so I installed manually. Well.. That didn&amp;rsquo;t go to smooth. Manually installing CentOS, and the GPT partition table was, looking at it afterwards, the least of my problems.&lt;/p&gt;
&lt;p&gt;Booting the system was. The system was throwing me into an EFI shell, instead of booting the system. After doing some RTFM on EFI the issue became clear : The EFI BIOS wasn&amp;rsquo;t seeing the controller, because the BIOS on the Areca RAID card isn&amp;rsquo;t EFI capable, but only supports plain old BIOS.&lt;/p&gt;
&lt;p&gt;End of story. Areca isn&amp;rsquo;t going to provide an EFI BIOS, because no OS supports it. No OS supports it because no EFI BIOS is avaiable. You get the point&amp;hellip; So, back to a plain old MS-DOS partition table.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Migrating to SSO</title>
			<link>https://www.palsenberg.com/2010/07/23/migrating-to-sso/</link>
			<pubDate>Fri, 23 Jul 2010 08:15:45 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2010/07/23/migrating-to-sso/</guid>
			<description>&lt;p&gt;We at JDI are moving to a project based working method. We decided to use the tools from &lt;a href=&#34;http://www.atlassian.com&#34;&gt;Atlassian&lt;/a&gt;, since those tools seem to do what we require. We also run a number of internal tools, and all those together mean remembering about 6 different usernames and password.&lt;/p&gt;
&lt;p&gt;We decided to give &lt;a href=&#34;http://www.atlassian.com/software/crowd/&#34;&gt;Crowd &lt;/a&gt;a try : SSO, with an option to integrate with custom applications. It uses SOAP internally, and SSO is managed with a domain cookie. About a day work, but now all Atlassian tools we use, our administration system and subversion are authenticating against crowd :-)&lt;/p&gt;
</description>
		</item>
		<item>
			<title>We&#39;re at Maildir now</title>
			<link>https://www.palsenberg.com/2010/04/11/were-at-maildir-now/</link>
			<pubDate>Sun, 11 Apr 2010 20:59:59 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2010/04/11/were-at-maildir-now/</guid>
			<description>&lt;p&gt;As noted in &lt;a href=&#34;http://www.palsenberg.com/jdi/moving-from-mbox-to-maildir&#34;&gt;this&lt;/a&gt; posting, we migrated to Maildir. It went relatively smooth, and faster then anticipated. I&amp;rsquo;ll be posting the code to the actual migration script (41 lines of PHP code), and the code code to the milter that temporary locks the mailbox (aboyt 150 lines of C actually written by me). This way, it reduced downtime to the actual time needed to do the conversion, instead of shutting down the whole MTA.&lt;/p&gt;
&lt;p&gt;The source for the PHP script and milter are &lt;a href=&#34;http://www.palsenberg.com/wp-content/uploads/2010/04/maildirmigration.tar.bz2&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Moving from mbox to maildir</title>
			<link>https://www.palsenberg.com/2010/03/12/moving-from-mbox-to-maildir/</link>
			<pubDate>Fri, 12 Mar 2010 07:39:54 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2010/03/12/moving-from-mbox-to-maildir/</guid>
			<description>&lt;p&gt;I&amp;rsquo;ve decided that it&amp;rsquo;s time to move from mbox to Maildir. Mailboxes are getting larger every year, and so serverload continues to increase. During scheduled maintenance the end of March, I&amp;rsquo;m converting all mailboxes to Maildir format.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve run into a number of issues during some preliminary tests :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The conversion can&amp;rsquo;t hand the situation that mail get&amp;rsquo;s delivered during the conversion&lt;/li&gt;
&lt;li&gt;IMAP / POP mutations on the mailbox while converting screws up the conversion process.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The IMAP / POP3 part can be handled the simple way: Lock the user during the conversion, then re-enable  user after the conversion is done. The incoming part is a more challenging issue : You don&amp;rsquo;t want to shutdown the mailserver during the while conversion. You can&amp;rsquo;t tell sendmail to delay mail during a certain time by default.&lt;/p&gt;
&lt;p&gt;To solve this, I&amp;rsquo;ve written a milter (see &lt;a href=&#34;https://www.milter.org&#34;&gt;www.milter.org&lt;/a&gt;), so that during the RCPT TO phase, it checks the user&amp;rsquo;s homedir for a .maildisable file, and echo&amp;rsquo;s the first line of that file if it exists with a 4xx error. That solves the problem :-)&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Moved to VPS</title>
			<link>https://www.palsenberg.com/2010/02/24/moved-to-vps/</link>
			<pubDate>Wed, 24 Feb 2010 13:33:36 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2010/02/24/moved-to-vps/</guid>
			<description>&lt;p&gt;Today I&amp;rsquo;ve move all my personal stuff to a VPS. It let&amp;rsquo;s me run my own software (although I manage our company&amp;rsquo;s web server, I can now run several services I&amp;rsquo;m not otherwise able to use).&lt;/p&gt;
&lt;p&gt;Email wil follow today, and so will be a restoration of all the personal project pages. I&amp;rsquo;ve lost some source due to a disk crash (and  the stupid assumption that I&amp;rsquo;ve had backups), but I&amp;rsquo;ll put that info on the projectpages themselves.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Finding a new editor</title>
			<link>https://www.palsenberg.com/2009/06/25/finding-a-new-editor/</link>
			<pubDate>Thu, 25 Jun 2009 09:36:49 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/2009/06/25/finding-a-new-editor/</guid>
			<description>&lt;p&gt;We, at JDI, are used to working in vi. When we started 11 years ago, most IDE&amp;rsquo;s wheren&amp;rsquo;t existant, and with 3 people with their own OS and configuration developing locally wasn&amp;rsquo;t an option. So we just shelled in, vim&amp;rsquo;ed all of our files, and created nice things that way.&lt;/p&gt;
&lt;p&gt;Today, when the compay has grown, this isn&amp;rsquo;t an option anymore. People want an IDE, mainly for code completion and debugging. We run multiple OS&amp;rsquo;ses (Windows, Linux, Mac OS), so everything windows-only isn&amp;rsquo;t an option.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve looked at three options :&lt;/p&gt;
&lt;p&gt;Zend Studio for Eclipse
Eclipse
Netbeans&lt;/p&gt;
&lt;p&gt;Zend studio is buggy, especially when it comes to Remote Systems. Not to mentions it&amp;rsquo;s slow as hell when it comes to importing a remote project. Eclipse suffers from the same problems, and NetBeans is missing remote SFTP support.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m trying Netbeans with MacFusion at the moment&lt;/p&gt;
</description>
		</item>
		<item>
			<title>About Igmar</title>
			<link>https://www.palsenberg.com/about/</link>
			<pubDate>Tue, 01 Jan 2008 08:00:00 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/about/</guid>
			<description>&lt;p&gt;I&amp;rsquo; a C, C++, Rust, Golang and Java, en work at ING as a advisory solutions architect.&lt;/p&gt;
&lt;p&gt;I have a broad knowledge on today&amp;rsquo;s IT world, and specialise in giving teams advise on the technical direction they need
to take in order to use available infrastructure and technology at best.&lt;/p&gt;
&lt;p&gt;In my spare time, I do retro computing, mostly in Rust and the hardware designs in Verilog. PCB&amp;rsquo;s are done in KiCad.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Open Source</title>
			<link>https://www.palsenberg.com/opensource/</link>
			<pubDate>Tue, 01 Jan 2008 08:00:00 +0000</pubDate>
			<guid isPermaLink="true">https://www.palsenberg.com/opensource/</guid>
			<description>&lt;p&gt;A few of the things I&amp;rsquo;ve coded in the past years :&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/igmar/mod_suid/&#34;&gt;Apache mod_suid&lt;/a&gt; : An apache module to un all scripts under a seperate user ID. Available on github.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/igmar/etoken_key&#34;&gt;etoken_key&lt;/a&gt; : Small module that spits out a key when a Aladdin Etoken key is inserted. Handy in case you need a way to decrypt your filesystem.&lt;/p&gt;
</description>
		</item>
	</channel>
</rss>
