Qpid on CentOS 5

Build using Fedora

  1. Install the RPM development tools

    sudo yum install rpmdevtools mock
    
  2. Add yourself to the mock group

    sudo /usr/sbin/usermod --groups mock --append $USER
    
  3. Setup build directories

    rpmdev-setuptree
    
  4. Install spec and source files (or get latest here)

    rpm -i ftp://ftp.redhat.com/pub/redhat/linux/enterprise/5Server/en/RHEMRG/SRPMS/qpidc-0.5.752581-17.el5.src.rpm
    rpm -i ftp://ftp.redhat.com/pub/redhat/linux/enterprise/5Server/en/RHEMRG/SRPMS/amqp-1.0.750054-1.el5.src.rpm
    rpm -i ftp://ftp.redhat.com/pub/redhat/linux/enterprise/5Server/en/RHEMRG/SRPMS/python-qpid-0.5.752581-3.el5.src.rpm
    
  5. Build qpidc

    rpmbuild -bs --nodeps ~/rpmbuild/SRPM/qpidc.spec
    mock -vr epel-5-x86_64 ~/rpmbuild/SRPMS/qpidc-*.src.rpm
    scp /var/lib/mock/epel-5-x86_64/result/*.rpm CENTOS_HOST:SOME_PATH
    
  6. Build amqp

    rpmbuild -bs --nodeps ~/rpmbuild/SPECS/amqp.spec
    mock -vr epel-5-x86_64 ~/rpmbuild/SRPMS/amqp-*.src.rpm
    scp /var/lib/mock/epel-5-x86_64/result/*.rpm CENTOS_HOST:SOME_PATH
    
  7. Build python-qpid

    rpmbuild -bs --nodeps ~/rpmbuild/SPECS/python-qpid.spec
    mock -vr epel-5-x86_64 ~/rpmbuild/SRPMS/python-qpid-*.src.rpm
    scp /var/lib/mock/epel-5-x86_64/result/*.rpm CENTOS_HOST:SOME_PATH
    

Install on CentOS

  1. Become root

    sudo su -
    
  2. Install Qpid server and Python client packages

    cd SOME_PATH
    yum localinstall --nogpgcheck qpidc-*.el5.x86_64.rpm qpidd-*.el5.x86_64.rpm amqp-*.el5.noarch.rpm python-qpid-*.el5.noarch.rpm
    
  3. Disable auth for testing

    echo 'auth=no' >> /etc/qpidd.conf
    
  4. Start qpidd

    service qpidd start
    
  5. Test using these instructions.

NOTE: I realize you can build the SRPMs without installing them.

Pipe Apache (or any) Logs to Scribe

I created a simple Python script called scribe_log to tail a log file and pipe it to Scribe.

I use supervisor to start and keep the pipe running.

Relevant supervisord.conf configuration:

[program:scribe.apache.access]
command=/usr/local/sbin/scribe_log --category apache.access --file /var/log/httpd/access_log

Options

usage: scribe_log [options]

options:
  -h, --help           show this help message and exit
  --file=FILE          file to tail into Scribe
  --category=CATEGORY  Scribe category
  --host=HOST          destination Scribe host server
  --port=PORT          destination Scribe port
  --prefix=PREFIX      add to the beginning of each log line
  --postfix=POSTFIX    add to the end of each log line

Scribe – Scalable Real Time Log Aggregation for CentOS 5 / RHEL 5

"Scribe is a server for aggregating log data streamed in real time from a large number of servers. It is designed to be scalable, extensible without client-side modification, and robust to failure of the network or any specific machine. Scribe was developed at Facebook and released as open source."

I've packaged Thrift, fb303 and Scribe for CentOS 5 / RHEL 5.

SRPM

Scribe depends on fb303 which in turns depends on Thrift so you'll need to setup a local repository and build them in that order. To build the above packages for Fedora 9+ you'll need to tweak the Python sub-packages to include the egg files.

Both fb303 and Scribe need some tweaks upstream before they're suitable for a package review, but I'd like to get them in Fedora shortly (I've already submitted Thrift).

If you'd like to hack around with my latest Fedora specs you can grab them here.

Managing Large Networks with Puppet

Puppet is an open source configuration management tool written in Ruby. It allows a systems administrator to define how a system should be configured using Puppet's declarative language. Each Puppet client pulls its catalog at a regular interval and figures out how to make the catalog definitions true for the local operating system.

The Puppet Introduction uses the following diagram to show how Puppet works.

Puppet

Currently Puppet is most useful when you have lots of nodes with similar setups. Unfortunately Puppet's declarative language is a bit weak when it comes to inheritance and users familiar with true object oriented systems will soon become frustrated (at least I did). I'm assuming this issue will be addressed in the future, but for now I'm going to tell you how I setup a 100+ node system while adhering to DRY principles.

A quick note, I'm assuming you already know how to use Puppet.

First lets start with the Puppetmaster configuration layout:

puppet/
 - fileserver.conf
 - manifests/
   - classes/
     - initialize.pp
   - nodes/
     - net/
       - example/
         - web01.pp   # web01.example.net
   - site.pp
   - templates.pp
 - modules/           # application specific modules
   - httpd/
     - files/         # static assets (ex: default HTML file)
     - manifests/     # application configuration logic
     - templates/     # dynamic configuration files (ex: httpd.conf)

The layout was adapted from recommendations in Pulling Strings with Puppet by James Turnbull.

When I was initially designing my Puppet setup the common practice was to define and initialize the various Puppet types and classes throughout the inheritance tree. So if you had a generic resolv.conf configuration you would include it at the top of the inheritance tree. This worked great until I needed to change one attribute of a class further down. I initially tackled this problem by hacking in if/case statements, but eventually it became unmanageable.

After a couple of rewrites I came up with the idea of wrapping the internals of each class in a conditional statement and initializing all classes at the end of each node.

The key components of my setup were:

  • import all modules in the site.pp manifest
  • wrap the code of each class in a conditional statement
  • define and extend attributes throughout the inheritance tree (including the class conditional)
  • include all classes at the end of each node

This lets you both arbitrarily redefine or extend class attributes (including the on/off state) throughout the inheritance tree.

I've created a simple example to show how this setup works. The main files are listed below (you'll want to go through each in order):

Also note that I designed this setup about 8 months ago and I haven't kept as up-to-date on recent developments as I should. If there is a better way to do this please let me know.

funcshell — A Shell Interface to Func

Features

  • advanced client selection (you can use + and - to add/remove hosts/groups)
  • tab completion
  • persistent history
  • a command sub-shell
  • quick help (just hit the "?" key)

funcshell took a similar approach to features as Func; it allows developers to easily extend and customize its functionality using a plugin system. It also assumes the most useful commands will be the ones you write yourself. That being said, funcshell currently comes with both the command and service module.

Here are some things you can do with funcshell.

Get a list of all clients (not very useful if you have hundreds):

funcshell> set clients *
funcshell> get clients
webapp001.example.net
webapp002.example.net
webapp003.example.net
webstatic001.example.net
webstatic002.example.net

Assuming webapp00[1-3].example.net are in the app and bpstatic00[1-2].example.net1 are in the static groups; remove some clients and restart a service:

funcshell> set clients - @static;webapp001*
funcshell> get clients
webapp002.example.net
webapp003.example.net
funcshell> service httpd restart
==> webapp003.example.net <==
True
==> webapp002.example.net <==
True

Run a command and get the results:

funcshell> set clients - webapp003*
funcshell> set clients + webstatic002*
funcshell> command run grep MemTotal /proc/meminfo | awk '{ print $2/1024 }'
==> webstatic002.example.net :: 0 <==
4099.44
==> webapp002.example.net :: 0 <==
8198.88

Get help:

funcshell> command <TAB><TAB>
exists   run      shell
funcshell> command ?
  exists Check if a command exists
  run    Run a command
  shell  Run a command shell

Run a couple of commands in a row:

funcshell> set c<TAB> @static
funcshell> command shell
> du -sh /tmp
==> webstatic002.example.net :: 0 <==
7.2M    /tmp
==> webstatic001.example.net :: 0 <==
3.4M    /tmp
> cp -r /tmp /tmp
==> webstatic002.example.net :: 1 <==
cp: cannot copy a directory, '/tmp', into itself, '/tmp/tmp'
==> webstatic001.example.net :: 1 <==
cp: cannot copy a directory, '/tmp', into itself, '/tmp/tmp'
> asdf
==> webstatic002.example.net :: 127 <==
/bin/sh: asdf: command not found
==> webstatic001.example.net :: 127 <==
/bin/sh: asdf: command not found
> <CTRL-D>
funcshell> exit

funcshell is a shell interface to Func which provides some useful features for managing a large number of machines.

String Slicing in Bash (like Python)

A simple function to slice strings in Bash similar to Python's string slicing functionality.

Examples

[silas@pluto ~]$ string_slice "12345" 0 1
1
[silas@pluto ~]$ string_slice "12345" 0 3
123
[silas@pluto ~]$ string_slice "12345" 2 3
3
[silas@pluto ~]$ string_slice "12345" 2 -2
3
[silas@pluto ~]$ string_slice "12345" -3
345

Implementation

function string_slice {
    STRING="$1"
    declare -i LENGTH="${#STRING}"
    declare -i START="$2"
    declare -i END="$3"
    if [ $START -lt 0 ]; then
        START=$[ $LENGTH + $START ]
    fi
    if [ $END -le 0 ]; then
        END=$[ $LENGTH + $END ]
    fi
    START=$[ $START + 1 ]
    (echo "$STRING" | cut -c $START-$END) 2> /dev/null
}

Profile Management with Git and GitHub

The following describes a simple way to manage you profile configuration files using GitHub.

Features

  • Centralized configuration management
  • Files live in their native locations (no symbolic linking)
  • Home directory is not a Git repository
  • All the power of git with a simple alias

Setup Repository

  • Log into GitHub and create a repository named config
  • Add your public keys to GitHub (if you haven't done so already)
  • Open a terminal and switch to your home directory

    cd ~
    
  • Create a configuration directory

    mkdir .config.git
    
  • Add the following alias to your current session and your .bash_profile

    alias config='git --git-dir=$HOME/.config.git/ --work-tree=$HOME'
    echo "alias config='git --git-dir=$HOME/.config.git/ --work-tree=$HOME'" >> .bash_profile
    
  • Add your .bash_profile to the configuration repository

    config add .bash_profile
    
  • Commit the changes

    config commit -m 'Initial commit'
    
  • Change the origin to GitHub

    config remote add origin git@github.com:GITHUB_USERNAME/config.git
    
  • Push the changes

    config push origin master
    

If you get an error when running config pull to the effect of You asked me to pull without... run the follow:

    echo -e '[branch "master"]\n  remote = origin\n  merge = refs/heads/master' >> ~/.config.git/config

Setup Configuration Management on a Different System

  1. Add your public keys to GitHub (if you haven't done so already)
  2. Switch to your home directory

    cd ~
    
  3. Backup your local configuration files, example:

    mv .bash_profile .bash_profile.bk
    
  4. Clone your configuration repository

    git clone git@github.com:GITHUB_USERNAME/config.git config.git
    
  5. Move the git metadata to ~/.config.git

    mv config.git/.git .config.git
    
  6. Enable dotglob

    shopt -s dotglob
    
  7. Move your configuration files to your home directory

    mv -i config.git/* .
    
  8. Delete the config.git directory

    rmdir config.git
    
  9. Logout and log back in

Basic Usage

  • config pull - get latest configuration changes
  • config add FILENAME - add a configuration file
  • config commit -a - save all configuration changes
  • config push - push configuration changes to GitHub
  • and any other config GIT_OPTION

You can see my configuration repository at http://github.com/silas/config.

Source: Manage your $HOME with git by Robert Escriva

Upgrade the Android Developer Phone (ADP) to RC33 Manually

Please note that you will lose all data on your phone when performing these steps.

  • Mount the ADP MicroSD card
  • Download hboot-0.95.0000.zip to the mount and rename it to update.zip
  • Unmount the card and shutdown the phone (unplug the USB cable if connected)
  • Hold Home+Power to boot
  • When prompted press Alt+S and wait for the update to finish
  • Press Home+Back to reboot and wait for second update to finish and boot into the Android recovery system
  • Press Home+Back to reboot again
  • Mount the MicroSD card
  • Delete update.zip
  • Download signed-holiday_devphone-ota-130444-debug.55489994.zip to the mount and rename it to update.zip
  • Unmount the card and shutdown the phone
  • Hold Home+Power to boot
  • Press Alt+S to update and wait for update to finish
  • Press Home+Back to reboot and wait for the second update to finish and boot into the Android system recovery utility
  • Press Alt+W to wipe all data
  • Press Home+Back to reboot and wait for the reboot to finish (this could take a couple of minutes)
  • Re-setup the ADP (hint: press menu to setup custom APN settings)

Introducing the FuncShell

Update: I am currently refactoring FuncShell; please use the following code: shell.py.

I created funcshell for running Func modules in a more intuitive manner.

The current implementation only supports the command module, but more will be released shortly.

Code: http://github.com/silas/funcshell

Example Usage

[root@pluto ~]# python shell.py
fs> use web*.example.org
fs> get hosts
web01.example.org
web02.example.org
fs> !du -sh /tmp
================================================================================
== web02.example.org                                                          ==
================================================================================

236K    /tmp

================================================================================
== web01.example.org                                                          ==
================================================================================

217M    /tmp

fs> !cat /proc/meminfo | grep MemTotal | awk '{ print $2 }'
================================================================================
== web02.example.org                                                          ==
================================================================================

1027116

================================================================================
== web01.example.org                                                          ==
================================================================================

1027116

fs> exit
[root@pluto ~]#

IPython + Python: Single Bash Command

The following is a simple Bash function you can paste into your bashrc file to start Python/IPython depending on the context.

~/.bashrc

function python {
    IPYTHON="/usr/bin/ipython"
    PYTHON="/usr/bin/python"

    if [[ -n $1 ]]; then
        $PYTHON $@
    elif [[ -e $IPYTHON ]]; then
        $IPYTHON
    else
        $PYTHON
    fi
}