Disk I/O errors on Adaptec ASR8805 raid controller

We have an Adaptec ASR8805 controller on one of the servers we manage. For various reasons we need to shrink a logical volume that is sitting on a RAID 6 logical device created and exposed by this controller, but we can’t because we’re getting seek errors:

Buffer I/O error on device dm-2, logical block 3330419721
sd 6:0:1:0: [sdb]  Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
sd 6:0:1:0: [sdb]  Sense Key : Hardware Error [current] 
sd 6:0:1:0: [sdb]  Add. Sense: Internal target failure
sd 6:0:1:0: [sdb] CDB: Read(16): 88 00 00 00 00 06 34 11 69 00 00 00 01 00 00 00
end_request: critical target error, dev sdb, sector 26643360000
sd 6:0:1:0: [sdb]  Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE

From what the controller is reporting, the RAID 6 is healthy, and all the physical drives SMART information seems ok(ish).

It turns out, no background checking of the RAID 6 parity has been enabled, and that is probably the problem, as reported by this article.

To get a “quick” fix (it’s a 24T array), I started:

# arcconf task start 1 logicaldrive 1 verify_fix

when it’ll be finished, I’ll enable the background check with:

# arcconf consistencycheck 1 on

I really hope this saves time to some fellow admin out there :)

How to display IOwait percentage in Prometheus

Prometheus has a few quirks, dealing with cpu time is one of these. this article explains how to deal with cpu time, and these are the rules I made for my own Prometheus/Grafana dashboard:

avg by (instance) (irate(node_cpu{mode="iowait"}[1m])) * 100

this rule groups by instance the iowait average for the system (all cpus)

avg by (instance) (irate(instance=~"hostname.*", node_cpu{mode="iowait"}[1m])) * 100

while this rule is like the one above, with the difference that you can filter which systems are reported, by hostname

hopefully this will be useful for someone out there :)

How to run a Flask application in Docker

Flask is a nice web application framework for Python.

My example app.py looks like:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
  return 'Hello, World!'

According to Flask documentation, to run the application we need to run FLASK_APP=app.py flask run. So our Dockerfile will run this command and we’ll pass an environment variable with the application name when we start the container:

FROM python:3-onbuild
EXPOSE 5000
CMD [ "python", "-m", "flask", "run", "--host=0.0.0.0" ]

The --host=0.0.0.0 parameter is necessary so that we will be able to connect to flask from outside the docker container.

Using the -onbuild version of the Python container is handy because it will import a file named requirements.txt and install the Python modules listed in it, so go on and create this file in the same directory, containing the single line, flask.

Now we can build our container:

docker build -t flaskapp .

This might take a while. When it ends, we’ll be able to run the container, passing the FLASK_APP environment variable:

docker run -it --rm --name flaskapp \
  -v "$PWD":/usr/src/app -w /usr/src/app \
  -e LANG=C.UTF-8 -e FLASK_APP=app.py \
  -p 5000:5000 flaskapp

As you can see I’m mounting the local directory $PWD to /usr/src/app in the container and setting the work directory there. I’m also passing the -p 5000:5000 parameter so that the container tcp port 5000 is available by connecting to my host machine port 5000.

You can test your app with your browser or with curl:

$ curl http://127.0.0.1:5000/
Hello, World!

I hope this will be useful to someone out there, have fun! :)

How to fix Fedora 25 dnf upgrade “certificate expired” failure

After logging on a Fedora 25 system I didn’t log for a while, I ran dnf clean all ; dnf upgrade to update it, but I ran into this problem:

# dnf -vvvv -d 5 upgrade
cachedir: /var/cache/dnf
Loaded plugins: playground, builddep, config-manager, debuginfo-install, generate_completion_cache, needs-restarting, copr, protected_packages, noroot, download, Query, reposync
DNF version: 1.1.10
Cannot download 'https://mirrors.fedoraproject.org/metalink?repo=updates-released-f25&arch=x86_64': Cannot prepare internal mirrorlist: Curl error (60): Peer certificate cannot be authenticated with given CA certificates for https://mirrors.fedoraproject.org/metalink?repo=updates-released-f25&arch=x86_64 [Peer's Certificate has expired.].
Errore: Failed to synchronize cache for repo 'updates'

The certificates expired and dnf refuses to work. To update the certificates, I simply installed with rpm the packages ca-certificates, p11-kit, p11-kit-trust, openssl and openssl-libs from the distro upgrades.

# rpm -Uvh http://www.nic.funet.fi/pub/mirrors/fedora.redhat.com/pub/fedora/linux/updates/25/x86_64/c/ca-certificates-2017.2.11-1.1.fc25.noarch.rpm \ http://www.nic.funet.fi/pub/mirrors/fedora.redhat.com/pub/fedora/linux/updates/25/x86_64/p/p11-kit-0.23.2-3.fc25.x86_64.rpm \ http://www.nic.funet.fi/pub/mirrors/fedora.redhat.com/pub/fedora/linux/updates/25/x86_64/p/p11-kit-trust-0.23.2-3.fc25.x86_64.rpm \
http://www.nic.funet.fi/pub/mirrors/fedora.redhat.com/pub/fedora/linux/updates/25/x86_64/o/openssl-1.0.2k-1.fc25.x86_64.rpm \ http://www.nic.funet.fi/pub/mirrors/fedora.redhat.com/pub/fedora/linux/updates/25/x86_64/o/openssl-libs-1.0.2k-1.fc25.x86_64.rpm
# dnf upgrade
Fedora 25 - x86_64 - Updates  
Fedora 25 - x86_64
Ultima verifica della scadenza dei metadati: 0:00:19 fa il Mon Apr 17 13:47:09 2017.
[...]

You might have to find the latest version by browsing around your favourite Fedora mirror (you can find the base url in /etc/yum.repos.d/fedora-updates.repo).

Some links worth reading:

PHP Sessions on MS Azure Redis service

I sure hope you’ll never end up facing this, but in case you do indeed have a PHP application on MS Azure, and you want to use MS Azure Redis service for the session backend, you’ll have to set your session.save_path to something like:

session.save_path='tcp://UNIQUENAME.redis.cache.windows.net:6379?auth=MSHATESYOU4FUNandPROFIT=&timeout=1&prefix=OHNOMS'

Easy enough, unless your auth key happens to contain a + symbol. In that case, your PHP session creation will fail with this error:

# php count.php
PHP Fatal error:  Uncaught exception 'RedisException' with message 'Failed to AUTH connection' in count.php:3
Stack trace:
#0 count.php(3): session_start()
#1 {main}
  thrown in count.php on line 3
PHP Fatal error:  Uncaught exception 'RedisException' with message 'Failed to AUTH connection' in [no active file]:0
Stack trace:
#0 {main}
  thrown in [no active file] on line 0

From redis-cli the authentication was working fine, so it took us a while to debug. It ended up being a problem with the + symbol, and the the quickest solution in our case was to just regen the auth key so it didn’t have a + in it, but I suspect (but I didn’t test this solution) that URLencoding the + as %2B might work as well.

Pane di farro mini-HOWTO

Questo mini-HOWTO spiega brevemente come fare il pane con la farina di farro.

Update: aggiornato il procedimento in seguito a successivi esperimenti! Ora il pane viene ancora più morbido!

Soddisfatto del mio 5° esperimento, voglio condividere con l’Internet la ricetta e le varie note d’interesse da tenere in mente.

La ricetta che ho seguito inizialmente prevede:

  • 300g di farina di farro (nel mio caso integrale, ma fate come vi pare)
  • 100g di farina bianca (tipo 00)
  • 250ml d’acqua tiepida
  • 3 o 4g di lievito di birra
  • uno o due cucchiaini di sale, secondo i gusti
  • un paio di cucchiai d’olio d’oliva

A questa lista, nell’ultimo esperimento ho provato ad aggiungere anche:

  • un cucchiaino di zucchero bianco

per favorire la lievitazione.

Strumenti necessari

  • contenitore graduato o bilancia per misurare sia la farina che l’acqua
  • contenitore per scaldare l’acqua (pentola o bollitore)
  • contenitore per lasciare il lievito ad “attivarsi” nell’acqua (una ciotolina grande abbastanza per contenere 250ml d’acqua)
  • scodella per impastare il pane (vedi note più avanti)
  • forno (eh)
  • teglia adatta al summenzionato forno
  • guanti da forno per maneggiare la teglia bollente
  • carta da forno
  • stoviglie varie: cucchiai, cucchiaini, coltelli, etc
  • un panno morbido e pulito (nel mio caso, di cotone)

Preparativi

La prima cosa da fare è mettere l’acqua a scaldare: non serve farla bollire, vi servirà tiepida, cioè più calda della temperatura ambiente, ma non abbastanza da scottarvi se ci mettete un dito dentro.

Mentre l’acqua si scalda, iniziate a misurare la farina.

Nota importante: non mettete via la farina dopo averla misurata! Quasi sicuramente ve ne servirà qualche altro pizzico durante la lavorazione.

Una volta che l’acqua è tiepida, mettetela in una ciotolina col lievito e un cucchiaino di zucchero, mescolate un po’ e lasciate il composto da parte: dopo qualche minuto dovrebbe fare una bella schiuma scura tipo quella della Guinness. Quello è il Segno[tm] che il lievito si è “attivato” correttamente.

Nota: l’acqua troppo fredda non “attiva” il lievito, mentre quella troppo calda lo uccide. Non esagerate in un senso o nell’altro!

Mentre aspettate che il lievito si attivi, mettete nella Scodella Per Impastare Il Pane tutta la farina e il sale, mischiateli bene e lasciate un buco al centro (la cosiddetta “fontanella”), dove più tardi verserete l’acqua col lievito.

Nota: la Scodella Per Impastare Il Pane è una scodella di acciaio inox piuttosto larga con il fondo in gomma per mantenerla ferma e attutire un po’ le botte sul tavolo durante la lavorazione dell’impasto. Geniale.

Scodella Per Impastare Il Pane

Nota: c’è chi dice di mettere il sale successivamente, perché può rallentare/diminuire la lievitazione. Non ho ancora verificato come si comporta l’impasto facendo in quel modo, ma mettendolo a questo punto, nella mia limitata esperienza non si sono verificati problemi.

L’impasto

Quando l’acqua col lievito ha sviluppato una bella schiuma, versatela nel “buco” lasciato in mezzo alla farina nella Scodella Per Impastare Il Pane.

Aggiungete un paio di cucchiai d’olio.

Nota importante: come detto per la farina, non mettete via l’olio, ve ne servirà ancora un goccio più avanti.

Iniziate a impastare. Personalmente vi consiglio di farlo con una sola mano a questo punto, perché l’altra potrà servirvi per aggiungere farina, se necessario, e pulire le mani sporche di impasto è piuttosto complicato.

L’impasto sarà inizialmente molto appiccicaticcio, ma si asciugherà rapidamente, man mano che assorbe tutta la farina. Se rimane troppo appiccicoso, aggiungete poca farina per volta mentre continuate a impastare.

Dopo un paio di minuti l’impasto dovrebbe avere la consistenza “giusta” e non dovrebbe più restare appiccicato alle mani o alla Scodella e potrete impastarlo con entrambe le mani per qualche minuto ancora, in modo che la pasta si compatti ancora meglio.

A questo punto potete coprire la Scodella con un panno e mettere l’impasto a lievitare per un’ora e mezza. Io l’ho messo nel forno (spento!).

Reimpasto e seconda lievitazione

Passata l’ora e mezza sarà il momento di recuperare l’impasto, lavorarlo ancora un po’ e prepararlo per la successiva infornatura.

Se tutto è andato bene, l’impasto dovrebbe essere raddoppiato (!) di volume. Se è rimasto più o meno uguale, potete stenderlo con un mattarello, aggiungere olio e rosmarino e fare delle gustose schiacciatine, ma il pane ve lo potete scordare.

Dovrete lavorare ancora un po’ l’impasto con entrambe le mani. Se è molto appiccicoso e difficile da staccare dalla Scodella Per Impastare Il Pane, potete aggiungere un po’ di farina per asciugarlo un po’.

Dopo averlo lavorato per qualche minuto, prendete abbastanza carta da forno da coprire il fondo della teglia, bagnatela con un po’ d’acqua (per renderla più maneggevole!) e disponetela sul fondo della teglia.

Versate un po’ d’olio d’oliva sulla carta da forno e spandetelo in uno strato sottile a coprire tutta l’area (potete aiutarvi con un pennellino o usare direttamente le dita).

Togliete l’impasto dalla Scodella Per Impastare Il Pane e disponetelo sulla teglia nel formato che vi è più congeniale… personalmente trovo che con questa quantità di farina abbia senso fare due o quattro “panetti”, tagliando l’impasto e facendoci delle palline. È possibile anche lasciare l’impasto tutto insieme per fare un singolo “pane”, ma ho trovato che è più difficile da cuocere correttamente.

Una volta posizionati i panetti sulla teglia, ricopritela e lasciateli ancora in forno solo con la luce accesa a lievitare per un’altra ora e mezza.

Infornare!

Terminata la seconda fase di lievitazione, togliete l’impasto dal forno e accendete quest’ultimo a 240° (o al massimo se il vostro a 240° non arriva).

Mentre aspettate che il forno si scaldi, scoprite l’impasto, che sarà di nuovo cresciuto, e praticate con un coltello alcuni tagli nella parte superiore (ad esempio il classico taglio “a croce”), che permetteranno al pane di crescere ancora durante la cottura senza rompersi.

Appena il forno è caldo, infornate!

Per la cottura, io mi sto trovando bene con 15 minuti a 230° (il massimo per il mio forno), per fare una crosta bella croccante e poi altri 20-25 minuti a 200°.

Al momento di sfornare potrete usare il panno di cui sopra per maneggiare il pane bollente e metterlo a riposare finché non raggiunge una temperatura adatta al palato :)

Riferimenti