<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://thobalose.github.io//feed.xml" rel="self" type="application/atom+xml" /><link href="https://thobalose.github.io//" rel="alternate" type="text/html" /><updated>2025-08-31T18:48:59+02:00</updated><id>https://thobalose.github.io//feed.xml</id><title type="html">thobalose.co.za 👋</title><subtitle>Thoba Lose&apos;s blog</subtitle><author><name>Thoba Lose</name></author><entry><title type="html">Provisioning OpenStack instances with docker-machine</title><link href="https://thobalose.github.io//2019/provisioning-openstack-instances-with-docker-machine/" rel="alternate" type="text/html" title="Provisioning OpenStack instances with docker-machine" /><published>2019-03-14T00:00:00+02:00</published><updated>2019-03-14T00:00:00+02:00</updated><id>https://thobalose.github.io//2019/provisioning-openstack-instances-with-docker-machine</id><content type="html" xml:base="https://thobalose.github.io//2019/provisioning-openstack-instances-with-docker-machine/"><![CDATA[<p class="text-justify">I had previously published a post about <a href="https://thobalose.co.za/2017/add-existing-host-docker-machine/">adding existing instances to Docker Machine</a> using the <a href="https://docs.docker.com/machine/drivers/generic/">generic driver</a>.</p>
<p class="text-justify">In this post, I wanted to write about how I go about provisioning <a href="https://www.openstack.org/">OpenStack</a> instances with <code class="language-plaintext highlighter-rouge">docker-machine</code> using the <a href="https://docs.docker.com/machine/drivers/openstack/">openstack driver</a>.</p>

<h2 id="assumption">Assumption</h2>

<p class="text-justify">You have provisioned some OpenStack resources (networks, routers, etc.) and want to use Docker Machine to
provision instances for a more <a href="https://success.docker.com/article/dev-pipeline">docker driven development workflow</a>.</p>

<h2 id="download-and-source-openstack-rc-file">Download and source OpenStack RC file</h2>

<p class="text-justify">Log in to the OpenStack Dashboard (Horizon), select the project for which you want
to download the <a href="https://docs.openstack.org/zh_CN/user-guide/common/cli-set-environment-variables-using-openstack-rc.html">OpenStack RC file</a>, and run the following commands:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">source</span> ~/Downloads/PROJECT-openrc.sh
Please enter your OpenStack Password <span class="k">for </span>project PROJECT as user username:
</code></pre></div></div>

<p class="text-justify">Check your OpenStack environment variables:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">env</span> | <span class="nb">grep </span>OS_
<span class="nv">OS_PROJECT_DOMAIN_ID</span><span class="o">=</span>default
<span class="nv">OS_PROJECT_ID</span><span class="o">=</span>454f9cfc5f29d5108fe0cca0c74ad352
<span class="nv">OS_REGION_NAME</span><span class="o">=</span>RegionOne
<span class="nv">OS_USER_DOMAIN_NAME</span><span class="o">=</span>Default
<span class="nv">OS_PROJECT_NAME</span><span class="o">=</span>ProjectName
<span class="nv">OS_IDENTITY_API_VERSION</span><span class="o">=</span>3
<span class="nv">OS_PASSWORD</span><span class="o">=</span>fIUj!KqwertyC5Jrwqwy@
<span class="nv">OS_AUTH_URL</span><span class="o">=</span>https://openstackurl:5000/v3
<span class="nv">OS_USERNAME</span><span class="o">=</span>username
<span class="nv">OS_INTERFACE</span><span class="o">=</span>public
</code></pre></div></div>

<h2 id="install-the-openstack-cli-client">Install the OpenStack CLI client</h2>

<p class="text-justify">Install the <a href="https://docs.openstack.org/newton/user-guide/common/cli-install-openstack-command-line-clients.html">OpenStack CLI client</a> and run the following commands, taking note of the output as some of these are <strong>mandatory</strong> for <code class="language-plaintext highlighter-rouge">docker-machine</code> <a href="https://docs.docker.com/machine/drivers/openstack/">CLI options</a>:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>openstack flavor list
+---
</code></pre></div></div>

<p>to get a list of available flavors,</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>openstack image list
+---
</code></pre></div></div>

<p>to get a list of available images,</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>openstack network list <span class="nt">--external</span>
+---
</code></pre></div></div>

<p>to get the floating ip pool,</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>openstack network list <span class="nt">--internal</span>
+---
</code></pre></div></div>

<p>to get a list of available internal networks, and</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>openstack security group list
+---
</code></pre></div></div>

<p>to get a list of available security groups</p>

<p class="text-justify"><strong>Note:</strong> I got into some authentication <a href="https://github.com/docker/machine/issues/679">issues</a> with OpenStack identity v3 and
set the following environment variables as a workaround.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">export </span><span class="nv">OS_TENANT_ID</span><span class="o">=</span><span class="nv">$OS_PROJECT_ID</span>
<span class="nv">$ </span><span class="nb">export </span><span class="nv">OS_DOMAIN_ID</span><span class="o">=</span><span class="nv">$OS_PROJECT_DOMAIN_ID</span>
</code></pre></div></div>

<h2 id="create-a-machine-on-openstack">Create a machine on OpenStack</h2>

<p class="text-justify">To create a machine on OpenStack, specify <code class="language-plaintext highlighter-rouge">-d openstack</code>.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>docker-machine create <span class="nt">-d</span> openstack <span class="se">\</span>
<span class="nt">--openstack-flavor-name</span> <span class="s2">"m1.medium"</span> <span class="se">\</span>
<span class="nt">--openstack-image-name</span> <span class="s2">"ubuntu-18.04-server"</span> <span class="se">\</span>
<span class="nt">--openstack-net-name</span> <span class="s2">"INTERNAL_NET"</span> <span class="se">\</span>
<span class="nt">--openstack-floatingip-pool</span> <span class="s2">"PUBLIC_POOL"</span> <span class="se">\</span>
<span class="nt">--openstack-ssh-user</span> ubuntu <span class="se">\</span>
<span class="nt">--openstack-sec-groups</span> default,OTHER-SEC-GROUP <span class="se">\</span>
os-dm-instance
</code></pre></div></div>

<p class="text-justify">To connect your Docker client to the Docker Engine running on this instance, run:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">eval</span> <span class="si">$(</span>docker-machine <span class="nb">env </span>os-dm-instance<span class="si">)</span>
</code></pre></div></div>

<p>E.g, <code class="language-plaintext highlighter-rouge">docker-machine inspect os-dm-instance</code> lists the machine details.</p>

<p class="text-justify">To disconnect, run:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">eval</span> <span class="si">$(</span>docker-machine <span class="nb">env</span> <span class="nt">-u</span><span class="si">)</span>
</code></pre></div></div>

<h2 id="docker-mtu-issues-on-openstack">Docker MTU issues on OpenStack</h2>

<p class="text-justify">Docker creates and configures the host system’s <code class="language-plaintext highlighter-rouge">docker0</code> with an IP address, netmask,
IP allocation range, and a default <a href="https://en.wikipedia.org/wiki/Maximum_transmission_unit">MTU</a>
of <code class="language-plaintext highlighter-rouge">1500</code> bytes.</p>

<p class="text-justify">The default MTU will causes <a href="https://github.com/moby/moby/issues/22297">network issues</a>
if it’s greater than the MTU of the outgoing interface (<code class="language-plaintext highlighter-rouge">ens3</code>), leading to containers not being able to access the Internet.
You can check the MTU size with the following command:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>docker-machine ssh os-dm-instance
ubuntu@os-dm-instance:~<span class="nv">$ </span> ip <span class="nb">link</span> | <span class="nb">grep </span>mtu
1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
2: ens3: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1450 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
3: docker0: &lt;NO-CARRIER,BROADCAST,MULTICAST,UP&gt; mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
ubuntu@os-dm-instance:~<span class="err">$</span>
</code></pre></div></div>

<p class="text-justify">To fix this, create or edit <code class="language-plaintext highlighter-rouge">/etc/docker/daemon.json</code>, with:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ubuntu@os-dm-instance:~<span class="nv">$ </span> <span class="nb">sudo </span>vi /etc/docker/daemon.json
</code></pre></div></div>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">//daemon.json</span><span class="w">
</span><span class="p">{</span><span class="w">
  </span><span class="nl">"mtu"</span><span class="p">:</span><span class="w"> </span><span class="mi">1450</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>Restart Docker and ensure that the MTU is set.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ubuntu@os-dm-instance:~<span class="nv">$ </span><span class="nb">sudo </span>systemctl daemon-reload
ubuntu@os-dm-instance:~<span class="nv">$ </span><span class="nb">sudo </span>systemctl restart docker
ubuntu@os-dm-instance:~<span class="nv">$ </span><span class="nb">sudo </span>docker run <span class="nt">-it</span> alpine /bin/sh
/ <span class="c"># ip link</span>
1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    <span class="nb">link</span>/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
6: eth0@if7: &lt;BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN&gt; mtu 1450 qdisc noqueue state UP
    <span class="nb">link</span>/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
/ <span class="c"># ping alpinelinux.org</span>
PING alpinelinux.org <span class="o">(</span>147.75.101.119<span class="o">)</span>: 56 data bytes
64 bytes from 147.75.101.119: <span class="nb">seq</span><span class="o">=</span>0 <span class="nv">ttl</span><span class="o">=</span>47 <span class="nb">time</span><span class="o">=</span>147.360 ms

</code></pre></div></div>

<p class="text-justify">If you’re using <a href="https://docs.docker.com/compose/overview/">docker-compose</a> to deploy your containers,
beware that compose creates a new network (mtu <code class="language-plaintext highlighter-rouge">1500</code>) by default. Add the following
in the <a href="https://github.com/thobalose/neo4j-openstack-deploy/blob/master/docker-compose.yml#L17">network</a>
section of your compose file to change the MTU size:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#docker-compose.yml</span>
<span class="na">networks</span><span class="pi">:</span>
  <span class="na">default</span><span class="pi">:</span>
    <span class="na">driver</span><span class="pi">:</span> <span class="s">bridge</span>
    <span class="na">driver_opts</span><span class="pi">:</span>
      <span class="na">com.docker.network.driver.mtu</span><span class="pi">:</span> <span class="m">1450</span>
</code></pre></div></div>

<p class="text-justify">Hope someone finds this helpful.</p>]]></content><author><name>Thoba Lose</name></author><category term="Technology" /><category term="docker" /><category term="docker-compose" /><category term="docker-machine" /><category term="openstack" /><summary type="html"><![CDATA[Provisioning OpenStack instances with docker-machine.]]></summary></entry><entry><title type="html">Docker storage after kernel upgrade</title><link href="https://thobalose.github.io//2018/docker-storage-after-kernel-update/" rel="alternate" type="text/html" title="Docker storage after kernel upgrade" /><published>2018-01-09T00:00:00+02:00</published><updated>2018-01-09T00:00:00+02:00</updated><id>https://thobalose.github.io//2018/docker-storage-after-kernel-update</id><content type="html" xml:base="https://thobalose.github.io//2018/docker-storage-after-kernel-update/"><![CDATA[<p class="text-justify">I recently upgraded my linux kernel to <code class="language-plaintext highlighter-rouge">4.9.75</code>, the latest <code class="language-plaintext highlighter-rouge">4.14</code> release gave me network related issues, on <code class="language-plaintext highlighter-rouge">Ubuntu 16.04.2</code> after hearing about the <a href="https://www.theregister.co.uk/2018/01/02/intel_cpu_design_flaw/" target="_blank">Meltdown and Spectre</a> security flaws and reading <a href="http://www.kroah.com/log/blog/2018/01/06/meltdown-status/" target="_blank">Greg Kroah-Hartman’s blog</a>.</p>

<h2 id="upgrading-the-kernel">Upgrading the kernel</h2>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">cd</span> /tmp/
<span class="nv">$ </span>wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.9.75/linux-headers-4.9.75-040975-generic_4.9.75-040975.201801051530_amd64.deb
<span class="nv">$ </span>wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.9.75/linux-image-4.9.75-040975-generic_4.9.75-040975.201801051530_amd64.deb
<span class="nv">$ </span>wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.9.75/linux-headers-4.9.75-040975_4.9.75-040975.201801051530_all.deb
<span class="nv">$ </span><span class="nb">sudo </span>dpkg <span class="nt">-i</span> <span class="se">\*</span>.deb
<span class="nv">$ </span><span class="nb">sudo </span>update-grub
<span class="nv">$ </span><span class="nb">sudo </span>reboot
</code></pre></div></div>

<p class="text-justify">Bob was my uncle until I had to get on with my daily development workflow which makes heavy use of <a href="https://docs.docker.com/">docker</a>. I got an error that pointed to <strong><code class="language-plaintext highlighter-rouge">storage driver \"aufs\" failed: driver not supported</code></strong>.</p>

<p class="text-justify">After some digging, I found that for <code class="language-plaintext highlighter-rouge">aufs</code> one has to install, depending on the distribution, <code class="language-plaintext highlighter-rouge">linux-image-extra</code>. However, only the <a href="https://packages.ubuntu.com/search?keywords=linux-image-extra-virtual" target="_blank">kernel version</a> that ships with the distribution is officially supported. I then discovered that <code class="language-plaintext highlighter-rouge">overlay2</code> is <a href="https://docs.docker.com/engine/userguide/storagedriver/aufs-driver/" target="_blank">recommended</a> for kernel v4.0 and higher.</p>

<h2 id="changing-the-storage-driver">Changing the storage driver</h2>

<p><strong><a href="https://docs.docker.com/storage/storagedriver/select-storage-driver/">NOTE</a></strong>: You will lose access to all your current images and containers due to layers! Reverting your changes will make your old images and containers accessible again.
You can use</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>docker save IMAGE:TAG <span class="o">&gt;</span> IMAGE.tar.gz
</code></pre></div></div>

<p>to save your current images, and</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>docker load &lt; IMAGE.tar.gz
</code></pre></div></div>

<p class="text-justify">to import them on the new storage driver.</p>

<p>Stop <code class="language-plaintext highlighter-rouge">docker</code>:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>systemctl stop docker
</code></pre></div></div>

<p>Edit the file <code class="language-plaintext highlighter-rouge">/etc/docker/daemon.json</code> (create it if doesn’t exist) and add the following to the file:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"storage-driver"</span><span class="p">:</span><span class="w"> </span><span class="s2">"overlay2"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>Start <code class="language-plaintext highlighter-rouge">docker</code>:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>systemctl start docker
</code></pre></div></div>

<p>Use <code class="language-plaintext highlighter-rouge">docker info</code> to verify that the storage driver is being used:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>docker info
...
Storage Driver: overlay2
...
</code></pre></div></div>

<p class="text-justify">Hope someone out there finds this helpful.</p>]]></content><author><name>Thoba Lose</name></author><category term="Technology" /><category term="docker" /><category term="aufs" /><category term="overlay2" /><category term="linux" /><category term="kernel" /><summary type="html"><![CDATA[Docker storage after kernel upgrade.]]></summary></entry><entry><title type="html">Add existing VM/Host to docker-machine</title><link href="https://thobalose.github.io//2017/add-existing-host-docker-machine/" rel="alternate" type="text/html" title="Add existing VM/Host to docker-machine" /><published>2017-09-28T00:00:00+02:00</published><updated>2017-09-28T00:00:00+02:00</updated><id>https://thobalose.github.io//2017/add-existing-host-docker-machine</id><content type="html" xml:base="https://thobalose.github.io//2017/add-existing-host-docker-machine/"><![CDATA[<p class="text-justify">I use Docker a lot in my development lifecycle and like to manage my instances with Docker <a href="https://github.com/docker/machine" target="\_blank">Machine</a>, a powerful tool for provisioning and managing your Dockerized instances with <code class="language-plaintext highlighter-rouge">docker-machine</code> commands.</p>
<p class="text-justify">Docker Machine has a driver plugin architecture and the <a href="https://github.com/docker/machine/tree/master/drivers/generic" target="\_blank">generic driver</a> is useful if you are using a provider that it does not support directly or if you would like to import an existing host.
This is how I go about adding my existing host(s).</p>

<h2 id="add-newuser">Add newuser</h2>

<p>Use <code class="language-plaintext highlighter-rouge">adduser</code> to add new user on remote host.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>adduser <span class="nv">$USER</span>
</code></pre></div></div>

<h2 id="add-password-less-sudo-privileges">Add password-less sudo privileges</h2>

<p>Use <code class="language-plaintext highlighter-rouge">visudo</code> to add new configuration file on remote host.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>visudo <span class="nt">-f</span> /etc/sudoers.d/passwdless-users
</code></pre></div></div>

<p>and add <code class="language-plaintext highlighter-rouge">$USER ALL=(ALL) NOPASSWD:ALL</code>. Save and exit.</p>

<h2 id="configure-key-based-authentication">Configure Key-based Authentication</h2>

<p>On your localhost, generate a SSH key pair.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>ssh-keygen <span class="nt">-b</span> 4096
</code></pre></div></div>

<p>Copy your public key to remote host using <code class="language-plaintext highlighter-rouge">ssh-copy-id</code>.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>ssh-copy-id <span class="nv">$USER</span>@REMOTE_HOST
</code></pre></div></div>

<h2 id="create-machine">Create machine</h2>

<p class="text-justify">To create a machine, specify <code class="language-plaintext highlighter-rouge">--driver generic</code>, the IP address or DNS name of the host and the path to the SSH private key authorized to connect to the host.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>docker-machine create <span class="nt">--driver</span> generic <span class="se">\</span>
 <span class="nt">--generic-ip-address</span> REMOTE_HOST_IP <span class="se">\</span>
 <span class="nt">--generic-ssh-user</span> <span class="nv">$USER</span> <span class="se">\</span>
 <span class="nt">--generic-ssh-key</span> ~/.ssh/id_rsa <span class="se">\</span>
 REMOTE_HOST
</code></pre></div></div>

<p class="text-justify">When the machine is created, Docker generates a unique SSH key and stores it in <code class="language-plaintext highlighter-rouge">~/.docker/machines</code>. This is used under the hood to access the host directly with the <code class="language-plaintext highlighter-rouge">docker-machine ssh</code> command.</p>

<p class="text-justify">To connect your Docker client to the Docker Engine running on this instance, run:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">eval</span> <span class="si">$(</span>docker-machine <span class="nb">env </span>REMOTE_HOST<span class="si">)</span>
</code></pre></div></div>

<p>E.g, <code class="language-plaintext highlighter-rouge">docker-machine inspect REMOTE_HOST</code> lists the machine details.</p>

<p class="text-justify">To disconnect, run:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">eval</span> <span class="si">$(</span>docker-machine <span class="nb">env</span> <span class="nt">-u</span><span class="si">)</span>
</code></pre></div></div>

<p class="text-justify">Hope someone finds this helpful.</p>]]></content><author><name>Thoba Lose</name></author><category term="Technology" /><category term="docker" /><category term="docker-machine" /><category term="linux" /><summary type="html"><![CDATA[Add existing VM/Host to docker-machine.]]></summary></entry><entry><title type="html">Docker Remote API on Ubuntu 16.04.2</title><link href="https://thobalose.github.io//2017/docker-remote-api/" rel="alternate" type="text/html" title="Docker Remote API on Ubuntu 16.04.2" /><published>2017-04-21T00:00:00+02:00</published><updated>2017-04-21T00:00:00+02:00</updated><id>https://thobalose.github.io//2017/docker-remote-api</id><content type="html" xml:base="https://thobalose.github.io//2017/docker-remote-api/"><![CDATA[<p class="text-justify">I was recently tasked with an issue to allow an application, deployed using <code class="language-plaintext highlighter-rouge">docker-compose</code>, to launch containers
and I did not want to go the <a href="https://github.com/jpetazzo/dind" target="_blank">docker-in-docker</a> route.</p>
<p class="text-justify">I then figured that using the <a href="https://docs.docker.com/engine/api/" target="_blank">Docker Remote API</a> to provide this functionality would be sufficient, however, I had difficulties on how to enable the <code class="language-plaintext highlighter-rouge">tcp</code> Socket on distributions running <code class="language-plaintext highlighter-rouge">systemd</code> like <em>Ubuntu 16.04.2</em>, as adding</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">DOCKER_OPTS</span><span class="o">=</span><span class="s2">"-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock"</span>
</code></pre></div></div>

<p>to <code class="language-plaintext highlighter-rouge">/etc/default/docker</code> does not work.</p>

<p>This is what I pieced together from the Internet:</p>

<p>Edit the file <code class="language-plaintext highlighter-rouge">/lib/systemd/system/docker.service</code>:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="nv">$ </span><span class="nb">sudo </span>vi /lib/systemd/system/docker.service
</code></pre></div></div>

<p><em>Append</em> the following to the <code class="language-plaintext highlighter-rouge">ExecStart=/usr/bin/dockerd -H fd://</code> line:</p>

<div class="language-conf highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-<span class="n">H</span> <span class="n">tcp</span>://<span class="m">0</span>.<span class="m">0</span>.<span class="m">0</span>.<span class="m">0</span>:<span class="m">2375</span> -<span class="n">H</span> <span class="n">unix</span>:///<span class="n">var</span>/<span class="n">run</span>/<span class="n">docker</span>.<span class="n">sock</span>
</code></pre></div></div>

<p>Reload <code class="language-plaintext highlighter-rouge">systemd</code>:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>systemctl daemon-reload
</code></pre></div></div>

<p>Restart <code class="language-plaintext highlighter-rouge">docker</code>:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>systemctl restart docker
</code></pre></div></div>

<p>Test with <code class="language-plaintext highlighter-rouge">curl</code>:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>curl <span class="nt">-X</span> GET http://0.0.0.0:2375/_ping
</code></pre></div></div>

<p>The above should respond with <code class="language-plaintext highlighter-rouge">OK</code>.</p>

<p>Hope someone out there finds this helpful.</p>

<p class="text-justify"><strong>NOTE:</strong> <em>This provides un-encrypted and un-authenticated direct access to the daemon.</em></p>]]></content><author><name>Thoba Lose</name></author><category term="Technology" /><category term="docker" /><category term="linux" /><summary type="html"><![CDATA[Docker Remote API on Ubuntu 16.04.2.]]></summary></entry><entry><title type="html">Docker Swarm Mode and Machine</title><link href="https://thobalose.github.io//2016/docker-swarm-mode/" rel="alternate" type="text/html" title="Docker Swarm Mode and Machine" /><published>2016-08-19T00:00:00+02:00</published><updated>2016-08-19T00:00:00+02:00</updated><id>https://thobalose.github.io//2016/docker-swarm-mode</id><content type="html" xml:base="https://thobalose.github.io//2016/docker-swarm-mode/"><![CDATA[<p class="text-justify">In this post we will be making use of Docker Engine 1.12 Swarm mode for natively managing a cluster of Docker Engines called a Swarm.</p>
<p class="text-justify">We will be using <code class="language-plaintext highlighter-rouge">docker-machine</code> to create our nodes and deploy a simple Flask application that returns the <code class="language-plaintext highlighter-rouge">hostname</code> and <code class="language-plaintext highlighter-rouge">ip address</code> of the container/host it’s running on.</p>

<h2 id="prerequisites">Prerequisites</h2>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker <span class="nt">-v</span>
Docker version 1.12.0, build 8eab29e
</code></pre></div></div>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker-machine <span class="nt">-v</span>
docker-machine version 0.8.0, build b85aac1
</code></pre></div></div>

<h2 id="creating-our-nodes">Creating our nodes</h2>

<p>We will create our nodes using <code class="language-plaintext highlighter-rouge">docker-machine</code>:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for </span>node <span class="k">in </span>manager-1 worker-1 worker-2<span class="p">;</span> <span class="k">do
    </span>docker-machine create <span class="nt">-d</span> virtualbox <span class="nv">$node</span>
<span class="k">done</span>
</code></pre></div></div>

<h2 id="initializing-our-managers">Initializing our managers</h2>

<p>Here, we are creating a swarm on the <code class="language-plaintext highlighter-rouge">manager-1</code> node and telling it to advertise it’s address using the <code class="language-plaintext highlighter-rouge">--advertise-addr</code> flag.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">eval</span> <span class="sb">`</span>docker-machine <span class="nb">env </span>manager-1<span class="sb">`</span>
</code></pre></div></div>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker swarm init <span class="se">\</span>
 <span class="nt">--advertise-addr</span> <span class="sb">`</span>docker-machine ip manager-1<span class="sb">`</span>:2377
</code></pre></div></div>

<p>You should see the below output after executing the <code class="language-plaintext highlighter-rouge">swarm init</code> command</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>To add a worker to this swarm, run the following <span class="nb">command</span>:
docker swarm <span class="nb">join</span> <span class="se">\</span>
 <span class="nt">--token</span> SWMTKN-1-44bmnrfrkfpyb4lgryudjd4uaamkozpien1lr6oddhdiq995pc-0mwe6lfak4wjy828vmt63t9ot <span class="se">\</span>
 192.168.99.102:2377
</code></pre></div></div>

<p><strong>NOTE</strong>:  Your <code class="language-plaintext highlighter-rouge">--token</code> will differ.</p>

<h2 id="joining-our-workers">Joining our workers</h2>

<p>Here, we add worker nodes to our swarm.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">WORKER_JOIN_TOKEN</span><span class="o">=</span><span class="sb">`</span>docker swarm join-token <span class="nt">-q</span> worker<span class="sb">`</span>
</code></pre></div></div>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for </span>worker <span class="k">in </span>1 2<span class="p">;</span> <span class="k">do
    </span><span class="nb">eval</span> <span class="sb">`</span>docker-machine <span class="nb">env </span>worker-<span class="nv">$worker</span><span class="sb">`</span>
    
    docker swarm <span class="nb">join</span> <span class="se">\</span>
    <span class="nt">--token</span> <span class="nv">$WORKER_JOIN_TOKEN</span> <span class="se">\</span>
    <span class="sb">`</span>docker-machine ip manager-1<span class="sb">`</span>:2377
<span class="k">done</span>
</code></pre></div></div>

<p class="text-justify">Let’s execute <code class="language-plaintext highlighter-rouge">docker node ls</code> on our manager to confirm</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">eval</span> <span class="sb">`</span>docker-machine <span class="nb">env </span>manager-1<span class="sb">`</span>
</code></pre></div></div>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker node <span class="nb">ls</span>
</code></pre></div></div>

<p>You should see the following</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ID                           HOSTNAME    STATUS  AVAILABILITY  MANAGER STATUS
01x30nznfg6tv95jl1uyr0wrf <span class="k">*</span>  manager-1   Ready   Active        Leader
0w36v8c8z9vxya9p9vuwrdi9o    worker-1    Ready   Active
e0fk1094a8ihzp1ien27cogku    worker-2    Ready   Active
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">*</code> tells us which node we are currently using and <code class="language-plaintext highlighter-rouge">MANAGER</code> indicating <code class="language-plaintext highlighter-rouge">manager-1</code> is the <code class="language-plaintext highlighter-rouge">Leader</code>.</p>

<h2 id="deploying-our-service">Deploying our service</h2>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker service create <span class="nt">--name</span> flasip <span class="se">\</span>
 <span class="nt">--replicas</span><span class="o">=</span>1 <span class="se">\</span>
 <span class="nt">-p</span> 80:5000 <span class="se">\</span>
 thoba/flasip:latest
</code></pre></div></div>

<p class="text-justify">The above command creates a single instance (<code class="language-plaintext highlighter-rouge">--replicas=1</code>) service named <code class="language-plaintext highlighter-rouge">flasip</code> (<code class="language-plaintext highlighter-rouge">--name flasip</code>) and mapping port <code class="language-plaintext highlighter-rouge">80</code> to <code class="language-plaintext highlighter-rouge">5000</code> (<code class="language-plaintext highlighter-rouge">-p 80:5000</code>) using the <code class="language-plaintext highlighter-rouge">thoba/flasip:latest</code> Docker image.</p>

<p class="text-justify">To check for running services, type the following commands:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker service <span class="nb">ls</span>
</code></pre></div></div>

<p class="text-justify">We can use <code class="language-plaintext highlighter-rouge">docker service scale SERVICE_NAME=NUM_TASKS</code> to scale our service to the desired number of tasks:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker service scale <span class="nv">flasip</span><span class="o">=</span>6
flasip scaled to 6
</code></pre></div></div>

<p>To see which node(s) these are deployed/running in, execute:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker service ps flasip
</code></pre></div></div>

<p>Get the manager’s IP by executing the following command:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker-machine ip manager-1
192.168.99.102
</code></pre></div></div>

<p class="text-justify">To access the <code class="language-plaintext highlighter-rouge">flasip</code> service, point your browser to <a href="http://192.168.99.102"><code class="language-plaintext highlighter-rouge">192.168.99.102</code></a> and :boom:</p>

<p><img src="/assets/images/flasip_app.png" alt="FlasIp_App" title="FlasIp_App" /></p>

<p class="text-justify">Internally, Docker makes use of Linux <a href="http://www.linuxvirtualserver.org/software/ipvs.html">IPVS</a>, an in-kernel Layer 4 multi-protocol load balancer. With IPVS routing packets inside the kernel, <a href="https://blog.docker.com/2016/06/docker-1-12-built-in-orchestration/">swarm’s routing mesh</a> delivers high performance container-aware load-balancing.</p>

<p class="text-justify"><strong>Refresh the browser to see the load balancing feature.</strong></p>

<p class="text-justify">Hope someone finds this helpful. :smiley:</p>]]></content><author><name>Thoba Lose</name></author><category term="Technology" /><category term="docker" /><category term="docker-machine" /><category term="docker swarm" /><category term="linux" /><category term="swarm mode" /><summary type="html"><![CDATA[Docker Swarm Mode and Machine.]]></summary></entry><entry><title type="html">Grails GORM for Neo4j</title><link href="https://thobalose.github.io//2016/grails-neo4j/" rel="alternate" type="text/html" title="Grails GORM for Neo4j" /><published>2016-07-15T00:00:00+02:00</published><updated>2016-07-15T00:00:00+02:00</updated><id>https://thobalose.github.io//2016/grails-neo4j</id><content type="html" xml:base="https://thobalose.github.io//2016/grails-neo4j/"><![CDATA[<p class="text-justify">In this post, we are going to make use of the Grails <a href="http://gorm.grails.org/latest/neo4j/manual/index.html">GORM for Neo4j</a> to create a Graph database representing the simplified <a href="http://gmod.org/wiki/Introduction_to_Chado#The_Sequence_Module_and_Features">Sequence Ontology</a> shown in the image below:</p>
<p><img src="http://gmod.org/mediawiki/images/1/16/So-slim-example.png" alt="So-slim-example" title="So-slim-example" /></p>

<p><strong>NB</strong>: Before we get started, I am using the following versions and the IntelliJ IDE:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>thoba at xps <span class="k">in</span> ~
<span class="nv">$ </span>sdk c
Using:
gradle: 2.14
grails: 3.1.9
groovy: 2.4.7
</code></pre></div></div>

<p>With that out of the way, let’s get started.</p>

<h2 id="getting-started">Getting Started</h2>

<p class="text-justify">To get started, we need to install the plugin into our Grails application (<code class="language-plaintext highlighter-rouge">soneo</code>) by editing the <code class="language-plaintext highlighter-rouge">build.gradle</code> file and adding the plugin as a dependency.</p>

<figure class="highlight"><pre><code class="language-groovy" data-lang="groovy"><span class="n">dependencies</span> <span class="o">{</span>
<span class="n">compile</span> <span class="s1">'org.grails.plugins:neo4j:5.0.10'</span>
<span class="o">}</span></code></pre></figure>

<p class="text-justify"><em>By default Neo4j will be used in embedded mode, the default directory for the Neo4j datastore is <code class="language-plaintext highlighter-rouge">data/neo4j</code>.</em></p>

<h2 id="creating-our-domains-and-controllers">Creating our Domains and Controllers</h2>

<p class="text-justify">Let’s create our domains and their respective controllers.</p>
<p class="text-justify">By default our classes will be persisted by Hibernate and not Neo4j. To persist our domain classes with Neo4j, we must use the <code class="language-plaintext highlighter-rouge">mapWith</code> property:</p>

<figure class="highlight"><pre><code class="language-groovy" data-lang="groovy"><span class="kd">static</span> <span class="n">mapWith</span> <span class="o">=</span> <span class="s2">"neo4j"</span></code></pre></figure>

<h3 id="domains">Domains:</h3>

<p><code class="language-plaintext highlighter-rouge">Feature domain</code>:</p>

<figure class="highlight"><pre><code class="language-groovy" data-lang="groovy"><span class="c1">// Feature domain</span>
<span class="kn">package</span> <span class="nn">soneo</span>
<span class="kn">import</span> <span class="nn">groovy.transform.ToString</span>

<span class="nd">@ToString</span><span class="o">(</span><span class="n">includes</span> <span class="o">=</span> <span class="s1">'name'</span><span class="o">)</span>
<span class="kd">class</span> <span class="nc">Feature</span> <span class="o">{</span>
<span class="n">String</span> <span class="n">name</span>
<span class="n">Date</span> <span class="n">created</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Date</span><span class="o">()</span>
<span class="kd">static</span> <span class="n">hasMany</span> <span class="o">=</span> <span class="o">[</span><span class="nl">gene:</span> <span class="n">Gene</span><span class="o">,</span> <span class="nl">exon:</span><span class="n">Exon</span><span class="o">,</span> <span class="nl">transcript:</span><span class="n">Transcript</span><span class="o">,</span> <span class="nl">utr:</span><span class="n">Utr</span><span class="o">]</span>

    <span class="kd">static</span> <span class="n">constraints</span> <span class="o">=</span> <span class="o">{</span>
        <span class="n">name</span><span class="o">(</span><span class="nl">blank:</span> <span class="kc">false</span><span class="o">)</span>
    <span class="o">}</span>
    <span class="kd">static</span> <span class="n">mapWith</span> <span class="o">=</span> <span class="s2">"neo4j"</span>

<span class="o">}</span></code></pre></figure>

<p><code class="language-plaintext highlighter-rouge">Transcript domain</code>:</p>

<figure class="highlight"><pre><code class="language-groovy" data-lang="groovy"><span class="c1">// Transcript domain</span>
<span class="kn">package</span> <span class="nn">soneo</span>
<span class="kn">import</span> <span class="nn">groovy.transform.ToString</span>

<span class="nd">@ToString</span><span class="o">(</span><span class="n">includes</span> <span class="o">=</span> <span class="s1">'name'</span><span class="o">)</span>
<span class="kd">class</span> <span class="nc">Transcript</span> <span class="o">{</span>
<span class="n">String</span> <span class="n">name</span>
<span class="n">Date</span> <span class="n">created</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Date</span><span class="o">()</span>
<span class="kd">static</span> <span class="n">belongsTo</span> <span class="o">=</span> <span class="o">[</span><span class="nl">is_a:</span> <span class="n">Feature</span><span class="o">,</span> <span class="nl">part_of:</span> <span class="n">Gene</span><span class="o">]</span>

    <span class="kd">static</span> <span class="n">constraints</span> <span class="o">=</span> <span class="o">{</span>
        <span class="n">name</span><span class="o">(</span><span class="nl">blank:</span> <span class="kc">false</span><span class="o">)</span>
    <span class="o">}</span>
    <span class="kd">static</span> <span class="n">mapWith</span> <span class="o">=</span> <span class="s2">"neo4j"</span>

<span class="o">}</span></code></pre></figure>

<p><code class="language-plaintext highlighter-rouge">Gene domain</code>:</p>

<figure class="highlight"><pre><code class="language-groovy" data-lang="groovy"><span class="c1">// Gene domain</span>
<span class="kn">package</span> <span class="nn">soneo</span>
<span class="kn">import</span> <span class="nn">groovy.transform.ToString</span>

<span class="nd">@ToString</span><span class="o">(</span><span class="n">includes</span> <span class="o">=</span> <span class="s1">'name'</span><span class="o">)</span>
<span class="kd">class</span> <span class="nc">Gene</span> <span class="o">{</span>
<span class="n">String</span> <span class="n">name</span>
<span class="n">Date</span> <span class="n">created</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Date</span><span class="o">()</span>
<span class="kd">static</span> <span class="n">belongsTo</span> <span class="o">=</span> <span class="o">[</span><span class="nl">is_a:</span> <span class="n">Feature</span><span class="o">]</span>
<span class="kd">static</span> <span class="n">hasMany</span> <span class="o">=</span> <span class="o">[</span><span class="nl">coding_gene:</span><span class="n">Codinggene</span><span class="o">,</span> <span class="nl">noncoding_gene:</span><span class="n">Noncodinggene</span><span class="o">]</span>
<span class="kd">static</span> <span class="n">constraints</span> <span class="o">=</span> <span class="o">{</span>
<span class="n">name</span><span class="o">(</span><span class="nl">blank:</span> <span class="kc">false</span><span class="o">)</span>
<span class="o">}</span>

    <span class="kd">static</span> <span class="n">mapWith</span> <span class="o">=</span> <span class="s2">"neo4j"</span>

<span class="o">}</span></code></pre></figure>

<p><code class="language-plaintext highlighter-rouge">Noncodinggene domain</code>:</p>

<figure class="highlight"><pre><code class="language-groovy" data-lang="groovy"><span class="c1">// Noncodinggene domain</span>
<span class="kn">package</span> <span class="nn">soneo</span>
<span class="kn">import</span> <span class="nn">groovy.transform.ToString</span>

<span class="nd">@ToString</span><span class="o">(</span><span class="n">includes</span> <span class="o">=</span> <span class="s1">'name'</span><span class="o">)</span>
<span class="kd">class</span> <span class="nc">Noncodinggene</span> <span class="o">{</span>
<span class="n">String</span> <span class="n">name</span>
<span class="n">Date</span> <span class="n">created</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Date</span><span class="o">()</span>
<span class="kd">static</span> <span class="n">belongsTo</span> <span class="o">=</span> <span class="o">[</span><span class="nl">is_a:</span> <span class="n">Gene</span><span class="o">]</span>
<span class="kd">static</span> <span class="n">constraints</span> <span class="o">=</span> <span class="o">{</span>
<span class="n">name</span><span class="o">(</span><span class="nl">blank:</span> <span class="kc">false</span><span class="o">)</span>
<span class="o">}</span>

    <span class="kd">static</span> <span class="n">mapWith</span> <span class="o">=</span> <span class="s2">"neo4j"</span>

<span class="o">}</span></code></pre></figure>

<p><code class="language-plaintext highlighter-rouge">Codinggene domain</code>:</p>

<figure class="highlight"><pre><code class="language-groovy" data-lang="groovy"><span class="c1">// Codinggene domain</span>
<span class="kn">package</span> <span class="nn">soneo</span>
<span class="kn">import</span> <span class="nn">groovy.transform.ToString</span>

<span class="nd">@ToString</span><span class="o">(</span><span class="n">includes</span> <span class="o">=</span> <span class="s1">'name'</span><span class="o">)</span>
<span class="kd">class</span> <span class="nc">Codinggene</span> <span class="o">{</span>
<span class="n">String</span> <span class="n">name</span>
<span class="n">Date</span> <span class="n">created</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Date</span><span class="o">()</span>
<span class="kd">static</span> <span class="n">belongsTo</span> <span class="o">=</span> <span class="o">[</span><span class="nl">is_a:</span> <span class="n">Gene</span><span class="o">]</span>
<span class="kd">static</span> <span class="n">constraints</span> <span class="o">=</span> <span class="o">{</span>
<span class="n">name</span><span class="o">(</span><span class="nl">blank:</span> <span class="kc">false</span><span class="o">)</span>
<span class="o">}</span>

    <span class="kd">static</span> <span class="n">mapWith</span> <span class="o">=</span> <span class="s2">"neo4j"</span>

<span class="o">}</span></code></pre></figure>

<p><code class="language-plaintext highlighter-rouge">Utr domain</code>:</p>

<figure class="highlight"><pre><code class="language-groovy" data-lang="groovy"><span class="c1">// Utr domain</span>
<span class="kn">package</span> <span class="nn">soneo</span>
<span class="kn">import</span> <span class="nn">groovy.transform.ToString</span>

<span class="nd">@ToString</span><span class="o">(</span><span class="n">includes</span> <span class="o">=</span> <span class="s1">'name'</span><span class="o">)</span>
<span class="kd">class</span> <span class="nc">Utr</span> <span class="o">{</span>
<span class="n">String</span> <span class="n">name</span>
<span class="n">Date</span> <span class="n">created</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Date</span><span class="o">()</span>
<span class="kd">static</span> <span class="n">belongsTo</span> <span class="o">=</span> <span class="o">[</span><span class="nl">is_a:</span> <span class="n">Feature</span><span class="o">,</span> <span class="nl">part_of:</span> <span class="n">Transcript</span><span class="o">]</span>

    <span class="kd">static</span> <span class="n">constraints</span> <span class="o">=</span> <span class="o">{</span>
        <span class="n">name</span><span class="o">(</span><span class="nl">blank:</span> <span class="kc">false</span><span class="o">)</span>
    <span class="o">}</span>
    <span class="kd">static</span> <span class="n">mapWith</span> <span class="o">=</span> <span class="s2">"neo4j"</span>

<span class="o">}</span></code></pre></figure>

<p><code class="language-plaintext highlighter-rouge">Exon domain</code>:</p>

<figure class="highlight"><pre><code class="language-groovy" data-lang="groovy"><span class="c1">// Exon domain</span>
<span class="kn">package</span> <span class="nn">soneo</span>
<span class="kn">import</span> <span class="nn">groovy.transform.ToString</span>

<span class="nd">@ToString</span><span class="o">(</span><span class="n">includes</span> <span class="o">=</span> <span class="s1">'name'</span><span class="o">)</span>
<span class="kd">class</span> <span class="nc">Exon</span> <span class="o">{</span>
<span class="n">String</span> <span class="n">name</span>
<span class="n">Date</span> <span class="n">created</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Date</span><span class="o">()</span>
<span class="kd">static</span> <span class="n">belongsTo</span> <span class="o">=</span> <span class="o">[</span><span class="nl">is_a:</span> <span class="n">Feature</span><span class="o">,</span> <span class="nl">part_of:</span><span class="n">Transcript</span><span class="o">]</span>

    <span class="kd">static</span> <span class="n">constraints</span> <span class="o">=</span> <span class="o">{</span>
        <span class="n">name</span><span class="o">(</span><span class="nl">blank:</span> <span class="kc">false</span><span class="o">)</span>
    <span class="o">}</span>

    <span class="kd">static</span> <span class="n">mapWith</span> <span class="o">=</span> <span class="s2">"neo4j"</span>

<span class="o">}</span></code></pre></figure>

<p><code class="language-plaintext highlighter-rouge">TrnaGene domain</code>:</p>

<figure class="highlight"><pre><code class="language-groovy" data-lang="groovy"><span class="c1">// TrnaGene domain</span>
<span class="kn">package</span> <span class="nn">soneo</span>
<span class="kn">import</span> <span class="nn">groovy.transform.ToString</span>

<span class="nd">@ToString</span><span class="o">(</span><span class="n">includes</span> <span class="o">=</span> <span class="s1">'name'</span><span class="o">)</span>
<span class="kd">class</span> <span class="nc">TrnaGene</span> <span class="o">{</span>
<span class="n">String</span> <span class="n">name</span>
<span class="n">Date</span> <span class="n">created</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Date</span><span class="o">()</span>
<span class="kd">static</span> <span class="n">belongsTo</span> <span class="o">=</span> <span class="o">[</span><span class="nl">is_a:</span> <span class="n">Noncodinggene</span><span class="o">]</span>

    <span class="kd">static</span> <span class="n">constraints</span> <span class="o">=</span> <span class="o">{</span>
        <span class="n">name</span><span class="o">(</span><span class="nl">blank:</span> <span class="kc">false</span><span class="o">)</span>
    <span class="o">}</span>
    <span class="kd">static</span> <span class="n">mapWith</span> <span class="o">=</span> <span class="s2">"neo4j"</span>

<span class="o">}</span></code></pre></figure>

<p><code class="language-plaintext highlighter-rouge">TrnaTranscript domain</code>:</p>

<figure class="highlight"><pre><code class="language-groovy" data-lang="groovy"><span class="c1">// TrnaTranscript domain</span>
<span class="kn">package</span> <span class="nn">soneo</span>
<span class="kn">import</span> <span class="nn">groovy.transform.ToString</span>

<span class="nd">@ToString</span><span class="o">(</span><span class="n">includes</span> <span class="o">=</span> <span class="s1">'name'</span><span class="o">)</span>
<span class="kd">class</span> <span class="nc">TrnaTranscript</span> <span class="o">{</span>
<span class="n">String</span> <span class="n">name</span>
<span class="n">Date</span> <span class="n">created</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Date</span><span class="o">()</span>
<span class="kd">static</span> <span class="n">belongsTo</span> <span class="o">=</span> <span class="o">[</span><span class="nl">is_a:</span> <span class="n">Transcript</span><span class="o">,</span> <span class="nl">part_of:</span> <span class="n">TrnaGene</span><span class="o">]</span>

    <span class="kd">static</span> <span class="n">constraints</span> <span class="o">=</span> <span class="o">{</span>
        <span class="n">name</span><span class="o">(</span><span class="nl">blank:</span> <span class="kc">false</span><span class="o">)</span>
    <span class="o">}</span>
    <span class="kd">static</span> <span class="n">mapWith</span> <span class="o">=</span> <span class="s2">"neo4j"</span>

<span class="o">}</span></code></pre></figure>

<h3 id="controllers">Controllers</h3>

<p class="text-justify">We will modify our controllers to use dynamic scaffolding, so they will all have the following, replacing <code class="language-plaintext highlighter-rouge">{DomainName}</code> with the appropriate domain name:</p>

<figure class="highlight"><pre><code class="language-groovy" data-lang="groovy"><span class="kn">package</span> <span class="nn">soneo</span>

<span class="kd">class</span> <span class="err">{</span><span class="nc">DomainName</span><span class="o">}</span><span class="n">Controller</span> <span class="o">{</span>
<span class="kd">static</span> <span class="n">scaffold</span> <span class="o">=</span> <span class="o">{</span><span class="n">DomainName</span><span class="o">}</span>

    <span class="kt">def</span> <span class="nf">index</span><span class="o">()</span> <span class="o">{}</span>

<span class="o">}</span></code></pre></figure>

<p class="text-justify">With this in place, we can run our app using the <code class="language-plaintext highlighter-rouge">grails run-app</code> command, pointing our browser to <a href="http://localhost:8080">localhost:8080</a> and start to populate data.</p>

<h2 id="viewing-our-data-in-neo4j">Viewing our data in Neo4j</h2>

<p class="text-justify">In order for us to view our data in Neo4j, we are going to make use of a slightly modified docker image (<code class="language-plaintext highlighter-rouge">thoba/neo4j_galaxy_ie:soneo</code>) to cater for user permissions as, by default, docker runs as <code class="language-plaintext highlighter-rouge">root</code>.</p>
<p class="text-justify">Also, our application is integrated with Neo4j in embedded mode. This means that one program and only one program can read and write to the database at a time. We will have to stop grails and run the following:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">cd </span>soneo
<span class="nv">$ </span>docker run <span class="nt">-d</span> <span class="se">\</span>
 <span class="nt">-e</span> <span class="nv">NEO4J_UID</span><span class="o">=</span><span class="si">$(</span><span class="nb">id</span> <span class="nt">-u</span><span class="si">)</span> <span class="nt">-e</span> <span class="nv">NEO4J_GID</span><span class="o">=</span><span class="si">$(</span><span class="nb">id</span> <span class="nt">-g</span><span class="si">)</span> <span class="nt">-e</span> <span class="nv">NEO4J_AUTH</span><span class="o">=</span>none <span class="se">\</span>
 <span class="nt">-v</span> <span class="se">\$</span><span class="o">(</span><span class="nb">pwd</span><span class="o">)</span>/data/neo4j:/data <span class="se">\</span>
 <span class="nt">-p</span> 7474:7474 <span class="se">\</span>
 thoba/neo4j_galaxy_ie:soneo
</code></pre></div></div>

<p class="text-justify">When we see our running container via <code class="language-plaintext highlighter-rouge">docker ps</code>, we can point our browser to <a href="http://localhost:7474">localhost:7474</a>. Clicking on the <code class="language-plaintext highlighter-rouge">IS_A</code> relationship on the side shall present data similar to the graph depicted below:</p>
<p><img src="https://raw.githubusercontent.com/thobalose/soneo/master/soneo.png" alt="SO" title="SO" /></p>

<p><strong>Code for this post can be found <a href="https://github.com/thobalose/soneo" target="_blank">here.</a></strong></p>]]></content><author><name>Thoba Lose</name></author><category term="Technology" /><category term="neo4j" /><category term="groovy" /><category term="grails" /><category term="ogm" /><category term="gorm" /><category term="chado" /><category term="sequence ontology" /><summary type="html"><![CDATA[Grails GORM for Neo4j.]]></summary></entry><entry><title type="html">docker-compose SSL error</title><link href="https://thobalose.github.io//2016/docker-compose-ssl-error/" rel="alternate" type="text/html" title="docker-compose SSL error" /><published>2016-05-06T00:00:00+02:00</published><updated>2016-05-06T00:00:00+02:00</updated><id>https://thobalose.github.io//2016/docker-compose-ssl-error</id><content type="html" xml:base="https://thobalose.github.io//2016/docker-compose-ssl-error/"><![CDATA[<p class="text-justify">I recently hit a rather intesting error using <code class="language-plaintext highlighter-rouge">docker-compose</code> with <code class="language-plaintext highlighter-rouge">docker-machine</code>, the error looked like:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">eval</span> <span class="sb">`</span>docker-machine <span class="nb">env </span>dev<span class="sb">`</span>
<span class="nv">$ </span>docker-compose build
...
backports.ssl_match_hostname.CertificateError: <span class="nb">hostname</span> <span class="s1">'192.168.2.211'</span> doesn<span class="s1">'t match '</span>localhost<span class="s1">'
</span></code></pre></div></div>

<p class="text-justify">To fix this, I did some trickery with the <code class="language-plaintext highlighter-rouge">/etc/hosts</code> file and added the <code class="language-plaintext highlighter-rouge">192.168.2.211</code> as <code class="language-plaintext highlighter-rouge">localhost</code>. I then</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">env</span> | <span class="nb">grep </span>DOCKER_HOST
<span class="nv">DOCKER_HOST</span><span class="o">=</span>tcp://192.168.2.211:2376
<span class="nv">$ </span><span class="nb">export </span><span class="nv">DOCKER_HOST</span><span class="o">=</span>tcp://localhost:2376
<span class="nv">$ </span><span class="nb">env</span> | <span class="nb">grep </span>DOCKER_HOST
<span class="nv">DOCKER_HOST</span><span class="o">=</span>tcp://localhost:2376
<span class="nv">$ </span>docker-compose build
Building web
Step 1 : FROM python:2.7
...
</code></pre></div></div>

<p class="text-justify">Hope this trickery helps someone, it’s not the best solution. However, it can save you a lot of time.</p>]]></content><author><name>Thoba Lose</name></author><category term="Technology" /><category term="docker" /><category term="docker-compose" /><category term="docker-machine" /><category term="linux" /><summary type="html"><![CDATA[docker-compose SSL error.]]></summary></entry><entry><title type="html">Getting Started with Neomodel</title><link href="https://thobalose.github.io//2016/neomodel/" rel="alternate" type="text/html" title="Getting Started with Neomodel" /><published>2016-03-28T00:00:00+02:00</published><updated>2016-03-28T00:00:00+02:00</updated><id>https://thobalose.github.io//2016/neomodel</id><content type="html" xml:base="https://thobalose.github.io//2016/neomodel/"><![CDATA[<p class="text-justify"><a href="https://github.com/robinedwards/neomodel">Neomodel</a> is an Object Graph Mapper (OGM) for the <a href="http://neo4j.com/">Neo4j</a> graph database built on <a href="http://py2neo.org/">py2neo</a> and provides a <a href="https://www.djangoproject.com/">Django</a> ORM style definition.</p>
<p class="text-justify">We are going to look at using <code class="language-plaintext highlighter-rouge">neomodel</code> in a ‘DevOpsy’ manner using <a href="https://docs.docker.com/linux/">Docker</a>.</p>
<p>Below is our resulting graph:</p>

<p><img src="https://raw.githubusercontent.com/thobalose/neo4j_neomodel/master/neo4j_neomodel.png" alt="Result" title="Resulting Graph" /></p>

<p class="text-justify">Let’s start by using the <a href="https://hub.docker.com/_/neo4j/">Neo4j docker image</a> to get up and running with the neo4j graph database:</p>
<p><em>I’m assuming that you have <a href="https://docs.docker.com/linux/step_one/">docker installed</a></em></p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>docker run <span class="nt">-d</span> <span class="se">\</span>
 <span class="nt">-p</span> 7474:7474 <span class="se">\</span>
 <span class="nt">-v</span> <span class="nv">$HOME</span>/Desktop/neo4j/data:/data <span class="se">\</span>
 <span class="nt">--name</span> neomodel_neo4j <span class="se">\</span>
 neo4j:2.3.3
</code></pre></div></div>

<p class="text-justify">This will mount <code class="language-plaintext highlighter-rouge">$HOME/Desktop/neo4j/data</code> in our Docker host to <code class="language-plaintext highlighter-rouge">/data</code> inside the container.</p>
<p class="text-justify">Point your browser at <a href="http://localhost:7474">http://localhost:7474</a>, login with <code class="language-plaintext highlighter-rouge">neo4j/neo4j</code> and set a new <code class="language-plaintext highlighter-rouge">password</code>.</p>

<h3 id="installing-neomodel">Installing neomodel</h3>

<p>Let’s install neomodel using <a href="https://pypi.python.org/pypi/pip">pip</a></p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>pip <span class="nb">install </span>neomodel
</code></pre></div></div>

<h3 id="setting-the-neo4j-location">Setting the neo4j location</h3>

<p class="text-justify">Neomodel requires that we set the location of neo4j via an environment variable, this defaults to <code class="language-plaintext highlighter-rouge">http://localhost:7474/db/data/</code></p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">export </span><span class="nv">NEO4J_REST_URL</span><span class="o">=</span>http://neo4j:password@localhost:7474/db/data/
</code></pre></div></div>

<h3 id="defining-models-and-properties">Defining models and properties</h3>

<p class="text-justify">We then define a Python module by the name of <code class="language-plaintext highlighter-rouge">model.py</code> and within that define three <code class="language-plaintext highlighter-rouge">StructuredNode</code> classes and one <code class="language-plaintext highlighter-rouge">StructuredRel</code> class with their properties and relationships. An <code class="language-plaintext highlighter-rouge">Author</code> <code class="language-plaintext highlighter-rouge">WROTE</code> a <code class="language-plaintext highlighter-rouge">Book</code>, and the <code class="language-plaintext highlighter-rouge">Reader</code> <code class="language-plaintext highlighter-rouge">READ</code> the <code class="language-plaintext highlighter-rouge">Book</code>. The <code class="language-plaintext highlighter-rouge">Book</code> may also be <code class="language-plaintext highlighter-rouge">RECOMMENDED</code> by the <code class="language-plaintext highlighter-rouge">Reader</code> reading it, an <code class="language-plaintext highlighter-rouge">Author</code> may also recommend a <code class="language-plaintext highlighter-rouge">Book</code> that they have written.</p>

<p class="text-justify"><code class="language-plaintext highlighter-rouge">StructuredRel</code> is used to define the properties stored on relations.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="c1"># model.py
</span>
<span class="kn">from</span> <span class="n">neomodel</span> <span class="kn">import</span> <span class="p">(</span><span class="n">StructuredNode</span><span class="p">,</span> <span class="n">StructuredRel</span><span class="p">,</span>
    <span class="n">StringProperty</span><span class="p">,</span> <span class="n">DateProperty</span><span class="p">,</span>
    <span class="n">RelationshipTo</span><span class="p">,</span> <span class="n">OneOrMore</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">Recommended</span><span class="p">(</span><span class="n">StructuredRel</span><span class="p">):</span>
    <span class="n">date</span> <span class="o">=</span> <span class="nc">DateProperty</span><span class="p">(</span><span class="n">default</span><span class="o">=</span><span class="bp">None</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">Author</span><span class="p">(</span><span class="n">StructuredNode</span><span class="p">):</span>
    <span class="n">name</span> <span class="o">=</span> <span class="nc">StringProperty</span><span class="p">(</span><span class="n">Unique_Index</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">required</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
    <span class="n">born</span> <span class="o">=</span> <span class="nc">DateProperty</span><span class="p">()</span>
    <span class="n">died</span> <span class="o">=</span> <span class="nc">DateProperty</span><span class="p">(</span><span class="n">default</span><span class="o">=</span><span class="bp">None</span><span class="p">)</span>

    <span class="n">wrote</span> <span class="o">=</span> <span class="nc">RelationshipTo</span><span class="p">(</span><span class="sh">'</span><span class="s">Book</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">WROTE</span><span class="sh">'</span><span class="p">,</span> <span class="n">OneOrMore</span><span class="p">)</span>
    <span class="n">recommended</span> <span class="o">=</span> <span class="nc">RelationshipTo</span><span class="p">(</span>
        <span class="sh">'</span><span class="s">Book</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">RECOMMENDED</span><span class="sh">'</span><span class="p">,</span> <span class="n">OneOrMore</span><span class="p">,</span> <span class="n">model</span><span class="o">=</span><span class="n">Recommended</span>
        <span class="p">)</span>

<span class="k">class</span> <span class="nc">Book</span><span class="p">(</span><span class="n">StructuredNode</span><span class="p">):</span>
    <span class="n">title</span> <span class="o">=</span> <span class="nc">StringProperty</span><span class="p">(</span><span class="n">Unique_Index</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">required</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
    <span class="n">published</span> <span class="o">=</span> <span class="nc">DateProperty</span><span class="p">()</span>

<span class="k">class</span> <span class="nc">Reader</span><span class="p">(</span><span class="n">StructuredNode</span><span class="p">):</span>
    <span class="n">name</span> <span class="o">=</span> <span class="nc">StringProperty</span><span class="p">(</span><span class="n">Unique_Index</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">required</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
    <span class="n">born</span> <span class="o">=</span> <span class="nc">DateProperty</span><span class="p">()</span>

    <span class="n">read</span> <span class="o">=</span> <span class="nc">RelationshipTo</span><span class="p">(</span><span class="sh">'</span><span class="s">Book</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">READ</span><span class="sh">'</span><span class="p">,</span> <span class="n">OneOrMore</span><span class="p">)</span>
    <span class="n">recommended</span> <span class="o">=</span> <span class="nc">RelationshipTo</span><span class="p">(</span>
        <span class="sh">'</span><span class="s">Book</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">RECOMMENDED</span><span class="sh">'</span><span class="p">,</span> <span class="n">OneOrMore</span><span class="p">,</span> <span class="n">model</span><span class="o">=</span><span class="n">Recommended</span>
        <span class="p">)</span>
</code></pre></div></div>

<h3 id="persisting-and-querying-models-and-properties">Persisting and querying models and properties</h3>

<p class="text-justify">With our model in place, let’s define another Python module: <code class="language-plaintext highlighter-rouge">ctrlmodel.py</code>.
This will be used to populate and ‘control’ our Neo4j database.</p>
<p class="text-justify">We will start by defining a function that creates the nodes and saves them in our database.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="c1"># ctrlmodel.py
</span>
<span class="kn">from</span> <span class="n">model</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="n">neomodel</span> <span class="kn">import</span> <span class="n">UniqueProperty</span><span class="p">,</span> <span class="n">DoesNotExist</span><span class="p">,</span> <span class="n">db</span>
<span class="kn">from</span> <span class="n">datetime</span> <span class="kn">import</span> <span class="n">date</span>

<span class="k">class</span> <span class="nc">ctrlModel</span><span class="p">():</span>

    <span class="k">def</span> <span class="nf">createNodes</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="c1"># Create Authors
</span>            <span class="nc">Author</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="sh">'</span><span class="s">Pless</span><span class="sh">'</span><span class="p">,</span> <span class="n">born</span><span class="o">=</span><span class="nf">date</span><span class="p">(</span><span class="mi">1900</span><span class="p">,</span> <span class="mi">01</span><span class="p">,</span> <span class="mi">01</span><span class="p">),</span>
                   <span class="n">died</span><span class="o">=</span><span class="nf">date</span><span class="p">(</span><span class="mi">1990</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">12</span><span class="p">)).</span><span class="nf">save</span><span class="p">()</span>
            <span class="nc">Author</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="sh">'</span><span class="s">Lucy</span><span class="sh">'</span><span class="p">,</span> <span class="n">born</span><span class="o">=</span><span class="nf">date</span><span class="p">(</span><span class="mi">1950</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">12</span><span class="p">)).</span><span class="nf">save</span><span class="p">()</span>
            <span class="c1"># Create Books
</span>            <span class="nc">Book</span><span class="p">(</span><span class="n">title</span><span class="o">=</span><span class="sh">'</span><span class="s">Here be dragons</span><span class="sh">'</span><span class="p">,</span> <span class="n">published</span><span class="o">=</span><span class="nf">date</span><span class="p">(</span><span class="mi">1950</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">12</span><span class="p">)).</span><span class="nf">save</span><span class="p">()</span>
            <span class="nc">Book</span><span class="p">(</span><span class="n">title</span><span class="o">=</span><span class="sh">'</span><span class="s">Initial Commit</span><span class="sh">'</span><span class="p">,</span> <span class="n">published</span><span class="o">=</span><span class="nf">date</span><span class="p">(</span><span class="mi">1990</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">12</span><span class="p">)).</span><span class="nf">save</span><span class="p">()</span>
            <span class="c1"># Create Readers
</span>            <span class="nc">Reader</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="sh">'</span><span class="s">John</span><span class="sh">'</span><span class="p">,</span> <span class="n">born</span><span class="o">=</span><span class="nf">date</span><span class="p">(</span><span class="mi">1980</span><span class="p">,</span> <span class="mi">05</span><span class="p">,</span> <span class="mi">06</span><span class="p">)).</span><span class="nf">save</span><span class="p">()</span>
            <span class="nc">Reader</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="sh">'</span><span class="s">Mary</span><span class="sh">'</span><span class="p">,</span> <span class="n">born</span><span class="o">=</span><span class="nf">date</span><span class="p">(</span><span class="mi">1985</span><span class="p">,</span> <span class="mi">03</span><span class="p">,</span> <span class="mi">07</span><span class="p">)).</span><span class="nf">save</span><span class="p">()</span>
        <span class="k">except</span> <span class="n">UniqueProperty</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
            <span class="k">raise</span> <span class="n">e</span>

</code></pre></div></div>

<p class="text-justify">We then define another function to search the created nodes by <code class="language-plaintext highlighter-rouge">name</code> for the <code class="language-plaintext highlighter-rouge">Author</code> and <code class="language-plaintext highlighter-rouge">Reader</code>, and <code class="language-plaintext highlighter-rouge">title</code> for the <code class="language-plaintext highlighter-rouge">Book</code>.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="c1"># ctrlmodel.py
</span>
<span class="k">def</span> <span class="nf">searchNodes</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="k">print</span> <span class="sh">'</span><span class="s">Searching Author Node with Name=</span><span class="sh">'</span><span class="p">,</span> <span class="n">name</span> <span class="c1"># Search all nodes with Label Author
</span>        <span class="n">node</span> <span class="o">=</span> <span class="n">Author</span><span class="p">.</span><span class="n">nodes</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="n">name</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">node</span>
    <span class="k">except</span> <span class="n">DoesNotExist</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
        <span class="k">pass</span>
    <span class="k">try</span><span class="p">:</span> <span class="c1"># Searching all nodes with Label Book
</span>        <span class="k">print</span> <span class="sh">'</span><span class="s">Searching Book Node with Title=</span><span class="sh">'</span><span class="p">,</span> <span class="n">name</span>
        <span class="n">node</span> <span class="o">=</span> <span class="n">Book</span><span class="p">.</span><span class="n">nodes</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="n">title</span><span class="o">=</span><span class="n">name</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">node</span>
    <span class="k">except</span> <span class="n">DoesNotExist</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
        <span class="k">pass</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="k">print</span> <span class="sh">'</span><span class="s">Searching Reader Node with Name=</span><span class="sh">'</span><span class="p">,</span> <span class="n">name</span> <span class="c1"># Search all nodes with Label Reader
</span>        <span class="n">node</span> <span class="o">=</span> <span class="n">Reader</span><span class="p">.</span><span class="n">nodes</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="n">name</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">node</span>
    <span class="k">except</span> <span class="n">DoesNotExist</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
        <span class="k">pass</span>
    <span class="k">return</span> <span class="bp">None</span>

</code></pre></div></div>

<p class="text-justify">Let’s add functions that borrow functionality from the above to create relationships between our nodes.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="c1"># ctrlmodel.py
</span>
<span class="k">class</span> <span class="nc">ctrlModel</span><span class="p">():</span>
    <span class="k">def</span> <span class="nf">createWroteRel</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="k">print</span> <span class="sh">'</span><span class="s">Creating WROTE relationship between given nodes</span><span class="sh">'</span>
            <span class="nf">searchNodes</span><span class="p">(</span><span class="sh">'</span><span class="s">Pless</span><span class="sh">'</span><span class="p">).</span><span class="n">wrote</span><span class="p">.</span><span class="nf">connect</span><span class="p">(</span>
            <span class="nf">searchNodes</span><span class="p">(</span><span class="sh">'</span><span class="s">Here be dragons</span><span class="sh">'</span><span class="p">))</span>
            <span class="nf">searchNodes</span><span class="p">(</span><span class="sh">'</span><span class="s">Lucy</span><span class="sh">'</span><span class="p">).</span><span class="n">wrote</span><span class="p">.</span><span class="nf">connect</span><span class="p">(</span>
            <span class="nf">searchNodes</span><span class="p">(</span><span class="sh">'</span><span class="s">Initial Commit</span><span class="sh">'</span><span class="p">))</span>
            <span class="k">print</span> <span class="sh">'</span><span class="s">Creating WROTE relationship between given nodes</span><span class="sh">'</span>
        <span class="k">except</span> <span class="nb">Exception</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">e</span>

    <span class="k">def</span> <span class="nf">createReadRel</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="k">print</span> <span class="sh">'</span><span class="s">Creating READ relationship between given nodes</span><span class="sh">'</span>
            <span class="nf">searchNodes</span><span class="p">(</span><span class="sh">'</span><span class="s">John</span><span class="sh">'</span><span class="p">).</span><span class="n">read</span><span class="p">.</span><span class="nf">connect</span><span class="p">(</span>
                <span class="nf">searchNodes</span><span class="p">(</span><span class="sh">'</span><span class="s">Here be dragons</span><span class="sh">'</span><span class="p">))</span>
            <span class="nf">searchNodes</span><span class="p">(</span><span class="sh">'</span><span class="s">John</span><span class="sh">'</span><span class="p">).</span><span class="n">read</span><span class="p">.</span><span class="nf">connect</span><span class="p">(</span>
                <span class="nf">searchNodes</span><span class="p">(</span><span class="sh">'</span><span class="s">Initial Commit</span><span class="sh">'</span><span class="p">))</span>
            <span class="nf">searchNodes</span><span class="p">(</span><span class="sh">'</span><span class="s">Mary</span><span class="sh">'</span><span class="p">).</span><span class="n">read</span><span class="p">.</span><span class="nf">connect</span><span class="p">(</span>
                <span class="nf">searchNodes</span><span class="p">(</span><span class="sh">'</span><span class="s">Initial Commit</span><span class="sh">'</span><span class="p">))</span>
            <span class="k">print</span> <span class="sh">'</span><span class="s">Done creating READ relationship between nodes</span><span class="sh">'</span>
        <span class="k">except</span> <span class="nb">Exception</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
            <span class="k">raise</span> <span class="n">e</span>

    <span class="k">def</span> <span class="nf">createRecommendedRel</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="k">print</span> <span class="sh">'</span><span class="s">Creating RECOMMENDED relationship between given nodes</span><span class="sh">'</span>
            <span class="nf">searchNodes</span><span class="p">(</span><span class="sh">'</span><span class="s">John</span><span class="sh">'</span><span class="p">).</span><span class="n">recommended</span><span class="p">.</span><span class="nf">connect</span><span class="p">(</span>
                <span class="nf">searchNodes</span><span class="p">(</span><span class="sh">'</span><span class="s">Here be dragons</span><span class="sh">'</span><span class="p">),</span>
                <span class="p">{</span><span class="sh">'</span><span class="s">date</span><span class="sh">'</span><span class="p">:</span> <span class="nf">date</span><span class="p">(</span><span class="mi">1995</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">12</span><span class="p">)})</span>
            <span class="nf">searchNodes</span><span class="p">(</span><span class="sh">'</span><span class="s">Pless</span><span class="sh">'</span><span class="p">).</span><span class="n">recommended</span><span class="p">.</span><span class="nf">connect</span><span class="p">(</span>
                <span class="nf">searchNodes</span><span class="p">(</span><span class="sh">'</span><span class="s">Here be dragons</span><span class="sh">'</span><span class="p">),</span>
                <span class="p">{</span><span class="sh">'</span><span class="s">date</span><span class="sh">'</span><span class="p">:</span> <span class="nf">date</span><span class="p">(</span><span class="mi">1997</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">1</span><span class="p">)})</span>
            <span class="nf">searchNodes</span><span class="p">(</span><span class="sh">'</span><span class="s">Mary</span><span class="sh">'</span><span class="p">).</span><span class="n">recommended</span><span class="p">.</span><span class="nf">connect</span><span class="p">(</span>
                <span class="nf">searchNodes</span><span class="p">(</span><span class="sh">'</span><span class="s">Initial Commit</span><span class="sh">'</span><span class="p">),</span>
                <span class="p">{</span><span class="sh">'</span><span class="s">date</span><span class="sh">'</span><span class="p">:</span> <span class="nf">date</span><span class="p">(</span><span class="mi">2005</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">3</span><span class="p">)})</span>
            <span class="k">print</span> <span class="sh">'</span><span class="s">Done creating RECOMMENDED relationship between nodes</span><span class="sh">'</span>
        <span class="k">except</span> <span class="nb">Exception</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
            <span class="k">raise</span> <span class="n">e</span>

</code></pre></div></div>

<p class="text-justify">I thought I should add another function to delete any existing data before executing our <code class="language-plaintext highlighter-rouge">createNodes</code> function. This will help avoid the <a href="https://github.com/robinedwards/neomodel/blob/master/neomodel/exception.py#L18"><code class="language-plaintext highlighter-rouge">MultipleNodesReturned</code></a> exception when searching our database.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="c1"># ctrlmodel.py
</span>
<span class="k">def</span> <span class="nf">deleteData</span><span class="p">():</span>
    <span class="k">print</span> <span class="sh">'</span><span class="s">Delete all nodes and relationships...</span><span class="sh">'</span>
    <span class="n">query</span> <span class="o">=</span> <span class="sh">'</span><span class="s">MATCH (n) DETACH DELETE n</span><span class="sh">'</span>
    <span class="n">db</span><span class="p">.</span><span class="nf">cypher_query</span><span class="p">(</span><span class="n">query</span><span class="p">)</span>
</code></pre></div></div>

<p>We then create another Python module and give the name <code class="language-plaintext highlighter-rouge">main.py</code>.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="n">model</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="n">ctrlmodel</span> <span class="kn">import</span> <span class="o">*</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="sh">'</span><span class="s">__main__</span><span class="sh">'</span><span class="p">:</span>
    <span class="c1"># Start by deleting existing data
</span>    <span class="nf">deleteData</span><span class="p">()</span>
    <span class="n">create</span> <span class="o">=</span> <span class="nf">ctrlModel</span><span class="p">()</span>
    <span class="n">create</span><span class="p">.</span><span class="nf">ctrlNodes</span><span class="p">()</span>
    <span class="n">create</span><span class="p">.</span><span class="nf">createWroteRel</span><span class="p">()</span>
    <span class="n">create</span><span class="p">.</span><span class="nf">createReadRel</span><span class="p">()</span>
    <span class="n">create</span><span class="p">.</span><span class="nf">createRecommendedRel</span><span class="p">()</span>
    <span class="k">print</span> <span class="sh">'</span><span class="s">Done!</span><span class="sh">'</span>
</code></pre></div></div>

<p>Executing our <code class="language-plaintext highlighter-rouge">main.py</code>.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>python main.py
</code></pre></div></div>

<p>Would give us the graph depicted above.</p>

<p class="text-justify">Thanks to <a href="https://www.packtpub.com/application-development/building-web-applications-python-and-neo4j">Building Web Applications with Python and Neo4j </a>.</p>]]></content><author><name>Thoba Lose</name></author><category term="Technology" /><category term="neo4j" /><category term="python" /><category term="neomodel" /><category term="ogm" /><category term="docker" /><summary type="html"><![CDATA[Getting Started with Neomodel.]]></summary></entry><entry><title type="html">Wi-Fi on the DELL XPS 13 running Ubuntu 14.04</title><link href="https://thobalose.github.io//2016/xps13-wifi/" rel="alternate" type="text/html" title="Wi-Fi on the DELL XPS 13 running Ubuntu 14.04" /><published>2016-01-08T00:00:00+02:00</published><updated>2016-01-08T00:00:00+02:00</updated><id>https://thobalose.github.io//2016/xps13-wifi</id><content type="html" xml:base="https://thobalose.github.io//2016/xps13-wifi/"><![CDATA[<p class="text-justify">You’ll need to download the following packages:</p>

<ul>
  <li><a href="https://launchpad.net/ubuntu/trusty/amd64/libfakeroot">libfakeroot</a></li>
  <li><a href="https://launchpad.net/ubuntu/trusty/amd64/fakeroot">fakeroot</a></li>
  <li><a href="https://launchpad.net/ubuntu/trusty/amd64/dkms">dkms</a></li>
  <li><a href="https://launchpad.net/ubuntu/trusty/amd64/bcmwl-kernel-source">bcmwl-kernel-source</a></li>
</ul>

<p class="text-justify">Copy these packages onto a USB drive and manually install them. I downloaded these using my mobile and connected it via <a href="http://developer.android.com/reference/android/mtp/MtpDevice.html">MTP</a>, I then copied the packages to my <code class="language-plaintext highlighter-rouge">$HOME/Desktop</code> and manually installed them.</p>
<p class="text-justify">Launch the terminal (<code class="language-plaintext highlighter-rouge">Ctrl + Alt + T</code>) and enter the following commands to manually install:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd</span> <span class="nv">$HOME</span>/Desktop
<span class="nv">$ </span><span class="nb">sudo </span>dpkg <span class="nt">-i</span> libfakeroot<span class="k">*</span>.deb
<span class="nv">$ </span><span class="nb">sudo </span>dpkg <span class="nt">-i</span> fakeroot<span class="k">*</span>.deb
<span class="nv">$ </span><span class="nb">sudo </span>dpkg <span class="nt">-i</span> dkms<span class="k">*</span>.deb
<span class="nv">$ </span><span class="nb">sudo </span>dpkg <span class="nt">-i</span> bcmwl-kernel-source<span class="k">*</span>.deb
</code></pre></div></div>

<p class="text-justify">Upon completion, you shall be able to connect to Wi-Fi.</p>]]></content><author><name>Thoba Lose</name></author><category term="Technology" /><category term="ubuntu" /><category term="wifi" /><category term="xps13" /><category term="linux" /><summary type="html"><![CDATA[Wi-Fi on the DELL XPS 13 running Ubuntu 14.04.]]></summary></entry></feed>