Using Damn Small Linux to install a large ISO remotely to ESXi

While working with a client I had the unique issue of trying to upload a large ISO file to a ESXi datastore while being connected remotely through VPN. The UCOS for Cisco Unified Communications Manager and Cisco Unity Connection is over 5GB and trying to manage that download and moving it to a datastore can be challenging across small internet pipes especially when you do not have a local machine.

Enter Damn Small Linux, or DSL for short. This 50MB iso has all the tools you need in a small package to facilitate getting your ESXi environment up and running. Contained within is a GUI, FTP client, Firefox, NFS and others to get you going. After you are finished installing the UCOS the DSL guest can be deleted to fee up disk space or kept for other tasks.

The process is pretty simple; download DSL, upload it to the remote ESXi datastore, set it to boot the ISO, configure NFS, FTP or HTTP the larger ISO, mount the NFS datastore and start installing the large ISO directly. Below I detail the process to getting DSL up and running quick and easily.

  1. Download current.iso DSL from http://distro.ibiblio.org/damnsmall/current/
  2. Using the vSphere client copy current.iso to the ESXi datastore
  3. Create a new guest as Other Linux 2.6.x Kernel with 1 CPU, at least 256Mb RAM, E1000 network interface and a IDE virtual disk with at least 6GB(I used 9GB thin provisioned)
  4. Set the guest to boot the ISO by selecting Datastore ISO and browse for current.iso and set Device Status to “Connect at power on”
  5. Power on the guest and go to the Console tab, DSL should start to boot
  6. Once DSL has come up to the GUI install to hard disk and reboot
  7. Using the menu go to Setup –> Net Setup –> netcardconf and configure a static IP on on eth0 in the VLAN you configured when you created the guest
  8. Navigate to System –> Control Panel and update mirrors(I had to use http://distro.ibiblio.org/damnsmall/)
  9. Open MyDSL on the desktop, update the database and install dsl-dpkg.dsl from system and nfs-kernel-server.dsl from testing
  10. Open Term and use nano to edit /etc/hosts.allow and /etc/exports to allow the IP of the server to access the NFS on the DSL guest
  11. Start /etc/init.d/portmap and /etc/init.d/nfs-kernel-server services
  12. Use FTP from the Apps –> Net menu to copy your file to /home/dsl
  13. Go back to the host in vSphere client and navigate to Configuration –> Storage
  14. Select Add Storage and select NFS as the type
  15. Use the IP of the DSL guest as the server, /home for the folder and give it a name like dsl-home

Chicken CoopCam and Environment Sensor

So I recently built a chicken coop for our 4 chickens. I wanted to keep track of the weather conditions and view what is going on inside the coop. I put together a small Raspberry Pi project using Python and motion to get everything working.

I purchased a powered USB hub, Raspberry Pi Zero, 32Gb sd card, wifi module, SenseHat and NoIR camera. I used the USB hub to power the Raspberry Pi and in the future to power some infrared LEDs for night time viewing. I also used a empty box that my Garmin vivosmart came in to enclose the device with cutouts for the camera (small diamond on the left and the larger opening for the SenseHat. I mounted it using a small piece of lattice wood and velcro so I could easily take it down and perform service.

After setting up the basics like installing Rapsbian Jessie(do not use Stretch) and running raspi-config to enable SSH, 144Mb for GPU under split memory and the camera module, updating & upgrading, and configuring wifi on the Raspberry Pi I moved on to installing motion to create the streaming webcam server.


sudo apt-get update && sudo apt-get upgrade
sudo apt-get install -y cmake git libjpeg-dev libavformat56 libavformat-dev libavcodec56 libavcodec-dev libavutil54 libavutil-dev libc6-dev zlib1g-dev libmysqlclient18 libmysqlclient-dev libpq5 libpq-dev
git clone https://github.com/raspberrypi/userland
git clone https://github.com/lowflyerUK/motion.git
cd motion/
git checkout mmal-test
USERLANDPATH=/home/pi/userland cmake .
make

Thanks to lowflyer

Here is the Python code used to collect information from the sensors and run the graph. The following came mostly from blogmywiki with some modifications for calculating Fahrenheit, tuning the temperature, and removing the FTP as I am sending the graph and video output files directly to a NAS using a mounted share. Install matplotlib first with sudo pip3 install matplotlib.


#!/usr/bin/python

import matplotlib
matplotlib.use('Agg')   # used as running headless without windows
import matplotlib.pyplot as plt
from time import sleep
from sense_hat import SenseHat
import time
from datetime import datetime
import os

def getCPUtemperature():
 res = os.popen('vcgencmd measure_temp').readline()
 return(res.replace("temp=","").replace("'C\n",""))

sense = SenseHat()

interval_min = 5 # measurement interval in minutes
hrs_shown = 24  # number of hours covered by chart
chart_span = int(hrs_shown*(60/interval_min)) # calculate number of readings to show

# uncomment these lines to write headers to CSV file
#fd = open('logging.csv','a')
#fd.write('time,pressure,temperature,humidity\n')
#fd.close()

while True:
    pressure_list = []
    temp_list = []
    humidity_list = []
    x = []
    a = 0
    daily_max_humidity = 0
    daily_max_temp = 0
    daily_max_pressure = 0
    daily_min_humidity = 2000
    daily_min_temp = 2000
    daily_min_pressure = 2000

    for a in range (chart_span):
        sense.clear()
        fd = open('/mnt/envmon/logging.csv','a')
        #convpress = round(sense.get_pressure() * 0.0295299830714,1)
        pressure = sense.get_pressure()*0.0295299830714
        pressure_list.append(pressure)
# attempt to calculate ambient temperature
# based on dgaust in https://www.raspberrypi.org/forums/viewtopic.php?f=104&t=111457
        cpuTemp=int(float(getCPUtemperature()))
        ambient = sense.get_temperature_from_pressure()
#        calctemp = ambient - ((cpuTemp - ambient)/ 1.5)
        temp_c = sense.get_temperature()
        calctemp = (temp_c - ((cpuTemp - temp_c)/0.32))*9/5+32
        temp_list.append(calctemp)

        humidity = sense.get_humidity()*(2.5-0.01*temp_c)
        humidity_list.append(humidity)

        timestamp = str(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
        fd.write(timestamp+','+str(pressure)+','+str(calctemp)+','+str(humidity)+'\n')
        fd.close()
#        print(timestamp, pressure, calctemp, humidity)

        x.append(a)
        a += 1

        if humidity > daily_max_humidity:
            daily_max_humidity = humidity
        if calctemp > daily_max_temp:
            daily_max_temp = calctemp
        if pressure > daily_max_pressure:
            daily_max_pressure = pressure
        if humidity < daily_min_humidity:
            daily_min_humidity = humidity
        if calctemp < daily_min_temp:
            daily_min_temp = calctemp
        if pressure < daily_min_pressure:
            daily_min_pressure = pressure

        print('max humidity '+str(daily_max_humidity))
        print('max temp '+str(daily_max_temp))
        print('max pressure '+str(daily_max_pressure))
        print('min humidity '+str(daily_min_humidity))
        print('min temp '+str(daily_min_temp))
        print('min pressure '+str(daily_min_pressure))

        fig = plt.figure()
        plt.plot(x,humidity_list)
        plt.plot(x,temp_list,'r')
        plt.plot(x,pressure_list,'g')
        plt.title('SenseHAT WX '+timestamp)
        plt.figtext(0, 0.9, "max "+str(round(daily_max_humidity,0))+"%",color='blue',fontsize=8)
        plt.figtext(0, 0.85, "min "+str(round(daily_min_humidity,0))+"%",color='blue',fontsize=8)
        plt.figtext(0, 0.8, "max "+str(round(daily_max_temp,0))+"F",color='red',fontsize=8)
        plt.figtext(0, 0.75, "min "+str(round(daily_min_temp,0))+"F",color='red',fontsize=8)
        plt.figtext(0, 0.7, "max "+str(round(daily_max_pressure,0))+"in",color='green',fontsize=8)
        plt.figtext(0, 0.65, "min "+str(round(daily_min_pressure,0))+"in",color='green',fontsize=8)
        plt.figtext(0, 0.04, "current ",color='black',fontsize=10)
        plt.figtext(0.08, 0.04, "humidity "+str(round(humidity,0))+"%",color='blue',fontsize=10)
        plt.figtext(0.3, 0.04, "temp "+str(round(calctemp,1))+"$^\circ$F",color='red',fontsize=10)
        plt.figtext(0.44, 0.04, "pressure "+str(round(pressure,1))+" in",color='green',fontsize=10)
        fig.savefig('/mnt/envmon/wx_chart6.png')
        
        sense.show_message(".", text_colour=[0,80,0])
        sleep(interval_min*60)
        plt.close(fig)

Lastly I updated my fstab to mount the drives on boot using systemd


//192.168.128.201/WebCam/Monitor /mnt/camshare cifs username=,password=,iocharset=utf8,file_mode=0777,dir_mode=0777,x-systemd.automount 0 0
//192.168.128.201/ContainerStation/container-station-data/lib/docker/volumes/b0ce997730fdbc24d0754b4e489c5f781e9bae573109ad2be1ac8337b7e9f474/_data/wp-content/uploads/2017/02 /mnt/envmon cifs username=,password=,iocharset=utf8,file_mode=0777,dir_mode=0777,x-systemd.automount 0 0

And created a startup script to start the python program and motion (don't forget to chmod +x the file, place in /etc/init.d/ and "sudo update-rc.d env-motion.sh defaults")


#! /bin/sh
### BEGIN INIT INFO
# Provides:          env-motion.sh
# Required-Start:    $all
# Required-Stop:     
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Startup script to chart environmental monitoring and start motion web cam
### END INIT INFO

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin

. /lib/init/vars.sh
. /lib/lsb/init-functions
# If you need to source some other scripts, do it here

case "$1" in
  start)
    log_begin_msg "Starting to monitor environments and capture chicken videos"
    nohup python3 /home/pi/Scripts/senseplot.py &
    /home/pi/motion/motion -c /home/pi/motion/configs/motion-mmalcam-both.conf
    log_end_msg $?
    exit 0
    ;;
  stop)
    log_begin_msg "Stopping the service"

    # do something to kill the service or cleanup or nothing

    log_end_msg $?
    exit 0
    ;;
  *)
    echo "Usage: /etc/init.d/env-motion.sh {start|stop}"
    exit 1
    ;;
esac

Here are the results.

And the live video stream using motion.
Chicken Coop WebCam (CoopCam)

Next step is to add some servo motors to automatically open the doors in the morning and close them at night, and add a 40 pin ribbon cable between the SenseHat and Pi to provide some distance between the CPU which runs hot. Then I can remove the calculations for temperature and humidity.

F5 Big-IP VE Setup

Here is how I set up a F5 Big-IP on my QNAP TS-251 NAS using Virtualization Station.
Setup the VM on the NAS:
  1. Download the BIGIP-12.1.2.0.0.249.ALL-scsi.ova from F5
  2. Upload image to NAS
  3. Import VM with 2 CPU and 4096Mb ram
Configure management IP using the CLI wizard:
  1. Console in and enter config
  2. Set up management ip
Log into the web interface and run setup wizard:
  1. Log in to web interface using https://<management_IP_address>
  2. Install license
  3. Provision with LTM only
  4. Change Admin and Root passwords
  5. Select Finished to exit the wizard
  6. Go to System —> Configuration —> Device —> NTP and add a NTP server
  7. Go to DNS and add the DNS servers and search domain
  8. Go to Network —> VLANs
  9. Create internal with 1.1 and untagged
  10. Check Interface 1.1 is now UP
  11. Create Self IP with internal VLAN, port lockdown as Allow Default and local-traffic-group-only
    1. CLI – create net self 192.168.128.240/24 vlan internal traffic-group traffic-group-local-only allow-service default
Install Hotfix:
  1. Go to System —> Software Management —> Hotfix List —> Import and select the hot fix and import
  2. Go to Image List and import the base image
  3. Log into the console
  4. Type tmsh and then vgdisplay
  5. show /sys software
  6. install /sys software <image|hotfix> <ISO> create-volume volume <HDx.y>
  7. show /sys software
  8. Log bac into the web GUI and go to System —> Software Management —> Boot Locations
  9. Select the new volume with the hot fix applied
  10. Next to Install Configuration select Yes and make sure the current volume is selected next to Source Volume
  11. Click Activate
Setting up a Virtual Server:
  1. Go to Local Traffic —> Virtual Servers —> Pools and create a pool with the ip, and port of the actual server and add a HTTP or HTTPS health monitor
  2. Go to nodes and edit the node that was created to add a ICMP health monitor
  3. Go to Virtual servers and add a virtual server with a new IP, port, select the pool and set Source Address Translation to AutoMap
  4. Test the new virtual server

 

Network Troubleshooting Methodology

Troubleshooting your network is probably one of the most difficult tasks a network engineer has to perform. Hopefully you are not doing this too much on your network but if you do, having a good methodology will help so you are not going insane. If you are performing several tests in a random order it is easy to make false assumptions and go down a troubleshooting rabbit hole. I use the following methodology to gather all the information I need before making assumptions and trying to put in a fix.
Symptoms:
Connectivity  – probably VLAN/Layer 3 or spanning tree
Latency – could be spanning tree loop or physical connectivity
The following is a list of commands that I use to collect the information necessary to narrow down the culprit.
General Troubleshooting
  1. show logging
  2. show ip interface brief
  3. show cdp neighbor
  4. show ip protocol [vrf <vrf name>]
  5. show ip route [vrf <vrf name>]
  6. ping [vrf <vrf name>]
  7. traceroute
  8. show ip arp
  9. show mac address-table
  10. show run vrf <vrf name>
  11. show ip vrf interface
Services
  1. show ntp status
  2. show netflow
  3. show snmp
  4. show logging
EIGRP
  1. show ip eigrp [vrf <vrf name>] neighbor
  2. show ip eigrp [vrf <vrf name>] interface
  3. show ip eigrp [vrf <vrf name>] topology pending – check for pending routes
OSPF
  1. show ip ospf [vrf <vrf name>] interface brief
  2. show ip ospf [vrf <vrf name>] neighbor
  3. show ip ospf <process #> database
Spanning-tree (perform on both connected switches):
  1. show cdp neighbor – look at the ports connected between switches
  2. show interface status – look at port channel descriptions to match to switches
  3. show etherchannel <port-channel> summary – compare ports listed to cdp neighbor output
VLAN/Layer 3 (perform on both connected switches):
  1. show interface status – look at port channel descriptions to match to switches
  2. show interface port-channel <port-channel> trunk – lists the VLANs that are attached to the trunk
  3. show vlan – make sure the VLANs listed on the trunk are in the VLAN database and active (layer 2)
  4. show ip interface brief – make sure the VLANs listed on the trunk are up/up and have the right IP address and mask (layer3)
  5. ping [vrf <vrf name>] <self IP>
  6. ping [vrf <vrf name>] <neighbor IP>
  7. show ip route [vrf <vrf name>]
  8. show ip eigrp [vrf <vrf name>] neighbor
  9. show ip eigrp [vrf <vrf name>] topology pending – check for pending routes
  10. ping [vrf <vrf name>] 4.2.2.2
Physical Connectivity (perform on both connected switches):
  1. Check to make sure same SFPs are used on both sides
  2. Use flashlight to check fiber paths
  3. show interface status – check SFP type, speed and duplex
  4. clear counter – start at 0 interface statistics before troubleshooting
  5. show interface | include errors – check if errors are incrementing