Gheek.net

November 18, 2008

Multipath.conf/iscsi.conf install and howto

Filed under: Uncategorized — lancevermilion @ 10:45 am

These install/howto instructions are for CentOS 5.x and Dell MD3000i. You can easily modify these slightly for your specific iSCSI disk.

iSCSI/Multipath/LVM

iSCSI/Multipath Installation

Install iSCSI initiator utilities

yum install iscsi-initiator-utils

Install multipath device mapper

yum install device-mapper-multipath

Configure multipath, iscsi, and iscsid to start on startup. Check first to make sure they are not already set to start on startup. If they are set to start you will see something like below, if they are not you will not see anything output listed as “on”.

/sbin/chkconfig --list | egrep -i "iscsi|iscsid|multipathd"
iscsi 0:off 1:off 2:off 3:on 4:on 5:on 6:off
iscsid 0:off 1:off 2:off 3:on 4:on 5:on 6:off
multipathd 0:off 1:off 2:on 3:on 4:on 5:on 6:off

To configure multipathd to start on startup do the following. iSCSI(d)already have this defined in their init script.

/sbin/chkconfig multipathd on

iSCSI Configuration

Edit /etc/iscsi/iscsid.conf and make sure it is identical to this config.
**I need to verify this iscsid.conf but for now this is what I have logged as a working configs from years back.

#
# Open-iSCSI default configuration.
# Could be located at /etc/iscsi/iscsid.conf or ~/.iscsid.conf
#
# Note: To set any of these values for a specific node/session run
# the iscsiadm --mode node --op command for the value. See the README
# and man page for iscsiadm for details on the --op command.
#

################
# iSNS settings
################
# Address of iSNS server
#isns.address = 192.168.0.1
#isns.port = 3205

#############################
# NIC/HBA and driver settings
#############################
# open-iscsi can create a session and bind it to a NIC/HBA.
# To set this up see the example iface config file.

#*****************
# Startup settings
#*****************

# To request that the iscsi initd scripts startup a session set to "automatic".
# node.startup = automatic
#
# To manually startup the session set to "manual". The default is automatic.
node.startup = automatic

# *************
# CHAP Settings
# *************

# To enable CHAP authentication set node.session.auth.authmethod
# to CHAP. The default is None.
#node.session.auth.authmethod = CHAP

# To set a CHAP username and password for initiator
# authentication by the target(s), uncomment the following lines:
#node.session.auth.username = username
#node.session.auth.password = password

# To set a CHAP username and password for target(s)
# authentication by the initiator, uncomment the following lines:
#node.session.auth.username_in = username_in
#node.session.auth.password_in = password_in

# To enable CHAP authentication for a discovery session to the target
# set discovery.sendtargets.auth.authmethod to CHAP. The default is None.
#discovery.sendtargets.auth.authmethod = CHAP

# To set a discovery session CHAP username and password for the initiator
# authentication by the target(s), uncomment the following lines:
#discovery.sendtargets.auth.username = username
#discovery.sendtargets.auth.password = password

# To set a discovery session CHAP username and password for target(s)
# authentication by the initiator, uncomment the following lines:
#discovery.sendtargets.auth.username_in = username_in
#discovery.sendtargets.auth.password_in = password_in

# ********
# Timeouts
# ********
#
# See the iSCSI REAME's Advanced Configuration section for tips
# on setting timeouts when using multipath or doing root over iSCSI.
#
# To specify the length of time to wait for session re-establishment
# before failing SCSI commands back to the application when running
# the Linux SCSI Layer error handler, edit the line.
# The value is in seconds and the default is 120 seconds.
node.session.timeo.replacement_timeout = 120

# To specify the time to wait for login to complete, edit the line.
# The value is in seconds and the default is 15 seconds.
node.conn[0].timeo.login_timeout = 15

# To specify the time to wait for logout to complete, edit the line.
# The value is in seconds and the default is 15 seconds.
node.conn[0].timeo.logout_timeout = 15

# Time interval to wait for on connection before sending a ping.
node.conn[0].timeo.noop_out_interval = 5

# To specify the time to wait for a Nop-out response before failing
# the connection, edit this line. Failing the connection will
# cause IO to be failed back to the SCSI layer. If using dm-multipath
# this will cause the IO to be failed to the multipath layer.
node.conn[0].timeo.noop_out_timeout = 5

#******
# Retry
#******

# To speficy the number of times iscsiadm should retry a login
# to the target when we first login, modify the following line.
# The default is 4. Valid values are any integer value. This only
# affects the initial login. Setting it to a high value can slow
# down the iscsi service startup. Setting it to a low value can
# cause a session to not get logged into, if there are distuptions
# during startup or if the network is not ready at that time.
node.session.initial_login_retry_max = 4

################################
# session and device queue depth
################################

# To control how many commands the session will queue set
# node.session.cmds_max to an integer between 2 and 2048 that is also
# a power of 2. The default is 128.
node.session.cmds_max = 128

# To control the device's queue depth set node.session.queue_depth
# to a value between 1 and 128. The default is 32.
node.session.queue_depth = 32

#***************
# iSCSI settings
#***************

# To enable R2T flow control (i.e., the initiator must wait for an R2T
# command before sending any data), uncomment the following line:
#
#node.session.iscsi.InitialR2T = Yes
#
# To disable R2T flow control (i.e., the initiator has an implied
# initial R2T of "FirstBurstLength" at offset 0), uncomment the following line:
#
# The defaults is No.
node.session.iscsi.InitialR2T = No

#
# To disable immediate data (i.e., the initiator does not send
# unsolicited data with the iSCSI command PDU), uncomment the following line:
#
#node.session.iscsi.ImmediateData = No
#
# To enable immediate data (i.e., the initiator sends unsolicited data
# with the iSCSI command packet), uncomment the following line:
#
# The default is Yes
node.session.iscsi.ImmediateData = Yes

# To specify the maximum number of unsolicited data bytes the initiator
# can send in an iSCSI PDU to a target, edit the following line.
#
# The value is the number of bytes in the range of 512 to (2^24-1) and
# the default is 262144
node.session.iscsi.FirstBurstLength = 262144

# To specify the maximum SCSI payload that the initiator will negotiate
# with the target for, edit the following line.
#
# The value is the number of bytes in the range of 512 to (2^24-1) and
# the defauls it 16776192
node.session.iscsi.MaxBurstLength = 16776192

# To specify the maximum number of data bytes the initiator can receive
# in an iSCSI PDU from a target, edit the following line.
#
# The value is the number of bytes in the range of 512 to (2^24-1) and
# the default is 131072
node.conn[0].iscsi.MaxRecvDataSegmentLength = 131072

# To specify the maximum number of data bytes the initiator can receive
# in an iSCSI PDU from a target during a discovery session, edit the
# following line.
#
# The value is the number of bytes in the range of 512 to (2^24-1) and
# the default is 32768
#
discovery.sendtargets.iscsi.MaxRecvDataSegmentLength = 32768

# To allow the targets to control the setting of the digest checking,
# with the initiator requesting a preference of enabling the checking, uncommen
# the following lines (Data digests are not supported and on ppc/ppc64
# both header and data digests are not supported.):
#node.conn[0].iscsi.HeaderDigest = CRC32C,None
#
# To allow the targets to control the setting of the digest checking,
# with the initiator requesting a preference of disabling the checking,
# uncomment the following lines:
#node.conn[0].iscsi.HeaderDigest = None,CRC32C
#
# To enable CRC32C digest checking for the header and/or data part of
# iSCSI PDUs, uncomment the following lines:
#node.conn[0].iscsi.HeaderDigest = CRC32C
#
# To disable digest checking for the header and/or data part of
# iSCSI PDUs, uncomment the following lines:
#node.conn[0].iscsi.HeaderDigest = None
#
# The default is to never use DataDigests and to allow the target to control
# the setting of the HeaderDigest checking with the initiator requesting
# a preference of disabling the checking.

#***************
# iSCSI Multipath settings
#***************
# Specify the use of having multiple network paths to the same target.
# Valid values are
# no - there is no multipathing. Establish at most one session to the
# target and use all portals for failover, if failover is not disabled.
# portal - establish a session to the target using each of the n/w portals to
# the target, and bind each session to a different host SCSI address.
# No portal failover is possible since each session has only one portal.
# portalgroup - establish a session to one portal from each portal group that
# reaches the target and bind each session to a different host SCSI
# address. If a portal group has more than one portal, portal failover
# can occur between that group's portals if failover is not disabled.
Multipath = portalgroup

Edit /etc/iscsi/initiatorname.iscsi and add the alias name you created (in the MD3000i for this host) to this config.

InitiatorAlias=iqn.SERVER_HOSTNAME

Discover the iSCSI target.

iscsiadm -m discovery -t sendtargets -p 192.168.130.101

192.168.130.101:3260,1 iqn.1984-05.com.dell:powervault.6001c23000c66e31000000004715e09f
192.168.130.102:3260,2 iqn.1984-05.com.dell:powervault.6001c23000c66e31000000004715e09f
192.168.131.101:3260,1 iqn.1984-05.com.dell:powervault.6001c23000c66e31000000004715e09f
192.168.131.102:3260,2 iqn.1984-05.com.dell:powervault.6001c23000c66e31000000004715e09f

Login to the iSCSI target.

iscsiadm -m node -l

Login session [iface: default, target: iqn.1984-05.com.dell:powervault.6001c23000c66e31000000004715e09f, portal: 192.168.130.101,3260]
Login session [iface: default, target: iqn.1984-05.com.dell:powervault.6001c23000c66e31000000004715e09f, portal: 192.168.131.102,3260]
Login session [iface: default, target: iqn.1984-05.com.dell:powervault.6001c23000c66e31000000004715e09f, portal: 192.168.131.101,3260]
Login session [iface: default, target: iqn.1984-05.com.dell:powervault.6001c23000c66e31000000004715e09f, portal: 192.168.130.102,3260]

Verify you are logged in to the iSCSI target and have a session

iscsiadm -m session

tcp: [5] 192.168.131.102:3260,2 iqn.1984-05.com.dell:powervault.6001c23000c5a15e00000000471474b5
tcp: [6] 192.168.130.101:3260,1 iqn.1984-05.com.dell:powervault.6001c23000c5a15e00000000471474b5
tcp: [7] 192.168.131.101:3260,1 iqn.1984-05.com.dell:powervault.6001c23000c5a15e00000000471474b5
tcp: [8] 192.168.130.102:3260,2 iqn.1984-05.com.dell:powervault.6001c23000c5a15e00000000471474b5

Logout of the iSCSI target (if you ever need to).

iscsiadm -m node -u

Logout session [sid: 9, target: iqn.1984-05.com.dell:powervault.6001c23000c66e31000000004715e09f, portal: 192.168.130.101,3260]
Logout session [sid: 10, target: iqn.1984-05.com.dell:powervault.6001c23000c66e31000000004715e09f, portal: 192.168.131.102,3260]
Logout session [sid: 11, target: iqn.1984-05.com.dell:powervault.6001c23000c66e31000000004715e09f, portal: 192.168.131.101,3260]
Logout session [sid: 12, target: iqn.1984-05.com.dell:powervault.6001c23000c66e31000000004715e09f, portal: 192.168.130.102,3260]

Verify that the iSCSI target has you as a host and has disks mapped to you.
You will want to ignore any Disk the doesn’t contain a valid partition table
You can also check /var/log/dmesg to see similar but more verbose info, but is not covered here.

fdisk -l

Disk /dev/sda: 72.7 GB, 72746008576 bytes
255 heads, 63 sectors/track, 8844 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Device Boot Start End Blocks Id System
/dev/sda1 * 1 13 104391 83 Linux
/dev/sda2 14 8844 70935007+ 8e Linux LVM

Disk /dev/sdb: 1497.3 GB, 1497314099200 bytes
255 heads, 63 sectors/track, 182038 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Disk /dev/sdb doesn't contain a valid partition table

Disk /dev/sdc: 1497.3 GB, 1497314099200 bytes
255 heads, 63 sectors/track, 182038 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Disk /dev/sdc doesn't contain a valid partition table

Disk /dev/sdf: 20 MB, 20971520 bytes
1 heads, 40 sectors/track, 1024 cylinders
Units = cylinders of 40 * 512 = 20480 bytes

Disk /dev/sdf doesn't contain a valid partition table

Disk /dev/sdg: 20 MB, 20971520 bytes
1 heads, 40 sectors/track, 1024 cylinders
Units = cylinders of 40 * 512 = 20480 bytes

Disk /dev/sdg doesn't contain a valid partition table

Disk /dev/sdh: 20 MB, 20971520 bytes
1 heads, 40 sectors/track, 1024 cylinders
Units = cylinders of 40 * 512 = 20480 bytes

Disk /dev/sdh doesn't contain a valid partition table

Disk /dev/sdi: 20 MB, 20971520 bytes
1 heads, 40 sectors/track, 1024 cylinders
Units = cylinders of 40 * 512 = 20480 bytes

Disk /dev/sdi doesn't contain a valid partition table

Disk /dev/dm-3: 1497.3 GB, 1497314099200 bytes
255 heads, 63 sectors/track, 182038 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Disk /dev/dm-3 doesn't contain a valid partition table

Multipath Configuration

Now that we have the modules compiled and installed, we need to setup a configuration file so that the multipath modules/daemon will choose the correct devices.

Edit /etc/multipath.conf‘ by commenting out everything that is not already commented out. Then insert the following

# This is a basic configuration file with some examples, for device mapper
# multipath.
# For a complete list of the default configuration values, see
# /usr/share/doc/device-mapper-multipath-0.4.7/multipath.conf.defaults
# For a list of configuration options with descriptions, see
# /usr/share/doc/device-mapper-multipath-0.4.7/multipath.conf.annotated

defaults {
        udev_dir                /dev
        user_friendly_names     yes
}
blacklist {
        devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
        devnode "^hd[a-z]"
        devnode "^sda"
        devnode "^sda[0-9]"
        device {
                vendor DELL
                product "PERC|Universal|Virtual"
        }
}
devices {
        device {
                vendor                  DELL
                product                 MD3000i
                hardware_handler        "1 rdac"
                path_checker            rdac
                path_grouping_policy    group_by_prio
                prio_callout            "/sbin/mpath_prio_rdac /dev/%n"
                failback                immediate
                getuid_callout          "/sbin/scsi_id -g -u -s /block/%n"
        }
}
multipaths {
        mulitpath {
                device {
                        vendor DELL
                        product MD3000i
                }
        }
}

Multipath Discovery

Now we have a configuration and modules, lets clear multipath database and re-establish the paths.

To flush the database use -F and the restart the deamon.

/sbin/multipath -F
/etc/init.d/multipathd restart
Now run multipath with the -ll option to see if you can see the 4 paths, and that the correct hardware-handler is being used. If everything is going well you should have something similar to the following.

multipath -ll
mpath0 (36001c23000c5a15e0000036747e24910) dm-3 DELL,MD3000i
[size=1.4T][features=0][hwhandler=1 rdac]
\_ round-robin 0 [prio=200][active]
\_ 18:0:0:0 sdb 8:16 [active][ready]
\_ 19:0:0:0 sdc 8:32 [active][ready]
\_ round-robin 0 [prio=0][enabled]
\_ 17:0:0:0 sdd 8:48 [active][ghost]
\_ 20:0:0:0 sde 8:64 [active][ghost]

LVM configuration

To ensure that you don’t scan the ‘real’ devices and not the multipath devices, you need to change the filter in /etc/lvm/lvm.conf and rebuild the cache.
Find the filter line and change using your favourite editor.

####filter = [ "a/.*/" ] ###Original filter will be uncommented
filter = [ "a|/dev/sda|", "r|/dev/sd.*|", "r|/dev/dm-.*|", "a|/dev/mapper/mpath.*|", "r|/dev/.*|" ]

Now rebuild the cache.

rm /etc/lvm/cache/.cache
/sbin/vgscan

iSCSI mounting

Create a partition with fdisk

/sbin/fdisk /dev/sdb

The number of cylinders for this disk is set to 182038.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
(e.g., DOS FDISK, OS/2 FDISK)
Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

Command (m for help): m

n add a new partition
p print the partition table

Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-182038, default 1):
Using default value 1
Last cylinder or +size or +sizeM or +sizeK (1-182038, default 182038):
Using default value 182038

Command (m for help): p

Disk /dev/sdb: 1497.3 GB, 1497314099200 bytes
255 heads, 63 sectors/track, 182038 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Device Boot Start End Blocks Id System
/dev/sdb1 1 182038 1462220203+ 83 Linux

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.
Create the new file system and mount it.

/usr/bin/nohup /sbin/mkfs.ext3 /dev/sdb1 &
/usr/bin/nohup: appending output to `nohup.out'
[1] 13610
[1]+ Done sudo /usr/bin/nohup /sbin/mkfs.ext3 /dev/sdb1

mkdir /mnt/iscsi
mount /dev/mapper/mpath0p1 /mnt/iscsi/

Verify you see the new partition

df -h

Filesystem Size Used Avail Use% Mounted on
/dev/mapper/VolGroup00-LogVol00
25G 13G 12G 51% /
/dev/sda1 99M 31M 64M 33% /boot
tmpfs 1014M 0 1014M 0% /dev/shm
/dev/mapper/VolGroup00-LogVol02
39G 6.3G 31G 17% /local
/dev/mapper/mpath0p1 1.4T 198M 1.3T 1% /mnt/iscsi

To mount the iSCSI disk on book ad it to /etc/fstab

/dev/mapper/mpath0p1 /mnt/iscsi ext3 _netdev 0 0

Advertisements

November 13, 2008

Cisco IPS support for rancid

Filed under: Cisco, perl, rancid — Tags: , , , — lancevermilion @ 1:43 pm

In order to get rancid to collect the config from an IPS module you will need to make sure you have the correct login creds in the rancid users “.cloginrc”, add the type of ips to “rancid-fe” and you also need to create the “ipsrancid” script.

Sample addition for your “.cloginrc”. Make sure this is above anything else so no other wildcards in the “.cloginrc” get caught.

add autoenable ips-primary 1
add user ips-primary rancid
add password ips-primary <>
add method ips-primary ssh

Changes required for “rancid-fe”.

'ips' => 'ipsrancid',

Create the “ipsrancid” script as “<rancid_home>/bin/ipsrancid”. Make sure you “chmod 755 <rancid_home>/bin/ipsrancid” and “chown <rancid_user>:<rancid_user_group> <rancid_home>/bin/ipsrancid”.

#!/usr/bin/perl
##
## Copyright (C) 1997-2004 by Terrapin Communications, Inc.
## All rights reserved.
##
## This software may be freely copied, modified and redistributed
## without fee for non-commerical purposes provided that this license
## remains intact and unmodified with any RANCID distribution.
##
## There is no warranty or other guarantee of fitness of this software.
## It is provided solely "as is". The author(s) disclaim(s) all
## responsibility and liability with respect to this software's usage
## or its effect upon hardware, computer systems, other software, or
## anything else.
##
## Except where noted otherwise, rancid was written by and is maintained by
## Henry Kilmer, John Heasley, Andrew Partan, Pete Whiting, and Austin Schutz.
##
#
# hacked version of Hank's rancid - this one tries to deal with Hitachi's.
#
# Modified again by Lance Vermilion (11/13/08)
# Modified from htrancid by Jeremy M. Guthrie
# Created on 5/4/2007
#
# This is meant to try handle Cisco's IPS V5.X line and on
#
# RANCID - Really Awesome New Cisco confIg Differ
#
# usage: ipsrancid [-d] [-l] [-f filename | $host]
use Getopt::Std;
getopts('dfl');
$log = $opt_l;
$debug = $opt_d;
$file = $opt_f;
$host = $ARGV[0];
$clean_run = 0;
$found_end = 0;
$timeo = 90; # clogin timeout in seconds

my(@commandtable, %commands, @commands);# command lists
my(%filter_pwds); # password filtering mode

# This routine is used to print out the router configuration
sub ProcessHistory {

($new_hist_tag,$new_command,$command_string, @string) = (@_);
if ((($new_hist_tag ne $hist_tag) || ($new_command ne $command))
&& defined %history) {
print eval "$command \%history";
undef %history;
}
if (($new_hist_tag) && ($new_command) && ($command_string)) {
if ($history{$command_string}) {
$history{$command_string} = "$history{$command_string}@string";
} else {
$history{$command_string} = "@string";
}
} elsif (($new_hist_tag) && ($new_command)) {
$history{++$#history} = "@string";
} else {
print "@string";
}
$hist_tag = $new_hist_tag;
$command = $new_command;
1;
}

sub numerically { $a $b; }

# This is a sort routine that will sort numerically on the
# keys of a hash as if it were a normal array.
sub keynsort {
local(%lines) = @_;
local($i) = 0;
local(@sorted_lines);
foreach $key (sort numerically keys(%lines)) {
$sorted_lines[$i] = $lines{$key};
$i++;
}
@sorted_lines;
}

# This is a sort routine that will sort on the
# keys of a hash as if it were a normal array.
sub keysort {
local(%lines) = @_;
local($i) = 0;
local(@sorted_lines);
foreach $key (sort keys(%lines)) {
$sorted_lines[$i] = $lines{$key};
$i++;
}
@sorted_lines;
}

# This is a sort routine that will sort on the
# values of a hash as if it were a normal array.
sub valsort{
local(%lines) = @_;
local($i) = 0;
local(@sorted_lines);
foreach $key (sort values %lines) {
$sorted_lines[$i] = $key;
$i++;
}
@sorted_lines;
}

# This is a numerical sort routine (ascending).
sub numsort {
local(%lines) = @_;
local($i) = 0;
local(@sorted_lines);
foreach $num (sort {$a $b} keys %lines) {
$sorted_lines[$i] = $lines{$num};
$i++;
}
@sorted_lines;
}

# This is a sort routine that will sort on the
# ip address when the ip address is anywhere in
# the strings.
sub ipsort {
local(%lines) = @_;
local($i) = 0;
local(@sorted_lines);
foreach $addr (sort sortbyipaddr keys %lines) {
$sorted_lines[$i] = $lines{$addr};
$i++;
}
@sorted_lines;
}

# These two routines will sort based upon IP addresses
sub ipaddrval {
my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#);
$a[3] + 256 * ($a[2] + 256 * ($a[1] +256 * $a[0]));
}
sub sortbyipaddr {
&ipaddrval($a) &ipaddrval($b);
}

# This routine parses "show config"
sub ShowConfig {
print STDERR " In ShowConfig: $_" if ($debug);

$firstexit=0;

while () {
tr/15//d;
tr/20//d;

#strip out the stupid spinning running-config progress thingy
s/Generating current config: \.*[\|\/\-\\]//gi;
$skipprocess=0;

#sometimes an 'exit' appears at the top of the config, we don't want them
if ( (/^exit/) && ( ! $firstexit ) ) {
$firstexit=1;
$skipprocess=1;
}

#remove spaces left over from lame spinning progress thingy
if ( /^\s+! ------------------------------/ ) {
s/^\s+!/!/g
}

if (/^(read-only-community) / && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 \n"); next;
}
if (/^(read-write-community) / && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 \n"); next;
}
if (/^(trap-community-name) / && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 \n"); next;
}
if (/^(ntp-keys \d+ md5-key) / && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 \n"); next;
}
if (/^(password) / && $filter_pwds >= 1) {
ProcessHistory("","","","!$1 \n"); next;
}

last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
if ( ! /^$prompt/) {
if ( ! $skipprocess ) {
print STDOUT " ShowConfig Data: $_" if ($debug);
ProcessHistory("","","","$_");
}
}
}
$clean_run=1;
print STDERR " Exiting ShowConfig: $_" if ($debug);
return(0);
}

# This routine parses single command's that return no required info
sub ShowVersion {
print STDERR " In ShowVersion: $_" if ($debug);
ProcessHistory("","","","!\n!IPS Show Version Start\n");

while () {
tr/15//d;

$skipprocess=0;

if ( /^Sensor up-time/ ) { $skipprocess=1; }
if ( ( /using.*bytes of available/i ) ) { $skipprocess=1; }

last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
if ( ! /^$prompt/) {
if ( ! $skipprocess ) {
print STDOUT " ShowVersion Data: $_" if ($debug);
ProcessHistory("","","","! $_");
}
}
}
ProcessHistory("","","","!\n!IPS Show Version End\n");
print STDERR " Exiting ShowVersion: $_" if ($debug);
return(0)
}

# This routine parses single command's that return no required info
sub ShowUsersAll {
print STDERR " In ShowUsersAll: $_" if ($debug);
ProcessHistory("","","","!\n!IPS User Database Start\n");

while () {
tr/15//d;

$skipprocess=0;

s/^ CLI ID //g;
s/^ //g;
s/^\* +[0-9]+ +//g;

last if (/^$prompt/);
next if (/^(\s*|\s*$cmd\s*)$/);
if ( ! /^$prompt/) {
if ( ! $skipprocess ) {
print STDOUT " ShowUsersAll Data: $_" if ($debug);
ProcessHistory("","","","!$_");
}
}
}
ProcessHistory("","","","!\n!IPS User Database End\n!\n!\n");
print STDERR " Exiting ShowUsersAll: $_" if ($debug);
return(0)
}

# dummy function
sub DoNothing {print STDOUT;}

# Main
@commandtable = (
{'show version' => 'ShowVersion'},
{'show users all' => 'ShowUsersAll'},
{'show configuration' => 'ShowConfig'}
);
# Use an array to preserve the order of the commands and a hash for mapping
# commands to the subroutine and track commands that have been completed.
@commands = map(keys(%$_), @commandtable);
%commands = map(%$_, @commandtable);

$cisco_cmds=join(";",@commands);
$cmds_regexp=join("|",@commands);

open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n";
select(OUTPUT);
# make OUTPUT unbuffered if debugging
if ($debug) { $| = 1; }

# The IPS doesn't like the TERM of network so we must change it
if ( $ENV{TERM} eq 'network' ) {
$ENV{TERM} = 'vt100';
}
if ($file) {
print STDERR "opening file $host\n" if ($debug);
print STDOUT "opening file $host\n" if ($log);
open(INPUT,"<$host") || die "open failed for $host: $!\n";
} else {
print STDERR "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug);
print STDOUT "executing clogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log);
if (defined($ENV{NOPIPE})) {
system "clogin -t $timeo -c \"$cisco_cmds\" $host $host.raw 2>&1" || die "clogin failed for $host: $!\n";
open(INPUT, "< $host.raw") || die "clogin failed for $host: $!\n";
} else {
open(INPUT,"clogin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "clogin failed for $host: $!\n";
}
}
# Change the TERM back to network
if ( $ENV{TERM} eq 'vt100' ) {
$ENV{TERM} = 'network';
}

# determine password filtering mode
if ($ENV{"FILTER_PWDS"} =~ /no/i) {
$filter_pwds = 0;
} elsif ($ENV{"FILTER_PWDS"} =~ /all/i) {
$filter_pwds = 2;
} else {
$filter_pwds = 1;
}

ProcessHistory("","","","!RANCID-CONTENT-TYPE: ipsrancid\n!\n");
TOP: while() {
tr/15//d;

#strip out the stupid spinning running-config progress thingy
s/Generating current config: \.*[\|\/\-\\]//gi;

if (/^.*logout$/) {
$clean_run=1;
last;
}
if (/^Error:/) {
print STDOUT ("$host clogin error: $_");
print STDERR ("$host clogin error: $_") if ($debug);
$clean_run=0;
last;
}
while (/($cmds_regexp)/) {
$cmd = $1;
if (!defined($prompt)) {
$prompt = ($_ =~ /^([^#]+#)/)[0];
$prompt =~ s/([][}{)(\\])/\\$1/g;
print STDERR ("PROMPT MATCH: $prompt\n") if ($debug);
}
print STDERR ("IPS COMMAND:$_") if ($debug);
if (! defined($commands{$cmd})) {
print STDERR "$host: found unexpected command - \"$cmd\"\n";
$clean_run = 0;
last TOP;
}
$rval = };
delete($commands{$cmd});
if ($rval == -1) {
$clean_run = 0;
last TOP;
}
}
}
print STDOUT "Done $logincmd: $_\n" if ($log);
# Flush History
ProcessHistory("","","","");
# Cleanup
close(INPUT);
close(OUTPUT);

if (defined($ENV{NOPIPE})) {
unlink("$host.raw") if (! $debug);
}

# check for completeness
if (scalar(%commands) || !$clean_run ) {
if (scalar(%commands)) {
printf(STDOUT "$host: missed cmd(s): %s\n", join(',', keys(%commands)));
printf(STDERR "$host: missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug);
}
if (!$clean_run ) {
print STDOUT "$host: End of run not found\n";
print STDERR "$host: End of run not found\n" if ($debug);
system("/usr/bin/tail -1 $host.new");
}
unlink "$host.new" if (! $debug);
}

November 7, 2008

How to add a button to your wordpress default WYSIWYG

Filed under: javascript, wordpress — Tags: , — lancevermilion @ 12:33 pm

First you will need to edit your default javascript file called “quicktags.js”.

vi /wp-includes/js/quicktags.js

Find something that looks like the entry below. This will be your Bold or if you prefer HTML language strong button.

edButtons[edButtons.length] =
new edButton('ed_strong'
,'b'
,''
,''
,'b'
);

You can add anything after that or before that. For example I use WP-CodeBox for all of my code entries. It puts them in these pretty boxes with some nice features if I encase my code in a pre statement and tell it what type of language. So I simply added a new button called pre and adds the pre statement to the beginning and to the end of the highlighted text. I also told it to define the language by default as just text.

Please note WP-CodeBox will not handle HTML pre syntax so I have modified it like so.

 

.

edButtons[edButtons.length] =
new edButton('ed_pre'
,'pre'
,'
'
,'

'
,'c'
);

iSCSI init script supporting MySQL checking

Filed under: centos, iscsi, linux, mysql, shell scripts — Tags: , , , — lancevermilion @ 10:17 am

Here is a iSCSI init script for CentOS 5.x. I presume it will work on all flavors of Linux, but haven’t tested. This init script is the original init script but modified to support checking for MySQL databases that might be using the iSCSI mounted disk. So we do not want to umount the iSCSI disk while MySQL is running. I also added checks to see if iscsid is actually running, if it is then make sure you are not already logged in. If you are then don’t try to login again. Also once iSCSI is successfully started we want to mount the iSCSI disk so it is available.

*NOTE: Make sure to adjust your boot init setup. Normally mysql will start before iscsi and iscsid EXCEPT for init 5. Which by default init 5 is the only level which will start mysqld. If you have changed this or yours if not the same make sure you account for this.


chkconfig --list | egrep "iscsi|mysql"
iscsi 0:off 1:off 2:off 3:on 4:on 5:on 6:off
iscsid 0:off 1:off 2:off 3:on 4:on 5:on 6:off
mysqld 0:off 1:off 2:off 3:off 4:off 5:on 6:off

init level 3

ls -l /etc/rc.d/rc3.d/ | egrep -i "mysql|iscsi" | awk '{print $9, $10, $11, $12;}'
K36mysqld -> ../init.d/mysqld
S07iscsid -> ../init.d/iscsid
S13iscsi -> ../init.d/iscsi

init level 5

ls -l /etc/rc.d/rc5.d/ | egrep -i "mysql|iscsi" | awk '{print $9, $10, $11, $12;}'
S07iscsid -> ../init.d/iscsid
S13iscsi -> ../init.d/iscsi
S64mysqld -> ../init.d/mysqld

/etc/init.d/iscsi

#!/bin/sh
#
# chkconfig: 345 13 89
# description: Logs into iSCSI targets needed at system startup
#
# Source function library.
. /etc/init.d/functions

PATH=/sbin:/bin:/usr/sbin:/usr/bin

RETVAL=0

start()
{

        status iscsid > /dev/null 2>&1
        RETVAL=$?

        if [ $RETVAL -ne 0 ]; then
                /etc/init.d/iscsid start
        fi


        status iscsid > /dev/null 2>&1
        RETVAL=$?

        #
        # Verify iscsi is logged in to the iscsi disk
        # and iscsid is actually running.
        #
        iscsiadm -m session -R > /dev/null 2>&1
        iscsiadmcheck=$?
        if [ $RETVAL -eq  0 ]; then
           if [ $iscsiadmcheck -ne "0" ]; then
             echo -n $"Setting up iSCSI targets: "
             # this script is normally called from startup so log into
             # nodes marked node.startup=automatic
             iscsiadm -m node --loginall=automatic
             touch /var/lock/subsys/iscsi
             success
             echo
             sleep 5
             mount -a -O _netdev
           else
             action $"iscsid: " /bin/true
             echo "iscsi:   [ is running ]"
           fi
        else
           action $"Starting iscsid: " /bin/false
           RETVAL=1
        fi
}

stop()
{
        rm -f /var/lock/subsys/iscsi

        # If this is a final shutdown/halt, do nothing since
        # lvm/dm, md, power path, etc do not always handle this
        if [ "$RUNLEVEL" = "6" -o "$RUNLEVEL" = "0" -o "$RUNLEVEL" = "1" ]; then
                success
                return
        fi

        # Do NOT turn off iscsi if root is possibly on a iscsi disk
        rootopts=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $4; }}' /etc/mtab)
        if [[ "$rootopts" =~ "_netdev" ]] ; then
                action $"Stopping iscsid: " /bin/false
                echo $"Can not shutdown iSCSI. Root is on a iSCSI disk."
                exit 1
        fi

        #
        # MySQL checking. If MySQL loads a DB from an iscsi disk we need to make sure
        # MySQL is NOT running before we shutdown iscsi and umount the iscsi disk.
        #
        mysqlopts=$(awk '{  if ( $1 ~ /^datadir/ ) { gsub("datadir=", "", $1); print $1; } }' /etc/my.cnf)
        iscsiopts=$(awk -v mysqlopts=$mysqlopts '{ if ($1 !~ /^[ \t]*#/ && $2 != "/" && mysqlopts ~ $2 ) { print $4; }}' /etc/mtab)
        /etc/init.d/mysqld status > /dev/null 2>&1
        mysqlcheck=$?
        if [[ "$iscsiopts" =~ "_netdev" ]] ; then
                if [ "$mysqlcheck" -eq 0 ]; then
                  action $"Stopping iscsid: " /bin/false
                  echo "Can not shutdown iSCSI. MySQL is mounted on a iSCSI disk."
                  exit 1
                fi
        fi
        iscsiadm -m node --logoutall=all
        /etc/init.d/iscsid stop
        success

        status iscsid > /dev/null 2>&1
        RETVAL=$?
        iscsiadm -m session -R > /dev/null 2>&1
        iscsiadmcheck=$?
        if [[ "$iscsiadmcheck" -ne 0 && $RETVAL -ne 0 ]]; then
          umount -a -O _netdev
        else
           action $"Stopping iscsid: " /bin/false
           echo "iSCSI did NOT logout successfully"
           RETVAL=1
        fi
}

case "$1" in
        start)
                start
                ;;
        stop)
                stop
                ;;
        restart)
                stop
                start
                ;;
        status)
                status iscsid
                RETVAL=$?
                ;;
        condrestart)
                [ -f /var/lock/subsys/iscsi ] && restart
                ;;
        *)
                echo $"Usage: $0 {start|stop|restart|status|condrestart}"
                exit 1
esac
exit $RETVAL

/etc/init.d/iscsid

#!/bin/sh
#
# chkconfig: 345 7 89
# description: Starts and stops the iSCSI daemon.
#
# processname: iscsid
# pidfile: /var/run/iscsid.pid
# config:  /etc/iscsi/iscsid.conf

# Source function library.
. /etc/init.d/functions

PATH=/sbin:/bin:/usr/sbin:/usr/bin

RETVAL=0

start()
{
        echo -n $"Turning off network shutdown. "
        # we do not want iscsi or network to run during system shutdown
        # incase there are RAID or multipath devices using
        # iscsi disks
        chkconfig --level 06 network off
        rm /etc/rc0.d/*network
        rm /etc/rc6.d/*network

        echo -n $"Starting iSCSI daemon: "
        modprobe -q iscsi_tcp
        modprobe -q ib_iser
        daemon iscsid
        RETVAL=$?
        echo
        [ $RETVAL -eq 0 ] || return

        touch /var/lock/subsys/iscsid

        success
        echo
        sleep 5
}

stop()
{
        rm -f /var/lock/subsys/iscsid

        # If this is a final shutdown/halt, do nothing since
        # we may need iscsid for as long as possible (halt script kills
        # us at the last second)
        if [ "$RUNLEVEL" = "6" -o "$RUNLEVEL" = "0" -o "$RUNLEVEL" = "1" ]; then
                success
                return
        fi

        # don't turn off iscsi if root is possibly on a iscsi disk
        rootopts=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $4; }}' /etc/mtab)
        if [[ "$rootopts" =~ "_netdev" ]] ; then
                echo $"Can not shutdown iSCSI. Root is on a iSCSI disk."
                exit 1
        fi

        mysqlopts=$(awk '{  if ( $1 ~ /^datadir/ ) { gsub("datadir=", "", $1); print $1; } }' /etc/my.cnf)
        iscsiopts=$(awk -v mysqlopts=$mysqlopts '{ if ($1 !~ /^[ \t]*#/ && $2 != "/" && mysqlopts ~ $2 ) { print $4; }}' /etc/mtab)
        /etc/init.d/mysqld status > /dev/null 2>&1
        mysqlcheck=$?
        if [[ "$iscsiopts" = "rw,_netdev" ]] ; then
                if [ "$mysqlcheck" -eq 0 ]; then
                  echo "Can not shutdown iSCSI. MySQL is on a iSCSI disk."
                  exit 1
                fi
        fi


        echo -n $"Stopping iSCSI daemon: "

        # iscsid does not have a nice shutdown process.
        # It really should never be stopped
        #pkill -KILL iscsid
        killproc iscsid
        echo

        modprobe -r ib_iser 2>/dev/null
        modprobe -r iscsi_tcp 2>/dev/null
}

restart()
{
        stop
        start
}

case "$1" in
        start)
                start
                ;;
        stop)
                stop
                ;;
        restart)
                stop
                start
                ;;
        status)
                status iscsid
                RETVAL=$?
                ;;
        condrestart)
                [ -f /var/lock/subsys/iscsid ] && restart
                ;;
        *)
                echo $"Usage: $0 {start|stop|restart|status|condrestart}"
                exit 1
esac

exit $RETVAL

MySQL init script supporting iSCSI disk mount checking

Filed under: centos, iscsi, linux, mysql, shell scripts — Tags: , , — lancevermilion @ 9:45 am

Here is a MySQLd init script for CentOS 5.x. I presume it will work on all flavors of Linux, but haven’t tested. The init script is the original init script but modified to support checking for iSCSI disk support. Basically if the my.cnf specifies a directory that is on an iSCSI mounted disk it will make sure iscsi/iscsid are running and the mount is present in /etc/mtab. I also added a check to see if MySQL is already running and if so do NOT try to restart mysql when a user issues “/etc/init.d/mysqld start”. Basically The user must first issue “/etc/init.d/mysqld restart” or “/etc/init.d/mysqld stop” then “/etc/init.d/mysqld start”. I also added a chkconfig bit. MySQLd needs to start after iSCSI has started just in case it needs to the iSCSI disk. Multipath should be enabled with “/sbin/chkconfig multipathd on” which by default sets init levels 2, 3, 4, and 5 to on. So you would have the services start up as so: multipathd, iscsid, iscsi, mysqld. They will shut down in reverse order: mysqld, iscsi, iscsid, multipathd.


#!/bin/bash
#
# mysqld This shell script takes care of starting and stopping
# the MySQL subsystem (mysqld).
#
# chkconfig: 345 64 36
# description: MySQL database server.
# processname: mysqld
# config: /etc/my.cnf
# pidfile: /var/run/mysqld/mysqld.pid

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

prog="MySQL"

# extract value of a MySQL option from config files
# Usage: get_mysql_option SECTION VARNAME DEFAULT
# result is returned in $result
# We use my_print_defaults which prints all options from multiple files,
# with the more specific ones later; hence take the last match.
get_mysql_option(){
result=`/usr/bin/my_print_defaults "$1" | sed -n "s/^--$2=//p" | tail -n 1`
if [ -z "$result" ]; then
# not found, use default
result="$3"
fi
}

get_mysql_option mysqld datadir "/var/lib/mysql"
datadir="$result"
get_mysql_option mysqld socket "$datadir/mysql.sock"
socketfile="$result"
get_mysql_option mysqld_safe log-error "/var/log/mysqld.log"
errlogfile="$result"
get_mysql_option mysqld_safe pid-file "/var/run/mysqld/mysqld.pid"
mypidfile="$result"

start(){
#
# iscsi checking. If we need mysql to create/load a DB that is one an iscsi
# disk we ned to make sure iscsi is running, we can successfully login,
# and verify the iscsi disk is moutned before starting mysql.
#
status mysqld > /dev/null 2>&1
mysqlcheck=$?
mysqlopts=$(awk '{ if ( $1 ~ /^datadir/ ) { gsub("datadir=", "", $1); print $1; } }' /etc/my.cnf)
iscsiopts=$(awk -v mysqlopts=$mysqlopts '{ if ($1 !~ /^[ \t]*#/ && $2 != "/" && mysqlopts ~ $2 ) { print $4; }}' /etc/mtab)
status iscsid > /dev/null 2>&1
iscsicheck=$?
if [ "$mysqlcheck" -eq 0 ]; then
echo "MySQL [ already running ]"
exit 1
else
if [ "$iscsicheck" -ne 0 ] ; then
if [[ "$iscsiopts" =~ "_netdev" ]]; then
action $"Checking iscsid: " /bin/true
action $"Starting $prog: " /bin/false
echo "Can not start MySQL, iSCSI disk is not mounted. MySQL is on a iSCSI disk."
exit 1
fi
elif [ "$iscsicheck" -eq 0 ]; then
if [[ "$iscsiopts" =~ "_netdev" ]]; then
iscsiadm -m session -R > /dev/null 2>&1
iscsiadmcheck=$?
if [ "$iscsiadmcheck" -ne 0 ]; then
action $"Checking iscsid: " /bin/true
action $"Starting $prog: " /bin/false
echo "iSCSI login check failed. QUITING!!!"
exit 1
fi
fi
else
action $"Checking iscsid: " /bin/false
action $"Starting $prog: " /bin/false
echo "Can not start MySQL, iSCSI is not running. MySQL is on a iSCSI disk."
exit 1
fi
fi
touch "$errlogfile"
chown mysql:mysql "$errlogfile"
chmod 0640 "$errlogfile"
[ -x /sbin/restorecon ] && /sbin/restorecon "$errlogfile"
if [ ! -d "$datadir/mysql" ] ; then
action $"Initializing MySQL database: " /usr/bin/mysql_install_db
ret=$?
chown -R mysql:mysql "$datadir"
if [ $ret -ne 0 ] ; then
return $ret
fi
fi
chown mysql:mysql "$datadir"
chmod 0755 "$datadir"
# Pass all the options determined above, to ensure consistent behavior.
# In many cases mysqld_safe would arrive at the same conclusions anyway
# but we need to be sure.
/usr/bin/mysqld_safe --datadir="$datadir" --socket="$socketfile" \
--log-error="$errlogfile" --pid-file="$mypidfile" \
>/dev/null 2>&1 &
ret=$?
# Spin for a maximum of N seconds waiting for the server to come up.
# Rather than assuming we know a valid username, accept an "access
# denied" response as meaning the server is functioning.
if [ $ret -eq 0 ]; then
STARTTIMEOUT=30
while [ $STARTTIMEOUT -gt 0 ]; do
RESPONSE=`/usr/bin/mysqladmin -uUNKNOWN_MYSQL_USER ping 2>&1` && break
echo "$RESPONSE" | grep -q "Access denied for user" && break
sleep 1
let STARTTIMEOUT=${STARTTIMEOUT}-1
done
if [ $STARTTIMEOUT -eq 0 ]; then
echo "Timeout error occurred trying to start MySQL Daemon."
action $"Starting $prog: " /bin/false
ret=1
else
action $"Starting $prog: " /bin/true
fi
else
action $"Starting $prog: " /bin/false
fi
[ $ret -eq 0 ] && touch /var/lock/subsys/mysqld
return $ret
}

stop(){
MYSQLPID=`cat "$mypidfile" 2>/dev/null `
if [ -n "$MYSQLPID" ]; then
/bin/kill "$MYSQLPID" >/dev/null 2>&1
ret=$?
if [ $ret -eq 0 ]; then
STOPTIMEOUT=60
while [ $STOPTIMEOUT -gt 0 ]; do
/bin/kill -0 "$MYSQLPID" >/dev/null 2>&1 || break
sleep 1
let STOPTIMEOUT=${STOPTIMEOUT}-1
done
if [ $STOPTIMEOUT -eq 0 ]; then
echo "Timeout error occurred trying to stop MySQL Daemon."
ret=1
action $"Stopping $prog: " /bin/false
else
rm -f /var/lock/subsys/mysqld
rm -f "$socketfile"
action $"Stopping $prog: " /bin/true
fi
else
action $"Stopping $prog: " /bin/false
fi
else
ret=1
action $"Stopping $prog: " /bin/false
fi
return $ret
}

restart(){
stop
start
}

condrestart(){
[ -e /var/lock/subsys/mysqld ] && restart || :
}

# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status mysqld
;;
restart)
restart
;;
condrestart)
condrestart
;;
*)
echo $"Usage: $0 {start|stop|status|condrestart|restart}"
exit 1
esac

exit $?

November 3, 2008

SQL commands

Filed under: mysql, sql — Tags: , — lancevermilion @ 1:40 pm
mysql> select table2.name, phone_number, email_address, count(t1.field1_id) from table1 t1 right outer join table2 t2 on (t1.field1_id = t2.field1_id) group by t2.name;

This will create an output similar to this.

The “Table2 Name” is just a distinct list from the name field of table2 table.
The “# of entries per name in table2” is just a result from count( where field1_id(from
table1 table) = field1_id (from table2 table) )

+————————————-+————————————————–+
| Table 2 Name               | # of entries per name in table2 |
+————————————-+————————————————–+
| xxxx.xxx.1.S000018      |                                          43 |
| x.xxx.xxxx.1.s000032    |                                           5 |
| xxxx01                        |                                           13 |
| xxxx03                        |                                           15 |
| xxx.xxx.xx.1.s000031   |                                           17 |
| xxx.x.xxxx.s00017       |                                           28 |
| xxx.xxx.s000003         |                                           47 |
| xxx.xxx.aaaabbb         |                                            0 |
+————————————-+————————————————–+

Blog at WordPress.com.