Wednesday, April 28, 2010

Using x3270if commands against s3270 without calling a script

Recently I needed to start playing around with automating SLES installs on IBM z Series mainframe guests.  I needed to be able to have a script be able to send commands to the guest thorugh a 3270 terminal.  I found s3270 which starts a 3270 terminal that can then be passed commands via a script to be ran against the guest.  This was good but I ran into a limitation that I had to open s3270 and then tell it to run a script that contained what I wanted to due.  This was limiting because I wanted the script to be more dynamic in asking for username/passwords/ips/etc and monitoring output with expect to work through different scenarios.

This initially led me to develop multiple shell and expect scripts that called eachother passing arguments between eachother that was received from a 'master' script.  This is very ugly though codewise and also that you could see entered passwords via 'ps' because I was passing it as an argument to other scripts.

To get around my issues I needed to:
  • Use 1 script
  • Have script start s3270 and be able to pass commands to it (not have s3270 call a script)
  • have expect functionality
First I figured out how to pass commands to s3270 instead of having s3270 call a script with a list of commands.  This was done be creating 2 FIFOs and redirecting stdin and stdout to those FIFOs when starting s3270:
mkfifo /tmp/3270.in /tmp/3270.out
s3270 /tmp/3270.out &
I also backgorunded the s3270 process because otherwise you are stuck in s3270 to enter commands for it.

I then created filedescripors that copied my FIFOs:
exec 5>/tmp/3270.in 6
rm -f /tmp/3270.in /tmp/3270.out
Now I set 2 enviornment variables that x3270if uses to know what filedescriptors to use when communicating with an s3270 process:
X3270INPUT=5
X3270OUTPUT=6
export X3270INPUT X3270OUTPUT
That's it for goal #1!  I can now do commands such as the following:
x3270if "connect(192.168.1.100)"
Which would instruct my s3270 terminal to connect to a frame on IP 192.168.1.100.

With this functionality alone I can then use expect scripting alone to do everything I want which meets my other goals.  However, I don't like Tcl expect so I chose to use python scripting using pexpect for expect functionality to script everything.

I found the redirect solution I detailed above after scouring google and finding the following link to a script that someone else made @ http://www.sfr-fresh.com/unix/misc/x3270-3.3.9ga12.tgz:a/x3270-3.3/Examples/cms_logon.sh

Thursday, March 18, 2010

access files below a mountpoint

Today I needed to be able to access a directory that is normally used as a mountpoint. I needed to do this because we wanted to transition some automounts to hardmounts without interruption.

So an example is we have auto mount table /test specfied in /etc/auto.master which automounts /test/1 and /test/2 automatically.

Say someone was on a system using /test/1 actively. I would want to 'fix' the system by setting up new entries in /etc/fstab for /test/1 and /test/2 and remove /test from /etc/auto.master. Then I would want to restart automount.

/test/1 would still be mounted since its in use which is good as then there is no interruption to the user. I would create /test/2 and mount a 'hard' mount on that. Since automount was restarted and no longer has an entry for /test in /etc/auto.master then /test/1 will never timeout from automount anymore.

However, the base mountpoint that automount was using is /test ... so on a reboot /test will still exist but directories /test/1 and /test/2 will no longer exist and the system will fail to mount on those /etc/fstab entries ...

What I ended up doing was:
  • mount --bind / /mnt
  • cd /mnt/test
This allows me to be 'underneath' the /test mountpoint which currently has /test/1 mounted from automount earlier.
  • mkdir 1 2
  • cd /
  • umount /mnt
Now if the system reboots /test/1 and /test/2 will exist and the mounts specified in /etc/fstab will mount correctly.

Saturday, March 13, 2010

mkinitrd: device /dev/ does not have a driver

I recently ran into an issue when trying to update the kernel on my openSUSE 11.0 system. When installing the kernel and mkinitrd ran during the kernel rpm post-scriptlet mkinitrd would fail. When I ran it on my own I would get:
Fatal storage error. device /dev/ does not have a driver
I dove into the code for mkinitrd and found 2 spots where it was getting hung up on having '/dev/' as a value in a variable called blockdev.

One was in /lib/mkinitrd/scripts/setup-block.sh and another in /lib/mkinitrd/scripts/setup-iscsi.sh.

The variable blockdev is a space delimited list of devices that these scripts loop through and execute commands against with for loops. The for loops looks like:
for bd in $blockdev; do
So each value in blockdev then get assigned temporarily to bd. I therefore added a further check right after the for bd in $blockdev; do line to check if variable bd equals exactly /dev/ and if so to skip that value:
if [ "$bd" == "/dev/" ]; then
verbose "[BLOCK] ignoring $bd (gaf)"
continue
fi
So before:
...
for bd in $blockdev; do
...
And after:
...
for bd in $blockdev; do
if [ "$bd" == "/dev/" ]; then
verbose "[BLOCK] ignoring $bd (gaf)"
continue
fi
...
I'm guessing /dev/ is being included into the blockdev variable erroneously, but I'm not gonna waste anymore time figuring that part out. :P

Hope this helps as I didn't see anyone with a solution to this issue when searching for one myself (to save time ...).

NOTE: This issue seems to be addressed in 11.2 after some update (still an issue in base 11.2). I ran into it while upgrading to 11.2 from 11.0.

Tuesday, February 9, 2010

install ubuntu 9.10 karmic on lvm

Recently I upgraded my Ubuntu install on my netbook to the latest version of 9.10 karmic. I wasn't too happy with the leftovers and some applet configurations that were missing after upgrading so I decided to just reinstall directly to 9.10. I thought this would also give me a chance to redo my filesystem layouts to better utilize my 4GB SSD and 12G SSD in my netbook.

Things quickly turned ugly as I found out that the 'advanced partitioning' provided by ubuntu is no where near what I am used to when installing RHEL or SLES at work. I soon found out to install to LVM you first need to setup your LVM configuration and mkfs your volumes BEFORE you start the ubuntu install. After everything is setup it will see them and you can then specify what you want to mount where and the install will work as you want it.

Of course there are some workarounds to doing all this ... here is the process I used.

  1. Get your Ubuntu 9.10 install/live cd
  2. If you do not have network for the system your installing to (wired or wireless) then download the following to a USB drive (these are 32-bit versions since I have a netbook, you may need to find 64-bit versions for your install)
  3. Boot your system using the Ubuntu 9.10 install/live cd
  4. Once booted open a terminal and get root
    • sudo su -
  5. For systems with no network:
    • Insert your USB stick with the packages you downloaded above
    • cd to /media/[USBdriveName]/[directoryWithPackages]
    • Install lvm2 and watershed to the live cd OS
      • dpkg -i lvm2*.dev watershed*.deb
  6. For systems with network:
    • apt-get update
    • apt-get install lvm2
Now that lvm2 is installed you can create your PVs, VGs, LVs. You can do this however you want. The following is what I did as a reference for people who may not know much about LVM. My setup including striping between 2 disks so you may want to adjust how you do things ...

  1. fdisk /dev/sda
    • o
    • w
    • n
    • p
    • 1
    • 1
    • +100M
    • n
    • p
    • 2


    • t
    • 2
    • 8e
    • w
  2. fdisk /dev/sdb
    • o
    • w
  3. This is where I had some issues. I had some type of lock on /dev/sdb when trying to do the next step of pvcreate to pull it into LVM ... so I needed to reboot to release it. If you need to reboot to use your disk you will need to follow steps 1-6 from the first section to get a live boot enviornment with LVM running again.
  4. pvcreate /dev/sda2
  5. pvcreate /dev/sdb
  6. mkfs.ext2 /dev/sda1
  7. vgcreate rootdisk /dev/sda2 /dev/sdb
  8. lvcreate -i2 -I4 -L6G -nroot_lv rootdisk
  9. lvcreate -l100%PVS -nvar_lv rootdisk /dev/sda2
  10. lvcreate -l100%PVS -nhome_lv rootdisk /dev/sdb
  11. mkfs.ext4 /dev/rootdisk/root_lv
  12. mkfs.ext4 /dev/rootdisk/var_lv
  13. mkfs.ext4 /dev/rootdisk/home_lv
We now have LVM setup to host /, /var and /home filesystems. /boot will exist directly on /dev/sda1 (I later found out I could have tried to include it in LVM because 9.10 uses grub2, but too late now :( ) . So now you can initiate the install.
  1. Start install
  2. When you get to partition/disk setup section choose advanced
  3. You will see the /dev/mapper/[vg]-[lv] devices you created in LVM. Below them will be the filesystem you put on each. Highlight the filesystem one and click the "Change..." button to specify the filesystem to use (should match how you mkfs above) and where to mount. DO NOT HAVE THE INSTALL REFORMAT THE FILESYSTEM.
  4. For /dev/sda1 highlight and click "Change...". Specify the filesystem, where to mount (/boot) and DO HAVE IT FORMAT IT!
  5. Proceed through the rest of the questions to start the install
One the install is finished WE ARE NOT DONE YET. The install installed it to where we want it, but it did NOT install LVM to our new OS! So now we need to mount everything by hand and chroot to our new OS to install LVM and then remake the initramfs. (If you reboot at this point it will not boot stating it can not find your /dev/mapper/[rootVG]-[rootLV]

These instructions follow how I setup my system, you need to make adjustments for the VG/LV names you created.
  1. mount /dev/rootdisk/root_lv /mnt
  2. mount /dev/rootdisk/var_lv /mnt/var
  3. mount /dev/rootdisk/home_lv /mnt/home
  4. mount /dev/sda1 /mnt/boot
  5. mount -t proc proc /mnt/proc
  6. mount -t sysfs sys /mnt/sys
  7. mount -o bind /dev /mnt/dev
  8. IF YOU DO NOT HAVE NETWORK:
    • Insert your USB stick with the packages you downloaded above
    • cd to /media/[USBdriveName]/[directoryWithPackages]
    • cp lvm2*.dev watershed*.deb libreadline5*.deb /mnt/var/tmp
    • chroot /mnt
    • cd /var/tmp
    • dpkg -i lvm2*.dev watershed*.deb libreadline5*.deb
  9. IF YOU HAVE NETWORK:
    • chroot /mnt
    • apt-get update
    • apt-get install lvm2
  10. mkinitramfs -o /boot/[filenameOfCurrentInitramfs]
  11. reboot
That should be it. I made these instructions all after-the-fact, so its all from memory trying to walkthrough what I did. I hope I didn't miss anything, but this should set you on the right track regardless. Below are links I referenced while trying to figure this out that may be helpful as well:

Friday, November 6, 2009

undelete on ext3 filesystem

So I wiped out a directory that I thought I no longer needed. Turns out there was a 900K file that I didn't have copies of anywhere else in that directory. :(

So I quick googled on undelete for ext3 filesystems and found numerous posts on how its not possible. Funny thing it is possible ...

I eventually found http://code.google.com/p/ext3grep/ which was my lifesaver.

I'm not going to go into how to use this tool because there is already a great writeup @ http://www.xs4all.nl/~carlo17/howto/undelete_ext3.html

Suffice it to say I got my file back and I'm happy!

Friday, September 4, 2009

animate your desktop in linux

I've always wanted to have a slideshow of pictures for my desktop instead of just having 1 static image. I now know of 2 ways to do this. One I scripted myself, and another is program I found and learned to utilize which works better and is better.

First I'll detail my script, but be sure to continue to read further down as a better solution exists!

I initially created a script for GNOME that I was able to point to a directory full of images and have it randomly display a picture from the directory of images as my background. I then created a cronjob to execute the script so about every couple hours I would have a new backgroup.

NOTE: This will only work in GNOME 2.x as the script utilizes gconftool-2. I'm sure it can be modified to work with other versions of GNOME as well.
  • Create the script!
    • vi chgBackground.sh
    • #!/bin/sh

      PID=$$

      PHOTO_DIR=$1

      if [[ -z ${PHOTO_DIR} ]]; then
      echo "You must specify a directory that has your photos."
      exit 1
      fi

      if [[ ! -d ${PHOTO_DIR} ]]; then
      echo "Directory '${PHOTO_DIR}' does not exist."
      exit 1
      fi

      # Look for files with extension .jpg or .png
      PIC_COUNT="`find ${PHOTO_DIR} -iregex ".*\.\(jpg\|png\)$" | wc -l`"

      if [[ ${PIC_COUNT} -eq 0 ]]; then
      echo "No pictures found!"
      exit 1
      fi

      find ${PHOTO_DIR} -iregex ".*\.\(jpg\|png\)$" > /tmp/chgBackground.${PID}

      RANDOM=${PID}
      RAN_VAR=`echo $[(${RANDOM} % ${PIC_COUNT}) + 1]`

      BKG_PATH=`head -${RAN_VAR} /tmp/chgBackground.${PID} | tail -1`

      /opt/gnome/bin/gconftool-2 -t string -s /desktop/gnome/background/picture_filename ${BKG_PATH}

      rm -f /tmp/chgBackground.${PID}
  • Set perms to execute the script
    • chmod +x chgBackground.sh
  • Run the script!
    • chgBackground.sh /path/to/pics
  • Schedule in crontab to run automatically
    • crontab -e
    • Add the following to change every hour:
      • 0 * * * * sh -x /path/to/script/chgBackground.sh > /dev/null
I later learned of a program called xwinwrap. This binary allows you to run a program over your desktop. That is to say you could use this program to have VLC playing a video and make that your background. Below are the steps I used to have gslideshow from xscreensaver run as my background, with glslideshow configured to point to a directory full of images.
Now, the command I use is:
  • /path/to/xwinwrap -fs -st -sp -b -ov -- /usr/lib64/xscreensaver/glslideshow -window-id WID -duration 8 -pan 8 -fade 2 &
What the above command does is:
  • -fs : parameter for xwinwrap to run fullscreen
  • -st and -sp : I set these so that when xwinwrap runs it does not show up with a program window in the "Workspace Switcher" applet
  • -b : This has xwinwrap run below GNOME panels
  • -ov : This allows xwinwrap to run in all virtual desktops
  • -- /usr/lib64/xscreensaver/glslideshow -window-id WID -duration 8 -pan 8 -fade 2 : This is an argument passwed to xwinwrap of the command you pass to xwinwrap to be run over your desktop
    • -window-id WID : parameter for glslideshow to run fullscreen in your GNOME window
    • -duration 8 : parameter for glslideshow on how long to have a single photo displayed
    • -pan 8 : how long to pan the image for (if less then duration it will pan the image over 2 cycles for same image)
    • -fade 2 : parameter for glslideshow on how to to fade between images
  • & : allows xwinwrap to run in the background
To set the imageDirectory for glslideshow to use:
  • vi ~/.xscreensaver
    • edit/add the line containing "imageDirectory" to point to the directory of images
      • EXAMPLE:
        imageDirectory: /path/to/images
You can obviously change the argument you pass to xwinwrap to run different image/video applications to have overlayed over your desktop.

Sunday, August 23, 2009

linux pptp configuration with MS vpn

I've been trying for a while to configure pptp to connect to my work vpn which uses an MS vpn server. Turns out configuration is fairly straightforward and that my main issue was really simple actually... anyways, the errors I was getting when trying to debug it were the following:
root@mclittle:/etc/ppp# pon myvpn debug dump logfd 2 nodetach
pppd options in effect:
debug # (from command line)
nodetach # (from command line)
logfd 2 # (from command line)
dump # (from command line)
noauth # (from /etc/ppp/options.pptp)
refuse-pap # (from /etc/ppp/options.pptp)
refuse-chap # (from /etc/ppp/options.pptp)
refuse-mschap # (from /etc/ppp/options.pptp)
refuse-eap # (from /etc/ppp/options.pptp)
name jdoe # (from /etc/ppp/peers/myvpn)
user jdoe # (from /etc/ppp/peers/myvpn)
remotename PPTP # (from /etc/ppp/peers/myvpn)
# (from /etc/ppp/options.pptp)
pty pptp vpn.domain.com --nolaunchpppd # (from /etc/ppp/peers/myvpn)
crtscts # (from /etc/ppp/options)
# (from /etc/ppp/options)
asyncmap 0 # (from /etc/ppp/options)
lcp-echo-failure 4 # (from /etc/ppp/options)
lcp-echo-interval 30 # (from /etc/ppp/options)
hide-password # (from /etc/ppp/options)
ipparam myvpn # (from /etc/ppp/peers/myvpn)
proxyarp # (from /etc/ppp/options)
nobsdcomp # (from /etc/ppp/options.pptp)
nodeflate # (from /etc/ppp/options.pptp)
require-mppe-128 # (from /etc/ppp/peers/myvpn)
noipx # (from /etc/ppp/options)
using channel 26
Using interface ppp0
Connect: ppp0 <--> /dev/pts/2
sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x556ea98d> <pcomp> <accomp>]
rcvd [LCP ConfReq id=0x0 <mru 1400> <auth eap> <magic 0x20e4721> <pcomp> <accomp> <callback CBCP> <mrru 1614> <endpoint [local:e7.d1.73.2d.b1.7b.49.5b.bc.41.b8.ae.36.14.95.be.00.00.00.00]> < 17 04 19 f5>]
No auth is possible
sent [LCP ConfRej id=0x0 <auth eap> <callback CBCP> <mrru 1614> < 17 04 19 f5>]
rcvd [LCP ConfAck id=0x1 <asyncmap 0x0> <magic 0x556ea98d> <pcomp> <accomp>]
rcvd [LCP TermReq id=0x1 02 0e 47 21 00 3c cd 74 00 00 03 97]
sent [LCP TermAck id=0x1]
sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x556ea98d> <pcomp> <accomp>]
sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x556ea98d> <pcomp> <accomp>]
^CTerminating on signal 2
sent [LCP TermReq id=0x2 "User request"]
Child process pptp vpn.domain.com --nolaunchpppd (pid 5494) terminated with signal 2
Modem hangup
Connection terminated.
Anyways, here is what I did on an ubuntu system to get it to work, should be pretty much the same for other distributions.

First I am going to go through the information we will need and setup some "variables" so you know where to use them in your configs. I'll post configs with the "variable", and a config with sample data.

Packages Needed:


The followingm packages are needed to be installed:
  • pptpd
  • pptp-linux
  • ppp
These can be installed with the following command:
  • sudo apt-get install ppp pptpd pptp-linux
Config Data Needed:
  • PPTP server name: ${VPN_SERVER}: vpn.doamin.com
  • VPN User Name: ${USERNAME}: jdoe
  • VPN Domain: ${DOMAIN}: USA
  • VPN Password: ${PASSWORD}: jpass
  • Connection name: ${CONFIG_FILE}: myvpn
  • Password Alias: ${PASS_ALIAS}: myvpnalias
Here are the steps to take:
  1. First lets configure our username/password that will be used for the VPN. We will edit /etc/ppp/chap-secrets:
    • SAMPLE:

      ${DOMAIN}\\${USERNAME} ${PASS_ALIAS} ${PASSWORD} *
    • EXAMPLE:

      USA\\jdoe myvpnalias jpass *
  2. Now we will create a connection config file. This file is to be created in /etc/ppp/peers/. With our example data that would mean /etc/ppp/peers/myvpn
    • SAMPLE:

      pty "pptp ${VPN_SERVER} --nolaunchpppd"
      name ${DOMAIN}\\${USERNAME}
      user ${DOMAIN}\\${USERNAME}
      remotename ${PASS_ALIAS}
      require-mppe-128
      file /etc/ppp/options.pptp
      ipparam ${CONFIG_FILE}
    • EXAMPLE:

      pty "pptp vpn.domain.com --nolaunchpppd"
      name USA\\jdoe
      user USA\\jdoe
      remotename myvpnalias
      require-mppe-128
      file /etc/ppp/options.pptp
      ipparam myvpn
  3. We can now connect to our pptp server:
    • pon ${CONFIG_FILE}
    • pon myvpn
      • Watch your /var/log/messages file on the status of your connection
      • When connected, you should have a new IP provided by the VPN server on a ppp0 device
  4. To disconnect your vpn connection:
    • poff ${CONFIG_FILE}
    • poff myvpn
Troubleshooting:

If you are not getting connected, you can start your pptp with the following command for debugging output:
  • pon ${CONFIG_FILE} debug dump logfd 2 detach
  • pon myvpn debug dump logfd 2 detach
References: