Archive for October, 2009

Amazon Releases Relational Database Service (Amazon RDS)

Amazon has released a new cloud service, the relational database service.  The service allows a sysadmin to launch an EC2 instance running MySQL without the trouble of patch management and backup.  The instance is fully MySQL compliant so any code which runs against a MySQL database should be fully functional, including native MySQL connectors.

While the Amazon instances are fairly scalable, there is no word yet on clustering multiple instances for redundancy or capacity.

Outside of Amazon’s marketing speak, it also saves the headache of trying to save your MySQL data to elastic block store instead of to your ec2 storage, which isn’t persistent.

From Amazon’s point of view, RDS will increase the ease of use of EC2 and probably sell more instances.

Replacing the Hard Disk on a Mac Mini

I was thinking about doing this until I saw how involved it was.  My Mac Mini has 160 GB of storage, which is not even close to enough.  I am confident I would succeed in the upgrade, but considering the drive is a 2.5 inch drive anyway, the cost to benefit ratio just isn’t there.  I think instead I’ll look for some good network attached storage.

I Love MySecureShell

MySecureShell is an application which modifies SFTP to allow chrooted connections and remove shell access.  I couldn’t be more impressed with how it works or how easy it is to set up.

However…

Lately, the debian and ubuntu repositories haven’t been working.  Installing packages by hand is somewhat annoying.  I know, it’s nothing compared to compiling from source, but still annoying.

Consider this my formal proposal to host MySecureShell’s Debian and Ubuntu repositories, mysecureshell.free.fr.  Since I can’t seem to reach the developers, I hope they reach me.

How To: Recursively Search Text Files on Linux

I have often used a handy script to recursively search text files on a linux machine (recursively grep). The script is written by Joe Grossberg and is currently on version 2.0.  The second version adds handy colorful output.

Slicehost API Made Easy

I’ve been playing with the Slicehost API and ran accross PHP interface for the Slicehost API and am now sold on using PHP for the slicehost API.  Track multiple slices, multiple accounts if you like.  You can also launch slices or delete them as needed.  Here’s how to grab a bunch of info about your account:

include('slicemanager.php');
 
$api_key = '';  //Enter your API Key
 
$sm = new SliceManager($api_key);
 
echo "======== Slices ========\n";
foreach($sm->listSlices() as $slice)
{
	echo 'Name: '.$slice['name']."\n";
	echo 'Status: '.$slice['status']."\n";
	echo 'Bandwidth-in:    '.$slice['bw-in']."\n";
	echo 'Bandwidth-out:   '.$slice['bw-out']."\n";
	echo 'Bandwidth-total: '.((float)$slice['bw-in'] + (float)$slice['bw-out'])."\n";
	echo "\n";
}
 
echo "======== Zones ========\n";
foreach($sm->listZones() as $zone => $info)
{
	echo 'Zone: '.$zone."\n";
	echo 'ID: '.$info['id']."\n";
	echo 'TTL: '.$info['ttl']."\n";
	echo 'Active: '.$info['active']."\n";
	echo "\n";
}

Upload a directory to Rackspace Cloudfiles

I put a little piece of sample code together that uploads a directory to Cloudfiles. I plan on running this on my web servers to upload the backup script to a safe place. This will replace my current pull method, which works fine, but costs me plenty in slicehost bandwidth charges.

Obviously, you will want to include php-cloudfiles and set $username, $key, $container and $location as desired. Note: This currently doesn’t do any recursive uploads. I’m sure that will come with time but it’s not something I needed for this application; I am creating tarballs to upload.

$username = 'username';  //Your rackspace cloud username
$key = '';  //Your rackspace cloud API key
$container = 'backup-'.date('Y-m-d'); //Any string you want.  I choose to make mine change daily
$location = '/var/www'; //The path you want to backup
 
//Create Connection
$auth = new CF_Authentication($username, $key);
$auth->authenticate();
$conn = new CF_Connection($auth);
 
//Create the container
$cont = $conn->create_container($container);
 
$handle = dir($location);
while($file = $handle->read())
{
	// upload files:
	if((! is_dir($handle->path."/".$file)))
	{
		echo "Uploading:".($obj = $cont->create_object($file))."\n";
		$obj->load_from_filename($handle->path."/".$file);
	}
}

How to: Connect to Rackspace Cloudfiles from Slicehost

I’m trying to migrate to a Cloudfiles backup solution and since my slices are in the DFW1, I can get free bandwidth to and from Cloudfiles. So, I went to try and do some initial script testing. Everything worked great locally but failed miserably when trying to connect from my slice. Since my slice was older (pre cloudfiles), I bounced around the web a bit and found that you need to add a route on the private network to Cloudfiles, so I added this to the bottom of /etc/networking/interfaces:

up route add -net 10.176.0.0 netmask 255.248.0.0 gw 10.176.32.1
down route add -net 10.176.0.0 netmask 255.248.0.0 gw 10.176.32.1
up route add -net 10.191.192.0 netmask 255.255.192.0 gw 10.176.32.1
down route add -net 10.191.192.0 netmask 255.255.192.0 gw 10.176.32.1

Replacing:

up route add -net 10.176.0.0 gw 10.176.32.1
down route add -net 10.176.0.0 gw 10.176.32.1

From there, connectivity testing worked great:

$ telnet snet-storage.clouddrive.com 443
Trying 10.191.196.33...
Connected to snet-storage.clouddrive.com.

Looping through Mysql Columns

Recently I was looking into a way to echo out each column name of a mysql database. Of course I needed to do it dynamically as the database could change and the application is in PHP.

First the Query:

$col_query = "SHOW COLUMNS FROM `your_tablename`";
$col_res = mysql_query($col_query) or die(mysql_error());

This query result will return an array of the columns. There are a few keys to the array to point out. Field is your column name. Type is the data type. Others include Null, Key, Default, and Extra. So to get the results I’ve been looking for I had to add the following PHP code.

$col_query = "SHOW COLUMNS FROM `your_tablename`";
$col_res = mysql_query($col_query) or die(mysql_error());
 
//Here is what I needed to add
while($col = mysql_fetch_assoc($col_res))
{
     echo $col['Field'];
}

This little snippet of code can make life easier if you are displaying data in a database dynamically.

List Contacts from Highrise

Pull your contacts from highrise. Use this and the last post to do a one or two-way sync. More to come on this.

$highrise_url = 'http://yoururl.highrisehq.com'; // your highrise url, e.g. http://yourcompany.highrisehq.com
$api_token = ''; // your highrise api token; can be found under My Info
$task_assignee_user_id = ''; // user id of the highrise user who gets the task assigned
 
$curl = curl_init($highrise_url.'/people.xml');
curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
curl_setopt($curl,CURLOPT_USERPWD,$api_token.':x'); //Username (api token, fake password as per Highrise api)
 
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,0);
curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,0);
 
$xml = curl_exec($curl);
curl_close($curl);
 
//Parse XML
$people = simplexml_load_string($xml);
 
//var_dump($people->person);
 
foreach ($people->person as $person )
{
	//var_dump($person->{first-name});
	echo "Name: ".$person->{'first-name'}.' '.$person->{'last-name'}."\n";
	echo "Emails: \n";
	foreach($person->{'contact-data'}->{'email-addresses'} as $email)
	{
		echo $email->{'email-address'}->address."\n";
	}
	echo "Phone Numbers: \n";
	foreach($person->{'contact-data'}->{'phone-numbers'} as $phone)
	{
		echo $phone->{'phone-number'}->number."\n";
	}
	echo "=================\n";
}
return $id;

Enumerate Gmail Contacts

Here’s some sample code I’ve piled together to list gmail contacts:

require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Gapps');
Zend_Loader::loadClass('Zend_Gdata_Query');
 
$user = 'user@gmail.com';
$pass = 'password';
 
// Using Client Login
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, 'cp');
$gdata = new Zend_Gdata($client);
$query = new Zend_Gdata_Query('http://www.google.com/m8/feeds/contacts/'.$user.'/full');
$query->setMaxResults(100);
$feed = $gdata->getFeed($query);
 
$xml = new SimpleXMLElement($feed->getXML());
$entries = $xml->children('http://www.w3.org/2005/Atom');
 
foreach ($entries->entry as $entry )
{
	$defaults = $entry->children('http://schemas.google.com/g/2005');
	echo 'title: '. $entry->title."\n";
	if(isset($defaults->email))
	{
		echo ' email: '.$defaults->email->attributes()->address."\n";
	}
	echo ' address: '.$defaults->postalAddress."\n";
	echo "\n";
}