2015년 3월 22일 일요일

Archlinux: Temporary workaround for xinit failure after upgrading to xorg-xinit 1.3.4-2

After updating my Archlinux system running kernel 3.19.2-1 with pacman -Syyu X windows' xinit refuses to start with the error "/dev/tty0 does not exist". Instead of startx, I invoke XFCE4 DE from the CLI with startxfce4. On Arch, you can browse recently-installed packages with the following:

tac /var/log/pacman.log | less

Among the xorg-related packages, I noticed xorg-xinit (1.3.4-1 -> 1.3.4-2) and xorg-fonts-misc (1.0.3-2 -> 1.0.3-3) had been upgraded in the most recent update. The fonts package probably isn't the cause of X refusing to start, so I tried downgrading xorg-xinit to 1.3.4-1 (first cd to the pacman package cache folder at /var/cache/pacman/pkg and then manually install the previous package version with pacman -U pkgName):

sudo pacman -U xorg-xinit-1.3.4-1-x86_64.pkg.tar.xz

With the previous xorg-xinit version, X Windows starts just fine. I haven't filed a bug report (to the Archlinux bug tracker or upstream) yet, but if the issue persists I will probably do so.

Postscript 2015-03-25:
Since I use the xfce4 Desktop Environment, xfce4-session must be upgraded to 4.12.1-2 in order for xorg-xinit 1.3.4-2 to work. The issue is now solved!

2015년 3월 19일 목요일

Review of LFCS Ubuntu exam taken on Feb. 28 2015 (Fri)



I am proud to announce that I am now a Linux Foundation Certified Sysadmin (LFCS-1500-0222-0100, last name Koh) . I took the exam on a VM with Ubuntu 14.04 installed and passed with a score of 86/100. Before March 1, 2015 the passing score was 65%, but after this date test takers need a score of 74% or better to achieve certification.

Below is a link to a gist containing an Emacs org-mode text file which I used to prepare for the exam:


Testing dates and times are quite convenient and numerous, but tests are not offered on the weekends (US Central Standard Time). I liked the fact that the current (as of March 2015) proctor Innovative Exams lists all testing dates in local time. I took the exam from the GMT + 9 time zone (Seoul / Tokyo), and the proctor scheduling system was able to take this into account.

Pre-test tasks

A few days before the exam, you will get an email from the proctor with a short confirmation code as well as basic info about the test. When you log into the exam site, you will be asked to provide this confirmation code by the human proctor.

Although the testing time itself is just 2 hours, it takes about 15~30 minutes for the proctor to verify your identity (you have to hold up official ID like a driver's license or passport in front of your webcam), make sure all plugins are installed in your browser, and check that screen sharing is working properly. Initially, screen sharing wasn't working, but after the proctor told me to reload the session, it worked just fine.

I took the test on a notebook with Archlinux installed (kernel 3.18.X) using XFCE4 desktop environment. I used the LF-recommended browser Chromium/Chrome. The proctor asked me to close all miscellaneous windows, close all browser tabs except for the exam session, and to also kill applets or programs running in the background such as dropbox and rescuetime. The proctor also asked me to show a list of running tasks, so I launched htop, which was fine. Finally, I was asked to use the webcam to pan around the room I was taking the test in. Because the proctor has access to your webcam and microphone, they can see and hear you for the duration of the test, but you are not supposed to talk to the proctor. You can only communicate through a chat window on the left side of the browser window.

Once the exam actually begins, the chat window gets minimized into a tab after 60 seconds of disuse allowing you to work in the VM full-screen. You will not be able to ALT-TAB out of the browser window.

The Exam

The test is divided into several sections, and a point value is indicated for each section as a whole. You aren't told, however, how many points each question within a section is worth. You can navigate between questions by clicking on special left and right arrows provided next to the VM window in the browser.

There weren't many surprises on the exam; if you diligently work through the topics provided in the syllabus for the LFCS exam (aka Overview of Domains and Competencies) and study a few of the topics in LFS 201 Essentials of Linux System Administration you should be able to pass the exam like I did. I also highly-recommend the free edX MOOC LFS101.2x Introduction to Linux for both those new to Linux and more experienced users/admins.

Although the final exam in LFS101.2x is much too easy, there is a lot of solid content that will help prepare you for the LFCS, in particular the material from chapters 8.4 backing up and compressing data10.2 Advanced editors vi and emacs, 13 Manipulating Text, 15 Bash Shell Scripting, 16 Advanced Bash Scripting.

I strongly recommend familiarizing yourself with vi/vim! Although I use Emacs as an IDE, terminal emulator, gpg frontend, irc client, etc., vi is almost always available when working on random servers in the field which is not true of Emacs. On the LFCS, knowing how to find/replace text within files is a must, and the commands for doing so are similar between sed and vi, so learning vi will also help you in other Linux/Unix utilities.

Make sure you know partition creation and LVM setup like the back of your hand using CLI-only tools. The VM you are provided with does not have X11 installed, so you have to do everything from the command-line so be prepared! You should know how to use fdisk, pvcreate, vgcreate, lvcreate, mkfs, etc. Before March 1, 2015 the LFCS also tested you on Linux SW RAID with mdadm, but now mdadm has been removed from the test.
Note -- you do NOT need to reboot the VM for it to detect newly-created LVM partitions. The relevant questions actually tell you to use the partprobe command to detect new volume groups and logical volumes without rebooting.

You should also be able to manage users and groups with usermod, groupadd, etc. and feel comfortable editing /etc/passwd

It is unnecessary for me to rehash the entire LFCS syllabus in this post, so just take a look at the LFCS syllabus for topics to review.

There were a few networking-related tasks that weren't on the syllabus that surprised me when they appeared on the exam. These questions were not difficult per se, and any sysadmin or engineer already working with Linux day-to-day should be able to solve them, but it might surprise test-takers with little-to-no experience of Linux networking commands.


Comparisons with RHCSA

As the LFCS is a lab practical-style exam similar to those from Red Hat, it is only natural to compare the two. One interesting thing to note is that at the end of February 2015, Red Hat discontinued RHCSA for RHEL 6.X (kernel 2.6.32...), so all tests are now based on RHEL 7.X (kernel 3.10...)

As some of you may already know, RHEL7/CentOS7 uses systemd instead of SysVinit and also has SELinux enabled by default. In contrast, as of the end of Feb 2015, the LFCS allows test takers the choice of getting certified on Ubuntu 14.04, CentOS 6.4, and OpenSUSE 13.1, but the first two don't use systemd and none has SELinux enabled by default. Of course, Ubuntu 15.04 and CentOS7 use systemd, so the LFCS will change in this respect as time goes on. 

The duration of both exams is similar, 2 hours for the actual exam, 30 minutes for pre-test setup. Red Hat certs are valid for 3 years, but the LF certs only last for 2. Also, there are pricing differentials by region. Here in South Korea, the RHCSA and RHCE exams cost 140,000 KRW (apprx $130) compared to $400 in the US, but the LFCS and LFCE cost $300 USD regardless of geographical location. These are just the superficial differences, however.

I am scheduled to take the RHCSA on March 27, 2015 after which I will post a detailed write-up of the differences I experienced between the LFCS and RHCSA.


Conclusion

In my opinion, the LFCS requires test takers to complete common tasks that would reasonably be expected of sysadmins. For those readers who currently work with Linux as sysadmins or system engineers, investing anywhere from 5~20 hours for review and preparation should be sufficient.

For those not using Linux in a professional capacity, I recommend taking edX LFS101.2x and scoring 100% on the final exam (I am not kidding; the exam is very easy and if you cannot get a perfect score on LFS101.2x you will have a hard time passing the LFCS exam) and perhaps taking LFS201 to fill in gaps in your knowledge. The Linux Foundation also offers shorter 1-day training courses such as LFS 202 LFCS Preparation which I reviewed in another post.

I think it's great that there now exists is a non-vendor-specific Linux certification modeled after Red Hat exams. Unless your company or clients use RHEL, you probably won't encounter SELinux, firewalld, etc. very often (in fact, most of the Korean telcos I work with disable SELinux on their development servers). Although I am more familiar with RHEL/CentOS than Ubuntu, I intentionally certified on Ubuntu 14.04 to familiarize myself with dpkg/apt package management and to prepare for the possibility that I might encounter Ubuntu servers in the field. 

Studying for the exam forced me to learn about a new distro and I hope that in time the Linux Foundation certs will become just as valued as those from Red Hat. If your company provides reimbursement for professional education and certification, I highly recommend getting LFCS/LFCE certified on Ubuntu or OpenSUSE to prove your knowledge of multiple Linux distros. If you want to test your CentOS knowledge, I think you should just take the RHCSA/RHCE.

2015년 3월 12일 목요일

mysql/mariadb supports utf-8 encoding within DB tables, but it doesn't support UTF-8 in /etc/my.cnf???

A few weeks ago, I installed RHEL 6.6 and MariaDB 10.X at a client site but had problems running a DB install script. The message I got was

found option without preceding group in config file /etc/my.cnf at line 1

A google search for this snippet turned up the following StackOverflow thread:

http://stackoverflow.com/questions/8020297/mysql-my-cnf-file-found-option-without-preceding-group

Apparently, the /etc/my.cnf config file for mysql/mariadb only supports ASCII! This was quite a shock, because I know UTF-8 support is now built-into both databases.

I verified that /etc/my.cnf was indeed encoded as UTF-8 text using the file utility:

$ file /etc/my.cnf
/etc/my.cnf: utf-8

To convert text within a file from one encoding to another, use the iconv utility:

iconv -c -f utf8 -t ascii /etc/my.cnf

Explanation of the option flags (from man iconv):
-c   silently discard chars that cannot be converted instead of terminating when encountering such chars

-f   from-encoding

-t   to-encoding

In 2015, virtually all POSIX programs get along just fine with UTF8, so why does mysql/mariadb have a problem with UTF8 in my.cnf? This bit of techno-trivia has now been added to my growing body Linux sysadmin lore, but this should issue should be fixed, in my opinion.

2015년 3월 2일 월요일

My first book translation is now in print! "Crossing Heaven's Border"

In Spring 2012, I was contacted by a South Korean newspaper reporter from The Chosun Ilbo about translating a book. As a freelance interpreter and translator from 2005-2014, I had done lots of one-off translations of thesis abstracts, short stories, ad copy, etc. but this was the first time I had the chance to translate a book.

The book's 1st edition title in Korean was "천국의 국경을 넘다" which became Crossing Heaven's Border in English. It was written by Hark Joon Lee, head of the Crossmedia Team at The Chosun Ilbo and also the director of a documentary about North Korean defectors. This book takes a closer look at events covered in the documentary and also follows up on the lives of North Korean refugees living in South Korea today.

I hear that the editing process in Korea and Japan is quite brief compared to that in the US and the UK; the Japanese edition of Crossing took less than 6 months to translate, edit and publish. For the US edition of Crossing..., however, contract negotiations, translation, editing and publishing took about 3 years. This is due to the fact that in Asia, editors basically just rubber-stamp the author's work, while in the US/UK, editors often revamp the entire book and go through the draft multiple times with a fine-toothed comb.

The editor for Crossing... was George Krompacky, Publications Manager of the Shorenstein Asia-Pacific Research Center at Stanford University. He did a great job of pointing out inconsistencies and errors in my translation drafts and his knowledge of Traditional Chinese was invaluable in deciphering the meaning of Sino-Korean words which I had mis-translated in places.

The author, Hark Joon Lee, was also very gracious in answering my questions about the original Korean text and answered my emails late at night and even on weekends. It seems like reporters check their email 24/7!

I enjoyed working on this book translation, and if I have the opportunity to do so, I hope to do more Korean to English book translations in the future.

2015년 2월 26일 목요일

Server Network Port Enumeration in RHEL5.X/6.X

Problem

Let's say you have three network cards plugged into your server's PCI expansion slots as well as four LOM (LAN On Motherboard) ports. The default port enumeration on the rear of the server is as follows:

LOM        PCI
===        ================
[3]        -[8 ]-[4]-[12]-
[2]        -[9 ]-[5]-[13]-
[1]        -[10]-[6]-[14]-
[0]        -[11]-[7]-[15]-
===        ================

You would like to change the port enumeration and set up bonding channels as follows:

LOM        PCI
===        ================
[15]        -[0]-[4]-[8 ]-   bond0: eth0,4
[14]        -[1]-[5]-[9 ]-   bond1: eth1,5
[13]        -[2]-[6]-[10]-   bond2: eth2,6
[12]        -[3]-[7]-[11]-   bond3: eth3,7
===        ================

In the days before RHEL 5.X (kernel 2.6.18.X) and RHEL 6.X (kernel 2.6.32.X) it was customary to explicitly assign network interface names (i.e. eth0, eth1, etc) to MAC addresses or UUID's in the files ifcfg-eth{0..N} in /etc/sysconfig/network-scripts/

For example, here is a sample ifcfg-eth0 that would work reliably pre-RHEL5.X/RHEL6.X:

DEVICE=eth0
ONBOOT=yes
BOOTPROTO=none
HWADDR= 00:1a:2b:3c:4d:5e
MASTER=bond0
SLAVE=yes
USERCTL=no

Regardless of the order in which network interfaces come up and make themselves known to the Linux kernel, since we have assigned the name eth0 to MAC 00:1a:2b:3c:4d:5e the interface will keep this name. If we had not explicitly mapped this HWADDR to eth0, it might for instance change to eth2 if it was the 3rd interface to come up on boot. Obviously port names that change with every boot would be a big headache.

Unfortunatelym explicitly mapping a MAC to a device name within ifcfg-ethX files is no longer guaranteed to work 100% of the time:
https://bugzilla.redhat.com/show_bug.cgi?id=491432


Solution

Because explicitly assigning HWADDR or UUID's to network device names within the files in /etc/sysconfig/network-scripts/ is not reliable, first we will comment out all lines starting with HWADDR or UUID within ifcfg-ethX files. Assuming there are 16 ports to be enumerated (0~15), you could achieve this with the following bash for-loop (assuming you are in the directory /etc/sysconfig/network-scripts):

for i in {0..15}; do
  sed -i "s/HWADDR/#HWADDR/g" ifcfg-eth$i
  sed -i "s/UUID/#UUID/g" ifcfg-eth$i
done

We will rely exclusively on /etc/udev/rules.d/70-persistent-net.rules to enumerate ports. The udev daemon reads from this file at boot to determine the device names for network ports. Within this file you can either map MAC addresses to ethX device names or PCI bus-info ID's to ethX device names.

Although it has historically been more common to use MAC addresses, I recommend using PCI bus-info ID's for device name mapping in 70-persistent-net.rules. When NIC's crash and you stop (start) the network with service network stop(start), two different device names using the same MAC can appear. For some reason, however, this same issue does not occur when using network cards' PCI bus-info ID's.

1. Find PCI bus-info ID's

You can find the PCI bus-info ID in several ways: from the kernel ring buffer with dmesg, from lspci or from ethtool -i. I will cover the latter two methods as they are easiest to parse.

# lspci -D | grep Solar
41:00.0 Ethernet controller: Solarflare Communications SFC9020 [Solarstorm]
41:00.1 Ethernet controller: Solarflare Communications SFC9020 [Solarstorm]

The -D flag makes sure that PCI bus numbers are printed. From man lscpi:
Always  show PCI domain numbers. By default, lspci suppresses them on machines which have only domain 0.
In the example above, I found the PCI bus-info ID's for two ports on a 10G Solarflare NIC. Since the first field from the above command will always show PCI bus-info, we can just print this field alone using awk `{print$1}`. We can print just the bus-info ID's for all Ethernet interfaces using the following commands:

lspci -D | grep -i ether | awk '{print$1}'

Note that the -i flag for grep above enables case-insensitive search.

On a machine with two 4-port NIC's plugged into PCI slots and with 3 onboard network ports the output of the above command might look something like the this:

0000:04:00.3
0000:04:00.2
0000:04:00.1
0000:04:00.0
0000:03:00.0
0000:03:00.1
0000:03:00.2
0000:03:00.3
0000:0d:04.2
0000:0d:04.1
0000:0d:04.0

You will notice that ports on the same NIC share the same PCI bus prefix, but differ only in the final number. Therefore we can deduce that 0000:04:00.{0..3} denote 4 ports on one particular PCI network card and that 0000:03:00.{0..3} denote 4 ports on a separate PCI NIC. Also notice that the 3 LOM (LAN On Motherboard) Ethernet ports have totally separate PCI bus-info ID's from the PCI NIC's. lspci | grep -i ether will print the NIC PCI bus ID's in order of network interface, so the first line would be eth0, second line eth1, and so on.

You can also obtain the PCI bus ID for each network port using ethtool -i ethX which returns the following fields:

driver: 
version:
firmware-version: 
bus-info:
supports-statistics:
supports-test:
supports-eeprom-access:
supports-register-dump:
supports-priv-flags:

Manually typing this command for each interface is not a good idea when you are working on a server with many network ports, so just use a bash for-loop one-liner:

for i in {0..n}; do ethtool -i eth$i; done


2. Map NIC port locations using ethtool -p ethX

In the problem statement at the beginning of this post, we assumed that you already knew the layout of device names to ports (i.e. eth0 is the bottom LOM port, eth12 is the top right-most NIC port). But if you're working on a brand-new server, how would you map out device name/port locations in the first place?

Thanks to ethtool -p ethX you can identify where each network port is located because this command will tell the port to flash it's status LED until the command is terminated. For the command to work, however, the network interface ethX must be up. To quickly put up all the Ethernet interfaces on a system, use the following bash for-loop one-liner (where N is the highest-numbered network port on your server):

for i in {0..N}; do ip link set eth$i up; done

It is better to use ip link set ... up from iproute2 rather than ifup from the venerable net-tools package because the first command is very fast; ifup is 8-10x slower because it tries to bind an IP to each interface when bringing it up, whereas ip link set ethX up simply activates the interface.

Once you have activated all Ethernet interfaces, you can use ethtool -p ethX , pencil and paper to write down the location of each port when it flashes. (Note that some LOM ports do not support ethtool -p)


3. Map PCI bus-info ID to network ifaces in 70-persistent-net.rules

The format for entries in /etc/udev/rules.d/70-persistent-net.rules for RHEL6.X using PCI bus ID's instead of MAC addresses is as follows:

SUBSYSTEM=="net",ACTION=="add",BUS=="pci",KERNEL=="eth*",KERNELS=="0000:01:00.0",NAME="ethX"
...
where ethX is eth0, eth1, etc.

In step 2, you should have found the PCI bus ID for each network port. To change the name of a given port, simply assign a different name to the line containing the relevant PCI bus ID number. The PCI bus-info ID should be entered between double quotes after KERNELS=

RHEL6.X initially generates /etc/udev/rules.d/70-persistent-net.rules automatically from the udev rule /lib/udev/rules.d/75-persistent-net-generator.rules but the network ifaces will not be nicely ordered in the file. By default this file will contain MAC addresses mapped to port names and will look something like this:

SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="40:a8:f0:3b:a1:c6", ATTR{type}=="1", KERNEL=="eth*", NAME="eth6"$
$
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="40:a8:f0:3b:a1:c7", ATTR{type}=="1", KERNEL=="eth*", NAME="eth7"$
$
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="28:80:23:a2:d7:c0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"$
$
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="40:a8:f0:3b:a1:c5", ATTR{type}=="1", KERNEL=="eth*", NAME="eth5"$
$
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="28:80:23:a2:d7:c2", ATTR{type}=="1", KERNEL=="eth*", NAME="eth2"$
$
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="28:80:23:a2:d7:c1", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"$
$
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="28:80:23:a2:d7:c3", ATTR{type}=="1", KERNEL=="eth*", NAME="eth3"$
$
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="40:a8:f0:3b:a1:c4", ATTR{type}=="1", KERNEL=="eth*", NAME="eth4"

This is inconvenient because eth6, not eth0, is on the first line, so when we change the port names, it is easy to get confused. It is apparent that the field separator character is comma "," and that the field we wish to sort in ascending order is field 7, "NAME". We can achieve this using the GNU coreutils program sort:

sort -t ',' -k7 -V 70-persistent-net.rules

where -t is the delimiter character, -k7 is for sorting based on the 7th column, and -V (--version-sort) sorts version numbers within text (of the form string+number). Without the -V flag, eth10, eth11 ... would follow eth1 instead of eth9.

If we now look at 70-persistent-net.rules we can see that the file is nicely sorted in ascending order of network ports:

SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="28:80:23:a2:d7:c0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="28:80:23:a2:d7:c1", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="28:80:23:a2:d7:c2", ATTR{type}=="1", KERNEL=="eth*", NAME="eth2"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="28:80:23:a2:d7:c3", ATTR{type}=="1", KERNEL=="eth*", NAME="eth3"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="40:a8:f0:3b:a1:c4", ATTR{type}=="1", KERNEL=="eth*", NAME="eth4"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="40:a8:f0:3b:a1:c5", ATTR{type}=="1", KERNEL=="eth*", NAME="eth5"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="40:a8:f0:3b:a1:c6", ATTR{type}=="1", KERNEL=="eth*", NAME="eth6"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="40:a8:f0:3b:a1:c7", ATTR{type}=="1", KERNEL=="eth*", NAME="eth7"

Now you have to replace the fields DRIVERS, ATTR, ATTR with the fields BUS and KERNELS and then paste in PCI bus ID's you obtained earlier through lspci -D | grep -i ether or ethtool -i ethX.

For RHEL5.X, however, the key KERNELS is not recognized by udev. You must use the key ID instead (RHEL6.X understands both the keys KERNELS and ID, however):

SUBSYSTEM=="net",ACTION=="add",BUS=="pci",KERNEL=="eth*",ID=="0000:04:00.0",NAME="eth7"
SUBSYSTEM=="net",ACTION=="add",BUS=="pci",KERNEL=="eth*",ID=="0000:04:00.1",NAME="eth6"
SUBSYSTEM=="net",ACTION=="add",BUS=="pci",KERNEL=="eth*",ID=="0000:04:00.2",NAME="eth5"
SUBSYSTEM=="net",ACTION=="add",BUS=="pci",KERNEL=="eth*",ID=="0000:04:00.3",NAME="eth4"
SUBSYSTEM=="net",ACTION=="add",BUS=="pci",KERNEL=="eth*",ID=="0000:03:00.0",NAME="eth0"
SUBSYSTEM=="net",ACTION=="add",BUS=="pci",KERNEL=="eth*",ID=="0000:03:00.1",NAME="eth1"
SUBSYSTEM=="net",ACTION=="add",BUS=="pci",KERNEL=="eth*",ID=="0000:03:00.2",NAME="eth2"
SUBSYSTEM=="net",ACTION=="add",BUS=="pci",KERNEL=="eth*",ID=="0000:03:00.3",NAME="eth3"

(Note that the network ifaces above in 70-persistent-net.rules are not sorted anymore because we have customized the port enumerations.)

Also when creating a port enumeration file for RHEL/CentOS 5.X, beware of existing port enumeration files in /etc/udev/rules.d/

Sometimes a file named 60-net.rules exists in this path in lieu of 70-persistent-net.rules, so if another udev rule file enumerating ports exists, edit that existing file instead of creating a new 70-persistent-net.rules!

For some reason, ATCA blade servers (from Emerson Network Power, Adlink, etc) will accept a shortened format for 70-persistent-net.rules that only contains the fields KERNEL, ID (for RHEL5.X) and NAME as follows:

KERNEL=="eth*", ID=="0000:07:00.0", NAME="ethX"

Note that this format only seems to work for ATCA (Advanced Telecom Computing Architecture) hardware. If you try this on HP Proliant machines, for example, /var/log/messages will complain of invalid udev rules.


4. Apply changes

First shut down network services:

service network stop

Unload all network drivers (this step is not always necessary, but it is good to get into the habit; you can find the network drivers being used by each iface using ethtool -i ethX)

modprobe -r driverName (tg3, igp, bnx, ixgbe, e1000e etc)
...

Note that if your machine uses Solarflare 10G cards, you cannot just remove the driver sfc with modprobe -r or rmmod; You must use a special script called onload_tool provided by Solarflare. From the directory containing the Solarflare scripts:

./onload_tool unload (without any arguments)

To reload the sfc driver , simply replace unload with reload.

Unload bonding module (if you have bonding channels defined in /etc/sysconfig/network-scripts)

modprobe -r bonding

Reload the kernel modules you just removed

modprobe drivername
modprobe bonding
...

Reload udev rules to apply the changes in 70-persistent-net.rules

start_udev
(or udevadm control --reload-rules)

Start network services

service network start

Verify with ethtool -p ethX that your network port enumerations have taken effect.

2015년 2월 20일 금요일

Latest pyglet 1.2 update breaks Brainworkshop - WORKAROUND

I upgraded Archlinux package python2-pyglet to version 1.2.0 from 1.1.4-2 on Feb. 19th:

[archjun@lenovoS310 log]$ tail pacman.log -n 30 |grep pyglet
[2015-02-19 19:10] [ALPM] upgraded python2-pyglet (1.1.4-2 -> 1.2.0-1)

Brainworkshop 4.8.4 gives the following error:

Traceback (most recent call last):
  File "/usr/share/brainworkshop/brainworkshop.pyw", line 4586, in
    updateLabel = UpdateLabel()
  File "/usr/share/brainworkshop/brainworkshop.pyw", line 2523, in __init__Postscript 2015-10-11
    anchor_x='center', anchor_y='center', batch=batch)
TypeError: __init__() got an unexpected keyword argument 'halign'

Looking at the the dunder function __init__() at around line 2523 reveals the following:


According to the pyglet.text.Label online documentation the halign keyword exists and is defined as follows:
Horizontal alignment of text on a line, only applies if a width is supplied. One of "left""center" or "right".
Perhaps the documentation only applies to versions < pyglet 1.2, because simply deleting the reference to halign in the code snippet above allows Brainworkshop to load without any errors.

Postscript 2015-12-20

This problem will occur if you have a recent version (> 1.2.0) of python2 pyglet installed on your system which will take precedence over the version of pyglet that is bundled in the Brainworkshop zip archive downloaded from Sourceforge. When using the pyglet files bundled in the BW zip, the program will run with halign = 'middle', halign = 'center' or even when halign is removed entirely.

I don't think it's a good idea to bundle pyglet with the Brainworkshop source, however. Better to tell users that pyglet is a dependency of BW and have them install it themselves; of course by bundling pyglet with the source, the developer can pin BW to a specific version of pyglet to avoid breakage in BW due to changes upstream. But this is a stopgap measure.

2015년 2월 12일 목요일

Notes on connecting to systems using a serial console cable

In my day job, I sometimes encounter ATCA hardware that doesn't have any external video ports. In these cases, I have to connect to the machine using a USB to RS232 serial console cable with DB9 connectors like the one pictured below:



along with a DB9 to RJ45 Cisco serial console cable:



The RJ45 end of the Cisco cable plugs into the ATCA serial console port.

Below are some tips for connecting to machines using serial console cables from a Linux host.


1. Verify that your Linux host is correctly detecting your USB-to-Serial device

First, check the output of journalctl -f (systemd) or tail -f /var/log/messages (non-systemd) and make sure that something like the following appears once you connect your USB-to-Serial cable:

[root@localhost ~]# journalctl -f
-- Logs begin at Wed 2014-12-17 16:39:00 KST. --
...
Dec 17 17:26:17 localhost.localdomain kernel: usb 2-3: new high-speed USB device number 8 using xhci_hcd
Dec 17 17:26:17 localhost.localdomain kernel: usb 2-3: New USB device found, idVendor=0403, idProduct=6010
Dec 17 17:26:17 localhost.localdomain kernel: usb 2-3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
Dec 17 17:26:17 localhost.localdomain kernel: usb 2-3: Product: Dual RS232-HS
Dec 17 17:26:17 localhost.localdomain kernel: usb 2-3: Manufacturer: FTDI
Dec 17 17:26:17 localhost.localdomain mtp-probe[10169]: checking bus 2, device 8: "/sys/devices/pci0000:00/0000:00:14.0/usb2/2-3"
Dec 17 17:26:17 localhost.localdomain mtp-probe[10169]: bus: 2, device: 8 was not an MTP device
Dec 17 17:26:17 localhost.localdomain kernel: usbcore: registered new interface driver ftdi_sio
Dec 17 17:26:17 localhost.localdomain kernel: usbserial: USB Serial support registered for FTDI USB Serial Device
Dec 17 17:26:17 localhost.localdomain kernel: ftdi_sio 2-3:1.0: FTDI USB Serial Device converter detected
Dec 17 17:26:17 localhost.localdomain kernel: usb 2-3: Detected FT2232H
Dec 17 17:26:17 localhost.localdomain kernel: usb 2-3: Number of endpoints 2
Dec 17 17:26:17 localhost.localdomain kernel: usb 2-3: Endpoint 1 MaxPacketSize 512
Dec 17 17:26:17 localhost.localdomain kernel: usb 2-3: Endpoint 2 MaxPacketSize 512
Dec 17 17:26:17 localhost.localdomain kernel: usb 2-3: Setting MaxPacketSize 512
Dec 17 17:26:17 localhost.localdomain kernel: usb 2-3: FTDI USB Serial Device converter now attached to ttyUSB0
Dec 17 17:26:17 localhost.localdomain kernel: ftdi_sio 2-3:1.1: FTDI USB Serial Device converter detected
Dec 17 17:26:17 localhost.localdomain kernel: usb 2-3: Detected FT2232H
Dec 17 17:26:17 localhost.localdomain kernel: usb 2-3: Number of endpoints 2
Dec 17 17:26:17 localhost.localdomain kernel: usb 2-3: Endpoint 1 MaxPacketSize 512
Dec 17 17:26:17 localhost.localdomain kernel: usb 2-3: Endpoint 2 MaxPacketSize 512
Dec 17 17:26:17 localhost.localdomain kernel: usb 2-3: Setting MaxPacketSize 512
Dec 17 17:26:17 localhost.localdomain kernel: usb 2-3: FTDI USB Serial Device converter now attached to ttyUSB1
...

In my case, since my USB-to-Serial cable has two connectors, my host has allocated /dev/ttyUSB0 and /dev/ttyUSB1 to each of the DB9 interfaces. We can verify this by looking at /sys/class/tty below:

[centipete@localhost ~]$ ls /sys/class/tty
console  tty1   tty13  tty17  tty20  tty24  tty28  tty31  tty35  tty39  tty42  tty46  tty5   tty53  tty57  tty60  tty7   ttyS1    ttyUSB1
ptmx     tty10  tty14  tty18  tty21  tty25  tty29  tty32  tty36  tty4   tty43  tty47  tty50  tty54  tty58  tty61  tty8   ttyS2
tty      tty11  tty15  tty19  tty22  tty26  tty3   tty33  tty37  tty40  tty44  tty48  tty51  tty55  tty59  tty62  tty9   ttyS3
tty0     tty12  tty16  tty2   tty23  tty27  tty30  tty34  tty38  tty41  tty45  tty49  tty52  tty56  tty6   tty63  ttyS0  ttyUSB0

To find the driver being used by the USB-to-Serial interface, let's take a look at the output of dmesg shortly after connecting the console cable:

[centipete@localhost ~]$ sudo dmesg |tail -n 20
[sudo] password for centipete:
[ 2836.672274] usb 2-3: New USB device found, idVendor=0403, idProduct=6010
[ 2836.672280] usb 2-3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 2836.672283] usb 2-3: Product: Dual RS232-HS
[ 2836.672285] usb 2-3: Manufacturer: FTDI
[ 2836.808456] usbcore: registered new interface driver ftdi_sio
[ 2836.808481] usbserial: USB Serial support registered for FTDI USB Serial Device
[ 2836.808536] ftdi_sio 2-3:1.0: FTDI USB Serial Device converter detected
[ 2836.808570] usb 2-3: Detected FT2232H
[ 2836.808572] usb 2-3: Number of endpoints 2
[ 2836.808574] usb 2-3: Endpoint 1 MaxPacketSize 512
[ 2836.808575] usb 2-3: Endpoint 2 MaxPacketSize 512
[ 2836.808576] usb 2-3: Setting MaxPacketSize 512
[ 2836.808693] usb 2-3: FTDI USB Serial Device converter now attached to ttyUSB0
[ 2836.808711] ftdi_sio 2-3:1.1: FTDI USB Serial Device converter detected
[ 2836.808746] usb 2-3: Detected FT2232H
[ 2836.808749] usb 2-3: Number of endpoints 2
[ 2836.808751] usb 2-3: Endpoint 1 MaxPacketSize 512
[ 2836.808753] usb 2-3: Endpoint 2 MaxPacketSize 512
[ 2836.808755] usb 2-3: Setting MaxPacketSize 512
[ 2836.810205] usb 2-3: FTDI USB Serial Device converter now attached to ttyUSB1

Using lsmod, let's make sure that this driver has been loaded by the kernel:

[centipete@localhost ~]$ lsmod |grep ftdi
ftdi_sio               48889  0

We could also look at the output of lsusb to verify that the USB-to-serial cable is connected, but this is unnecessary because we already know that the kernel has detected it and loaded the proper driver.


2. Connect to the remote machine using a serial communications program

Most of my fellow engineers at Growin use minicom, but putty and GNU Screen also work just fine.

Minicom
If you decide to use minicom, invoke it with minicom -s (--setup) and set the proper console speed. For ATCA machines, it is usually either 57600 or 115200 bps, but you should just use the speed the ATCA hardware engineer tells you to use (the console speed can be set in the ATCA BIOS).

In more recent versions of minicom (version 2.7-1 is installed on my machine as of 2015-02-12) you can access the options menu by pressing 'Ctrl-a' followed by 'z'. Make sure the terminal emulation (option 't') is set to ANSI (VT100), not VT102. For some reason, my default setting was VT102 and even with the correct speed setting, minicom just showed gibberish until I changed to VT100.

minicom may be overkill for what you are trying to do, however, and it is also finicky.

Putty
If you use Putty, you are asked to enter the speed settings and other comm parameters before connecting. On the left-hand scroll menu, select 'Serial' at the very bottom and enter the correct parameters in the following window:



If you are using a USB to Serial cable, don't forget to change the serial interface name to /dev/ttyUSB0 or whatever your kernel decides to name it.

GNU Screen
By far the easiest way to connect to another machine by serial console cable is screen. At first, I assumed tmux would also have this feature, but it does not, as its developer thinks such a function would be feature bloat. Thankfully, screen supports serial console connections and it is as easy as invoking the following:

[archjun@lenovoS310 ~]$ sudo screen /dev/ttyUSB0 57600

That's it! No fiddling with flow control, parity, etc. It just works as long as you specify the interface name /dev/tty... and the console speed in bps. I only recently learned that screen has this awesome feature while watching Canonical's Dustin Kirkland connecting to a BeagleBone ARM board using a USB-to-TTL serial console cable. In the Youtube video below at 4:34, Dustin uses screen to connect to the BeagleBone by invoking

sudo screen /dev/ttyUSB0 115200


There are other serial communication programs you can use (on Windows there are a variety of commercial programs like XShell, SecureCRT, etc) but I find GNU Screen to be the simplest way to connect to a serial console!