Nadja Lind presents Sofa Sessions

DevDocs

devdocs.io

SystemD

apenwarr - The world in which IPv6 was a good design

The world in which IPv6 was a good design

Idempotent redirect to a file

Let’s say you want to redirect the STDOUT of some command to a file (a config file for example) using the (bash) shell. In ideal case destination file should not be touched if it already has exactly the same content you are going to write into it. How to do that in a single pipe?

Here’s how:

echo "New contents" | diff -duaN "$target_path" - | patch --binary -s -p0 "$target_path"

Full example

#!/usr/bin/env bash

set -eu -o pipefail

to_stderr () {
  >&2 cat
}

printable_only () {
  tr -cd '\11\12\15\40-\176'
}

pipe_debug () {
  tee >(printable_only | to_stderr)
}

to_file () {
  local target_path="$1"
  local restore_pipefail

  # diff will return non-zero exit code if file differs, therefore
  # pipefail shell attribute should be disabled for this
  # special case
  restore_pipefail=$(shopt -p -o pipefail)
  set +o pipefail

  diff -duaN "$target_path" - | pipe_debug | patch --binary -s -p0 "$target_path"

  eval "$restore_pipefail"
}

md5 () {
  md5sum -b | cut -f 1 -d ' '
}

sample_binary_data () {
  local i

  for (( i=0; i<=255; i++ )); do
    printf "\x$(printf %x "$i")"
  done
}

sample_text_data () {
  cat <<EOF
Here be dragons
EOF
}


testfile='./testfile'

echo "Binary data MD5 $(sample_binary_data | md5)"
echo "Text data MD5: $(sample_text_data | md5)"

sample_text_data >"$testfile"

echo "$testfile is going to be modified"
sample_binary_data | to_file "$testfile"

echo "$testfile is NOT going to be modified"
sample_binary_data | to_file "$testfile"

echo "$testfile MD5: $(md5 <"$testfile")"

echo "$testfile is going to be modified"
sample_text_data | to_file "$testfile"

echo "$testfile is NOT going to be modified"
sample_text_data | to_file "$testfile"

echo "$testfile MD5: $(md5 <"$testfile")"

Sample output

Binary data MD5 e2c865db4162bed963bfaa9ef6ac18f0
Text data MD5: 890923a3ff411987e645531cc33548f6
./testfile is going to be modified
--- ./testfile	2017-07-07 07:21:39.853604436 +0100
+++ -	2017-07-07 07:21:39.856596473 +0100
@@ -1 +1,2 @@
-Here be dragons
+	
 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
\ No newline at end of file
./testfile is NOT going to be modified
./testfile MD5: e2c865db4162bed963bfaa9ef6ac18f0
./testfile is going to be modified
--- ./testfile	2017-07-07 07:21:39.994605593 +0100
+++ -	2017-07-07 07:21:40.146792083 +0100
@@ -1,2 +1 @@
-	
 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
\ No newline at end of file
+Here be dragons
./testfile is NOT going to be modified
./testfile MD5: 890923a3ff411987e645531cc33548f6

We need to go deeper

I’m an oldfag. I love playing old games “Baldur’s Gate” series or “Heroes of Might & Magic II”. I happen to own the original Gold Edition CD of the latter one which I enjoy playing with my daughters occasionally. The CD contains the state of the art soundtrack which is an essential part of the game.

Unfortunately, this version of the game doesn’t run well on the latest build of the Windows 10. Even with some workarounds applied game tends to crash now and then.

Y U do dis Microsoft

The version distributed by GOG (which is basically a repackaged DOS version of it) works, but it lacks network play and has some audio tracks replaced with the different ones for some reason.

My primary operating system, for the time being, is Windows 10 and I do not have plans to change this in the near future, therefore the obvious choice is to run the game in a VM. Windows XP/7 require an additional license, so I’ve decided to give Linux/Wine a shot. VirtualBox was used for the hypervisor as I use it for the other things anyway.

The tricky part was to get the CD audio working. By passing the host CD drive to the VM I was able to access the data track, but not the audio tracks. Passing the CD as ISO image wouldn’t work either, as the ISO format does not support the audio tracks. The solution was to create BIN/CUE/CCD image and load it into the emulated CD drive inside of the VM.

The result? Well, see for yourself :)

Timestripe

Timestripe https://timestripe.com

Uncle Bob

JWT/JWS in a Clojure app

Libvirt SR-IOV pools on a Cisco UCS in the CentOS7

Libvirt allows you to create a network definition with all the virtual functions (VF) from the specified SR-IOV physical function (PF). It will assign one of the available VFs to the guest VM connected to such network automatically when it’s powered on. This allows you to avoid hardcoding of the VF PCI addresses into the configuration of the guest.

To enable SR-IOV for the static vNIC on the Cisco UCS You need to create a Dynamic vNIC Connection Policy with the desired number of the dynamic vNICs and assign it to the static vNIC.

You will also need to enable VT-d in the BIOS policy of the service profile (by selecting the predefined SRIOV BIOS policy for example) and enable the IOMMU support for your Linux kernel (see the “17.1.6.2. Using SR-IOV” section of the “Guest virtual machine device configuration” chapter from the RH Virtualization Deployment and Administration Guide)

Typical example, like the one from the section “17.1.6.4. Setting PCI device assignment from a pool of SR-IOV virtual functions” of the mentioned chapter might not work on the UCS:

<network>
   <name>passthrough</name> <!-- This is the name of the file you created -->
   <forward mode='hostdev' managed='yes'>
     <pf dev='enpXs0f0'/>  <!-- Use the netdev name of your SR-IOV devices PF here -->
   </forward>
</network>

In my case I was getting the internal error: missing IFLA_VF_INFO in netlink response error after trying to power on the VM connected to the “passthrough” network.

In order to work properly, the SR-IOV VF needs the Port Profile and the Port Profile Client created on the UCS (VM tab in the GUI, see the Cisco UCS Manager VM-FEX for KVM GUI Configuration Guide for more details on configuring port profiles on the UCS) and specified in the Libvirt network or interface definition. This allows you to specify the allowed VLANs for the VM configured to use that port profile.

Working Libvirt network definition looks like this (notice the <driver name='vfio'/> I’ve had to add as well):

<network>
   <name>passthrough</name>
   <forward mode='hostdev' managed='yes'>
     <pf dev='enpXs0f0'/>
     <driver name='vfio'/>
   </forward>
  <portgroup name='libvirt_port_group1' default='yes'>
    <virtualport type='802.1Qbh'>
      <parameters profileid='UCS_Port_Profile'/>
    </virtualport>
  </portgroup>
 </network>

And the network interface for the VM can be defined like:

<interface type='network'>
  <mac address='52:54:00:ec:24:f1'/>
  <source network='passthrough' portgroup='libvirt_port_group1'/>
</interface>

One of the enpXs0f0 virtual functions (total number depends on the Dynamic vNIC Connection Policy assigned to the static vNIC) will be consumed by that VM as soon as you power it on.

Successful assignment of the VF from the pool