2022/09/23

Make the simple things difficult

Would it really be so hard to show how to replace one SID with another in a file ACL?
  $acl = get-acl thefile
  $sddl_orig = $acl.sddl
  $new_sddl = $sddl_orig -replace 'S-1-oldsid' 'S-1-newsid'
  $acl.SetSecurityDescriptorSddlForm($new_sddl)
  $acl | set-acl
Yes, this can be condensed to a single line, but as far as I can google, nobody has it:
  gci | get-acl | foreach { $_.setsecuritydescriptorsddlform($_.sddl.replace('S-1-oldsid','S-1-newsid'))} | set-acl

2019/03/26

Automating SSH tunnels

I need a persistent port forwarding configuration between two systems, where there may be more than one SSH jump between the two.  I want systemd to make sure it's running all the time.

A solution:
    # Systemd unit file for an SSH Tunnel service
    #
    [Service]
    Type=simple

    User=tunnel
    ExecStart=/usr/bin/ssh -F /home/tunnel/ssh-config-for-tunnel -vN tunnel.%i

    # On failure, wait 10 seconds to restart
    Restart=always
    RestartSec=10

    # 20 failures within a 10 minute window marks this service as failed.
    StartLimitInterval=600
    StartLimitBurst=20

    [Unit]
    Description="SSH Tunnel to %i"
    Requires=network-online.target

    [Install]
    WantedBy=multi-user.target
From here, I create a trusted keypair with
ssh-keygen -t ed25519
and configure the ssh-config-for-tunnel file:
# Configuration of the SSH tunnel from here to there
# Requirements:
#   This file in /home/tunnel/ssh-config-for-tunnel

#   Service /etc/systemd/system/ssh-tunnel@.service enabled and started
#
#   Additional tunnels can be enabled as ssh-tunnel@elsewhere.service

# Special defaults for tunnels
Host *
    ControlMaster no
    ExitOnForwardFailure yes
    IdentitiesOnly yes

#####################################################################
# Configure Tunnel:
#####################################################################
Host tunnel.myservice
    ### Connection:
    # Private IP of ultimate destination
    HostName 172.31.92.114
    # Identity on the CB master
    IdentityFile ~/.ssh/id_master
    # Public IP of Jump 1 bastion
    ProxyJump 192.168.100.142

    ### Tunnels:
    # Take near port :18443 and send it to master's listener
    LocalForward 8444 localhost:8443
    # Take far port :6100 and bring it back to local listener
    RemoteForward 6100 161.134.130.247:6100

# Jump configurations
Host 192.168.100.142
    # Configuration for the bastion system
    IdentityFile ~/.ssh/id_ed25519
    ProxyJump 10.192.107.33

Host 10.192.107.33
    IdentityFile ~/.ssh/id_ed25519

This example connects from localhost to 10.192.107.33, then from there to 192.168.100.142, then from there to 172.31.92.114, the server that I need the tunnel to, and it sets up port forwarding from end to end, without trying to get the ports on the series of jump servers.

2019/01/11

Create a python virtualenvironment and matching Jupyter kernel

I often work in Jupyter notebook for python scriptlets, and if there's a special package I need, I'd rather not pollute my global python environment. The answer, of course, is virtualenv and a jupyter kernel that references that venv, which I have to look up the command for every time.

 Automation to the rescue-- here's newkernel.cmd:

@echo off
REM newkernel.bat - create a python virtualenv and register it as a
REM Jupyter kernel
REM

SET /P _envname="Name of environment:"
if "%_envname%x" NEQ "x" goto :got_name
@REM else
     set _envname=py-%USERNAME%-%RANDOM%
@REM fi
:got_name

C:\tools\Anaconda3\python.exe -m venv %_envname%.venv

set /P _envkern="Kernel name:"
if "%_envkern%x" NEQ "x" goto :got_kern
@REM else
     set _envkern=py-%_envname%
@REM fi
:got_kern

set /P _envdesc="Kernel Description:"
if "%_envdesc%x" NEQ "x" goto :got_desc
@REM else
     set _envdesc="Python (%_envname%)"
@REM fi
:got_desc

%_envname%.venv\scripts\pip install ipykernel
%_envname%.venv\scripts\python -m ipykernel install --name %_envkern% --display-name "%_envdesc%"

2018/03/06

Automatically renew internal SSL certificates (DRAC and Windows)

A bunch of our DRACs have certificates that are about to expire.  I know I could go in and generate a new CSR in each web interface, copy them into the AD Certificate Services, and upload the results (that's how the previous admin did it) but.... I'm lazy.

Plus, new certificates generated that way still give a big warning since Chrome 58-- they don't have the X509v3 SAN extension which is now mandatory apparently.


C:\> "\Program Files\Dell\SysMgt\rac5\racadm.exe" -r dracname.dom.ain -u root -p redacted sslcsrgen -g -f dracname.dom.ain.csr
Security Alert: Certificate is invalid - Name on Certificate is invalid or does not match site name
Continuing execution. Use -S option for racadm to stop execution on certificate-related errors.
CSR generated and downloaded from RAC successfully

C:\> certreq -submit -attrib "san:dns=dracname.dom.ain\nCertificateTemplate: WebServer" dracname.dom.ain.csr dracname.dom.ain.crt
Active Directory Enrollment Policy
  {BFF41397-4CCE-41B5-AD8E-A029B2C2353B}
  ldap:
RequestId: 104238
RequestId: "104238"
Certificate retrieved(Issued) Issued  The certificate validity period will be shorter than the WebServer Certificate Tem
plate specifies, because the template validity period is longer than the maximum certificate validity period allowed by 
the CA.  Consider renewing the CA certificate, reducing the template validity period, or increasing the registry validit
y period.

C:\> "\Program Files\Dell\SysMgt\rac5\racadm.exe" -r dracname.dom.ain -u root -p redacted sslcertupload -t 1 -f dracname.dom.ain.crt
Security Alert: Certificate is invalid - Name on Certificate is invalid or does not match site name
Continuing execution. Use -S option for racadm to stop execution on certificate-related errors.
Certificate successfully uploaded to the RAC. The RAC will now
reset to enable the new certificate and may be offline temporarily.

C:\> "\Program Files\Dell\SysMgt\rac5\racadm.exe" -r dracname.dom.ain -u root -p redacted sslcertview -t 1
Serial Number            : redacted

Subject Information:
Country Code (CC)        : AU
State (S)                : Some-State
Locality (L)             : MyTown
Organization (O)         : Internet Widgits Pty Ltd
Organizational Unit (OU) : World Wide Web Pty Ltd
Common Name (CN)         : *.dom.ain

Issuer Information:
Common Name (CN)         : AD DOM.AIN Root Trust CA

Valid From               : Mar  6 16:01:02 2018 GMT
Valid To                 : Nov  6 15:13:19 2019 GMT

And the warning goes away for another year. And it took me less time to figure out how to automate it (throw the above commands into a .bat) than it would have to loop through all of them with a browser!

--Joe

2017/06/18

iPhone backup that wasn't

Spent a bit of time this weekend trying to help my cousin copy everything off of her iPhone 6, so that it can be wiped and transferred to another person.  But since I'm stubborn and contrary, I didn't want to do it in iTunes (plus I didn't have her password)...

Enter libimobiledevice, and idevicebackup, referenced by a nice post from Santoku Linux https://santoku-linux.com/howto/mobile-forensics/howto-create-a-logical-backup-of-an-ios-device-using-libimobiledevice-on-santoku-linux/ .  But since I'm stubborn and contrary, the CD image wouldn't install in VirtualBox on my laptop.  Sigh.  Ok, build from source.  Vagrant ubuntu, then clone libimobiledevice and just about all the other pieces of their github, run idevicebackup and... well, this iPhone is too new, try using idevicebackup2.  Cool, backing up, ##### marks dancing across the screen in little boxes, stuff being written unencrypted to disk, excellent.

Verify that the backup is readable and not encrypted, sweeet.  Now what did I get in my 2.5GB of disk space?  I still have no idea.

idevicebackup has an "unback" command that should convert the plist and SQLite files into a meaningful folder structure, which is said to work on version of IOS > 6.  Unfortunately, the feature on the phone (which needs to be plugged in) that they were using to read and translate the backup was broken between IOS 10.3.0 and 10.3.1 (this fact was, and still is undocumented in the toolset, except for the closed github issue).  So unback is not available.

End state: 2.5GB of possibly-useful-in-the-future data, and a wiped iPhone.   Oh well, that's life on the bleeding edge of tech.

2017/04/26

What I've learned today

A couple of useful Java tricks that I can't find consolidated elsewhere on the web:

Locking down Java: 

I have a Java instance that runs just my one application. (for example, /opt/foo/jre/bin/java) This application talks across systems, and can be set to use SSL. I don't want to pay for a "real" certificate-- I'll use our internal CA, besides, I don't really want to trust Verisign or any of the other 300+ CAs that Oracle/IBM have decided they like. (No offense intended, just paranoia about MITM attacks within my LAN)

Let's assume that I have this part working, and that SSL is being served happily on the first server.
I'll start by extracting the certificate chain from that first server:
:| openssl s_client -host firstinstance -port 8443 -prexit \
           -showcerts >firstinstance.crt
(No, that's not an emotionless command emoticon, it's a pipe)

From there, I can manipulate the Java keystore to trust (or not trust) my targets.
keytool -import -alias firstinstance -file firstinstance.crt \
  -keystore paranoid.jks -storepass changeme -noprompt \
  && cp paranoid.jks /opt/foo/jre/lib/security/cacerts

Did it work?:

Well, let's check.  Using the same Java environment as our app:
$ JRE_HOME=/opt/foo/jre
$ JAVA_HOME=/opt/foo/jre
$ /opt/foo/jre/bin/java -cp . SSLPoke firstinstance 8443
Successfully connected
In theory, a restart of the app should have it pick up the new (single-entry) list of trusted certificates. In practice...

WTF file is it loading from?

Hidden somewhere in the depths of the startup script for the app, something gets redefined so that instead of looking in $JAVA_HOME/lib/security/cacerts (which has been nicely cleaned up), it used /opt/foo/lib/security/cacerts. (But of course, I didn't know that until.. Hammer)
# apt-get install -y sysdig
# sysdig proc.name=java and evt.type=open | grep cacerts & systemctl restart foo
#7554308 14:25:48.107476643 3 java (6613) < open fd=22(/opt/foo/lib/security/cacerts) name=/opt/foo/lib/security/cacerts flags=1(O_RDONLY) mode=0 
Ah, there's the file I need to mangle for my application.

You may have noticed I slipped in the SSLPoke command above. That's a fetch of https://confluence.atlassian.com/download/attachments/117455/SSLPoke.java -- Thanks, #Atlassian!

2016/09/23

systemd unit file names

TL;DR: custom systemd unit files can not have "-" in their name, or at least mine can't.

I like to have third-party software installed in a version-specific directory.  In particular, I'm trying to get Elasticsearch to live in /opt/elasticsearch-2.4.0/ with a symlink /opt/elasticsearch -> /opt/elasticsearch-2.4.0, especially for service software that I might need to run multiple versions.  I'm using Ubuntu 16.04 (Xenial/LTS) so I'm forced to deal with systemd files that are not delivered OOTTB.  For comparison, I can install the .deb that elastic.co distributes, but that installs itself in /usr/, which means only one version.

Fortunately, the unit file is very simple:

[Unit]
Description=Elasticsearch 2.4.0
Documentation=http://www.elastic.co
Wants=network-online.target
After=network-online.target

[Service]
Environment=ES_HOME=/opt/elasticsearch-2.4.0
Environment=CONF_DIR=/opt/elasticsearch-2.4.0/config
Environment=DATA_DIR=/var/lib/elasticsearch
Environment=LOG_DIR=/var/log/elasticsearch
Environment=PID_DIR=/var/run/elasticsearch
EnvironmentFile=-/etc/default/elasticsearch-2.4.0

WorkingDirectory=/usr/share/elasticsearch

User=elasticsearch
Group=elasticsearch
ExecStart=/opt/elasticsearch-2.4.0/bin/elasticsearch

I save this as /usr/lib/systemd/system/elasticsearch-2.4.0.service, and... nothing happens.  Install the .deb, check that it has the right unit files (starts service ok).  copy /usr/lib/systemd/system/elasticsearch.service as elasticsearch-2.4.0.service -- This should use the exact same config options, just run with a different service name, and nothing.  Purge the .deb and put my unit file (above) in elasticsearch.service, and it runs.

The closest I can come to documentation of why servicename -dash- something is in the man page:
Some unit names reflect paths existing in the file system namespace.  Example: a device unit dev-sda.device [...]
 So there might be something special about unit names with a dash in them?  Hmm, mv elasticsearch.service elasticsearch_2.4.0.service ; systemctl daemon-reload ; service elasticsearch_2.4.0 start.  By golly, that works.

I guess I'll change the service naming.  (But note, cfengine3-web is apparently a perfectly valid systemd unit name for CFEngine Enterprise)

2014/12/28

Small Business Server crash and recovery

I'm the "tech guy" for my parents' small business, and the new point of sale software for them runs on top of MSSQL on Windows Server.

Step 1: Buy a system with Windows Server 2012 on it.  (Check.  $900 from Microcenter)
Step 2: Take it home and set it up so that the POS people can install their software on it.
Step 3: ???
Step 4: Profit.

Actually, I'm stuck in the middle of step 2.  I have to take this opportunity to make it more enterprisey, even though I have very little experience with modern Windows Server technologies... But how hard can it be?  I just want a server that can sit in their basement, run MSSQL and the POS app, plus do other little tasks, like print queueing and that sort of thing... And allow employees and owners to connect in remotely so that they can travel... And maybe help protect the terminals' web browsers from malware... and I need to be able to support it remotely.  And....

So I figure I have to do all this stuff anyway, I'll just go ahead and set it all up: Active Directory, VPN, Internet gateway/proxy, etc.  MSSQL will be the POS guy's problem :)

On the bright side, the server I bought has a Supermicro motherboard that supports KVMoverIP via IPMI.  Which means I can sit with my laptop on the couch, while the server sits in the basement without a keyboard or monitor.  Unfortunately, "in the basement" at the moment means in the middle of a construction zone.  The only flat place to put it (that was close enough to the shelf that has my Internet router) was on top of the washing machine.  Which apparently vibrates enough when it's running to bounce everything off of it.  So the server fell the 5 feet to our new concrete floor.  Crash.

Both hard drives are misbeaving, and there are broken platic bits of the front of the case.

Luckily, I have a spare 1TB hard drive in stock.

2014/05/01

Ok, iostat, what's the mountpoint

Fixing^WDiagnosing^WLooking at a performance problem, we're pretty sure it is a disk issue. iostat is helpful (for showing what's generally going on) but I have to keep remembering that /dev/sdk is mounted as oradata3 (etc). So instead, here's a script that remembers it for me:
iostat -xk 5 | sed -e "$(mount | awk '/ext3/{print $1"/"$3}' | awk -F/ '/dev/{printf "s/%-10s/%-10s/\n",$3,$NF}')"
Look at the mounted filesystems. If they're EXT3, grab the first and third entry (dev and mountpoint) and write out "s/sdk /oradata3 /" (spacing is important to keep the iostat columns aligned). Pass that to sed to transform the iostat output. --Joe

2013/09/09

Greenplum DCA and my roll-my-own ETL host

I'm trying to get my new Dell server with its 10gigE network cards to talk to the back-end switch of my greenplum DCA.
Other than the fact that Brocade doesn't seem to understand the difference between a support matrix that says "Using non-Brocade cables is not supported" and a software feature that checks to see if the inserted standards-compliant cable was manufactured by Brocade (vs a standards-compliant cable made/sold by Dell) and if not turning off the port. And other than the Dell sales tool not pointing out this incompatibility, I'm in good shape.
Once there's a link at the SFP+ layer, however, the greenplum switches are not set up for ETL work out of the box... And of course, since these back-end switches are not connected to the "real" network, I have to ssh-tunnel to get to the Switch Admin web tools.
The unused ports on the switches are set up as link aggregation members, and so do not work without even more of these cables. So first, I have to take them out of the CEE LAG groups (first disable the port via Port administration). Switch Administration -> CEE -> Link Aggregation, Edit LAG Group 2, and take out Te 0/18.
Then back over to Port Admin, to change the port to L2 Access mode, and we can enable it.
And finally, back over to Switch Administration -> CEE -> VLAN, edit VLAN 199, and add the Te 0/18 interface to the vlan.
And we have packets moving.
Testing with "gpssh -f hostfile ping -c 3 etl1-1" and "gpssh -f hostfile ping -c 3 etl1-2"
--Joe

2013/02/25

Moloch packet capture

I'm working to set up a full packet capture environment for our network, and so far Moloch is quite attractive. It seems "easy" to get started and so far is scaling out nicely. Unfortunately, it is almost completely undocumented. There's clearly a lot of power under the covers, but I'm having to dig through the source to figure it out. Oh well, I used to be a programmer. Here's some of what I have found so far. The easybutton-build.sh script works well. It downloads specific known-working versions of various dependencies (yara, libpcap, libnids, maxmind's geoip API) which is reasonable, and a libglib version, which is not. Really, let's not have to rebuild from scratch to fix a bug in a shared library. Just use the versions that the distribution provides unless there's a really good reason. apt-get install libgeoip-dev libglib2.0-dev libpcap-dev libnids-dev In my case (Ubuntu 12.10) this gives me the right version of geoip, +.14 versions of glib, the right version of libpcap, and -.01 version of libnids. Let's see if it all works with these minor differences. Now, on to the hacking...

2013/01/16

Common Event Format parsing

I've got some data in "Common Event Format" from our new Arcsight appliance, and I need to get it (or at least major parts of it) into a relational database. This should be fairly straightforward, except that the CEF format doesn't lend itself to be parsed easily.

CEF (if you're not aware) is a supposed standard that HP/Arcsight has for exchanging event data. I've found it described at various dead links to the arcisght.com website, or one active location at http://mita-tac.wikispaces.com/file/view/CEF+White+Paper+071709.pdf .

In theory, it has everything needed to wrap up any sort of event data into a convenient wrapper format. It's a pipe-delimited format, UTF-8 encoded, and each line indicates the CEF version (CEF:0 in all the data I have) so it's futureproof.

Except that it isn't really pipe-delimited. Sure, the first 7 columns are pipe-delimited, and have well-defined column names. And pipes embedded in the first 7 columns must be escaped with a backslash, and there's no support for quoting the value to escape the contents. But oh well, other than that, it's just a matter of looking for the first non-escaped 7 pipes.

It's the 8th column that's giving me fits, though. In order to make CEF a useful standard, everything interesting about the event is stuffed into the "Extension" field, which is made up of key=value pairs, where the keys and values are vendor-defined.

This Extension field is not pipe-delimited. It's space-separated key=value pairs. And the value can contain space characters without any protection. The only thing that's restricted in the values are \\, \=, \r, and \n. The following is a perfectly legal extension:

foo=bar baz=0
This straightforwardly sets two keys (foo and baz) to their appropriate values. Another valid extension is
foo=bar anotherkey=c:\\program files\\ceci n'est pas une pipe (|) has an \= to us!\n\\ so go away baz=0
This would set the same keys as above (foo and baz) plus the "anotherkey" would be set to
c:\program files\ceci n'est pas une pipe (|) has an = to us!
\ so go away

So to parse the CEF record, first I need to look at the first 7 columns where the only legal escapes are \| and \\, and I get 7 nicely-named fields. Then take the rest of the line, and split it on unescaped =, look back one word from there, and that becomes the key, and everything up to the last word before the next = is the value. (I'm pretty sure that the key can not contain a space, but that's not stated in the spec)

Here's what I came up with to parse out the extension pairs. Note that I'm not a great perl optimizer, suggestions are welcome.

        # Pull off thefirst keyword
        (undef,$key,$extension) = split( /([^\s]+)=/, $extension, 2);
        while ( $key ne "" ) {
                # split returns the value, the part that matches the () in the split
                # expression, and the rest of the string.
                ($prevval,$nextkey,$extension)=split( /([^\s\\]+)=/, $extension, 2);
                ($line{$key}=$prevval) =~s/\s+$//; # Store the discovered key/value pair
                $key=$nextkey;
        }

2012/10/18

Using Windows (Active Directory) passwords for Ubuntu

For various auditing reasons, we have centralized our passwords into our Active Directory environment. (Also because everybody gets a Windows account, and AD can easily enforce password changes, strong passwords, etc).

Most of our Linux systems are RHEL, and it's very easy to have them use AD for its password store, via kickstart. In the Kickstart file, set the "auth" options to include "--enablekrb5 --krb5kdc=winDC.your.dom.ain:88 --krb5adminserver=winDC.your.dom.ain:749 --krb5realm=YOUR.DOM.AIN"

But of course, Ubuntu doesn't use Kickstart, and if I had many Ubuntu machines to deploy I'd figure out how to set it up automatically. In the mean time, it's not too hard.
sudo apt-get install libpam-krb5 krb5-user
kinit myusername # Check that things work
sudo pam-auth-update # Tell PAM that you want both KRB and local authentication
ssh localhost # Use your windows password to log in
And then go in and change your /etc/shadow entry to lock out the password you initially set for your username, by changing the encrypted string to *KRB*.

2012/04/13

OpenSSL to Java keystores

I've been creating SSL configurations for various groups in the company, and since I like the standard command line, I've been doing it via OpenSSL. However, some groups use Java-based SSL servers that need their .key and .cert in the Java Keystore format.

So to get the whole instruction set together in one place,

openssl genrsa -out servername.key 2048
openssl req -new -x509 -key servername.key -out servername.csr
#
#Send off the CSR to get it signed, and pull down the intermediate CA certificates that our internal authority uses to sign.
#
openssl pkcs12 -export -in servername.cert -certfile intermediate.cert -inkey servername.key > servername.p12
#Give it a password at least 6 characters long so that Java doesn't complain
keytool -importkeystore -srckeystore servername.p12 -destkeystore servername.jks -srcstoretype pkcs12

2012/02/17

Yet another annoyance

I tend to keep a lot of stuff on my hard drive. Modern drives are big, and modern filesystems don't have a problem with searching through long, fragmented free lists that made the old suggestion of "keep the disks less than 90% full" smart. I defrag occasionally, and (at least on my laptop) a high-speed SD card configured for Readyboost to improve application-launch induced disk seeks.

So I've been getting popups (no, not malware) for several months reporting that I'm running out of disk space. These are Windows-looking officialish "Warning Event Notification" popups, reporting that "disk free space has fallen below the configured threshold." Annoying, displays in the center of the screen (even when locked/logged off) and takes focus from my work.

It turns out this particular message is caused by the Dell OpenManage Client utility that the company uses to set the BIOS password for the system, and it's controlled by a registry key: HKLM\SOFTWARE\Dell\OpenManage\Client\SysInfo\HDDThresholdValue. I set it to 0 to get rid of the messages entirely.

--Joe

2011/08/24

Listening ports

One of our many applications wouldn't start, with an obscure message that had nothing to do with the underlying problem (nsrexecd "Cannot start portmapper", to be specific and to make sure this is googleable for the next person)

It turns out that another process had been randomly assigned the ports that Networker had to listen on, to an outgoing TCP connection. Which, of course, meant that Networker couldn't bind to those ports to LISTEN. This is the first time this has happened. But it's a potential time bomb for any service that listens on specific ports. Such as Oracle, Weblogic, SAP, etc.

Linux controls what ports are randomly assigned using two sysctl's, ip_local_port_range and ip_local_reserved_ports. Unfortunately, the Oracle installer prerequisite check requires that ip_local_port_range be set wrong (1024-65500, which includes their own listener port) so we have to work with the other one, ip_local_reserved_ports. It's a "comma-separated list of ranges", so for us, I picked an excessive range for our big 3 applications- Oracle (1520 - 1530), SAP (3200 - 3699), and Networker (7937 - 8065).

sysctl net.ipv4.ip_local_reserved_ports=1520-1530,3200-3699,7937-8065


--Joe

2011/07/21

Scanner characterization (free) to correct the colors in scanned pictures

I'm working to get my non-digital life in order by scanning in the large underbed box of photos that I've accumulated, but I've noticed that the color isn't quite right on the scanned images. The scanner "autocorrect colors" checkbox doesn't seem to help. I figure the best way to deal with it is to scan the pictures without any scanner-based color correction, and then apply a proper color modification to the resulting image. But the challenge is in 1) convincing the HP "easy scanning" junk to just give me the bits, and in 2) mapping the colors that the scanner sees to what's on the print.

Now, I could spend $60+ on a standardized color card, and use an expensive program to generate a color profile that could be applied to make the correction. But come on, it's just software. Instead, I am sending a color card I generated to the local Walgreens.com in-store pickup, and I'll use that to characterize the scanner. There's a toolset called Argyll that seems to do what I want, but it's not exactly the clearest documentation for someone who doesn't do digital image workflow for a living. But here's what I've figured out so far:

There's a zip of Windows executables. They seem to run on my Win7 laptop.

First, we generate a "target".
targen -v -d 2 target


This gives us a "target.ti1" (that's a one, btw) file.

Second, we turn this ti1 file into a TIF image (and at the same time we make a .cht map of the image that the tool will later use to recognize the image)
printtarg -i SS -v -a .4 -t 300 -p 4x6 -s -m 10 target


This gives us target.tif, and target.cht (and whatever target.ti2 is)

Third, since Walgreens only deals in .jpg files, I convert it to a 100% quality jpeg via GIMP. And I end up with a 336k file to have printed.


And now I'm waiting to pick up that picture.

Before I found the Argyll software, I had grand plans of figuring out the formulas to do the transformation myself in gimp. I made my own blocks of color, got them printed, and discovered that the transformations required to map the resulting RGB values to their originals was, well, let's just say complicated. Probably there is an easier formula in some other color metric (HSV or CMYK or something) but that's a lot of work to figure out.

My next attempt was with Argyll, but I thought the hexagonal color pattern was nicer than the color bars that come out of the default TIF. Unfortunately, Argyll won't create a CHT file to recognize the hexagons. So that was another $0.20 wasted. Oh well.

More to come.

--Joe

2011/06/13

Link aggregation in a cross-platform environment

Everybody in the world knows that LACP (802.1ad) is the standard for Link Aggregation and Control, right? Well, not exactly.

We have VMware ESX and Solaris servers connected to our Cisco edge switches. Sounds good, right? We'd like to bond the multiple gig-E NICs into a multi-GB aggregate. Sounds good, right? Well, it's not so easy.

ESX doesn't support true 802.1ad aggregation. They fake it with their vSwitch NIC teaming properties. They do the same thing as L3 LACP (hash of the source and destination IPs) but don't call it that. Fortunately, they use the same hash algorithm as Cisco, so we can work with it.

On the cisco side, we add the interfaces to a channel-group with mode "on". This uses the default-for-the-switch port-channel load-balance setting, which we had to set to src-dst-ip.

Unfortunately, since that setting is a global switch option and is not set on a per-port-channel level, this means that our Solaris boxes (who speak LACP properly) can't use Layer-4 (hash of source and dest IPs and ports) balancing. This sucks, because our Solaris boxes are the heavy-network-hitters (backup servers) that could really use the extra bandwidth provided by spreading the multiple TCP connections across multiple links.

I'm not sure who to blame here, VMware for not doing LACP, or Cisco for not allowing multiple loadbalancing methods on different port channel groups.

--Joe

2011/05/31

Oh yeah, the rest of EMC World

The last days of EMC world were fairly uneventful. I was called in on a couple of work problems, which made it hard to concentrate on the talks. But from what I could tell, they were all either high-level "cloud is king" or very introductory sessions, so I didn't really get much out of them.

I did have a nice seafood dinner at the Rio after the conference closed out, and a quite forgettable plane ride home.

Now, back to the real world.

--Joe

Cleaning up View Composer VMs

We've had frequent issues where our VMware View desktops will get into a state of Provisioning Error (missing) with a popup box that a "Virtual Machine with Input Specification already exists"

This symptom is described pretty well in http://kb.vmware.com/selfservice/microsites/search.do?cmd=displayKC&docType=kc&externalId=1008658, but here's some more info:

At least in the version of Composer 4.5 that I'm running, the sviconfig command doesn't know the RemoveSviClone that they reference in the KB. So it's the manual way for me.

This seems to happen if the Composer database bits get out of sync with what's in the ADAM database that View uses (Can we please pick ONE database).

This weekend's problems came when the Oracle DB that supports our VirtualCenter, View Composer, and Update Manager environments had a corrupted file. I had to roll back to a previous Oracle state, which naturally meant that it wasn't quite the same as ADAM.

The manual cleanup (besides being MSSQL-specific in table names and interface reference) requires a significant amount of C&P to run through in SQL/Plus. So I declared an Oracle procedure that, given a VM name, cleans up the data automatically:


create or replace procedure cleanup_clone
( p_vmname in varchar )
as
begin
delete from SVI_VM_NAME where NAME = p_vmname;
delete from SVI_COMPUTER_NAME where NAME = p_vmname;
delete from SVI_SC_PDISK_INFO where PARENT_ID in
(select id from SVI_SIM_CLONE where VM_NAME = p_vmname);
delete from SVI_SC_BASE_DISK_KEYS where PARENT_ID in
(select id from SVI_SIM_CLONE where VM_NAME = p_vmname);
delete from SVI_SIM_CLONE where VM_NAME = p_vmname;

commit;

end cleanup_clone;


With this in place, I can "execute cleanup_clone('uscimposer-99');" at the SQL/Plus prompt (having logged in as the Composer user) and it nicely wipes out the input specification for that VM, and a new one can be provisioned. The only other manual step then, is to remove the provisioning-error'd VM from the View Admin interface.

--Joe