<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="https://evrard.me/xml/base.min.xml"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Categories on dd if=/dev/brain of=/var/log/site</title><link>https://evrard.me/categories/</link><description>Recent content in Categories on dd if=/dev/brain of=/var/log/site</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><atom:link href="https://evrard.me/categories/index.xml" rel="self" type="application/rss+xml"/><item><title>Custom Inventories with OpenStack-Ansible</title><link>https://evrard.me/custom-inventories-with-openstack-ansible/</link><pubDate>Fri, 31 Aug 2018 00:00:00 +0000</pubDate><guid>https://evrard.me/custom-inventories-with-openstack-ansible/</guid><description>
&lt;p&gt;Over the years, many users of OpenStack-Ansible came to me with simple
requests: How can I add an ansible group into OpenStack-Ansible? How can
I add hosts to this group?&lt;/p&gt;
&lt;p&gt;Please allow me to answer this in more detail here, with an explanation
of how OpenStack-Ansible inventories work.&lt;/p&gt;
&lt;h1 id=&#34;the-openstack-ansible-cli-s-inventory&#34;&gt;The &lt;code&gt;openstack-ansible&lt;/code&gt; CLI&amp;rsquo;s inventory&lt;/h1&gt;
&lt;p&gt;One of the early steps of an OpenStack-Ansible deployment is ensuring
Ansible is installed, with its right version and environment. This is
done by our &lt;code&gt;bootstrap-ansible.sh&lt;/code&gt; script.&lt;/p&gt;
&lt;p&gt;During this process, we ensure &lt;code&gt;ansible&lt;/code&gt; and &lt;code&gt;openstack-ansible&lt;/code&gt;
commands are in the user&amp;rsquo;s &lt;code&gt;PATH&lt;/code&gt;&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;. Both commands are, in fact, a
wrapper around Ansible&amp;rsquo;s binaries with a little twist: We load
environment variables from an &lt;code&gt;openstack-ansible.rc&lt;/code&gt;&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;This &lt;code&gt;openstack-ansible.rc&lt;/code&gt; contains environment variables altering the
runtime behavior of Ansible. This is done thanks to Ansible itself
reading some predefined environment variables&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;. One of these
environment variables is &lt;code&gt;ANSIBLE_INVENTORY&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For your information, ansible&amp;lt;=2.3 only accepts one inventory at a
time. When the OpenStack-Ansible project was created, all the
flexibility had to be built into a single inventory.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s how OpenStack-Ansible dynamic inventory appeared, with its
&lt;code&gt;env.d&lt;/code&gt; appeared. The &lt;code&gt;env.d&lt;/code&gt; is a way to structure the inventory seen
by Ansible. It is a very powerful but unfriendly mechanism. Its usage
has been described in OpenStack-Ansible&amp;rsquo;s documentation for many
branches and releases now&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;However, because of the complexity behind it, many deployers struggle
adapting the configuration of the inventory.&lt;/p&gt;
&lt;p&gt;This is one of the reasons I very early brought the idea of layering
inventories. My first attempt at it was a dynamic inventory (again!)
loading the usual OpenStack-Ansible dynamic inventory, and merging it
with a user provided static inventory.&lt;/p&gt;
&lt;p&gt;This sadly increased complexity of the inventory code, but decreased the
complexity for the users to manage their inventory.&lt;/p&gt;
&lt;p&gt;It was very easy to override default OpenStack-Ansible inventory, by
doing &lt;code&gt;export ANSIBLE_INVENTORY=/opt/my_own_inventory.py&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Hopefully, this proof of concept never made it into OpenStack-Ansible
tree, as we would have increased the code complexity and made the system
harder to maintain.&lt;/p&gt;
&lt;p&gt;After discussing with many people involved in Ansible (and particularily
interested in Ansible&amp;rsquo;s inventory), I realised what we needed in terms
of inventories was matching other requests in the community.&lt;/p&gt;
&lt;p&gt;Ansible 2.4 made possible to load and merge multiple inventories in one
command.&lt;/p&gt;
&lt;p&gt;So when OpenStack-Ansible was updated to Ansible 2.4, I added the fact
to load, by default, a static &lt;code&gt;inventory.ini&lt;/code&gt; next to the dynamic
inventory&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h1 id=&#34;how-does-this-static-inventory-work-in-queens&#34;&gt;How does this static inventory work in Queens?&lt;/h1&gt;
&lt;p&gt;In Queens, you could add your own &lt;code&gt;inventory.ini&lt;/code&gt; in
&lt;code&gt;/etc/openstack_deploy&lt;/code&gt; and it would be taken automatically using the
openstack-ansible CLI. That would allow you to extend your inventory
with new hosts, and new host_vars and group_vars using static files,
which is easier to extend than env.d.&lt;/p&gt;
&lt;p&gt;In fact, if you don&amp;rsquo;t want to extend your inventory but add extra host
and group vars, the &lt;code&gt;openstack-ansible&lt;/code&gt; wrapper automatically creates
the &lt;code&gt;inventory.ini&lt;/code&gt; for you&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:6&#34;&gt;&lt;a href=&#34;#fn:6&#34;&gt;6&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;However, there is no default structure present in OpenStack-Ansible
Queens, which forced users to a write a complete inventory for
OpenStack-Ansible in their &lt;code&gt;/etc/openstack_deploy/inventory.ini&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&#34;so-what-has-improved-in-rocky&#34;&gt;So, what has improved in Rocky?&lt;/h1&gt;
&lt;p&gt;Before Rocky, users had to still rely on the OSA dynamic inventory to
get a basic deployment of Openstack-Ansible, and were only using this
static inventory to extend the dynamic inventory.&lt;/p&gt;
&lt;p&gt;In Rocky, I ensured consistency and simplification of the playbooks&amp;rsquo;
targets.&lt;/p&gt;
&lt;p&gt;I also introduced a default inventory file structure&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:7&#34;&gt;&lt;a href=&#34;#fn:7&#34;&gt;7&lt;/a&gt;&lt;/sup&gt;, which allow
users to populate those groups to get a working deployment with only a
simple, static, inventory in userspace.&lt;/p&gt;
&lt;p&gt;Here is an example for a bare-metal deployment.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-.ini&#34;&gt;aio1 ansible_connection=local ansible_host=127.0.0.1
# is_metal=True
## Setup hosts
[physical_hosts]
aio1
## Setup infra
[etcd_all]
[galera_all]
aio1
[haproxy]
[memcached]
aio1
[rabbitmq_all]
aio1
[repo_all]
aio1
[rsyslog]
[unbound]
[utility_all]
aio1
## Setup openstack
[keystone_all]
aio1
# Glance
[glance_api]
aio1
[glance_registry]
aio1
# Neutron
[neutron_agent]
aio1
[neutron_dhcp_agent]
aio1
[neutron_l3_agent]
aio1
[neutron_linuxbridge_agent]
aio1
[neutron_metadata_agent]
aio1
[neutron_server]
aio1
# Cinder
[cinder_api]
aio1
[cinder_backup]
aio1
[cinder_scheduler]
aio1
[cinder_volume]
aio1
# Nova
[nova_conductor]
aio1
[nova_api_placement]
aio1
[nova_console]
aio1
[nova_scheduler]
aio1
[nova_api_os_compute]
aio1
[nova_consoleauth]
aio1
[nova_api_metadata]
aio1
[nova_compute]
aio1
# Heat
[heat_api]
aio1
[heat_api_cfn]
aio1
[heat_api_cloudwatch]
aio1
[heat_engine]
aio1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;openstack_user_config&lt;/code&gt; has extra variables that would then be
missing. You can add them as group vars or extra variables (depending on
your needs). The minimum required variables to set up an
openstack-ansible deployment could look like the following:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-.yaml&#34;&gt;---
internal_lb_vip_address: 172.29.236.100
# The external IP is quoted simply to ensure that the .aio file can be used as input
# dynamic inventory testing.
external_lb_vip_address: &amp;quot;10.0.2.15&amp;quot;
rabbitmq_hosts_entries: []
neutron_provider_networks:
network_types: &amp;quot;vxlan,flat&amp;quot;
network_mappings: &amp;quot;flat:eth12&amp;quot;
network_vxlan_ranges: &amp;quot;1:1000&amp;quot;
neutron_local_ip: &amp;quot;{{ ansible_host }}&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;With this article, I hope that you have enough information to extend the
inventories the way you want for your OpenStack-Ansible version.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;&lt;p&gt;See also:
&lt;a href=&#34;https://github.com/openstack/openstack-ansible/blob/7189ca7f1ed950944911c3418bf4afee47699315/scripts/bootstrap-ansible.sh#L157-L171&#34;&gt;https://github.com/openstack/openstack-ansible/blob/7189ca7f1ed950944911c3418bf4afee47699315/scripts/bootstrap-ansible.sh#L157-L171&lt;/a&gt;&lt;/p&gt;
&lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:1&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;&lt;p&gt;See also:
&lt;a href=&#34;https://github.com/openstack/openstack-ansible/blob/master/scripts/openstack-ansible.rc&#34;&gt;https://github.com/openstack/openstack-ansible/blob/master/scripts/openstack-ansible.rc&lt;/a&gt;&lt;/p&gt;
&lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:2&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;&lt;p&gt;The predefined environment variables have changed over time. Check
for example their definition as of today here:
&lt;a href=&#34;https://raw.githubusercontent.com/ansible/ansible/653d9c0f87f681ac386864bad4cb48f0c5e2ddfe/lib/ansible/config/base.yml&#34;&gt;https://raw.githubusercontent.com/ansible/ansible/653d9c0f87f681ac386864bad4cb48f0c5e2ddfe/lib/ansible/config/base.yml&lt;/a&gt;&lt;/p&gt;
&lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:3&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;&lt;p&gt;See also:
&lt;a href=&#34;https://docs.openstack.org/openstack-ansible/rocky/reference/inventory/understanding-inventory.html&#34;&gt;https://docs.openstack.org/openstack-ansible/rocky/reference/inventory/understanding-inventory.html&lt;/a&gt;&lt;/p&gt;
&lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:4&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li id=&#34;fn:5&#34;&gt;&lt;p&gt;See also:
&lt;a href=&#34;https://github.com/openstack/openstack-ansible/commit/ba6a3ed899de5f0b98386c20e736f61e58807c9b&#34;&gt;https://github.com/openstack/openstack-ansible/commit/ba6a3ed899de5f0b98386c20e736f61e58807c9b&lt;/a&gt;&lt;/p&gt;
&lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:5&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li id=&#34;fn:6&#34;&gt;&lt;a href=&#34;https://github.com/openstack/openstack-ansible/blob/39b718a5c12779bc15d8efc432cbadbe69745323/scripts/bootstrap-ansible.sh#L245-L249&#34;&gt;https://github.com/openstack/openstack-ansible/blob/39b718a5c12779bc15d8efc432cbadbe69745323/scripts/bootstrap-ansible.sh#L245-L249&lt;/a&gt;
&lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:6&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li id=&#34;fn:7&#34;&gt;&lt;p&gt;Extra structure for inventory.ini:
&lt;a href=&#34;https://review.openstack.org/#/c/580368/5&#34;&gt;https://review.openstack.org/#/c/580368/5&lt;/a&gt;&lt;/p&gt;
&lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:7&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>A review of OpenStack&#39;s LOCI and its extensibility</title><link>https://evrard.me/openstack-loci-how-it-works/</link><pubDate>Tue, 28 Aug 2018 00:00:00 +0000</pubDate><guid>https://evrard.me/openstack-loci-how-it-works/</guid><description>
&lt;p&gt;&lt;a href=&#34;https://github.com/openstack/loci&#34;&gt;LOCI&lt;/a&gt; is a very simple openstack
project focusing on building OCI images for OpenStack Services using a
Dockerfile and a series of shell scripts.&lt;/p&gt;
&lt;p&gt;Currently, 9 projects (Cinder, Glance, Heat, Horizon, Ironic, Keystone,
Neutron, Nova, and Octavia) can be built with it.&lt;/p&gt;
&lt;h1 id=&#34;flexibility-and-extensibility&#34;&gt;Flexibility and extensibility&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/openstack/loci&#34;&gt;LOCI&lt;/a&gt; is relying on passing
arguments to the Docker image building for its flexibility. It requires
you to pass at least the &lt;code&gt;PROJECT&lt;/code&gt; as CLI argument, to tell which
OpenStack project you want to build.&lt;/p&gt;
&lt;p&gt;The other parameters are optional. You can pass a base image as starting
point (&lt;code&gt;FROM&lt;/code&gt;) in argument if you do not want to build from the ubuntu
base image. Other variables can be provided, like your personal pip
web mirror, or proxy settings.&lt;/p&gt;
&lt;p&gt;The image building&amp;rsquo;s shell scripts receives the appropriate arguments
as environment variables. Many shell scripts do not need any updating to
leverage this flexibility. If your use case is not met, I doubt it would
be a problem to change the scripts to adapt your use case.&lt;/p&gt;
&lt;p&gt;On top of that, you can of course build a child image to your needs.&lt;/p&gt;
&lt;h1 id=&#34;the-build-process&#34;&gt;The build process&lt;/h1&gt;
&lt;p&gt;The build process currently behaves like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;python&lt;/em&gt; and &lt;em&gt;virtualenv&lt;/em&gt; are installed on the base image, using
distribution packages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A system user is created for the project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;virtualenv&lt;/em&gt; is upgraded, unconstrained, in a virtualenv. I suppose
if you want to have fully reproducible builds with no surprise on
the virtualenv version, you could implement a bypass using a docker
build argument.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;pip&lt;/em&gt; get installed in previous virtualenv, unconstrained again.
Previous comment applies here.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;em&gt;bindep&lt;/em&gt; pip package and extra pip packages based on the
project + profile (coming from a &lt;em&gt;pydep.txt&lt;/em&gt; file at the root of the
LOCI repo) are installed.&lt;/p&gt;
&lt;p&gt;If a wheel built image was created, its upper constraints file is
used for the installation of those &lt;code&gt;pydeps&lt;/code&gt; + &lt;em&gt;bindep&lt;/em&gt; pip packages.
These packages are installed in a binary form (only), from your pip
mirror of choice.&lt;/p&gt;
&lt;p&gt;If no pip mirror can be trusted, it would be technically possible to
implement a bypass by having an argument that flips the
&lt;code&gt;--only-binary&lt;/code&gt; parameter to &lt;code&gt;--no-binary&lt;/code&gt;, and copying your own
constraints file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The destination project is cloned with the user provided reference
(default is master branch&amp;rsquo;s HEAD).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The destination project, and any extra &lt;code&gt;PIP_PACKAGES&lt;/code&gt; (should
&lt;code&gt;PIP_PACKAGES&lt;/code&gt; be not empty), are installed based on projects&amp;rsquo;
&lt;code&gt;setup()&lt;/code&gt; content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Distribution packages are installed at this point using &lt;em&gt;bindep.txt&lt;/em&gt;
file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cleanup of installed distro packages (and other extra artifacts)
happen, and allows the system to use global packages.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&#34;security-and-reproducibility&#34;&gt;Security and reproducibility&lt;/h1&gt;
&lt;p&gt;While I did not have the chance to do a thorough security review, here
is my opinion: The &amp;ldquo;requirements&amp;rdquo; building, while optional, is in my
opinion necessary for security.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/openstack/loci&#34;&gt;LOCI&lt;/a&gt; can build wheels for all the
openstack requirements&amp;rsquo; upper-constraints in your environment, which
can then be published in a secure location for your next project
building. It means you would rely on OpenStack security team&amp;rsquo;s work,
which would eventually update the requirements/constraints of an
upstream project by blacklisting an insecure python package. If you do
not build the wheels with the &lt;em&gt;LOCI requirements&lt;/em&gt; project, there is no
reason to think you will pass a constraints file matching your OpenStack
projects versions. Therefore, you are probably using anything from PyPI
matching each project&amp;rsquo;s requirements, which can be very variable.&lt;/p&gt;
&lt;h1 id=&#34;build-speed&#34;&gt;Build speed&lt;/h1&gt;
&lt;p&gt;The image building itself is quite fast, due to the simplicity of the
process. If you have a CI pipeline, you can first build your
&amp;lsquo;requirements&amp;rsquo; image, then use its artifact for all the other projects
building in parallel, which should take around a total of 10 to 20
minutes maximum.&lt;/p&gt;
&lt;h1 id=&#34;gating-expectations&#34;&gt;Gating expectations&lt;/h1&gt;
&lt;p&gt;It is expected in the current gating process to expose the wheels built
in the &amp;lsquo;requirements&amp;rsquo; image on a web server. You cannot use locally
built files, unless you carry your own patch changing the base
Dockerfile.&lt;/p&gt;
&lt;h1 id=&#34;learning-pace&#34;&gt;Learning pace&lt;/h1&gt;
&lt;p&gt;Because the project itself is very simple, it is easy to track what is
happening there. It is easy to contribute, and a few minutes/hours
should be enough to get a grip of the whole codebase.&lt;/p&gt;
&lt;h1 id=&#34;conclusions&#34;&gt;Conclusions&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/openstack/loci&#34;&gt;LOCI&lt;/a&gt; is a very simple and efficient
way to build OpenStack images. It relies on Dockerfiles, simple shell
scripts, and the power of bindep to install OpenStack software from
sources.&lt;/p&gt;
&lt;p&gt;If you are looking for a way to build images based on distribution
packages, there is little to no point of using
&lt;a href=&#34;https://github.com/openstack/loci&#34;&gt;LOCI&lt;/a&gt;, as you could as well build
your image with a simple Dockerfile and a command like
&lt;code&gt;zypper install ${PACKAGE_LIST}&lt;/code&gt;. But that would also mean you will have
to package your software and its dependencies (maybe for two different
versions of Python), handle package conflicts, and other packaging work.&lt;/p&gt;
&lt;p&gt;The packaging can be completely avoided if you build from source relying
on the python ecosystem, OpenStack creation of upper constraints, and
bindep management by upstream team(s).&lt;/p&gt;</description></item><item><title>Switching to the new gandi mail service</title><link>https://evrard.me/opinion-on-new-gandi-email/</link><pubDate>Sun, 22 Apr 2018 00:00:00 +0000</pubDate><guid>https://evrard.me/opinion-on-new-gandi-email/</guid><description>
&lt;p&gt;If you are a Gandi customer, you probably already know they offer an
email service. What you might have missed, is Gandi&amp;rsquo;s services refactor
to be more modern. Emails are following the same treatment, starting
with the replacement of Roundcube.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://news.gandi.net/en/2017/08/introducing-the-new-gandi-mail/&#34;&gt;new gandi email
service&lt;/a&gt;
is based on &lt;a href=&#34;https://sogo.nu/&#34;&gt;SOGo&lt;/a&gt;, and was introduced in January last
year in
&lt;a href=&#34;https://news.gandi.net/en/2017/01/introducing-sogo-new-webmail-service-in-beta/&#34;&gt;beta&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First, the impact of the change (not mentioning mailpack changes):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New domains can only have the new service, and only 2 mailboxes are
provided by default.&lt;/li&gt;
&lt;li&gt;Existing domains can keep their 5 mailboxes.&lt;/li&gt;
&lt;li&gt;The new service now has 3GB storage per mailbox, instead of the 1GB
storage total.&lt;/li&gt;
&lt;li&gt;Switching to the new system prevents you from using the legacy
platform and api, whether for renewing your domain or for managing
your emails.&lt;/li&gt;
&lt;li&gt;The new webmail has a &lt;a href=&#34;https://sogo3.gandi.net/&#34;&gt;new address&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;SOGo brings new features, namely CalDAV and CardDAV support.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;switching-your-domain-to-the-new-service&#34;&gt;Switching your domain to the new service&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Make sure you have a gandi v5 account on &lt;a href=&#34;https://id.gandi.net&#34;&gt;https://id.gandi.net&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Go to domains &amp;gt; (your domain name) &amp;gt; Email. There is a switch
button on the page to use the new service.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you DNS Servers are outside gandi, ensure you have the following
records:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-.text&#34;&gt;@ 10800 IN MX 10 spool.mail.gandi.net.
@ 10800 IN MX 50 fb.mail.gandi.net.
@ 10800 IN TXT &amp;quot;v=spf1 include:_mailcust.gandi.net ?all&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next to that, configure CalDAV/CardDAV records for the DAV clients:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-.text&#34;&gt;imap IN CNAME access.mail.gandi.net.
pop IN CNAME access.mail.gandi.net.
smtp IN CNAME relay.mail.gandi.net.
_caldavs._tcp IN SRV 10 1 443 sogo3.gandi.net.
_carddavs._tcp IN SRV 10 1 443 sogo3.gandi.net.
_imaps._tcp IN SRV 10 1 993 mail.gandi.net.
_submission._tcp IN SRV 10 1 587 mail.gandi.net.
_caldavs._tcp IN TXT &amp;quot;path=/SOGo/dav/&amp;quot;
_carddavs._tcp IN TXT &amp;quot;path=/SOGo/dav/&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With all those records set, it should be easy for SOGo clients to work
with your domain, if they respect RFCs like the
&lt;a href=&#34;https://tools.ietf.org/html/rfc6764#page-4&#34;&gt;RFC6764&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For Android, I strongly suggest you to use f-droid, and DAVDroid. With
the above records set, you can just add your email, and everything will
be auto-discovered.&lt;/p&gt;
&lt;h1 id=&#34;feedback&#34;&gt;Feedback&lt;/h1&gt;
&lt;p&gt;The service&amp;rsquo;s web interface is slow, terribly slow. It prevents a daily
usage as a gmail/google calendar replacement. If you are only using
another interface, like your phone, it is easier to switch to this new
service, as you will not miss this new web interface.&lt;/p&gt;
&lt;p&gt;The web interface option for WebCAL files seems broken. The import of
the &lt;a href=&#34;https://releases.openstack.org/schedule.ics&#34;&gt;openstack combined releases
calendar&lt;/a&gt; comes up just
empty, while working perfectly fine in google calendar.&lt;/p&gt;
&lt;p&gt;Thanks Gandi for this welcomed change!&lt;/p&gt;</description></item><item><title>ansible-inventory tips</title><link>https://evrard.me/convert-ansible-inventories-with-ansible-inventory-cli/</link><pubDate>Mon, 09 Apr 2018 00:00:00 +0000</pubDate><guid>https://evrard.me/convert-ansible-inventories-with-ansible-inventory-cli/</guid><description>&lt;p&gt;The &lt;code&gt;ansible-inventory&lt;/code&gt; purpose is to &lt;em&gt;show Ansible inventory
information&lt;/em&gt;, as stated by its &lt;code&gt;--help&lt;/code&gt; message.&lt;/p&gt;
&lt;p&gt;However, this quite youg CLI has an interesting trick up its sleeve.&lt;/p&gt;
&lt;p&gt;Quick reminder, Ansible allows by default 4 kinds of inventories:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ini&lt;/li&gt;
&lt;li&gt;script&lt;/li&gt;
&lt;li&gt;host_list&lt;/li&gt;
&lt;li&gt;yaml&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Interesting fact number 1: All the inventory types above can be given as
input of the &lt;code&gt;ansible-inventory&lt;/code&gt; CLI.&lt;/p&gt;
&lt;p&gt;Interesting fact number 2: The output of the &lt;code&gt;ansible-inventory&lt;/code&gt; CLI is
a valid &lt;code&gt;json&lt;/code&gt; inventory.&lt;/p&gt;
&lt;p&gt;Interesting fact number 3: &lt;code&gt;ansible-inventory&lt;/code&gt; can output inventories
into the &lt;code&gt;yaml&lt;/code&gt; format.&lt;/p&gt;
&lt;p&gt;You can therefore &lt;strong&gt;use ansible-inventory to chain, merge, or convert
ansible inventories&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;Here is an example of how it can be used:&lt;/p&gt;
&lt;p&gt;The first type, &lt;code&gt;ini&lt;/code&gt; inventories, is the what you probably have seen in
your first usage of ansible, and may look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-.ini&#34;&gt;[glance_api]
localhost ansible_connection=local
[glance_registry]
localhost2 ansble_connection=local
[glance_all:children]
glance_api
glance_registry
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This &lt;code&gt;ini&lt;/code&gt; file can therefore be converted into a &lt;code&gt;yaml&lt;/code&gt; file:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-.shell-session&#34;&gt;$ ansible-inventory -i inventory.ini -y --list &amp;gt; inventory.yaml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The resulting &lt;code&gt;yaml&lt;/code&gt; file would be:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-.yaml&#34;&gt;all:
children:
glance_all:
children:
glance_api:
hosts:
localhost:
ansible_connection: local
glance_registry:
hosts:
localhost2:
ansble_connection: local
ungrouped: {}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the &lt;code&gt;-y&lt;/code&gt; was omitted, the output would be a &lt;code&gt;json&lt;/code&gt; inventory:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-.shell-session&#34;&gt;$ ansible-inventory -i inventory.ini --list &amp;gt; inventory.json
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Looking like:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-.json&#34;&gt;{
&amp;quot;_meta&amp;quot;: {
&amp;quot;hostvars&amp;quot;: {
&amp;quot;localhost&amp;quot;: {
&amp;quot;ansible_connection&amp;quot;: &amp;quot;local&amp;quot;
},
&amp;quot;localhost2&amp;quot;: {
&amp;quot;ansble_connection&amp;quot;: &amp;quot;local&amp;quot;
}
}
},
&amp;quot;all&amp;quot;: {
&amp;quot;children&amp;quot;: [
&amp;quot;glance_all&amp;quot;,
&amp;quot;ungrouped&amp;quot;
]
},
&amp;quot;glance_all&amp;quot;: {
&amp;quot;children&amp;quot;: [
&amp;quot;glance_api&amp;quot;,
&amp;quot;glance_registry&amp;quot;
]
},
&amp;quot;glance_api&amp;quot;: {
&amp;quot;hosts&amp;quot;: [
&amp;quot;localhost&amp;quot;
]
},
&amp;quot;glance_registry&amp;quot;: {
&amp;quot;hosts&amp;quot;: [
&amp;quot;localhost2&amp;quot;
]
},
&amp;quot;ungrouped&amp;quot;: {}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you might have noticed, there is &lt;strong&gt;no&lt;/strong&gt; &lt;code&gt;json&lt;/code&gt; inventory type. The
&lt;code&gt;json&lt;/code&gt; is the standard interface used for the \&amp;ldquo;script\&amp;rdquo; inventory type.&lt;/p&gt;
&lt;p&gt;A valid inventory \&amp;ldquo;script\&amp;rdquo; (also named &lt;em&gt;dynamic inventory&lt;/em&gt;), is an
executable which, when called with &lt;code&gt;--list&lt;/code&gt;, outputs a &lt;code&gt;json&lt;/code&gt; whose
content is following ansible conventions, like the &lt;code&gt;json&lt;/code&gt; above.&lt;/p&gt;
&lt;p&gt;As such, the &lt;code&gt;json&lt;/code&gt; above can be converted into a dynamic inventory
script, by making it executable and showing its content.&lt;/p&gt;
&lt;p&gt;Create a file &lt;code&gt;yourscript.sh&lt;/code&gt; with the following content:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-.bash&#34;&gt;#!/bin/bash
cat &amp;lt;&amp;lt;EOANSIBLESCRIPT
&amp;lt;the content of the yaml above&amp;gt;
EOANSIBLESCRIPT
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and then &lt;code&gt;chmod +x yourscript.sh&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That file can now be converted into &lt;code&gt;yaml&lt;/code&gt; with:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-.console&#34;&gt;$ ansible-inventory -i ./yourscript.sh -y --list &amp;gt; inventory.yaml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hope it helps you understand what can be done with the
&lt;code&gt;ansible-inventory&lt;/code&gt; CLI!&lt;/p&gt;</description></item><item><title>My view on Ansible 2.5</title><link>https://evrard.me/my-view-on-ansible-25/</link><pubDate>Sun, 08 Apr 2018 00:00:00 +0000</pubDate><guid>https://evrard.me/my-view-on-ansible-25/</guid><description>&lt;p&gt;Ansible 2.5 was released last month.&lt;/p&gt;
&lt;p&gt;If you didn&amp;rsquo;t read/hear about it, you should first read the &lt;a href=&#34;https://www.ansible.com/blog/ansible-2.5-traveling-space-and-time&#34;&gt;ansible
2.5 release
notes&lt;/a&gt;,
&lt;a href=&#34;https://github.com/ansible/ansible/blob/e8beb180e15eff1f54e0ac8a5a5143639794bbdc/CHANGELOG.md#2.5&#34;&gt;ansible 2.5
changelog&lt;/a&gt;,
and the &lt;a href=&#34;https://docs.ansible.com/ansible/devel/porting_guides/porting_guide_2.5.html&#34;&gt;ansible 2.5 porting
guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here is what I like and don&amp;rsquo;t like about this release:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Each module documentation is far more readable. Look at the stat
module &lt;a href=&#34;http://docs.ansible.com/ansible/2.5/modules/stat_module.html&#34;&gt;in
2.5&lt;/a&gt;
vs its documentation &lt;a href=&#34;http://docs.ansible.com/ansible/2.4/stat_module.html&#34;&gt;in
2.4&lt;/a&gt; .&lt;/li&gt;
&lt;li&gt;The module index documentation is far harder to automatically
search. That&amp;rsquo;s a big nuisance if you know your modules and want to
quickly search for modules parameters for example.&lt;/li&gt;
&lt;li&gt;While this isn&amp;rsquo;t shown up in the release notes, we finally have an
etcd module in ansible, for etcd3. The etcd2 module is still in the
works, so is its lookup.&lt;/li&gt;
&lt;li&gt;I do not have a strong opinion about using &lt;code&gt;loop:&lt;/code&gt; vs &lt;code&gt;with_&lt;/code&gt;. I
just do not like the fact I will have to do a grep and replace for
no foreseeable reason. It\&amp;rsquo;s replacing one evil with another. Same
goes for replacing the pipe (|) with [is]{.title-ref} for the
conditions (Although I agree that the latter is more readable).&lt;/li&gt;
&lt;li&gt;I like the namespace &lt;code&gt;ansible_facts&lt;/code&gt;. In fact (&lt;em&gt;pun intended&lt;/em&gt;), I
prefer using namespacing in many places. I even suggested using this
mechanism in &lt;code&gt;openstack-ansible&lt;/code&gt; for automatic variable loading in
test environment in a &lt;code&gt;test&lt;/code&gt; or &lt;code&gt;required&lt;/code&gt; namespace.&lt;/li&gt;
&lt;li&gt;The ansible config lookup might be interesting in the future.&lt;/li&gt;
&lt;li&gt;We now have new modules for InfluxDB, and grafana.&lt;/li&gt;
&lt;li&gt;A &lt;a href=&#34;http://docs.ansible.com/ansible/2.5/modules/ip_netns_module.html&#34;&gt;netns
module&lt;/a&gt;
was introduced, to have basic functionality of creation/deletion of
namespaces.&lt;/li&gt;
&lt;li&gt;An interesting &lt;a href=&#34;http://docs.ansible.com/ansible/2.5/modules/package_facts_module.html&#34;&gt;package_facts
module&lt;/a&gt;
has been introduced. It automatically registers the list of packages
installed on the host in the host vars, under the &lt;code&gt;ansible_facts&lt;/code&gt;
namespace. Similarily, you can use the &lt;a href=&#34;http://docs.ansible.com/ansible/2.5/modules/service_facts_module.html&#34;&gt;service_facts
module&lt;/a&gt;
to know the current state of a service.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;vdo&lt;/code&gt; module was added. If you want to know more about it, check
out this page for &lt;a href=&#34;https://rhelblog.redhat.com/2018/02/05/understanding-the-concepts-behind-virtual-data-optimizer-vdo-in-rhel-7-5-beta/&#34;&gt;VDO
install&lt;/a&gt;,
and for checking the &lt;a href=&#34;https://rhelblog.redhat.com/2018/02/08/determining-the-space-savings-of-virtual-data-optimizer-vdo-in-rhel-7-5-beta/&#34;&gt;VDO
benefits&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;I&amp;rsquo;d like to add a big thanks to ricardocarillocruz, gundalow, and
bcoca for their help on irc!&lt;/em&gt;&lt;/p&gt;</description></item><item><title>OpenStack Summit Sydney Recap</title><link>https://evrard.me/openstack-summit-sydney-recap/</link><pubDate>Sun, 19 Nov 2017 00:00:00 +0000</pubDate><guid>https://evrard.me/openstack-summit-sydney-recap/</guid><description>
&lt;h1 id=&#34;the-venue&#34;&gt;The venue&lt;/h1&gt;
&lt;p&gt;Due to its remote location, the OpenStack Summit in Sydney was smaller than other summits I attended.
The venue was excellent, it wasn&amp;rsquo;t hard to find the rooms, and everything was provided to be able to work constantly (energy, wifi, food, and the usual beverages!).
Sydney itself was a great location. The only downside was that nightlife in Sydney: it almost becomes a dead city after midnight!&lt;/p&gt;
&lt;h1 id=&#34;the-sessions&#34;&gt;The sessions&lt;/h1&gt;
&lt;p&gt;OpenStack summits never lack interesting sessions. You have to balance what you want to attend and be a good time juggler, to capitalize every minute.
For this recap, I will separate my session overview in three tracks: The recorded sessions, the etherpad based conversations, and the hallway track.&lt;/p&gt;
&lt;h2 id=&#34;the-recorded-sessions&#34;&gt;The recorded sessions&lt;/h2&gt;
&lt;p&gt;I usually skip this track because:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Sessions are recorded, so I can see them later&lt;/li&gt;
&lt;li&gt;You can generally have 1-to-1 with presenters and attendees in the hallway track.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This summit was no different.&lt;/p&gt;
&lt;p&gt;Kevin Carter, Amy Marrich, and I had our own recorded session for the OpenStack-Ansible project, named unsurprisingly &amp;ldquo;OpenStack-Ansible Project Update&amp;rdquo;.
Sadly, due to technical issues, our session didn&amp;rsquo;t run for its full 20 minutes length, and the presentation didn&amp;rsquo;t meet my excellence criteria.
Next time, I&amp;rsquo;ll prepare for the worst! If you want to see the extend of the new features we want to introduce during the Queens cycle, have a look at &lt;a href=&#34;https://git.openstack.org/cgit/openstack/election/plain/candidates/queens/OpenStackAnsible/evrardjp.txt&#34;&gt;this&lt;/a&gt; instead.&lt;/p&gt;
&lt;p&gt;I also attended the session &amp;ldquo;Practical k8s on OpenStack-Ansible&amp;rdquo;. I am glad it had a proper attendance, but sad the session wasn&amp;rsquo;t recorded. Well done Florian, I received good feedback from attendees!&lt;/p&gt;
&lt;h2 id=&#34;the-etherpad-based-conversations&#34;&gt;The etherpad based conversations&lt;/h2&gt;
&lt;p&gt;Those conversations are structured discussions, where the moderator lets the attendance discuss how to improve things on a specific topic, in non-interrupt based conversations.
I generally spend the majority of my time in those sessions.&lt;/p&gt;
&lt;p&gt;The first session I attended was the &lt;a href=&#34;https://etherpad.openstack.org/p/SYD-forum-openstack-health-feedback&#34;&gt;&amp;ldquo;OpenStack Health&amp;rdquo; session&lt;/a&gt;, talking about its relevance. I learned many things about the future of Zuul v3
dashboard there too, and how things will be improved in the future. I&amp;rsquo;ll stay in touch with the team to learn more about these dashboards.&lt;/p&gt;
&lt;p&gt;Our OpenStack-Ansible feedback session had a very good attendance. It had new, as well as existing faces, which is encouraging.
We mainly discussed Ansible&amp;rsquo;s OpenStack modules, and offline installs. Here is what I take from the conversation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We need to improve our documentation for offline installs, and make it simpler by removing all external dependencies outside the apt/pip/git parts (LXC download template files, extra packages outside the repositories, cirros images&amp;hellip;).
Having an apt mirror, an PyPI server, and git repos should be enough to deploy OpenStack from source in an offline fashion.
All of this was already planned for this cycle, so we are in sync with our community.&lt;/li&gt;
&lt;li&gt;We need to extend our test coverage for roles by testing idempotency of Ansible&amp;rsquo;s OpenStack modules.
Example: Designate role test should test the os_zone and os_recordset modules. On top of that,
we could extend Ansible&amp;rsquo;s test coverage by automatically testing changes in their OpenStack modules by using our role tests with the help of Zuul v3.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &amp;ldquo;Installation Guide&amp;rdquo; changes session was interesting, talking about its relevance nowadays, and how to improve it.
Because there is no radical change on the installation guide, OpenStack-Ansible won&amp;rsquo;t be impacted: the installation of OpenStack using OpenStack-Ansible is described in the &amp;ldquo;deploy guide&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://etherpad.openstack.org/p/SYD-forum-fast-forward-upgrades&#34;&gt;&amp;ldquo;skip level upgrade&amp;rdquo; session&lt;/a&gt; ended up by saying &amp;ldquo;We need a proper cross-project documentation that all projects can apply&amp;rdquo;. Someone volunteered for the documentation, and I suggested to compare their work with our &lt;a href=&#34;https://github.com/openstack/openstack-ansible-ops/tree/master/leap-upgrades/&#34;&gt;&amp;ldquo;Leapfrog&amp;rdquo; work&lt;/a&gt;, available in our openstack-ansible-ops repository.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://etherpad.openstack.org/p/SYD-forum-privsep&#34;&gt;Privsep&lt;/a&gt; session explained its impact on deployers in the future. Here is a short summary:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Documentation will be written on how to use privsep (sudo rootwrap that contains privsep or sudo privsep directly). We will need to adapt our roles based on it.&lt;/li&gt;
&lt;li&gt;I conveyed the need to implement this in a standard way accross all the projects, to simplify deployer&amp;rsquo;s life.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;a href=&#34;https://etherpad.openstack.org/p/SYD-stable-policy&#34;&gt;&amp;ldquo;stable policy&amp;rdquo;&lt;/a&gt; conversation agreed that deployment tools have different needs than the other projects. We decided to make sure NO deployment project should have this tag,
and each deployment project can pick and choose what&amp;rsquo;s best for its customers, because they are already opiniated.&lt;/p&gt;
&lt;p&gt;A &lt;a href=&#34;https://etherpad.openstack.org/p/self-healing-rocky-forum&#34;&gt;Self-Healing SIG&lt;/a&gt; was created, with as first action points creating mailing lists and IRC communication channels. There was a divergence of use cases already: Telcos wanted the self-healing to go as far as inside the openstack hosted applications. The group will first focus on the openstack applications themselves.
I reminded the group we should not be re-writing a monitoring solution, but instead creating a common base and/or modifying projects to fullfill our self-healing needs. The first item would be to implement a proper health checking system, usable by monitoring solutions and inside the self-healing framework.&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;Ansible Onboarding&amp;rdquo; session was a full house. The audience was split between Ansible beginners, OpenStack-Ansible beginners, and OpenStack-Ansible experienced users.
We covered the topic by browsing the docs, telling how it installs Ansible, and how everything works together, mentionning all the pain points people usually see.
I hope this will help those new contributors!&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;Ansible State of the Union&amp;rdquo; session was explaining where Ansible was, and is heading towards.
I currently don&amp;rsquo;t see anything conflicting with our strategy. We can improve Ansible&amp;rsquo;s modules by bringing real use cases, as mentionned above.&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;Neutron Pain Points&amp;rdquo; session was unsuccessful to me on one topic: Failure to agree there was a pain point for people who want to use OpenStack with Neutron like they would use VMware.
The rest of the session required some in-depth Neutron knowledge I didn&amp;rsquo;t have.&lt;/p&gt;
&lt;p&gt;Last, but not least, the (in my opinion, controversial) &amp;ldquo;Upstream LTS&amp;rdquo; session. I suggest you to visit the &lt;a href=&#34;https://etherpad.openstack.org/p/SYD-forum-upstream-lts-releases&#34;&gt;etherpad of the conversation&lt;/a&gt;, and the etherpad of the &lt;a href=&#34;https://etherpad.openstack.org/p/LTS-proposal&#34;&gt;&amp;ldquo;after conversation&amp;rdquo;&lt;/a&gt; to get a solid understanding of the issues.
I had plenty of hallway conversations about these topics, sharing my concerns on how things can go wrong, and how hard it will be to do it right.
There are other ways to solve the initial problem that spawned the need of an &amp;ldquo;LTS&amp;rdquo; for our users, but that&amp;rsquo;s probably worth another blog post, and another series of discussions.&lt;/p&gt;
&lt;h2 id=&#34;the-hallway-track&#34;&gt;The &amp;ldquo;hallway track&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;The &amp;ldquo;hallway track&amp;rdquo; is my favorite part. Every OpenStack gathering (summit/PTG/mid-cycles) allows you to meet more and more people, whether they are long time contributors or
new community members. This summit was no exception. I got the chance to meet with people from my own country, from the other side of the world, and
this time also with people from down under which don&amp;rsquo;t usually get the chance to travel to Europe or America. It was very nice to meet all of you!&lt;/p&gt;
&lt;p&gt;Here are a few highlights of some &amp;ldquo;hallway track&amp;rdquo; conversations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Explained how to increase test coverage of the telemetry stack, with the hope of seeing the test matrix increased in roles and our integrated gates.&lt;/li&gt;
&lt;li&gt;Discussed with Miguel Lavalle (Neutron PTL) about the inclusion of OpenStack-Ansible neutron testing as non-voting jobs, like we do for Keystone, nova-lxd, and Dragonflow already. There was no opposition to this idea. With the addition of Glance and Neutron, only Cinder would be missing to have a compute starter kit fully tested with our deployment tooling before it even get tested in our integration repository.&lt;/li&gt;
&lt;li&gt;Talked with Jay Bryant (Cinder PTL) about how we can help him having a &amp;ldquo;standalone cinder&amp;rdquo; test in our cinder role.&lt;/li&gt;
&lt;li&gt;Launched the idea of a collaboration channel with the Ansible&amp;rsquo;s team with the help of Ricardo Carrillo Cruz. This has to be followed up after the summit.&lt;/li&gt;
&lt;li&gt;Drafted &amp;ldquo;battle plans&amp;rdquo; on how to improve Dragonflow in Pike for Ubuntu. (Includes an etcd3 conversation).&lt;/li&gt;
&lt;li&gt;Prepared the work to spin off &amp;ldquo;config_template&amp;rdquo; outside of our plugins repo, to be able to use it as a meta dependency for any role, not only the OpenStack-Ansible ones (for example Sebastien Han&amp;rsquo;s ceph-ansible, or Flavio Percoco&amp;rsquo;s projects).&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;I am glad people are still interested in Ansible, and using it with OpenStack. OpenStack-Ansible has a sweet spot for deployers that don&amp;rsquo;t want to go for the full k8s experience to deploy OpenStack. We&amp;rsquo;ve proven once more our flexibility, by showing we are in line with our deployer needs, and demonstrating kubernetes can still be used (on top of your OpenStack-Ansible deployed cloud!).&lt;/p&gt;</description></item><item><title>Group and host variables overriding in OpenStack-Ansible</title><link>https://evrard.me/group-and-host-variables-overriding-in-openstack-ansible/</link><pubDate>Tue, 15 Aug 2017 00:00:00 +0000</pubDate><guid>https://evrard.me/group-and-host-variables-overriding-in-openstack-ansible/</guid><description>
&lt;p&gt;&lt;img src=&#34;https://evrard.me/images/Sergey_Svechnikov_large_buttons-small.jpg&#34; alt=&#34;group-overrides&#34; /&gt;&lt;/p&gt;
&lt;p&gt;You probably know it already, Ansible has different means of overriding a
variable, and also different levels of precedence.
OpenStack-Ansible is no different, and ships with different levels itself.
I&amp;rsquo;ll talk about the group and host variables here.&lt;/p&gt;
&lt;p&gt;If you manage your own Ansible configurations, you probably have
roles (inside their defaults and vars folders) variables, playbook
variables, and you probably tie all of these up with group and
host vars. You probably have noticed that these variables are
often modified, and are the core of your Ansible installation.&lt;/p&gt;
&lt;p&gt;Editing those is something highly inconvenient for an Ansible based
project that ships its own group/host variables: it
means your users have to edit the code of your project (for example,
OpenStack-Ansible), to match their needs.&lt;/p&gt;
&lt;p&gt;We still have ways to override group and host vars in OpenStack-Ansible, but
it depends on what you need, and which branch you are on. Let&amp;rsquo;s talk about that.&lt;/p&gt;
&lt;h1 id=&#34;for-pike&#34;&gt;For Pike&lt;/h1&gt;
&lt;p&gt;During Pike cycle, we moved the group variables into a &lt;a href=&#34;https://review.openstack.org/#/c/466379/&#34;&gt;different folder&lt;/a&gt;.
This allowed us to use our &lt;a href=&#34;https://review.openstack.org/#/c/445447/&#34;&gt;variables plugin&lt;/a&gt;, loading group and host
variables from different folders, with the precedence completely up to
the deployer (wiring can be seen &lt;a href=&#34;https://review.openstack.org/#/c/445437/&#34;&gt;here&lt;/a&gt;, if you want to replicate this
in your own environment)&lt;/p&gt;
&lt;p&gt;This series of commits allows you to override any group or host variable,
surgically. See also our &lt;a href=&#34;https://docs.openstack.org/openstack-ansible/pike/contributor/inventory-and-vars.html#variable-precedence&#34;&gt;upstream documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As usual, you could still use OpenStack-Ansible user variables, if you
want to set a variable for all your nodes. This has the highest level
of precedence, because it passes the user variable file in the CLI,
like you would if you were using
&lt;code&gt;ansible-playbook &amp;lt;...&amp;gt; -e @filename.yml&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&#34;for-newton-and-ocata&#34;&gt;For Newton, and Ocata&lt;/h1&gt;
&lt;p&gt;There was no consensus (yet) on whether or not OpenStack-Ansible
community should allow this backport of the variables into
the different folder. Newton and Ocata being
stable branches, it&amp;rsquo;s unlikely that you&amp;rsquo;ll be able to override
OpenStack-Ansible variables surgically, like you would in Pike.&lt;/p&gt;
&lt;p&gt;The variable plugin is still loaded, which means you can still
have extra group variables and extra host variables, if need be.
It&amp;rsquo;s a convenient way to add new variables, properly scoped, but
that won&amp;rsquo;t help you if you want to override, for example
&lt;a href=&#34;https://github.com/openstack/openstack-ansible/blob/73ee3eb9ae18add9c5c8a7872b736dddb129d8ce/playbooks/inventory/group_vars/all_containers.yml#L18-L19&#34;&gt;lxc_container_config_list&lt;/a&gt;, for one or a group of hosts.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see what is possible.&lt;/p&gt;
&lt;h2 id=&#34;the-lxc-container-config-list-example&#34;&gt;The lxc_container_config_list example&lt;/h2&gt;
&lt;p&gt;For this example, we want to override &lt;code&gt;lxc_container_config_list&lt;/code&gt;
for &lt;code&gt;cinder_api&lt;/code&gt; nodes.&lt;/p&gt;
&lt;p&gt;The task creating the container and using this list uses
&lt;a href=&#34;https://github.com/openstack/openstack-ansible-lxc_container_create/blob/258dad41ced7f9511d4e388470a759f46d9509fa/tasks/container_create.yml#L143-L153&#34;&gt;two variables&lt;/a&gt; you can technically override:
&lt;code&gt;lxc_container_default_config_list&lt;/code&gt; and &lt;code&gt;lxc_container_config_list&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;the-simplest-case&#34;&gt;The simplest case&lt;/h3&gt;
&lt;p&gt;If you want to keep the &lt;code&gt;lxc_container_config_list&lt;/code&gt; (the existing group
variable override), and add something on top, you could simply redefine
your &lt;code&gt;lxc_container_default_config_list&lt;/code&gt; into your
&lt;code&gt;/etc/openstack_deploy/group_vars/cinder_api.yml&lt;/code&gt; (please double
check that the vars plugin is loaded for you, by having a look at
your &lt;code&gt;in your /usr/local/bin/openstack-ansible.rc&lt;/code&gt;).&lt;/p&gt;
&lt;h3 id=&#34;overriding-the-group-variable-elegantly&#34;&gt;Overriding the group variable, elegantly.&lt;/h3&gt;
&lt;p&gt;Overriding the &lt;code&gt;lxc_container_config_list&lt;/code&gt; would be different, because
the precedence would force you to use our user variables.&lt;/p&gt;
&lt;p&gt;You could add into your own user variable file (let&amp;rsquo;s say
&lt;code&gt;/etc/openstack_deploy/user_cinder.yml&lt;/code&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;lxc_container_config_list: &amp;quot;{{ properties.lxc_container_config | default([&#39;lxc.aa_profile=lxc-openstack&#39;]) }}&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, you will be updating the lxc_config_list for all containers to the
lxc-openstack aa profile, but at the same time, you allow a container
property to override it!&lt;/p&gt;
&lt;p&gt;You can then create your &lt;code&gt;/etc/openstack_deploy/env.d/cinder.yml&lt;/code&gt; with
the following content:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;container_skel:
cinder_api_container:
properties:
lxc_container_config: [ &amp;quot;lxc.aa_profile=unconfined&amp;quot; ]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, you still need to ship env.d content for each of the groups
requiring a different value than &lt;code&gt;lxc-openstack&lt;/code&gt;. In other words,
in this case, you need to override the env.d content
for the cinder_volume and neutron_agent groups.&lt;/p&gt;
&lt;h3 id=&#34;overriding-the-group-variable-centrally&#34;&gt;Overriding the group variable, centrally.&lt;/h3&gt;
&lt;p&gt;There is an alternative:&lt;/p&gt;
&lt;p&gt;You could directly use group membership inside your user variables!&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cinder_lxc_container_config_list: [ &amp;quot;lxc.aa_profile=override&amp;quot; ]
others_lxc_container_config_list: [ &amp;quot;lxc.aa_profile=lxc-openstack&amp;quot; ]
lxc_container_config_list: &amp;quot;{% if &#39;cinder_api&#39; in group_names %}{{ cinder_lxc_container_config_list }}{% else %}{{ others_lxc_container_config_list }}{% endif %}&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or even better, if you want to add the cinder config list on top of the
existing ones:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;lxc_container_config_list: |-
{% set config_list = [] %}
{% set _ = config_list.extend(others_lxc_container_config_list) %}
{% if &#39;cinder_api&#39; in group_names %}
{% set _ = config_list.extend(cinder_lxc_container_config_list) %}
{% endif %}
{{ config_list }}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;overriding-a-host-variable&#34;&gt;Overriding a host variable.&lt;/h2&gt;
&lt;p&gt;What would you do if you need to override the cinder backends per host
on the storage hosts, and define their limit_container_types amongst
other data?&lt;/p&gt;
&lt;p&gt;For that you can configure your &lt;code&gt;conf.d/cinder.yml&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;storage_hosts:
aio1:
ip: 172.29.236.100
container_vars:
cinder_backends: &amp;quot;{{ cinder_backends_per_host.get(inventory_hostname) }}&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After that, you have to configure a user variable, where
&lt;code&gt;cinder_backends_per_host&lt;/code&gt; is a dictionary, and each host of your inventory
would be a key:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cinder_backends_per_host:
aio1_aodh_container-c065ea73:
limit_container_types: cinder_volume
lvm:
volume_group: cinder-volumes
volume_driver: cinder.volume.drivers.lvm.LVMVolumeDriver3
volume_backend_name: LVM_iSCSI
iscsi_ip_address: &amp;quot;172.29.236.100&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;It is possible to override your group variables and host variables
in every version of OpenStack-Ansible. The more recent your version
is, the more streamlined and user-friendly your experience will be.
Stay up to date, because Ansible 2.4 will
probably bring changes improving things even further&amp;hellip;&lt;/p&gt;</description></item><item><title>Usage of ansible local facts</title><link>https://evrard.me/usage-of-ansible-local-facts/</link><pubDate>Sat, 05 Aug 2017 00:00:00 +0000</pubDate><guid>https://evrard.me/usage-of-ansible-local-facts/</guid><description>
&lt;p&gt;&lt;img src=&#34;https://evrard.me/images/fact-check.jpg&#34; alt=&#34;facts-are-easy-to-check&#34; /&gt;&lt;/p&gt;
&lt;p&gt;If you haven&amp;rsquo;t looked at &lt;a href=&#34;http://docs.ansible.com/ansible/latest/playbooks_variables.html#local-facts-facts-d&#34;&gt;ansible &amp;lsquo;local&amp;rsquo; facts&lt;/a&gt; yet, maybe this article will encourage you to do so.
Ansible &amp;lsquo;local&amp;rsquo; facts is a very powerful tool to get information, statically or dynamically, on your hosts
WHEN the hosts are the authoritative source of truth.&lt;/p&gt;
&lt;p&gt;The example in the documentation is so simple it could be overlooked. You should use it
if you don&amp;rsquo;t already use facter or ohai.&lt;/p&gt;
&lt;h1 id=&#34;first-usage&#34;&gt;First usage&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s start with the example of the documentation:&lt;/p&gt;
&lt;p&gt;If you write a file named &lt;code&gt;something.&lt;/code&gt;&lt;strong&gt;fact&lt;/strong&gt; into &lt;code&gt;/etc/ansible/facts.d/&lt;/code&gt;, you may use its
content as local fact by using:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{{ ansible_local.something }}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;after running the &lt;code&gt;setup&lt;/code&gt; module.&lt;/p&gt;
&lt;p&gt;So, if you have a file, named &lt;code&gt;a.fact&lt;/code&gt;, containing:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[b]
c=True
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You could use &lt;code&gt;{{ ansible_local.a.b.c }}&lt;/code&gt; for anything. Tasks, conditionals&amp;hellip; (Remember you
could use set_fact for caching in your local play!)&lt;/p&gt;
&lt;p&gt;As long as this file is readable under a json or a ini form, ansible will take it.&lt;/p&gt;
&lt;h1 id=&#34;so-when-is-it-useful-and-what-could-i-use-it-for&#34;&gt;So, when is it useful, and what could I use it for?&lt;/h1&gt;
&lt;p&gt;If you have to configure a software depending on its state, and that software doesn&amp;rsquo;t
report to a centralized state management system, that&amp;rsquo;s where your local fact will shine.&lt;/p&gt;
&lt;p&gt;Example, you want to ensure your Galera cluster is in a correct state, and erase the state
of an incorrect node. For that, you may need to compare what each node &amp;ldquo;sees&amp;rdquo;, and
therefore a centralized view can&amp;rsquo;t help you.&lt;/p&gt;
&lt;p&gt;You can write a script (let&amp;rsquo;s call it &lt;code&gt;galera.fact&lt;/code&gt;) with the simple following content&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:fn-galera&#34;&gt;&lt;a href=&#34;#fn:fn-galera&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;#!/bin/bash
echo &#39;[cluster_status&#39;]
mysql mysql -e &amp;quot;SHOW GLOBAL STATUS LIKE &#39;wsrep_cluster_status&#39;\G&amp;quot; | awk &#39;/Value/{print &amp;quot;status=&amp;quot;$2}&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Don&amp;rsquo;t forget to mark it as executable.&lt;/p&gt;
&lt;p&gt;You can now see the status of your node(s) by looking at
&lt;code&gt;{{ ansible_local.galera.cluster_status.status }}&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Very useful.&lt;/p&gt;
&lt;h1 id=&#34;what-s-the-catch&#34;&gt;What&amp;rsquo;s the catch?&lt;/h1&gt;
&lt;h2 id=&#34;slowness&#34;&gt;Slowness&lt;/h2&gt;
&lt;p&gt;The local facts will slow up your playbooks!&lt;/p&gt;
&lt;p&gt;Calling the setup module (which happens by default on a playbook unless
&lt;code&gt;gather_facts&lt;/code&gt; is set to &lt;code&gt;no&lt;/code&gt;) will trigger the &amp;ldquo;local&amp;rdquo; data generation.
If your script is slow to execute, you will have to face the slowdown.&lt;/p&gt;
&lt;p&gt;On top of that, you&amp;rsquo;ll carry extra variables in your vars/hostvars, which burdens
ansible on very large environments.&lt;/p&gt;
&lt;p&gt;The alternative approach would be that your script pushes to a central local location,
like a redis k/v store, or etcd.&lt;/p&gt;
&lt;h2 id=&#34;unfriendliness&#34;&gt;Unfriendliness&lt;/h2&gt;
&lt;p&gt;To do an action when your galera cluster status is not &amp;ldquo;Primary&amp;rdquo;, you&amp;rsquo;d have to ensure
the full fact chain is set. If you are not sure about whether your fact is
defined or not, you could end up writing a waterfall of checks just to
be able to read &lt;code&gt;{{ ansible_local.galera.cluster_status.status }}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt; when:
- ansible_local is defined
- ansible_local.galera is defined
- ansible_local.galera.cluster_status is defined
- ansible_local.galera.cluster_status.status is defined
- ansible_local.galera.cluster_status.status != &amp;quot;Primary&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hopefully here, if you can install jmespath&lt;a href=&#34;http://jmespath.org/&#34;&gt;3&lt;/a&gt;, ansible got you covered with the &lt;code&gt;json_query&lt;/code&gt; filter.&lt;/p&gt;
&lt;p&gt;You can run in this case:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; when: &amp;quot;{{ ansible_local | json_query(&#39;galera.cluster_status.status&#39;) | default(&#39;Error&#39;,True) != &#39;Primary&#39; }}&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For your information, json_query will return an empty string, not an error, if the element is not found.
That&amp;rsquo;s why I am using &lt;code&gt;default(&#39;something&#39;,&lt;/code&gt;&lt;strong&gt;True&lt;/strong&gt;&lt;code&gt;)&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&#34;recap&#34;&gt;Recap&lt;/h1&gt;
&lt;p&gt;Ansible local facts is a double-edged sword.
It&amp;rsquo;s very powerful to get a complete a view of your environment if you don&amp;rsquo;t already
use another method. However, it comes with slowness.&lt;/p&gt;
&lt;p&gt;I would still recommend use local facts as much as possible if you can&amp;rsquo;t use a central approach, they
are more flexible and faster to write than writing an inventory, a var plugin, or an inventory plugin!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:fn-galera&#34;&gt;I know this example isn&amp;rsquo;t the best, because you could use &lt;a href=&#34;http://galeracluster.com/documentation-webpages/notificationcmd.html&#34;&gt;galera notification scripts&lt;/a&gt; better, but that&amp;rsquo;s just an example.
&lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:fn-galera&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>My view on Ansible 2.3 release notes</title><link>https://evrard.me/my-view-on-ansible-23-release-notes/</link><pubDate>Fri, 21 Apr 2017 00:00:00 +0000</pubDate><guid>https://evrard.me/my-view-on-ansible-23-release-notes/</guid><description>&lt;p&gt;&lt;img src=&#34;https://evrard.me/images/Shut-up-and-take-my-money.jpg&#34; alt=&#34;Shutup and take my money&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Ansible 2.3 was released. I&amp;rsquo;m pretty sure you&amp;rsquo;ve seen things online about it, and probably read the changelog.&lt;/p&gt;
&lt;p&gt;Networking modules were a big thing this release.&lt;/p&gt;
&lt;p&gt;So big, it&amp;rsquo;s easy to overlook the rest.
Here are, in my opinion, many other things worth glancing over for 2.3 (discovered from commits, or from the &lt;a href=&#34;https://github.com/ansible/ansible/blob/v2.3.0.0-1/CHANGELOG.md#23-ramble-on---2017-04-12&#34;&gt;changelog&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ansible_user&lt;/code&gt; &lt;a href=&#34;https://github.com/ansible/ansible/issues/23530&#34;&gt;doesn&amp;rsquo;t work anymore&lt;/a&gt; if you don&amp;rsquo;t have a variable explicitly set (depends on your connection plugin). If you have facts gathered, you may want to use &lt;code&gt;ansible_user_id&lt;/code&gt;. This bug has already been fixed in the 2.3 branch and will probably be shipped in version 2.3.0.1&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/ansible/ansible/commit/a2599cab794e9a2b8af88c012028ef45756cc973&#34;&gt;Vars precedence and inheritence&lt;/a&gt; have changed. Please have a look at the docs for variable precedence. I have to test if it broke my &lt;code&gt;vars_plugins&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;module_utils for custom modules can be shipped with roles. \o/&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;passwordstore&lt;/code&gt; lookup was introduced (see also passwordstore.org). Maybe it was there before, but I can&amp;rsquo;t remember it, and I love it.&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;keyring&lt;/code&gt; lookup was introduced.&lt;/li&gt;
&lt;li&gt;You can now have a more terse run output with the new &lt;code&gt;dense&lt;/code&gt; callback plugin.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;YAML&lt;/code&gt; and &lt;code&gt;pickle&lt;/code&gt; cache support! Interesting, I think I will prefer YAML compared to all of the existing cache plugins.&lt;/li&gt;
&lt;li&gt;There are new &lt;code&gt;combinations&lt;/code&gt; and &lt;code&gt;permutations&lt;/code&gt; filters.&lt;/li&gt;
&lt;li&gt;We now finally have &lt;code&gt;archive&lt;/code&gt;, long after &lt;code&gt;unarchive&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;New/Updated toys (modules) are available for ansible stats, wait for connection, nginx, openssl,
jenkins groovy scripts, parted, tempfile, zfs, Clear Linux, HP ILO, FreeIPA, iso extraction,
ldap, logstash, netapp, omapi, ovirt, serverless, openbsd, let&amp;rsquo;s encrypt, the usual clouds, &amp;hellip;&lt;/li&gt;
&lt;li&gt;Time to flatten your package lists yourself again! &lt;em&gt;removed &amp;lsquo;package&amp;rsquo; from default squash actions as not all package managers support it and it creates errors when using loops,
any user can add back via config options if they don&amp;rsquo;t use those package managers or otherwise avoid the errors.&lt;/em&gt;
&lt;strong&gt;Great&lt;/strong&gt;. Moar slowness.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Blocks can now have a name field&lt;/em&gt;. I like this improved readability.&lt;/li&gt;
&lt;li&gt;SO MUCH WOW with strategies: &lt;em&gt;Default strategy is now configurable via ansible.cfg or environment variable&lt;/em&gt;.
That&amp;rsquo;s a change I love, mainly because I now have a different way to use a strategy I wrote (with the help of Kevin Carter, see in &lt;a href=&#34;https://github.com/openstack/openstack-ansible-plugins&#34;&gt;openstack-ansible-plugins&lt;/a&gt;) without changing my playbook.&lt;/li&gt;
&lt;li&gt;There are changes in the way multiple &lt;code&gt;--tags&lt;/code&gt; given in the CLI behave. On this note, if you&amp;rsquo;re tired of all of these changes, you can use my/our tag filtering strategy ;)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;restructured how async works to allow it to apply to action plugins that choose to support it&lt;/em&gt;. Great, we&amp;rsquo;ll have to adapt config-template action plugin, if need be.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I am now forced to have a look at our custom connection plugin because of the multiple connection/retry behavior changes. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;On platforms that support it, use more modern system polling API instead of select in the ssh connection plugin. This removes one limitation on how many parallel forks are feasible on these systems&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;added optional &amp;lsquo;piped&amp;rsquo; transfer method to ssh plugin for when scp and sftp are missing, ssh plugin is also now &amp;lsquo;smarter&amp;rsquo; when using these options&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;On top of that, there were &lt;a href=&#34;https://github.com/ansible/ansible/commit/eed240797aed30a0e42a9d2cb6cdded16d75fb5c&#34;&gt;other&lt;/a&gt; &lt;a href=&#34;https://github.com/ansible/ansible/commit/1fe67f9f436595003f7951dd88159731e6d82498&#34;&gt;changes&lt;/a&gt; &lt;a href=&#34;https://github.com/ansible/ansible/commit/d1a6b07fe1ceb8099abf763ac7e4bb4ebfaf1d3f&#34;&gt;linked to connections/retries&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;I. FEEL. THE. DANGER.&lt;/strong&gt; : &lt;em&gt;Fixed issues with inventory formats not handling &amp;lsquo;all&amp;rsquo; and &amp;lsquo;ungrouped&amp;rsquo; in an uniform way&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Yum state: list&lt;/code&gt; now works with disable repo and enable repo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Split on newlines when searching become prompt (&lt;a href=&#34;https://github.com/ansible/ansible/commit/4a9c5d9574038b80d199daafc9d1273f8a659831&#34;&gt;5&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;LXC module doesn&amp;rsquo;t have a problem with HOSTNAME in bashrc anymore.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The ansible-galaxy init can now take a skeleton argument, and/or read env vars for skeleton role location.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The message &amp;ldquo;skipping: no hosts matched&amp;rdquo; has returned!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The apt_repository module got &lt;a href=&#34;https://github.com/ansible/ansible/commit/577d0e43ba339788989ecdf9a9da97477596ec6d&#34;&gt;a bug&lt;/a&gt; fixed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Installing an OpenStack-Ansible multi-node cloud in the cloud</title><link>https://evrard.me/installing-an-openstack-ansible-multi-node-cloud-in-the-cloud/</link><pubDate>Thu, 29 Dec 2016 00:00:00 +0000</pubDate><guid>https://evrard.me/installing-an-openstack-ansible-multi-node-cloud-in-the-cloud/</guid><description>
&lt;p&gt;&lt;img src=&#34;https://evrard.me/images/cloud-multi-node-title.png&#34; alt=&#34;Your cloud-based OpenStack-Ansible cloud&#34; /&gt;&lt;/p&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Installing openstack is not that hard, but it could be time consuming. When running your first installs, you probably want to prototype on instances instead of hardware, to shave time.
It is basically one of the &amp;ldquo;cloud&amp;rdquo; principles: Focus on your goal (a business man would have said &amp;ldquo;value&amp;rdquo;), and rely on your providers whenever possible.&lt;/p&gt;
&lt;p&gt;So, for me, it makes 100% sense to deploy OpenStack-Ansible in the cloud. So what are the steps?&lt;/p&gt;
&lt;p&gt;Note: This post&amp;rsquo;s relevance can change overtime, as OpenStack and OpenStack-Ansible evolves.&lt;/p&gt;
&lt;h2 id=&#34;general-overview&#34;&gt;General overview&lt;/h2&gt;
&lt;p&gt;If you want to deploy your OpenStack-Ansible cloud in the cloud, here are the top level steps.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You want to have, like you would in hardware, an &amp;ldquo;OpenStack-Ansible&amp;rdquo;-ready operating system.&lt;/li&gt;
&lt;li&gt;Because currently OpenStack-Ansible requires&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:fn-network-requirements-explained&#34;&gt;&lt;a href=&#34;#fn:fn-network-requirements-explained&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; your nodes to be on the same management network, you probably want them connected in some way.&lt;/li&gt;
&lt;li&gt;You then want to follow the usual steps for deploying ansible.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These steps are similar to steps needed to run OpenStack-Ansible nodes in your datacenter. The &amp;ldquo;cloud&amp;rdquo; nature brings more flexibility and constraints at the same time, so let&amp;rsquo;s go through these a little further&lt;/p&gt;
&lt;p&gt;In the future I&amp;rsquo;m presuming you have a host/node that can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;do git operations (clone)&lt;/li&gt;
&lt;li&gt;run python and ansible&lt;/li&gt;
&lt;li&gt;connect to your cloud provider(s) to create your instances.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This node is NOT the deploy node (but it could), it&amp;rsquo;s simply your laptop or whatever.&lt;/p&gt;
&lt;h2 id=&#34;step-1-prepare-the-operating-system-for-openstack-ansible&#34;&gt;Step 1: Prepare the operating system for OpenStack-Ansible&lt;/h2&gt;
&lt;p&gt;OpenStack-Ansible requires an Ubuntu 14.04 (up to Newton) or 16.04 (from Newton onwards) with specific packages. CentOS 7 is on the works, but let&amp;rsquo;s focus on Ubuntu 16.04 for this exercice.
Using a cloud provider already makes sense: Ubuntu being popular, you probably don&amp;rsquo;t have to roll your own image, everything is probably already ready to work. Give your ssh keypair, select ubuntu 16.04 and DONE!&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s say for the sake of the exercice you&amp;rsquo;ve created the following instances in your cloud provider:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;deploy&lt;/li&gt;
&lt;li&gt;haproxy01&lt;/li&gt;
&lt;li&gt;haproxy02&lt;/li&gt;
&lt;li&gt;infra01&lt;/li&gt;
&lt;li&gt;infra02&lt;/li&gt;
&lt;li&gt;infra03&lt;/li&gt;
&lt;li&gt;compute01&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You probably want to install:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git&lt;/code&gt;, &lt;code&gt;python&lt;/code&gt;, and some other ansible dependencies on the deploy node&lt;/li&gt;
&lt;li&gt;&lt;code&gt;python2.7&lt;/code&gt; on haproxy nodes&lt;/li&gt;
&lt;li&gt;a recent kernel, &lt;code&gt;python2.7&lt;/code&gt;, enough RAM/disk on the infra nodes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please check the current requirements for your version in the OpenStack-Ansible installation/deployment guide.&lt;/p&gt;
&lt;p&gt;You could do install these packages manually by running &lt;code&gt;apt-get install x&lt;/code&gt; on each of those nodes.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re like me, you probably want to automate it.
Enters the preliminary step: Using ansible to prepare your operating systems.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Warning: Using Ansible to bootstrap your hosts in order to deploy OpenStack-Ansible on your instances (one of these will be bootstraping Ansible for OpenStack-Ansible) can cause dizziness.
But don&amp;rsquo;t worry, we are not looping.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;step-1-0-preparing-ansible-inventory&#34;&gt;Step 1.0 Preparing ansible inventory&lt;/h3&gt;
&lt;p&gt;To use Ansible, you better have an inventory. You cannot use the OpenStack-Ansible inventory at this point of the lab yet, so you need to write your own.&lt;/p&gt;
&lt;p&gt;Ansible did most of the job for you by providing &lt;a href=&#34;http://docs.ansible.com/ansible/intro_dynamic_inventory.html&#34;&gt;dynamic inventories scripts&lt;/a&gt; for &lt;a href=&#34;https://raw.github.com/ansible/ansible/devel/contrib/inventory/ec2.py&#34;&gt;AWS&lt;/a&gt; or &lt;a href=&#34;https://raw.githubusercontent.com/ansible/ansible/89ce826a9fb53c304238923a73667ab820711338/contrib/inventory/openstack_inventory.py&#34;&gt;OpenStack&lt;/a&gt; clouds.
Put these scripts under your &lt;code&gt;inventory/&lt;/code&gt; and &lt;code&gt;chmod +x&lt;/code&gt; them (&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:fn-dynamic-inventories-fetching&#34;&gt;&lt;a href=&#34;#fn:fn-dynamic-inventories-fetching&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;). I am assuming you&amp;rsquo;re creating your own repo or folder for this.&lt;/p&gt;
&lt;p&gt;The Ansible OpenStack dynamic inventory script relies on shade and your &lt;code&gt;clouds.yaml&lt;/code&gt; (for example &lt;code&gt;~/.config/openstack/clouds.yaml&lt;/code&gt;), so make sure they are ready.&lt;/p&gt;
&lt;p&gt;For user-friendliness, you may want to add in your &lt;code&gt;clouds.yaml&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ansible:
use_hostnames: True
expand_hostvars: False
fail_on_errors: True
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Check your inventory by issuing &lt;code&gt;python &amp;lt;your inventory script&amp;gt; --list&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;step-1-1-targetting-the-proper-nodes&#34;&gt;Step 1.1 Targetting the proper nodes&lt;/h3&gt;
&lt;p&gt;Now that your Ansible inventory is ready, you can see its layout is flat, except if you have given metadata to your instances. This lack of groups could be problematic.&lt;/p&gt;
&lt;p&gt;Two ways to fix this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Make sure what you run is targetting the proper nodes by using an in-memory inventory features&lt;/li&gt;
&lt;li&gt;Use the ansible inventory merge behavior and complete the inventory with a static inventory file to make your life easier.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For the in-memory inventory, you need tasks holding the group/host names. If these tasks are not using variables, you will prevent the reuse of the plays. If using variables, their location would be, in my opinion, far less obvious than the inventory (in play, in a variable file, in group/host vars, &amp;hellip;).&lt;/p&gt;
&lt;p&gt;In this case, I think the solution two seems better. The node targetting should be done with an ansible inventory file (like an INI file) and benefit from ansible merge behavior.
So here is an extract of what you&amp;rsquo;d need in the INI file for this step:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[pre_osa]
infra01
infra02
infra03
deploy
haproxy01
haproxy02
compute01
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not that hard, right?&lt;/p&gt;
&lt;p&gt;If you skipped the step 1.0, your only choice would be to write an INI file with the following content:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[pre_osa]
infra01 ansible_host=xx.xx.xx.xx
infra02 ansible_host=xx.xx.xx.xx
infra03 ansible_host=xx.xx.xx.xx
deploy ansible_host=xx.xx.xx.xx
haproxy01 ansible_host=xx.xx.xx.xx
haproxy02 ansible_host=xx.xx.xx.xx
compute01 ansible_host=xx.xx.xx.xx
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Everytime you&amp;rsquo;d change your cloud node, you&amp;rsquo;d have to rewrite your &lt;code&gt;ansible_host&lt;/code&gt; value. Tedious but ok for small tests too. Your pick.&lt;/p&gt;
&lt;h3 id=&#34;step-1-2-installing-the-openstack-ansible-requirements&#34;&gt;Step 1.2 Installing the OpenStack-Ansible requirements&lt;/h3&gt;
&lt;p&gt;Now, you need to install the basic requirements for Ansible.
This is technically required on the deploy node, but some other nodes may require them too. For safety, install the packages everywhere!&lt;/p&gt;
&lt;p&gt;So, for Ubuntu you need the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ansible pre_osa -m raw -a &amp;quot;test -e /usr/bin/python || (apt-get -y update &amp;amp;&amp;amp; apt-get install -y python-minimal)&amp;quot;
ansible pre_osa -m raw -a &amp;quot;apt-get update -y &amp;amp;&amp;amp; apt-get install -y git build-essential python-simplejson libssl-dev libffi-dev bridge-utils&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: The above commands don&amp;rsquo;t specify a user or elevation method, nor the path to the inventory you just created. Adapt it to your needs.&lt;/p&gt;
&lt;p&gt;Note: The above commands only list the packages needed at the time of the writing of this article. Please check what is required in OpenStack-Ansible
by checking the &lt;code&gt;bindep.txt&lt;/code&gt; file in the root of your openstack-ansible repo. Or just install bindep and use it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;step-1-3-test-your-ansible-installation&#34;&gt;Step 1.3 Test your ansible installation&lt;/h3&gt;
&lt;p&gt;You can now run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ansible pre_osa -m ping
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And move on the real stuff.&lt;/p&gt;
&lt;h3 id=&#34;step-2-0-configure-networking&#34;&gt;Step 2.0 Configure networking&lt;/h3&gt;
&lt;h4 id=&#34;cloud-multi-node-problem-statement&#34;&gt;Cloud multi-node problem statement&lt;/h4&gt;
&lt;p&gt;The odds are really high that your cloud provider will prevent you from having network traffic coming to/from multiple ethernet addresses for one network. In general, you have one tuple (IP, hardware address) per network configured at your provider.
Because OpenStack-Ansible is relying on bridging to put containers together on the same networks, only the host traffic will be able to go outside.
It&amp;rsquo;s perfectly fine from an all-in-one (AIO) standpoint, because in this case the external world will only speak to the load balancer on the host, and the rest of the OpenStack traffic will stay inside the hosts and don&amp;rsquo;t need external world forwarding.
This won&amp;rsquo;t do in our multi-node scenario.&lt;/p&gt;
&lt;h4 id=&#34;the-solutions&#34;&gt;The solutions&lt;/h4&gt;
&lt;p&gt;You can do NAT, but I will not recommend it. This is a radical change from OpenStack-Ansible standard networking. You&amp;rsquo;ll be on your own, probably will have issues with some software, and your future hardware deploy of OpenStack-Ansible will probably not be deployed with NAT for scalability reasons (therefore the reproducibility of this exercice is quite limited). On top of that NAT isn&amp;rsquo;t really a good idea if you plan to have an OpenStack cloud from this century, i.e. with IPv6.&lt;/p&gt;
&lt;p&gt;You could deploy all your OpenStack-Ansible components on metal instead of in containers. You&amp;rsquo;d then multiply the amount of cloud instances you need, and complexity. Also I&amp;rsquo;d rather have the same configuration for OpenStack-Ansible in my cloud deploy as I would have in my hardware deploy.&lt;/p&gt;
&lt;p&gt;The other solution would be to encapsulate your Layer 2 traffic between your cloud instances: Your configuration won&amp;rsquo;t change for OpenStack-Ansible, you&amp;rsquo;ll only have different networking (and a smaller MTU in the case of cloud instances vs the hardware installation).
Keep in mind that there are many roles in the ansible galaxy to configure your networking for your needs.&lt;/p&gt;
&lt;h4 id=&#34;encapsulation-and-tunneling-using-vxlan&#34;&gt;Encapsulation and tunneling using VXLAN&lt;/h4&gt;
&lt;p&gt;Please note that &lt;a href=&#34;https://github.com/openstack/openstack-ansible&#34;&gt;the OpenStack-Ansible repo&lt;/a&gt; hides a hidden gem &lt;a href=&#34;https://github.com/openstack/openstack-ansible/tree/master/tests/roles/bootstrap-host&#34;&gt;here, in the bootstrap-host role&lt;/a&gt;.
OpenStack-Ansible uses this role (located in the tests folder) in its CI testing for configuring many things required to deploy/configure OpenStack.&lt;/p&gt;
&lt;p&gt;The bootstrap-host role has the ability to configure basic networking, but also VXLAN encapsulation.
If you want to use this role (&lt;sup class=&#34;footnote-ref&#34; id=&#34;fnref:make-sure-you-have-cloned-and-linked-the-repo&#34;&gt;&lt;a href=&#34;#fn:make-sure-you-have-cloned-and-linked-the-repo&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;), you probably want to select only its networking bits. Create your own playbook, target your cloud nodes, include the bootstrap-host role, and run the playbook with the proper tags. It should look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ansible-playbook osa-cloud-multinode-networking.yml --tags=prepare-networking
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: the bootstrap-host role need the excellent &lt;code&gt;config_template&lt;/code&gt; plugin to work. Make sure you have the plugin in your Ansible plugins path.
You can override the plugins folder location by adapting your ansible.cfg file, or using environment variables.
Alternatively, you may want to consider that the &lt;code&gt;bootstrap-host&lt;/code&gt; role as a meta dependency to the &lt;code&gt;openstack-ansible-plugins&lt;/code&gt; role, which makes possible to use the &lt;code&gt;config_template&lt;/code&gt; easily.
That&amp;rsquo;s what I usually prefer.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Adapt variables to trick the &lt;code&gt;bootstrap-host&lt;/code&gt; role into doing your bidding.&lt;/p&gt;
&lt;p&gt;For example, my &lt;code&gt;osa-cloud-multinode-networking.yml&lt;/code&gt; looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
- hosts: pre_osa
vars:
bootstrap_host_aio_config: no
bootstrap_host_encapsulation_interface: &amp;quot;{{ ansible_default_ipv4.interface }}&amp;quot; #Assuming you only have one interface, a public one, you want to assign this as exit interface and encapsulation carrying interface
bootstrap_host_public_interface: &amp;quot;{{ ansible_default_ipv4.interface }}&amp;quot;
bootstrap_host_encapsulation_enabled: True #not really necessary to define it, but hell it doesn&#39;t hurt to be explicit.
roles:
- bootstrap-host
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You probably want to give each of your nodes a &lt;code&gt;node_id&lt;/code&gt;. You can either assign the &lt;code&gt;node_id&lt;/code&gt; in the inventory (node per node or in a group var), or defining it in the playbook (set_facts/vars):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;node_id: &amp;quot;{{ groups.pre_osa.index(inventory_hostname) }}&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The trick here is that the bootstrap-host can configure a VXLAN overlay between all your nodes. This will be used to encapsulate traffic for br-mgmt, br-storage, br-vxlan, and br-vlan!&lt;/p&gt;
&lt;h4 id=&#34;other-solutions&#34;&gt;Other solutions&lt;/h4&gt;
&lt;p&gt;There are many other solutions for solving this issue (I think of L2TPv3, L2VPN with MPLS/VPLS, Tinc, GRE, &amp;hellip;). If you&amp;rsquo;re interested on how to do it in more details, contact me!&lt;/p&gt;
&lt;h3 id=&#34;step-2-1-verify-network-configuration&#34;&gt;Step 2.1 Verify network configuration&lt;/h3&gt;
&lt;p&gt;That&amp;rsquo;s the simplest of the steps:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; ansible pre_osa -m shell -a &amp;quot;cat /etc/network/interfaces.d/*&amp;quot;
ansible pre_osa -m setup
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Alternatively, you can check the connectivity on the br-mgmt of the nodes by pinging the nodes manually.&lt;/p&gt;
&lt;h3 id=&#34;step-3-0-deploy-and-use&#34;&gt;Step 3.0 Deploy and use!&lt;/h3&gt;
&lt;p&gt;From now on, the nodes will be &amp;ldquo;like if they were on the same layer 3&amp;rdquo;, which should be enough for your OpenStack-Ansible deployment.&lt;/p&gt;
&lt;p&gt;Use your br-mgmt IPs when configuring your conf.d/openstack_user_config and everything should be fine!&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Building overlays accross multiple datacenters/clouds is quite easy, and work by default in OpenStack-Ansible. Make use of it!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:fn-network-requirements-explained&#34;&gt;We don&amp;rsquo;t really require all the nodes to be in the same management network, but it makes your life quite simpler. This is the path chosen for this article.
&lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:fn-network-requirements-explained&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li id=&#34;fn:fn-dynamic-inventories-fetching&#34;&gt;Please remind me to write a tool for that.
&lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:fn-dynamic-inventories-fetching&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li id=&#34;fn:make-sure-you-have-cloned-and-linked-the-repo&#34;&gt;To use the bootstrap-host role, you have to clone the role in the appropriate folder!
&lt;a class=&#34;footnote-return&#34; href=&#34;#fnref:make-sure-you-have-cloned-and-linked-the-repo&#34;&gt;&lt;sup&gt;[return]&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>ansible-galaxy, my journey to install golang</title><link>https://evrard.me/ansible-galaxy-my-journey-to-install-golang/</link><pubDate>Sun, 02 Oct 2016 00:00:00 +0000</pubDate><guid>https://evrard.me/ansible-galaxy-my-journey-to-install-golang/</guid><description>
&lt;p&gt;&lt;img src=&#34;https://evrard.me/images/ansible-galaxy-install-golang.png&#34; alt=&#34;ansible-galaxy install golang -- 404 - proper role not found&#34; /&gt;&lt;/p&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I wanted to self-host &lt;a href=&#34;https://github.com/dutchcoders/transfer.sh/&#34;&gt;transfer.sh&lt;/a&gt;, and didn&amp;rsquo;t want to start using docker or new tech.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TL:DR;&lt;/strong&gt; As usual, I turned to ansible, and (as usual) I was disappointed by the quality of the roles on the &lt;a href=&#34;https://galaxy.ansible.com&#34;&gt;ansible-galaxy website&lt;/a&gt;. I wanted to submit PR to the best role, but at the end I&amp;rsquo;d have to modify it.&lt;/p&gt;
&lt;p&gt;So, what is really the point of &lt;a href=&#34;https://galaxy.ansible.com&#34;&gt;galaxy.ansible.com&lt;/a&gt;? What could we do to make it better?&lt;/p&gt;
&lt;h2 id=&#34;the-journey&#34;&gt;The journey&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/dutchcoders/transfer.sh/&#34;&gt;Transfer.sh&lt;/a&gt; is a simple tool to upload your files from the command line. It&amp;rsquo;s server side is developped with go.
To install this in a repeatable fashion, I wanted to use the available roles in ansible-galaxy.&lt;/p&gt;
&lt;h3 id=&#34;first-step-search-a-role-on-the-galaxy-website&#34;&gt;First step: Search a role on the galaxy website.&lt;/h3&gt;
&lt;p&gt;To find the best role, I trust the other users. I check the download count.
I had 2 targets: one role with 192 downloads and one with 164.
I then asked myself: how is it possible that a popular language like golang doesn&amp;rsquo;t have more download counts?&lt;/p&gt;
&lt;p&gt;Obviously there was an issue.&lt;/p&gt;
&lt;h3 id=&#34;second-step-verify-if-galaxy-website-ansible-galaxy-isn-t-borked-again&#34;&gt;Second step: Verify if &lt;a href=&#34;https://galaxy.ansible.com&#34;&gt;galaxy website&lt;/a&gt; isn&amp;rsquo;t borked again.&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://galaxy.ansible.com&#34;&gt;galaxy.ansible.com&lt;/a&gt; has caused me a lot of pain in the past.
The most memorable for me was this one time where I could not import the latest version of my role, and hoped disabling/enabling it could help the situation. Obviously(?) the role disable worked, but the enable failed, and all shell scripts relying on the presence of this repo started to fail. When this kind of things happen at 6PM, you know you are gonna stay up late to introduce fixes everywhere. All the trust you have for this website is now gone.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s get back to the matter here. A simple refresh (or &amp;ldquo;back&amp;rdquo;) on the page, shows me different results! Interesting.
I wonder how much people tried a terrible role because the best role was not shown in the results.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see what we have now:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://raw.githubusercontent.com/evrardjp/evrard.me/2d154fbf31f9666e37b578a5630394a824c08b66/content/images/ansible-galaxy-golang-roles.png&#34;&gt;
&lt;img src=&#34;{filename}/images/ansible-galaxy-golang-roles.png&#34; alt=&#34;this seems a better listing&#34; /&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Oh, that&amp;rsquo;s better, 6k downloads! This is where my focus will be.&lt;/p&gt;
&lt;p&gt;But before that, should I try once again? Do I really have only 10 records? I suppose I have at least 11 of them, since a new one showed up.
Let&amp;rsquo;s try that search again.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://raw.githubusercontent.com/evrardjp/evrard.me/2d154fbf31f9666e37b578a5630394a824c08b66/content/images/ansible-galaxy-golang-24-roles.png&#34;&gt;
&lt;img src=&#34;{filename}/images/ansible-galaxy-golang-24-roles.png&#34; alt=&#34;There are 24 roles listed&#34; /&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Finally, a proper list! So, I can now (after multiple tentatives) confirm there are 24 roles listed in the galaxy for golang.&lt;/p&gt;
&lt;p&gt;On another note, did you notice that the role with the most downloads did not appear in the first PAGE of results when sorted by relevance?&lt;/p&gt;
&lt;h3 id=&#34;third-step-elect-the-best-role&#34;&gt;Third step: Elect the best role&lt;/h3&gt;
&lt;p&gt;Obviously &lt;a href=&#34;https://galaxy.ansible.com&#34;&gt;galaxy website&lt;/a&gt; relevance sort was not reliable, so I tried to sort with downloads.
There were 4 of them with more than 100 downloads.&lt;/p&gt;
&lt;p&gt;The first one is supporting my distribution and installs the latest release of golang! Sadly, this could stop anytime, because the variables used for the version have to be manually set in default/main.yml . This seems brittle, but it will be fine if the maintainer of the role is answering to the community.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s therefore check the PRs!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2 open PR. Once from December last year, one in march this year. We are in september. That&amp;rsquo;s a long period for triaging/fixing for a role that small.&lt;/li&gt;
&lt;li&gt;Now the closed PRs. There are many of them, some of them closed recently. A good sign. Many of them are basically jumping the version to a more recent one. It makes sense, that&amp;rsquo;s what I&amp;rsquo;ve seen!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At that point, here are my options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PR to adapt the role to make it resilient to version changes&lt;/li&gt;
&lt;li&gt;Check the other roles&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I decided to check the other roles, maybe the grass is greener on the other side of the fence.&lt;/p&gt;
&lt;p&gt;The second in terms of downloads forced me to edit my &lt;code&gt;ansible.cfg&lt;/code&gt; to change the hash_merge behavior. Terrible. It didn&amp;rsquo;t support latest golang version either.&lt;/p&gt;
&lt;p&gt;The third is installing latest version, but has a dependant role for something I can&amp;rsquo;t explain yet. It also forces me to &lt;code&gt;become:&lt;/code&gt; and &lt;code&gt;become_user: root&lt;/code&gt;, on top of having terrible task readability.&lt;/p&gt;
&lt;p&gt;The last one was the debops one. debops has lots of roles, and probably fit use cases which isn&amp;rsquo;t mine: I don&amp;rsquo;t want to have this complex series of roles and dependencies, or being forced to use a playbook. Ansible should be simple.&lt;/p&gt;
&lt;p&gt;I give the golang example here, but trust me, it&amp;rsquo;s the same story for every single role I&amp;rsquo;m trying to install.&lt;/p&gt;
&lt;h3 id=&#34;fourth-step-analyse-how-long-would-it-take-me-to-adapt-the-best-role-vs-recreating-one&#34;&gt;Fourth step: Analyse how long would it take me to adapt the best role vs recreating one&lt;/h3&gt;
&lt;p&gt;This role has 6 tasks. I can keep 3 of them, and modify the rest.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve decided to &lt;a href=&#34;https://github.com/evrardjp/ansible-go/&#34;&gt;adapt the role&lt;/a&gt; and &lt;a href=&#34;https://github.com/jlund/ansible-go/pull/28&#34;&gt;submit a PR&lt;/a&gt;. My own golang role is still &lt;a href=&#34;https://galaxy.ansible.com/evrardjp/golang/&#34;&gt;published on the galaxy&lt;/a&gt;, until the PR are merged. It seems a good intermediary.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Even basic roles that should be properly done are done in a terrible way. IMO, RedHat should now invest in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a proper &lt;a href=&#34;https://galaxy.ansible.com&#34;&gt;galaxy&lt;/a&gt; website&lt;/li&gt;
&lt;li&gt;implementing a way to cleanup old role based on community feedback on the galaxy website&lt;/li&gt;
&lt;li&gt;ensuring roles on the &lt;a href=&#34;https://galaxy.ansible.com&#34;&gt;galaxy&lt;/a&gt; website are self-contained and concise. Reduce the relevance of roles based on the amount of dependencies, and at the same time, increase the relevance of roles with a minimum set of tasks.&lt;/li&gt;
&lt;li&gt;ensuring the community understand and applies the best practices.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Orchestrate a service restart during a maintenance window with ansible</title><link>https://evrard.me/orchestrate-a-service-restart-during-a-maintenance-window-with-ansible/</link><pubDate>Sat, 18 Jun 2016 00:00:00 +0000</pubDate><guid>https://evrard.me/orchestrate-a-service-restart-during-a-maintenance-window-with-ansible/</guid><description>
&lt;p&gt;&lt;img src=&#34;https://evrard.me/images/button.jpg&#34; alt=&#34;Ansible daemon orchestration&#34; /&gt;&lt;/p&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Someone recently asked me:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;How do I run all the playbooks as usual, but make sure that ansible &lt;strong&gt;DOESN&amp;rsquo;T&lt;/strong&gt; restart my service, and restart my service later?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;I didn&amp;rsquo;t get the purpose of this question. I suspected it might have to do with how people write their playbooks, and how &lt;em&gt;possibly long&lt;/em&gt; playbooks must run to fit in tight maintenance windows.&lt;/p&gt;
&lt;p&gt;The goal here was indeed to reduce the length of the maintenance windows by having ansible applying all the changes (like generating a daemon configuration), but handling the notifications for restarts at a later time. Of course, on the future run, most of the tasks should be entirely skipped and only the handler (the service restart) should run.&lt;/p&gt;
&lt;p&gt;What you&amp;rsquo;ll learn in this article is how to modify a role to get this behavior, not if it&amp;rsquo;s a good idea or not. (Hint: It&amp;rsquo;s not. Terrible idea. You should properly build your application/architecture to respond to signals, being HA-able and avoid these kind of tricks to &lt;strong&gt;always be in a consistent state&lt;/strong&gt;.)&lt;/p&gt;
&lt;h2 id=&#34;i-can-haz-code&#34;&gt;I can haz code?&lt;/h2&gt;
&lt;p&gt;You can find all the examples/methods for this exercice in my &lt;a href=&#34;https://github.com/evrardjp/ansible-pocs&#34;&gt;PoC repository&lt;/a&gt;, under the &lt;a href=&#34;https://github.com/evrardjp/ansible-pocs/blob/de0ebf6945ed3df4b26e0c707fde5eb7ef1f86ed/roles/conditionalhandler/tasks/main.yml&#34;&gt;conditionalhandler&lt;/a&gt; role.&lt;/p&gt;
&lt;p&gt;For the sake of the simplicity, the tasks are tagged with the name of each method they belong to, and have additional tags like &lt;code&gt;service_config&lt;/code&gt; (for the tasks simulating a service configuration generation) or &lt;code&gt;service_restart&lt;/code&gt; (for the tasks simulating a service restart).&lt;/p&gt;
&lt;p&gt;With this simple example, a standard task and a handler are enough to represent a real life example. The method here will explain what&amp;rsquo;s needed on top of these two steps to bring this &amp;ldquo;timely&amp;rdquo; restart feature.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re testing these, please add &lt;code&gt;-e &amp;quot;changed=True&amp;quot;&lt;/code&gt; if you want to simulate a service configuration change.&lt;/p&gt;
&lt;h2 id=&#34;how-would-you-do-this&#34;&gt;How would you do this?&lt;/h2&gt;
&lt;h3 id=&#34;method-1-use-an-intermediary-handler&#34;&gt;Method 1: Use an intermediary handler&lt;/h3&gt;
&lt;p&gt;My initial thought was to trick ansible&amp;rsquo;s handlers/notification systems.&lt;/p&gt;
&lt;p&gt;Remember this: if you have a &lt;em&gt;generate service configuration&lt;/em&gt; task notifying an intermediate handler task named &lt;em&gt;handling service restart&lt;/em&gt; instead of directly notifying the &lt;em&gt;service restart&lt;/em&gt; handler task, the only way to have a conditional behavior on the &lt;em&gt;service restart&lt;/em&gt; task is using a variable (i.e. using a &lt;code&gt;when:&lt;/code&gt; clause). Using the tags system won&amp;rsquo;t work for this case.&lt;/p&gt;
&lt;p&gt;In other words, this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ansible-playbook conditional-handler-playbook.yml -t method1 --skip-tags=service_restart -e &amp;quot;changed=True&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;will always run the &lt;em&gt;service_restart&lt;/em&gt; tagged task. So this is not the intended behavior.&lt;/p&gt;
&lt;h3 id=&#34;method-2-introduce-two-variables-a-task-and-make-the-tasks-run-conditionally-on-these-variables&#34;&gt;Method 2: Introduce two variables, a task and make the tasks run conditionally on these variables&lt;/h3&gt;
&lt;p&gt;You can define in your role&amp;rsquo;s default variables the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Set this to False to deny service restarts after a configuration change
conditionalhandler_allow_restart: True
# Set this to True to always restart the service.
conditionalhandler_force_restart: False
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A new task would be required to handle the force restart, while a condition should be added to the &lt;em&gt;service restart&lt;/em&gt; handler.&lt;/p&gt;
&lt;p&gt;For me, this is the least elegant way of doing it. This is really verbose, and requires variables that could be avoided. Readability is possible thanks to proper variable names. Replace the variable names by a and b, and read the code again. It will be far more difficult to read.&lt;/p&gt;
&lt;p&gt;Generating the configuration without restart is done by executing:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ansible-playbook conditional-handler-playbook.yml -t method2 -e &amp;quot;conditionalhandler_allow_restart=False&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Forcing the &lt;em&gt;service restart&lt;/em&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ansible-playbook conditional-handler-playbook.yml -t method2 -e &amp;quot;conditionalhandler_force_restart=True&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;method-3-remove-the-handler-use-register-and-add-one-variable&#34;&gt;Method 3: Remove the handler, use register and add one variable&lt;/h3&gt;
&lt;p&gt;In this method, the &lt;em&gt;service restart&lt;/em&gt; isn&amp;rsquo;t run as a handler, but as a standard task.
This &lt;em&gt;service restart&lt;/em&gt; task can therefore run traditionally (when &lt;em&gt;generate service configuration&lt;/em&gt; get its status as &amp;ldquo;changed&amp;rdquo;) OR
run when the new variable &lt;code&gt;conditionalhandler_force_restart&lt;/code&gt; is set to &lt;code&gt;True&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;Avoiding/forcing a &lt;em&gt;service restart&lt;/em&gt; becomes respectively:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ansible-playbook conditional-handler-playbook.yml -t method3 --skip-tags=service_restart
ansible-playbook conditional-handler-playbook.yml -t method3 -e &amp;quot;conditionalhandler_force_restart=True&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;method-4-using-a-marking-file-and-flushing-handlers-or-a-post-task&#34;&gt;Method 4: Using a marking file and flushing handlers (or a post_task)&lt;/h3&gt;
&lt;p&gt;In this method, we&amp;rsquo;ll have one more task, one more handler. We don&amp;rsquo;t use ansible &lt;code&gt;register:&lt;/code&gt; directive and we don&amp;rsquo;t add additional variables. We just make sure everything runs in two steps, by having either a post_task or a &lt;code&gt;flush_handlers&lt;/code&gt; meta. The &lt;code&gt;flush_handlers&lt;/code&gt; makes possible to execute the handlers, and then continue with the tasks. Here it&amp;rsquo;s what we need to have a temporary file created and/or deleted (depending on the case).&lt;/p&gt;
&lt;p&gt;Avoiding/forcing &lt;em&gt;service restart&lt;/em&gt; is respectively:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ansible-playbook conditional-handler-playbook.yml -t method4 --skip-tags=service_restart
ansible-playbook conditional-handler-playbook.yml -t method4 --skip-tags=service_config
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;final-words-what-is-the-most-elegant-way-to-do-it&#34;&gt;Final Words - What is the most elegant way to do it?&lt;/h2&gt;
&lt;p&gt;My preferred method is the method 4, because it&amp;rsquo;s far more readable, it avoids variable crawl, the tags are consistent, and it&amp;rsquo;s understandable from a &amp;ldquo;non ansible&amp;rdquo; point of view. As I said before, the most elegant method would be to &lt;strong&gt;NOT&lt;/strong&gt; do this at all, and make sure the system is always consistent after a run. Don&amp;rsquo;t forget that some services don&amp;rsquo;t require a restart to change their live status. Another signal could be used to take the change into consideration. This signal should be then used in the ansible handler.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo credit: &lt;a href=&#34;http://www.flickr.com/photos/135666453@N07/25128639121&#34;&gt;Maker-9070&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</description></item><item><title>My YubiKey Quickstart guide</title><link>https://evrard.me/my-yubikey-quickstart-guide/</link><pubDate>Mon, 13 Jun 2016 00:00:00 +0000</pubDate><guid>https://evrard.me/my-yubikey-quickstart-guide/</guid><description>
&lt;p&gt;&lt;img src=&#34;https://farm3.staticflickr.com/2625/3689896409_35043dc8ba_d.jpg&#34; alt=&#34;yubikey-photo&#34; /&gt;&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s been a while I&amp;rsquo;m thinking to step in the smart card world. It&amp;rsquo;s been years I&amp;rsquo;ve got a smart card on me all the time. I only use it once a year, for paying my taxes&amp;hellip; Everytime I use it, I&amp;rsquo;m complaining. A lot.&lt;/p&gt;
&lt;p&gt;Here are a few reasons for it:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Everything linked to its usage as a smart card is poorly documented. I really hope it&amp;rsquo;s not by design.&lt;/li&gt;
&lt;li&gt;It requires specific hardware: a special kind of smart card reader (so not every smart card reader works!)&lt;/li&gt;
&lt;li&gt;It requires specific software: a specific version of java (use java64 for an unreliable/unpleasant experience!), and sometimes even your version of java32 doesn&amp;rsquo;t work with it&lt;/li&gt;
&lt;li&gt;It doesn&amp;rsquo;t work on all the browsers! You need to have a specific plugin. Of course, if you insert your smart card &lt;strong&gt;AFTER&lt;/strong&gt; launching Firefox, you&amp;rsquo;re good for its restart.&lt;/li&gt;
&lt;li&gt;You can&amp;rsquo;t do whatever you want with it (can&amp;rsquo;t set your own keys &amp;hellip;)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Taxes feeling + grumpy {soft,hard}ware makes me unhappy. It&amp;rsquo;s unlikely I&amp;rsquo;ll use this smartcard in other circumstances (anyway, it&amp;rsquo;s maybe better -&lt;em&gt;security wise&lt;/em&gt;- to avoid mixing the same device for different security purposes).&lt;/p&gt;
&lt;p&gt;So, I decided to give YubiKeys a go.&lt;/p&gt;
&lt;h2 id=&#34;what-are-yubikeys-and-why-would-i-want-one&#34;&gt;What are YubiKeys, and why would I want one?&lt;/h2&gt;
&lt;p&gt;I recently found the YubiKeys more interesting.
The YubiKey 4 packs a big list of features, for a really low cost. Moreover, there is currently a 20% discount for github users on yubico website (&amp;ldquo;temporary offer&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;In terms of (hardware) requirements, you only need a good ol&amp;rsquo; USB port to work. The YubiKey Neo adds &lt;a href=&#34;https://en.wikipedia.org/wiki/Near_field_communication&#34;&gt;NFC&lt;/a&gt; to the mix for your mobile (but the Neo have drawbacks, check the cypto specs here: &lt;a href=&#34;https://www.yubico.com/products/yubikey-hardware/&#34;&gt;https://www.yubico.com/products/yubikey-hardware/&lt;/a&gt;). For your information, the Neo is currently cheaper on amazon than it is on yubico website.&lt;/p&gt;
&lt;p&gt;In terms of features, the YubiKey works as &lt;a href=&#34;https://en.wikipedia.org/wiki/USB_human_interface_device_class&#34;&gt;HID&lt;/a&gt; for &lt;a href=&#34;https://en.wikipedia.org/wiki/Two-factor_authentication&#34;&gt;&lt;strong&gt;2-F&lt;/strong&gt;actor &lt;strong&gt;A&lt;/strong&gt;uthentication&lt;/a&gt; mechanisms (&lt;a href=&#34;https://en.wikipedia.org/wiki/Universal_2nd_Factor&#34;&gt;fido u2fa&lt;/a&gt;, yubico OTP, &amp;hellip;) and it also works as &lt;a href=&#34;https://en.wikipedia.org/wiki/CCID_(protocol)&#34;&gt;CCID&lt;/a&gt; (smartcards! you can use it for signing, encryption, authentication with applications like &lt;a href=&#34;https://en.wikipedia.org/wiki/Pretty_Good_Privacy&#34;&gt;pgp&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/OpenSSH&#34;&gt;openssh&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/OpenSSL&#34;&gt;openssl&lt;/a&gt; and many others).&lt;/p&gt;
&lt;h2 id=&#34;ok-i-m-in-where-should-i-start&#34;&gt;Ok I&amp;rsquo;m in! Where should I start ?&lt;/h2&gt;
&lt;p&gt;Simple question, long answer. Don&amp;rsquo;t start with the &amp;ldquo;documentation&amp;rdquo; of the &lt;a href=&#34;https://developers.yubico.com/&#34;&gt;dev.yubico&lt;/a&gt; website!
There is so much documentation on their website, you&amp;rsquo;ll be lost in all the links.&lt;/p&gt;
&lt;p&gt;Here is what I&amp;rsquo;d do:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Simply start on your device page (&lt;a href=&#34;http://yubi.co/4&#34;&gt;yubikey 4&lt;/a&gt;/&lt;a href=&#34;https://www.yubico.com/products/yubikey-hardware/yubikey-neo/&#34;&gt;yubikey neo&lt;/a&gt;) and absorb what&amp;rsquo;s there.&lt;/li&gt;
&lt;li&gt;You should then find the &lt;a href=&#34;https://www.yubico.com/start/&#34;&gt;getting started page&lt;/a&gt; interesting.&lt;/li&gt;
&lt;li&gt;You should then go ahead with the &lt;a href=&#34;https://www.yubico.com/products/services-software/personalization-tools/&#34;&gt;personalisation tools page&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You have plenty links on these three pages to follow what&amp;rsquo;s really needed to your use case. The last page of this list have obviously a link for the &lt;a href=&#34;https://www.yubico.com/pt&#34;&gt;yubico personalisation tool&lt;/a&gt; download. This tool makes possible in-depth changes of your YubiKey.&lt;/p&gt;
&lt;h2 id=&#34;any-other-links&#34;&gt;Any other links?&lt;/h2&gt;
&lt;p&gt;For github/google, simply head to your account security settings. &lt;a href=&#34;https://en.wikipedia.org/wiki/Universal_2nd_Factor&#34;&gt;U2FA&lt;/a&gt; is very simple and doesn&amp;rsquo;t really need much explanation. You don&amp;rsquo;t need the personalisation tool to make it work. For non-U2FA, that&amp;rsquo;s where the fun begins&amp;hellip;&lt;/p&gt;
&lt;p&gt;Here are a few interesting explanations I found by browsing the interwebz/yubico website:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.yubico.com/products/services-software/personalization-tools/oath/&#34;&gt;Configuring Yubikey as generic OATH HOTP token generator&lt;/a&gt;. I read somewhere was possible to enable this kind of 2FA on Ubuntu One website, but I didn&amp;rsquo;t find the option there yet.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developers.yubico.com/PIV/Guides/SSH_with_PIV_and_PKCS11.html&#34;&gt;Configuring YubiKey as a smartcard for ssh authentication, CA or code signing&lt;/a&gt;. On this page, you should probably have a look at the SSH with PIV and PKCS#11 section. It&amp;rsquo;s easy to use a certificate stored on the yubikey for SSH authentication: you just have to pass the library interface (&lt;a href=&#34;https://en.wikipedia.org/wiki/OpenSC&#34;&gt;opensc&lt;/a&gt;) to the &lt;a href=&#34;https://en.wikipedia.org/wiki/PKCS_11&#34;&gt;PKCS#11&lt;/a&gt; as identity in your openssh command line. This is supported with a portable openssh version &amp;gt; 5.4p1. (It&amp;rsquo;s also easy to export your public key to set it in the authorized keys for example). Check also &lt;a href=&#34;https://developers.yubico.com/PIV/Introduction/Certificate_slots.html&#34;&gt;here&lt;/a&gt; for an explanation of your Yubikey&amp;rsquo;s PIV slots.&lt;/li&gt;
&lt;li&gt;Configuring PAM and SSH server for a 2FA with Yubico OTP (&lt;a href=&#34;https://derekriemer.com/2017/02/11/how-i-rolled-two-factor-authentication-for-ssh-access-to-the-server-that-powers-this-site/&#34;&gt;1&lt;/a&gt; &lt;a href=&#34;http://delyan.me/securing-ssh-with-totp/&#34;&gt;2&lt;/a&gt; &lt;a href=&#34;https://www.100tb.com/blog/ssh-two-factor-authentication-with-totp-in-debianubuntu/&#34;&gt;3&lt;/a&gt; &lt;a href=&#34;http://strugglers.net/~andy/blog/2016/05/06/using-a-totp-app-for-multi-factor-ssh-auth/&#34;&gt;4&lt;/a&gt; ). Take these with a pinch of salt (Some pages claim to improve security by using their method, where it clearly doesn&amp;rsquo;t. More on that in a later article).&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developers.yubico.com/PGP/&#34;&gt;Configuring PGP with YubiKeys&lt;/a&gt;. This is where you should head to for file encryption, mail encryption/signing, ssh authentication&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;last-words&#34;&gt;Last words&lt;/h2&gt;
&lt;p&gt;I think the YubiKey is a simple yet efficient device. It protects your accounts
in a simple manner, and everyone interested in security should at least consider
it (or one of its alternatives).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo credit: &lt;a href=&#34;https://www.flickr.com/photos/11506685@N07/3689896409/&#34;&gt;Thomas Flenstad&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Auto deployment of Pelican webpages to github user pages</title><link>https://evrard.me/auto-deployment-of-pelican-webpages-to-github-user-pages/</link><pubDate>Sun, 05 Jun 2016 00:00:00 +0000</pubDate><guid>https://evrard.me/auto-deployment-of-pelican-webpages-to-github-user-pages/</guid><description>
&lt;p&gt;&lt;img src=&#34;https://evrard.me/images/pelican.jpg&#34; alt=&#34;Mon calepin ecrit avec pelican&#34; /&gt;&lt;/p&gt;
&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;As you may already have seen, this website is static html. I want to share how I do it.
My goals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;have the technical out of the way when writing content&lt;/li&gt;
&lt;li&gt;have an automated way of publish content&lt;/li&gt;
&lt;li&gt;be simple to use wherever I am&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: I have a &lt;a href=&#34;https://github.com/evrardjp/evrardjp.github.io-sources/blob/9ae74fd7b532ca33c2aa14cbcd79a4d704bd802a/tox.ini&#34;&gt;tox configuration&lt;/a&gt; that does the heavy lifting for publishing content written with pelican, check how it&amp;rsquo;s done on the appropriate &lt;a href=&#34;https://github.com/evrardjp/evrardjp.github.io-sources/&#34;&gt;github repo&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&#34;pelican&#34;&gt;Pelican&lt;/h1&gt;
&lt;h1 id=&#34;multiple-solutions-for-the-automation&#34;&gt;Multiple solutions for the automation&lt;/h1&gt;
&lt;p&gt;So I had multiple choices:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Integrate with a CI/CD like &lt;a href=&#34;http://zonca.github.io/2013/09/automatically-build-pelican-and-publish-to-github-pages.html&#34;&gt;Travis CI&lt;/a&gt;, semaphore (my two favorites) or jenkins.&lt;/li&gt;
&lt;li&gt;Work in a &lt;a href=&#34;http://mathamy.com/migrating-to-github-pages-using-pelican.html&#34;&gt;manual way&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Use git hooks.&lt;/li&gt;
&lt;li&gt;Use &lt;a href=&#34;https://tox.readthedocs.io/en/latest/&#34;&gt;tox&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The first solution is simple to setup and relies on a lot of different parties (&amp;ldquo;vendors&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;The second seems more tedious on the long run.&lt;/p&gt;
&lt;p&gt;The git hooks is more contained (it&amp;rsquo;s pure git without fuss!) but requires to either have a proper git server that will handle my python builds, or a way to setup the client hooks and/or dependencies on the node that is used for writing the blog.&lt;/p&gt;
&lt;p&gt;As I&amp;rsquo;ll host everything on a public git (github in my case), I decided to go for the last one. The github server hooks are limited to curl things, So I can&amp;rsquo;t have proper testing there. And because I want an easy clone/work way of things, I can&amp;rsquo;t use use client side hooks. That&amp;rsquo;s why I&amp;rsquo;ll use &lt;a href=&#34;https://tox.readthedocs.io/en/latest/&#34;&gt;tox&lt;/a&gt; for testing.&lt;/p&gt;
&lt;h1 id=&#34;tox-to-the-rescue&#34;&gt;Tox to the rescue&lt;/h1&gt;
&lt;p&gt;If you don&amp;rsquo;t know &lt;a href=&#34;https://tox.readthedocs.io/en/latest/&#34;&gt;tox&lt;/a&gt;, I invite you to look at this wonder. In our case here, it&amp;rsquo;s basically a python&amp;rsquo;s virtualenv-aware make command. It&amp;rsquo;s a good python automation &amp;amp; testing tool.&lt;/p&gt;
&lt;p&gt;Thanks to tox behavior, I can just focus on content: The tox.ini will hold the information about the commands to run (I&amp;rsquo;ll definitely forget these, so having one ini file as a reminder is good for me!) and run each test in its own virtualenv, which I find good for avoiding pollution on your &amp;ldquo;writing node&amp;rdquo;.
The requirements for this &amp;ldquo;writing node&amp;rdquo; is simple: python, tox, and virtualenv.
If you really want to reduce your host dependencies, you could even run tox in a virtualenv.&lt;/p&gt;
&lt;p&gt;So, I have one repo with my environment, holding the pelican and tox configuration files, the markdown-rst-whatever files and other static content.
When I want to work, I clone this repository and use my text editor to write in content/. Simple, right?&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s have a look at my &lt;a href=&#34;https://github.com/evrardjp/evrardjp.github.io-sources/blob/9ae74fd7b532ca33c2aa14cbcd79a4d704bd802a/tox.ini&#34;&gt;tox.ini configuration file&lt;/a&gt;:&lt;/p&gt;
&lt;h2 id=&#34;sdist&#34;&gt;sdist&lt;/h2&gt;
&lt;p&gt;One of the first steps invoked when running tox is &lt;code&gt;python setup.py sdist&lt;/code&gt;, that should generate your &lt;code&gt;package.zip&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In our case, we don&amp;rsquo;t have a &lt;code&gt;setup.py&lt;/code&gt; or &lt;code&gt;setup.cfg&lt;/code&gt; holding our code. We&amp;rsquo;re barely using python stuff.
So, we can skip this step by setting:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;skipsdist = true
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;the-virtual-envs-creation&#34;&gt;the virtual envs creation&lt;/h2&gt;
&lt;p&gt;Tox then creates the virtualenvs. There are lots of ways to affect this, I invite you to check at the &lt;a href=&#34;https://tox.readthedocs.io/en/latest/&#34;&gt;tox documentation&lt;/a&gt;.
Tox, by default, creates its virtualenvs in &lt;code&gt;.tox/&lt;/code&gt; folder. Every tox command will create its own virtualenv inside this folder.&lt;/p&gt;
&lt;p&gt;I defined two different virtual environments, one for the linting (facultative), and one for pelican jobs. I want to keep them separate because they can have different dependencies.&lt;/p&gt;
&lt;h2 id=&#34;inside-the-virtualenvs&#34;&gt;Inside the virtualenvs&lt;/h2&gt;
&lt;p&gt;So, the next steps for tox is to calculate/install the dependencies.&lt;/p&gt;
&lt;p&gt;tox reads the &lt;code&gt;deps&lt;/code&gt; section of each environment configuration (if any). This overrides the default &lt;code&gt;testenv&lt;/code&gt; deps configuration.&lt;/p&gt;
&lt;p&gt;tox then installs the result of the &lt;code&gt;python setup.py sdist&lt;/code&gt; (for example, a &lt;code&gt;package.zip&lt;/code&gt;). Here this step is skipped.&lt;/p&gt;
&lt;p&gt;tox reads the &lt;code&gt;command&lt;/code&gt; section relative to the virtualenv to run the job.&lt;/p&gt;
&lt;h3 id=&#34;the-linters-case&#34;&gt;The linters case&lt;/h3&gt;
&lt;p&gt;I have a &amp;ldquo;linters&amp;rdquo; test command (&lt;code&gt;tox -e linters&lt;/code&gt;), that is used for &amp;hellip; linting the restructured text files, obviously.&lt;/p&gt;
&lt;p&gt;The linter tool is not being nice with the others, and like I said before, I&amp;rsquo;ve isolated the linter tool from the others. It has therefore its own configuration section, to setup a different list of dependencies. For the linters, I just needed &lt;a href=&#34;https://pypi.python.org/pypi/restructuredtext_lint&#34;&gt;restructuredtext_lint&lt;/a&gt; as dependency.&lt;/p&gt;
&lt;p&gt;For the &lt;code&gt;command&lt;/code&gt; part, I wrote a small python script that dumps (in a friendly manner) my next mistake.&lt;/p&gt;
&lt;h3 id=&#34;the-pelican-virtualenv&#34;&gt;the pelican virtualenv&lt;/h3&gt;
&lt;p&gt;My main &lt;code&gt;testenv&lt;/code&gt; section is for my pelican work. This section has multiple commands: one that can generates the content with the testing profile (&lt;code&gt;build&lt;/code&gt;), watch for saves changes (&lt;code&gt;watch&lt;/code&gt;), serve the web content using &lt;a href=&#34;https://twistedmatrix.com/trac/&#34;&gt;twisted&lt;/a&gt; (&lt;code&gt;serve&lt;/code&gt;) and finally deploy to production (&lt;code&gt;publish&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;To avoid having multiple virtualenvs (one per command), I make sure that all the commands have the same environment by setting &lt;code&gt;envdir&lt;/code&gt; in &lt;code&gt;testenv&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;envdir = {toxinidir}/.tox/functional
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because &lt;code&gt;testenv&lt;/code&gt; is the parent and &lt;code&gt;testenv:linters&lt;/code&gt; inherit from it, the previous change made linters&amp;rsquo; virtualenv the same as the others.
Thefore, I need to override the linters&amp;rsquo;s envdir configuration:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;envdir = {toxinidir}/.tox/linters
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It means that the linters virtualenv is now unlinked (again) from the &amp;ldquo;functional&amp;rdquo; virtualenv.&lt;/p&gt;
&lt;h2 id=&#34;last-words&#34;&gt;Last words&lt;/h2&gt;
&lt;p&gt;With the fact that python can easily be found on most OSes, I think this workflow is quite simple to follow.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo credit: &lt;a href=&#34;https://www.flickr.com/photos/68704638@N04/26835201760&#34;&gt;MDreibelbis&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</description></item></channel></rss>