Saturday 9 March 2013

Backup All VMs on a remote Xen host

Hi Everyone,

Continued digging of my old scripts has turned up another which I think may have some use. It's a script to backup all Xen VMs running on a remote host. I should explain that this ran between a backup host with plenty of space, and the Xen host, which contained a lab environment of several VMs.
I had also configured SSH keypair authentication between the two systems, as it largely relies on a string of SSH commands.

The script works as follows:
  1. Pause all guests running on the Xen host. (This helps to keep things between the hosts in sync)
  2. Takes each guest, and saves it in it's entirety on the local file system.
  3. Un-pause all the guests and show their status.
  4. Working through each of the guest backup files, it zips, transfers, and deletes the not needed copy.
After it's complete you have a backup for all your guests at a given time. 

As an aside, I would like to say the Xen project has really matured recently (last two/three years as I write this). I can remember a time when it was very buggy, VMs would randomly freeze and it was a complete pain to set-up. I still feel the pain of regularly compiling custom Kernels for it on RHEL machines. They even tried to push it on me during my RHCE study and it was not well behaved then! It's not always my virtualisation tool of choice, but it does have some advantages today like speed of install, opensource freedom and scriptability. If you didn't like it before, it might surprise you!

The Script:


#!/bin/bash
#
#  backup_lab.sh will log into the Dom0 machine containing the lab and 
#  instruct it to backup and zip every image it finds.

XENIP="10.1.1.1"
GUESTS=$(ssh root@$XENIP "xm list | grep -Ev '(Name|Domain-0)'" | awk '{ print $1 }')
DATE=$(date +%Y-%m-%d)

# First Get the list of machines, pause them all then save them, and restore, in order

echo "Working on Guests:  $GUESTS"
echo


# Pause all the guests before we start. (Not sure how needed this is, just helps not to let them get out of sync)
echo
for g in $GUESTS
do 
    echo Pausing $g 
    ssh root@$XENIP "xm pause $g" 
done

echo "All Guests should now be paused"
echo 
echo "Current Xen State:"
ssh root@$XENIP "xm list" 
echo 
echo

# Now unpause, then backup the guest, restore from its backup, and pause!
for g in $GUESTS
do
    echo "Backing up guest $g"
    echo
    ssh root@$XENIP "xm unpause $g"
    echo "Guest Un-paused for backup"
    echo
    echo "Saving Guest $g to /root/$g.bak"
    echo
    ssh root@$XENIP "xm save $g /root/$g.bak"
    echo "Guest $g Saved"
    echo 
    echo "Restarting Guest"
    echo
    ssh root@$XENIP "xm restore /root/$g.bak"
    echo "$g has been restored, pausing"
    ssh root@$XENIP "xm pause $g"
    echo "$g has been paused"
    echo
    echo "Guest $g has been backed up."
    echo
done


# Un-pause all the guests
echo
for g in $GUESTS
do 
    echo Un-pausing $g 
    ssh root@$XENIP "xm unpause $g" 
done

# Display the VM list in case anyone is watching
ssh root@$XENIP "xm list" 

# Now all the guests have a backed up file, we can zip and move these
for g in $GUESTS
do
    echo 

    # Tell the remote end to compress
    echo "Compressing /root/$g.bak"
    ssh root@$XENIP "gzip /root/$g.bak"

    # get the remote file back to this directory
    echo "Collecting /root/$g.bak.gz"
    scp root@$XENIP:/root/$g.bak.gz /backup/lab/$g.$DATE.gz

    # Delete the remote backup
    echo "Deleting remote backup /root/$g.bak.gz"
    ssh root@$XENIP "rm -fv /root/$g.bak.gz"
done

echo "All Done!"

Quickest Python Emailer

Hi Everyone,

Over the years I've written many scripts which end up sending an email report. Here is a short and sweet Python version, which has served me well a few times.
  1. This needs to run on a server which can send mail. (Many Unix or Linux will relay localhost with sendmail / postfix etc.)
  2. If you are sending to an external mail system, check your Spam / Junk folders. It may look suspicious, especially if you use a from address which is not the actual domain of the sending machine.
It's not wrapped in a class, or given any bells or whistles. It's just an easy way to send mail!

Enjoy.

'''
Created on 9 Mar 2013

@author: HRH

Probably the quickest way to send an email in python!

'''
import smtplib

SERVER  = "localhost"
FROM    = "Test_Script@myhost.co.uk"
TO      = ["joe_butler99@hotmail.com"] # must be a list
SUBJECT = "Test Mail from RoyalScripts"
TEXT    = "This message was sent with Python's smtplib."

# Prepare actual message
message = """\
From: %s
To: %s
Subject: %s

%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)


# Send the mail
server = smtplib.SMTP(SERVER)
server.sendmail(FROM, TO, message)
server.quit()


Friday 8 March 2013

Checking for the most recent database update with Python and Nagios

Hi Everyone,

Another update to kick-start this blog! I've found another script which I worked on a little over a year ago. This time its purpose was to check that we had a constant stream of new records appearing in a database table. The scripts output was designed to feed our Nagios monitoring system, but it will work just as well as a standalone or called from another script.

For those that don't know, Nagios works with exit codes and standard output from the checks it runs. It's also easy to make new, custom checks. For this to be considered a 're-usable nagios check' I should have made the script accept arguments to fill the variables I've hard coded at the top. It could also parse them to check what's been passed in is suitable. I don't have time tonight, but if someone asks nicely....

Anyway I hope you will see that writing these kind of checks can be very simple.


#!/usr/bin/python
'''
@author: HRH

A Nagios Check to ensure recent database records
'''

import sys
import datetime
import MySQLdb

# Script Variables
db_host    = "127.0.0.1"
db_user    = "root"
db_pass    = "password"
db_name    = "mydatabase"
db_table   = "mytable"
warn_secs  = 3600
error_secs = 7200
date_field = 2 # What column number contains the date we want to check (Zero indexed) 

# Make sure we can connect, if not something is wrong.
try:
    db = MySQLdb.connect(db_host, db_user, db_pass, db_name)
    db_c = db.cursor()
except:
    print "Unable to connect to database."
    sys.exit(2)

# Try and run the query for the latest data
try:    
    query = "SELECT * FROM `%s`.`%s` ORDER BY id DESC LIMIT 1 " % (db_name,db_table)
    db_c.execute(query)
    result = db_c.fetchall()[0]
except:
    print "Query Failed to select latest record from `%s`.`%s`" % (db_name,db_table)
    sys.exit(2)

latest_cdr  = result[date_field]
time_now    = datetime.datetime.now()
time_diff   = time_now - latest_cdr

# Check how long since last record and now 
if time_diff.seconds < warn_secs:
    print "New records within %d seconds" % warn_secs
    sys.exit(0)
elif time_diff.seconds < error_secs:
    print "Between %d and %d seconds since last record in DB" % (warn_secs,error_secs)
    sys.exit(1)
else:
    print "Over %d seconds since last record in DB" % error_secs
    sys.exit(2)


    

Log file class with Minimal Python Libraries

Hi Everyone,

Its been a long time since I was here, but I have worked on many scripts in the mean time and I think it would be nice to share a few!

I thought I would start with a small script I wrote about a year ago, the output of which was intended to be consumed by Splunk. Now I look at this, it could also be useful straight away for any work which wanted to keep a simple log file.

The reason I wrote this with 'time' as the only python import is because it was due to run on a hardware system with an old, cut back python installation. This may be an advantage for some, it should at least run on nearly any version of python out there.

The output is a nice timestamped line with all the key=value pairs displayed as strings. (quoted where necessary)


'''
A script to write simple timestamped logs to a file. 
@author: HRH

Example test usage below. Built with limited libraries
due to the tiny python installation where this script is
first intended to be used. 

'''
import time

class SplunkLog:
    
    # Writes a line to the given file with the current timestamp
    # the data value should be a python dictionary where the key => val is 
    # used for logtype=logtext 
    def write_local_log(self,fh,data):
        t = time.localtime()
        logtime = str(t[0])+"-"+str(t[1]).zfill(2)+"-"+str(t[2]).zfill(2)+" "+str(t[3]).zfill(2)+":"+str(t[4]).zfill(2)+":"+str(t[5]).zfill(2)
        log_line = logtime + "\t"
        for row in data:
            for k , v in row.iteritems():
                if " " in v:
                    log_line += k + "=" + '"' + v + '"' + ",\t"
                else:
                    log_line += k + "=" + v + ",\t"
            
        # Write the line, minus the last spacing and with added newline
        log_line = log_line.rstrip(",\t") + "\n"
        fh.write(log_line)


'''
#
#    A usage example - remember to include or add the main class somewhere
#
#
#
#        Main Loop
#
from sys import exit
dummy_data = []
dummy_data.append({"severity" : "Warning","EventID": "Bad Login", "user" : "Test"})
dummy_data.append({"severity" : "Major","EventID": "Possible DoS", "user" : "Remote"})
s = SplunkLog()

try:
    fh = open("splunk-test.txt",'a')
except:
    print "Unable to open log file"
    exit(1)
    
# If we are still here, then we can try write something into the file
for log in dummy_data:
    s.write_local_log(fh, log)

fh.close()
exit(0)
'''

Tuesday 30 November 2010

Managing ProCurve firmware updates with PHP and SNMP

When you look after a large number of switches, it can become important to manage firmware updates effectively. I have created a quick script to run though a list of IP addresses, and check what is the latest available firmware. This is thanks in part to the open way ProCurve allow you obtain new firmware. Not like some other switch vendors... Anyway, I hope this can help a few people out. It certainly comes in handy for me when it comes to update time.

When appling it to you own situation you just need to edit the SNMP community you are using and put your own switch IPs into the device_list array. You can add as many extras as you need.

<?php
/*
 *      ProCurve Firmware Manager
 *
 *      An HRH Script.
 */

### Setup some varibales
$SNMP_COM = 'yourcommunity';
$SYS_DESC_OID = "1.3.6.1.2.1.1.1.0";
$SYS_UP_OID = "1.3.6.1.2.1.1.3.0";
$SYS_NAME_OID = "1.3.6.1.2.1.1.5.0";
$HP_BASE_URL = 'http://h10144.www1.hp.com/customercare/support/software/switches.htm';

## Create a list of the devices we are monitoring
$device_list[] = "10.0.0.254";
$device_list[] = "10.0.1.254";
$device_list[] = "10.0.2.254";
$device_list[] = "10.0.3.254";

# Which Firmware branches are we interested in
$firmware_branch[] = 'E';
$firmware_branch[] = 'F';
$firmware_branch[] = 'G';
$firmware_branch[] = 'H';
$firmware_branch[] = 'I';
$firmware_branch[] = 'K';
$firmware_branch[] = 'R';


# Declare some common functions

# @ Clean output
# A function to remove the unnecessary from SNMP GET otuput
function clean_output($string) {
    $clean_output = preg_replace("/[A-Za-z]*:[ ]/", "", $string);
    $clean_output = preg_replace("/[(][0-9]*[)][ ]/", "", $clean_output);    
    $clean_output = str_replace("Gauge32", "", $clean_output);
    $clean_output = str_replace("Counter32", "", $clean_output);
    $clean_output = preg_replace("/[(][0-9][)]/", "", $clean_output);
    return $clean_output;
}

# @ clean to firmware
# A function to show the procurves running firmware from its 
function clean_to_firmware($string) {
    $clean_output = $string;
    $clean_output = str_replace("revision", "", $clean_output);
    $clean_output = str_replace(" ", "", $clean_output);
    $parts = explode(",",$clean_output);
    return $parts[1];
}

## Get the latest Available firmwares from HP
# Collect the latest list of firmwares from the HP website
exec("wget $HP_BASE_URL 2> error.txt");

## Build the firmware array, with the links and versions of firmware available
if(!file_exists("switches.htm")) {
    echo "Unable to locate switches.htm. Check connectivity to the internet";
    exit();
} else { 
    foreach($firmware_branch as $branch) {
        $output = `cat switches.htm | grep -m 2 $branch.[0-9][0-9][.][0-9][0-9]*\<`;
        # strip the beginning a href, and other bits, to leave a url and version name.
        $output = preg_replace("/[<]a href=\"/", "", $output);
        $output = preg_replace("/\" class=\"[a-z]*\">/", "_", $output);
        $output = preg_replace("%</a><[/brtd]*>%", "", $output);
        $output = str_replace(" ", "", $output);
        $output = str_replace("</a><br>", "", $output);        
        $output = str_replace("</a><spanclass=\"newmarker\">Updated</span><br>", "", $output);
        $lines = explode("\n", $output);
        $bits_pri = explode("_", $lines[0]);
        $bits_sec = explode("_", $lines[1]);
        $firmwares[$branch]['new_ver'] = $bits_pri[1];
        $firmwares[$branch]['new_url'] = $bits_pri[0];
        $firmwares[$branch]['old_ver'] = $bits_sec[1];
        $firmwares[$branch]['old_url'] = $bits_sec[0];
    }

    # Finally remove the switches.htm file so we get it fresh next time
    unlink("switches.htm");
}
?>

<html>
<head><title>Lightweight Network Manager</title></head>
<body bgcolor="silver">
<font face="arial" size="2">
<!-- This is the main display screen !-->
<center>
<h2> Lightweight Network Manager </h2>
<br><br>
</center>
<table cellpadding=5 cellspacing=5>
<tr><th>Device IP</th>
      <th>Device Name</th>
      <th>Device Uptime</th>
      <th>Running Firmware</th>
      <th>Newest Online Firmware</th>
</tr>
<?php

#       This is where the main page content starts
foreach ( $device_list as $device ) 
{
    $running_firmware = clean_to_firmware(clean_output(snmpget($device,$SNMP_COM,$SYS_DESC_OID))) ;
    $temp = explode(".",$running_firmware);
    $branch = $temp[0];
    $newest_firmware = $firmwares[$branch]['new_ver'];
    $newest_url = $firmwares[$branch]['new_url'];

    # Build the line
    echo "<tr>";
    echo "<td>$device</td>";
    echo "<td>" . clean_output(snmpget($device,$SNMP_COM,$SYS_NAME_OID)) . "</td>";
    echo "<td>" . clean_output(snmpget($device,$SNMP_COM,$SYS_UP_OID)) . "</td>";
    echo "<td>" . $running_firmware . "</td>";
    echo '<td><a href="'.$HP_BASE_URL.$newest_url.'">'.$newest_firmware.'</a></td>';
    echo "</tr>";
}
echo "</table>";
?>
</body>
</html>

Running on Windows
Ok, I'm going to have to admit something here. I took two little shortcuts when writing this on two lines (56, and 64 in the code) PHP executes some shell commands which run some common Bash commands. (wget, cat and grep)
There is however no reason why PHP can't do these things. It just requires a little modification to make the download on line 56 dump to a variable, and a couple of filters to replace line 64 which looks for the first occurance of the firmware version in the source code.

If you are behind a proxy, you may want to check the pecl_http extension at:
http://pecl.php.net/package/pecl_http
Which will allow you to specify proxy values to PHP



Notes
  • PHP should be compiled with SNMP, I think this is a defualt on most installations
  • If you have a slow connection to the internet, or a large number of switches to monitor, this could take up to a minute to run. Possibly longer if switches are down as it expects to be able to contact each device.

Monday 29 November 2010

Converting all video files within a directory with Bash & ffmpeg

I recently found myself needing to convert around 45 .flv videos into a format which my PS3 would find acceptable. Not being a fan of doing anything manually I decided to do this from within a small script. It requires that you have ffmpeg installed, and the 'rename' program, if you need to remove spaces from the  original filenames. (If not, you may want to comment out the line beginning rename)

You can also tweak the inputformat and outputformat variables and the ffmpeg settings to make it suitable for almost any type of conversion. If you start hitting errors in the conversion, its probably because you have some codec’s or packages missing on your system, so you can also check the extra codec’s section below.


#!/bin/bash
# A script to convert videos files within a directory
# An HRH Script!! 


# Set video types
inputformat=flv
outputformat=mp4
outputdir=converted

# Remove any spaces from filenames
rename s'/ //' *.$inputformat

# check if we have an output directory
if [ -d $outputdir ]
then
echo "Directory Exists, ready to convert files"
else
mkdir $outputdir
echo "Created directory $outputdir/"
fi

# read in the files and start the conversion
for file in `ls *.$inputformat | sed "s/\.$inputformat//"`
do
    ffmpeg -i "$file"."$inputformat" -ab 56k -ar 22050 -b 600k -s 640x480 $outputdir/"$file"."$outputformat" 
done




Getting more codec’s to work in ffmpeg  -  (This was what worked for me, ffmpeg can seem like a dark art at times!)

By going through the process below, I was able to get ffmpeg converting from and to a wide range of video formats. I don't think all the packages were necessary, but it would take me forever to go back and find out which ones made the difference, so I'm just going to show you all of them!

You may also need to enable the multiverse software source, if you do not currently have this enabled.
System -> Administration -> Software Sources


# Install some extra packages which will help ffmpeg handle more formats
# This should be done before installing a fresh version of ffmpeg
sudo apt-get install ubuntu-restricted-extras gstreamer0.10-plugins-ugly-multiverse 
sudo apt-get install gstreamer0.10-plugins-ugly gstreamer0.10-ffmpeg ffmpeg2theora 
sudo apt-get install mencoder libogg0 libogg-dev libvorbis0a libvorbis-dev vorbis-tools 
sudo apt-get install imagemagick youtube-dl poppler-util yasm


# Install the Trunk version of ffmpeg
sudo apt-get purge ffmpeg          # Make sure packaged version is removed
sudo apt-get install subversion    # Skip if subversion is already installed
cd ~
svn checkout svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg
cd ffmpeg
./configure
make
sudo make install 


Assuming the sudo make install completed without any errors, you should now be running with the latest ffmpeg installed on your system. You can check this with

ffmpeg -version

Friday 5 November 2010

Monitoring Avaya ACM Trunk Usage, with Cacti and PHP

After becoming frustrated with the lack of built in monitoring for Avaya ACM trunk usage (ie how many concurrent phone calls were happening) I decided to have a poke around using SNMP to see if it was possible. In the end, I found a way to poll for the current status of each channel on each trunk, and then it was just a case of adding up the active ones to get a number of concurrent calls. It is written in PHP and can either be called from the command line, or as I have done, tied into Cacti to create historic graphs for each trunk.

There are two scripts on offer here, both can be run as standalone scripts while troubleshooting. The first one is a tool which will interrogate your Avaya system. This provides feedback on all the trunks it contains, and which channels are active on each trunk. The information is dumped out to the CLI, but its in a nice PHP array form which is ready for any further modification you may wish to make.

The second script, will take the Avaya host and trunk number as parameters and will return the total number of channels and how many are active. This is the script which gets called by the Cacti poller to allow it to graph channel usage.






The CLI Script: avaya_active_trunks.php
<?php
/*      A SNMP Poller to find out what the Avaya trunks are doing.
 *
 *      An HRH script !!
 *
 */

/* Variables */
$server = "youravayaip"; # Set this to the Management IP of your Avaya box
$community = "yourcommunity";   # Should be set to the SNMP community configured on the Avaya box

/* do NOT run this script through a web browser */
if (!isset($_SERVER["argv"][0]) || isset($_SERVER['REQUEST_METHOD'])  || isset($_SERVER['REMOTE_ADDR'])) {
        die("<br><strong>This script is only meant to run at the command line.</strong>");
}
$no_http_headers = true;

/* display No errors */
error_reporting(0);

/* Do a quick dummy walk to 'wake up' the avaya box */
echo "Waking up SNMP on the Avaya, with a SNMPWALK request\n";
snmpwalk($server,$community,"1.3.6.1.4.1.6889.2.8.1.14.1.1.1.1");

echo "Collecting the trunk channels and membership array\n";
$raw_trunk_array = snmpwalk($server,$community,"1.3.6.1.4.1.6889.2.8.1.14.1.1.1");

echo "Collecting the channel status array\n";
$raw_channel_status = snmpwalk($server,$community,"1.3.6.1.4.1.6889.2.8.1.14.1.1.3");

# Start working with the data
$num_channels = count($raw_trunk_array);
$num_trunks = 0;
$b = 1;  // Incrementer for trunks
$c = 0; // Incrementer for chanels
for($a = 0; $a < $num_channels; $a ++) {
    $trunk_num = str_replace("INTEGER: ","",$raw_trunk_array[$a]);

    # Check if we are working on a different trunk to the previous loop
    if($trunk_num != $trunk_array[($b -1)]['name'] ) {
        $trunk_array[$b]['name'] = $trunk_num;
        $trunk_array[($b - 1 )]['channels'] = $c;
        $b++;
        $c = 0;
    }
    $c ++;
}
$trunk_array[$b -1]['channels'] = $c;
sort( $trunk_array );
array_shift( $trunk_array );

## Now that we have the trunk and channel groups, 
# we can add in the channel status to the trunk_array
for($a = 0; $a < count($trunk_array); $a ++) {
    $channels_in_use = 0;
    for($b = 0; $b < $trunk_array[$a]['channels']; $b ++) {
        $text = str_replace('"',"",str_replace("STRING: ","",$raw_channel_status[$num]));
        switch($text) {
        case "in-service/idle":
            $channel_status = 0;
            break;
        case "in-service/active":
            $channel_status = 1;
            break;
        case "OOS/FE-idle":
            $channel_status = -1;
            break;
        case "out-of-service-NE":
            $channel_status = -1;
            break;
        default:
            $channel_status = -1;
            break;
        }
        $trunk_array[$a]['status'][$b] = $channel_status;
        $channels_in_use += $channel_status;
    }

    $trunk_array[$a]['total'] = $channels_in_use;
    $channels_in_use = 0;
}

print_r($trunk_array);
?>


The Cacti Script: single_trunk_status.php
#!/usr/bin/php
<?php
/*      A script to find out how many channels are active on an Avaya Trunk
 * returned in a format which can be read by a person or Cacti.
 *
 *  An HRH script !!
 *
 */

/* variables */
$community = "yourcommunity";

/* do NOT run this script through a web browser */
if (!isset($_SERVER["argv"][0]) || isset($_SERVER['REQUEST_METHOD'])  || isset($_SERVER['REMOTE_ADDR'])) {
 die("
This script is only meant to run at the command line.");
}
$no_http_headers = true;

/* display No errors */
error_reporting(0);

/* Make sure that this script has been called with a hostname and trunk number */
if(isset($argv[1])) { $host = $argv[1]; } else { die("no host name"); }
if(isset($argv[2])) { $trunk_no = $argv[2]; } else { die("no trunk number"); }

/* create the OID we will walk from */
$oid = '1.3.6.1.4.1.6889.2.8.1.14.1.1.3.' . $trunk_no;

/* Do a quick dummy walk to 'wake up' the avaya box */
snmpwalk($host,$community,"1.3.6.1.4.1.6889.2.8.1.14.1.1.1.1");

/* now we have awoken the beast, do the real work */
$raw_channel_status = snmpwalk($host,$community,$oid);

/* work out how many were in use */
$used = 0;
for($a = 0; $a < count($raw_channel_status); $a ++) {
    $text = str_replace('"',"",str_replace("STRING: ","",$raw_channel_status[$a]));
 switch($text) {
 case "in-service/idle":
     $channel_status = 0;
     break;
 case "in-service/active":
     $channel_status = 1;
     break;
 case "OOS/FE-idle":
     $channel_status = -1;
     break;
 case "out-of-service-NE":
     $channel_status = -1;
     break;
 default:
     $channel_status = -1;
     break;
 }
 $used += $channel_status;
}

/* return the data */
echo "active_channels:$used total_channels:". count($raw_channel_status);

?>

Example output - When run from cli
[user@server scripts] php single_trunk_status.php 10.10.10.10 15   #15 is the trunk number
active_channels:2 total_channels:30

Installing into Cacti
Its been a while since I did this so if you get stuck, please let me know and I will try to assist! You might also want to read here, which is the Cacti guide to adding external scripts:
http://www.cacti.net/downloads/docs/html/making_scripts_work_with_cacti.html


1. Create the data input method - From the console, click on Data Input Methods, then click on Add in the top right hand corner. Give it a name, and put the path to the script in as below then click create. Once that is done, add in the Input and Output Fields as below.





 2. Click on the Data Source tab in the console, give it a name and and select Trunk Check for the Data input method. For the data Soure Item tab you will need to add in both "active_channels" & "total_channels". Finally you should add the Hostname and Trunk Number which the script will need to monitor.
3. With all that in place, you can create a graph for the data :)





Notes
  • You will need to ensure that your Avaya system is configured to accept SNMP requests. You can check your current settings from the web portal of the server under the maintenance tab. From there SNMP settings are listed. You will need to configure an SNMP community and allow access from the server which will poll it. In my experience I also had to restart the agent after each change.
  • Your PHP installation will need to have been installed with SNMP support (I believe this is normally a default)


OIDS - These were surprisingly hard to find, so I hope I can save someone some time!
g3pkprincipalCallsCCAC1.3.6.1.4.1.6889.2.8.1.139.6.1.9
g3trunksta1.3.6.1.4.1.6889.2.8.1.14
g3trunkstaTable1.3.6.1.4.1.6889.2.8.1.14.1
g3trunkstaEntry1.3.6.1.4.1.6889.2.8.1.14.1.1
g3trunkstaTrunkGroup1.3.6.1.4.1.6889.2.8.1.14.1.1.1
g3trunkstaConnPort61.3.6.1.4.1.6889.2.8.1.14.1.1.10
g3trunkstaConnPort71.3.6.1.4.1.6889.2.8.1.14.1.1.11
g3trunkstaConnPort81.3.6.1.4.1.6889.2.8.1.14.1.1.12
g3trunkstaConnPort91.3.6.1.4.1.6889.2.8.1.14.1.1.13
g3trunkstaMember1.3.6.1.4.1.6889.2.8.1.14.1.1.2
g3trunkstaServiceState1.3.6.1.4.1.6889.2.8.1.14.1.1.3
g3trunkstaMaintBusy1.3.6.1.4.1.6889.2.8.1.14.1.1.4
g3trunkstaConnPort11.3.6.1.4.1.6889.2.8.1.14.1.1.5
g3trunkstaConnPort21.3.6.1.4.1.6889.2.8.1.14.1.1.6
g3trunkstaConnPort31.3.6.1.4.1.6889.2.8.1.14.1.1.7
g3trunkstaConnPort41.3.6.1.4.1.6889.2.8.1.14.1.1.8
g3trunkstaConnPort51.3.6.1.4.1.6889.2.8.1.14.1.1.9