-->
Showing posts with label Cloud Computing. Show all posts
Showing posts with label Cloud Computing. Show all posts

Tuesday, 19 July 2011

Interfacing Talend with Amazon SDB (AWS SDB) – quick way

Hi all,

I had the following challenge : read some ftp account informations (ftp server, username, password, target directory) stored in Amazon SDB and use it in a Talend transformation, published as a web service. You know about SDB I hope. For those who don’t, SDB is a key / value database provided by Amazon. So you can name SDB a noSQL database.
I played with the SDB API from Amazon, and succeeded after some coding and “Talending”. Here is how I did.
Below is only a small part of a much larger project, composed of a large webservice collection, created for my client.
This project does the following :
  • Query into a database using dynamic params given by the user at run time from a Flex portal (a query engine like business objects !),
  • Return a rowcount of the query, into the portal. I’m working in web marketing : counting people (segments) before creating a campaign is very important …
  • Generate an extract of the data, process this extract according to the params given by the user (separator, encoding, spliting, zipping …),
  • Send this data file to different “tubes” : router, ftp, AWS S3, local download …
Here we focus on the ftp sending part, using SDB to retrieve infos.

 

The process.

 

image

The job (partial).

image

 

Data structure in AWS SDB.

I’m using a very nice firefox plugin in order to have easy and quick access to my SDB ecosystem : sdbtool. My data structure is simple ( “dd” is of course not the true value …) :
  • Item : ftp
    • Attribute names : Address :
        • Attribute value : dd
      • Attribute names :Login
        • Attribute value : dd
      • Attribute names : PKey
        • Attribute value : dd
      • Attribute names : Password
        • Attribute value : dd
      • Attribute names : Port
        • Attribute value : 21
Here is a screencap of my sdbtool view :
image

Explanations.

First, we load all the needed libraries, using tlibraryload component.
  • aws-java-sdk-1.0.14.jar
  • commons-codec-1.3.jar
  • commons-httpclient-3.0.1.jar
  • commons-logging-1.1.1.jar
  • jackson-core-asl-1.4.3.jar
  • stax-api-1.0.1.jar
  • stax-1.2.0.jar
For the aws-java-sdk-1.0.14.jar import, I had to write some imports. These imports are required to be able to use the aws jdk.
image
Then we have a tRowGenerator in which I create the value for the variable myDomain, that will be used in SDB queries (see code below). You can avoid this step, I created it only for quick testing purpose.
Then, we have to code a little tJavarow. This java code will :
  • connect to AWS SDB. You must have an account for AWS SDB.
  • run several queries, using SQL, to retrieve ftp account informations :
    • ftp server address
    • ftp server login
    • ftp server pass
    • ftp server port
    • ftp server pkey, if needed
  • store the query results in output_row.[name] so they can be used in Talend process.
The code in the tJavaRow. First we create some credentials (use yours) and then create an endpoint with sdb address from AWS : https://sdb.eu-west-1.amazonaws.com. Be carefull to set a valid endpoint, using a valid country zone.
The code is finally simple : create a string containing your sql query, then call a getItems() function. An Item is sent back, simply call a getAttribute in order to retrieve the value you need.
I chose, for simplicity, to run a different query for each item I need from SDB. Of course, you can write it shortly.
  
        BasicAWSCredentials credentials = new BasicAWSCredentials("KL45LKJ4325MLKJ2345", "LKJ45LKJmlkjdlkjGRhjKLJSFSDG432534");    
        
    final String[] FTP_Items;
    
        

        AmazonSimpleDB sdb = new AmazonSimpleDBClient(credentials);
        sdb.setEndpoint("https://sdb.eu-west-1.amazonaws.com");
        try {
        int i = 0;
            String myDomain = "Clients"; 
            String selectExpression = "select FTP_Address from `" + myDomain + "`where code_client = '" + context.client_name +"'";
           
            SelectRequest selectRequest = new SelectRequest(selectExpression);
            for (Item item : sdb.select(selectRequest).getItems()) {
                for (Attribute attribute : item.getAttributes()) {
                    output_row.FTP_Address = attribute.getValue().toString();
                }
            }         
            selectExpression = "select FTP_Login from `" + myDomain + "`where code_client = '" + context.client_name +"'";
            selectRequest = new SelectRequest(selectExpression);
            for (Item item : sdb.select(selectRequest).getItems()) {
                for (Attribute attribute : item.getAttributes()) {
                    output_row.FTP_Login = attribute.getValue().toString();
                }
            }
            selectExpression = "select FTP_Pass from `" + myDomain + "`where code_client = '" + context.client_name +"'";
            selectRequest = new SelectRequest(selectExpression);
            for (Item item : sdb.select(selectRequest).getItems()) {
                for (Attribute attribute : item.getAttributes()) {
                    output_row.FTP_Pass = attribute.getValue().toString();
                }
            }
            selectExpression = "select FTP_Port from `" + myDomain + "`where code_client = '" + context.client_name +"'";
            selectRequest = new SelectRequest(selectExpression);
            for (Item item : sdb.select(selectRequest).getItems()) {
                for (Attribute attribute : item.getAttributes()) {
                    output_row.FTP_Port = Integer.valueOf(attribute.getValue());
                }
            }
            selectExpression = "select FTP_PKey from `" + myDomain + "`where code_client = '" + context.client_name +"'";
            selectRequest = new SelectRequest(selectExpression);
            for (Item item : sdb.select(selectRequest).getItems()) {
                for (Attribute attribute : item.getAttributes()) {
                    output_row.FTP_PKey = attribute.getValue().toString();
                }
            }
        } catch (AmazonServiceException ase) {
            System.out.println("AWSException");
            System.out.println("ErrorMsg:    " + ase.getMessage());
            System.out.println("HTTPStatcode: " + ase.getStatusCode());
            System.out.println("AWS Errcode:   " + ase.getErrorCode());
            System.out.println("Errortype:       " + ase.getErrorType());
            System.out.println("RequestID:       " + ase.getRequestId());
        } catch (AmazonClientException ace) {
            System.out.println("AWSClientException");
            System.out.println("Error Message: " + ace.getMessage());


Final.

After retrieving all the item I need for sending on ftp (server, username, pass, port or location for ssh key), I store all this into global variables. Then, these global variables are used as arguments into two very customized scripts (needed in my case) that will send the files : simple ftp or sftp when needed. Finally, I catch some usefull infos from the custom ftp scripts, process it into a tmap and send this information into a tBufferOutput step. That way, I can provide a soap feed back when calling this webservice.

This post is very consice, feel free to ask me for more infos about this process.

Links.

Tuesday, 21 June 2011

… about AWS cloud, Talend, Jaspersoft, Postgresql and typical EC2 internal addressing issues …

Hi all,

I’m terribly late with this article, initially scheduled for January 2011 … sorry. Maybe it is a bit outdated now, anyway, I publish it …
Let’s talk about EC2 cloud computing, Talend, Postgresql and JasperServer. Basic setup.
You already know all the pros and cons with cloud computing, I won’t talk about that. As to me, I love cloud computing and use it everyday, because of these particular advantages :
  • Scalablity : scale up or down any instance, according to your needs,
  • Flexibility : create your own instances, boot them, create quick sandboxes, replicate data …
  • Pay per use : you pay for what you use (cpu, storage, security …),
  • Opex, no capex !
Cloud computing is still something new, and it is not surprising to discover softwares that are not ready for it or not fully “cloud compliant”. I recently faced such an issue when implementing Postgresql, Talend and Jaspersoft, which remain my preferred open source BI tools.

First issue

Let’s imagine we have a single server, hosting Postgresql. No big deal with that as long as we use this instance in a simple way : I can start my instance, host data on a persistent EBS, connect to it and stop it whenever I want. By using elastic IPs, I can assign a “fixed” IP address to this server and can easily set up a connection string. Note on 16/12/2010 : Amazon is now offering a DNS service.
Now let’s imagine we need a typical BI architecture (tiers) : one ETL (Talend or Pentaho of course !), a Postgresql database in the middle and Jaspersoft for reporting.
That’s a bit more complex because we need our Postgresql server to allow connections from the ETL and from the reporting tool. On top of that, we want to fully leverage all cloud computing features : stop the servers when they are not used, boot them when the service is needed, maybe change their network properties ... eventually we want this to be fully automated and working without any human actions like changing the connection strings, starting/stopping the servers …
Let’s have a look to a little schema now. As you can see, we have now our architecture up and running. We are also using elastic IPs for each server, which is mandatory for the following demonstration. IPs are fake.
image

How to read Public DNS, Private DNS and Elastic IPs on AWS EC2 ?
Imagine we have an instance running. This instance has an Elastic IP which is 46.52.186.25 and the private IP address is 11.235.33.6.
The Private DNS name is : ip-11-235-33-6.eu-west-1.compute.internal
The Public DNS name is : ec2-46-52-186-25.eu-west-1.compute.amazonaws.com
You see the relationship ?

Ok, now, how do you think we will configure Postgresql server to allow connexions from the ETL server and from the Reporting server ? Easy, here is one answer :
  1. By making the ETL Server and the reporting server point to Postgresql. For that, we will use this nice little Elastic IP we previously set up for Postgresql server because it’s soooo easy to do that way …
  2. By writing the ETL server Elastic IP and reporting server Elastic IP into Postgresql pg_hba.conf of course … because here again it is soooo easy natural to do so.
  3. Don’t forget to open the corresponding ports in your security groups (see picture above).
Ok, easy. Let’s go for it. We make Talend and Jasper point to Postgresql like this :
Jasper server connexion screen : Postgresql database <===> Jasperserver
image
Talend client connexion screen : your client <===> Talend server
image

Talend server connexion screen : Talend server <===> Postgresql database
image

And then we write down the Elastic IPs into the pg_hba file like this, in order to allow Talend server and JasperServer to connect to the postgresql database. This is a basic pg_hba.conf, I encourage you to add stronger authentication.
image
We are done. Don’t forget to adjust the security groups like this :
  • Talend Server : allow 8080, allow 22
  • Postgresql Server : allow 5432, allow 22
  • Jasperserver : allow 80 (or 443 if https), allow 22
Okay, this stuff is fully working, you can test it.
But wait … that’s not the good way to do ! By using the elastic IPs to set up communication between each server/node, we just created a weird monster that makes the traffic going OUT of the cloud and going BACK INTO the cloud. Don’t forget you are paying for that. Look at this schema.

image

First solution

The best practice is to avoid using elastic IPs in order to set up network traffic between servers that are hosted inside the EC2 cloud. Instead, use EC2 internal adresses.
Ok, but … wait a minute.
  • How do I do to retrieve the internal address from inside EC2 ? 
The solution rely on a poorly documented EC2 feature : when you query an ec2 public DNS server from inside EC2, you will be given back the corresponding internal IP address. Just what we need !!!!
For instance, if you query your ETL Server from your your Postgresql server, by using the famous host command, you will have :
image

You see what you have to do ? Replace all elastic IPs, except for your Talend client, by internal IPs. Like that, your internal data won’t leave the cloud, like below.

image
After using the internal addressing, the connexion screens will look like this :
Jasper server connexion screen : Postgresql database <===> Jasperserver

image

 

Talend server connexion screen : Talend server <===> Postgresql database
image


Second issue

Well, ok, we solved our first issue : using internal addresses between the ETL server and the Postgresql server. But, I can see two other issues :
  • Postgresql still does not accept DNS names in the pg_hba.conf ! Only IP addresses allowed. So We can’t ask Postgresql and pg_hba.conf to resolve the dns for us.
  • What if I decide to reboot the ETL server, or the Reporting server ? These internal adresses are nice but they are changing each time I reboot / restart server in EC2. Then, how to keep my Postgreqsl pg_hba.conf updated with frequently changing adresses ?
image…not allowed …

Second solution

No, there is still no support for DNS entries in the pg_hba.conf. I know this is a long awaited feature, at least by me. But, unless I’m wrong (tell me), writing down a DNS name in pg_hba.conf won’t work and the server won’t start.
We need to find a way to update the pg_hba.conf with the last / current ec2 internal addresses corresponding to the ETL server and the Reporting server. Easy, we will use a bit of shell code here. This script will retrieve the internal IP Address for each server (ETL and JasperServer) by using the command host and will update this address in the pg_hba.conf by using some sed or awk. Then, by using a sighup, Postgresql server will apply the new address configuration.
Nothing complex, but the success rely on a good timing.
image
Note here : I created an ORCHESTRATOR, a specialized instance in EC2, to monitor all my servers. This orchestrator will run this kind of script as soon as it detects any change in the internal addressing schema. This ORCHESTRATOR will be detailed in a future article (I made several public presentations, and a lot of people seem interested …).
And the shell script. This shell asks for the internal address, then updates the corresponding line. For that, you must  maintain your file in a tidy way : labels are needed.
################################ 
#                              # 

#      IP adress lookup        # 

#                              #  
################################ 
# POSTGRES (DATABASE) Server
# Public DNS : ec2-12-345-678-999.eu-west-1.compute.amazonaws.com 


# TALEND (ETL) Server     
ETL_SERVER=`host ec2-11-222-33-444.eu-west-1.compute.amazonaws.com | sed 's/.*has address //g'` 

# JASPER (BI & reports) Server    
JASPER_SERVER=`host ec2-22-33-444-555.eu-west-1.compute.amazonaws.com | sed 's/.*has address //g'` 



# Echoing all     
echo "" 

echo "################## EC2 Addresses Update ######################" 

echo "Will update EC2 Talend Server address with : " $ETL_SERVER 

echo "Will update EC2 Jasper Server address with : " $JASPER_SERVER 



echo ""

# Find and replace line Talend Server TALEND_NB=`grep -n "Talend server connexion" /mnt/postgres/data/pg_hba.conf | cut -d":" -f1` TALEND_NB=$((TALEND_NB+1)) sed -i "$TALEND_NB s%.*%host    all         all         $ETL_SERVER/32      md5%" /mnt/postgres/data/pg_hba.conf # Find and replace line Jasper Server JASPER_NB=`grep -n "JasperServer connexion" /mnt/postgres/data/pg_hba.conf | cut -d":" -f1` JASPER_NB=$((JASPER_NB+1)) sed -i "$JASPER_NB s%.*%host    all         all         $JASPER_SERVER/32      md5%" /mnt/postgres/data/pg_hba.conf



The end

Having a small (or even big) BI architecture up and running into EC2 is not a big deal. Having it properly set – in order not to pay extra fees – is something different and need some basic thinking before doing. The addressing issue which is technically simple, can have negative impact on your project if you don’t manage it from the start.

I will recommand any AWS / EC2 user (BI or not) to create their own admin tools and scripts, based on the various available APIs, in order to  :
  • reduce reaction time,
  • be fully independent,
  • spare time (graphical tools are nice but need clicks, clicks and clicks …)
Some usefull links about AWS / EC2 documentation :
    Feel free to contact me if this article is not clear enough.

    Monday, 6 December 2010

    Update : Amazon Simple DB data loading with Kettle

    Hi all,
    This is just an update for this old article : Amazon Simple DB data loading with Kettle.
    The files are now back and you can download them :
    • You can find the Kettle transformation HERE.
    • You can find the Jscript HERE.
    • You can find my little flat file HERE.

    Friday, 26 November 2010

    Postgresql dumps and storage on S3 : the sequel … using dynamic temp EBS

    Hi all,
    Here you can find a new and customized approach for Postgresql dumps and storage on S3. Based on my previous post, this script uses the EC2 API and has new features and will :
    1. Create an EBS volume on EC2,
    2. Prepare the EBS volume filesystem and mount it on you database server (in EC2 cloud),
    3. Run the postgresql dump utility and store the dumps on the EBS volume,
    4. Rend the dump files to S3, into the bucket you want,
    5. Manage dump file collections in the bucket : clean / delete the previous dump files according to the retention date/period,
    6. Un-mount and delete the EBS volume, like that you no longer pay for something you don’t need / don’t use.

    image
    Here is the script descriptions :
    1. Create the temporary EBS volume,
      • VOLUME=`ec2-create-volume  --size $VOL_SIZE --region $REGION -z $AVAIL_ZONE | cut -f2`
    2. Building the filesystem and mounting as /mnt/something
      • STATE=`ec2-attach-volume $VOLUME --instance $INSTANCE --device $DEVICE --region $REGION | cut -f5`
    3. Start database dump
      • su - postgres -c "$PG_DUMP $BASE | gzip | split -b $SPLITS - $DUMP_FILE"
    4. Send the dump files to S3 with s3cmd
      • s3cmd -p put $DUMP_FILE* $S3ENDPOINT
    5. Detaching the EBS Volume
      • STATE=`ec2-detach-volume $VOLUME --region $REGION | cut -f5`
    6. Clean up the historical dump files on S3, based on
      • for FILENAME in `$S3PUT ls $S3ENDPOINT | cut -d":" -f3`  ====> delete
    After running, the temporary EBS volume is no longer attached to the server and delete can be performed.

    image
    Below, you can find the script. Please note :
    • use database_name = bucket name, for convenience. Otherwise you will have to modify the script.
    • use database_name as parameter $1.
    • the final routine (lookup on s3 bucket files for cleanup) is a modified version of the one found here.
    • Be sure you have a working installation for the EC2 API (+path)
    • Variables to check :
      • Java path
      • Availability zone (EC2)
      • Region (EC2)
      • Device (something from sdf to sdxxxx)
      • Dump dir : will be hosted on the temp EBS once mounted on /mnt/something
      • Volume size : the size of the volume to create. Be sure you have enough space for your dumps
      • Splits : size for multi dump files.
    #!/bin/bash
    ######################################################
    #                                                    #
    #        POSTGRES startup script                     #
    # Author : Vincent Teyssier                          #
    # Date   : 20/11/2010                                #
    #                                                    #
    #####################################################
    #
    # General variables
    export JAVA_HOME="/mnt/postgres/jdk1.6.0_21"
    export EC2_HOME="/mnt/postgres/ec2-api-tools-1.3-53907"
    export EC2_PRIVATE_KEY="/mnt/postgres/ec2-api-tools-1.3-53907/keys/pk-file.pem"
    export EC2_CERT="/mnt/postgres/ec2-api-tools-1.3-53907/keys/cert-file.pem"
    export JDK_HOME="${JAVA_HOME}"
    export PATH="${JAVA_HOME}/bin:${PATH}"
    export PATH="$PATH:$EC2_HOME/bin"
    
    # EC2 Variables
    AVAIL_ZONE="eu-west-1a"
    REGION="eu-west-1"
    INSTANCE="your EC2 instance id"
    DEVICE="/dev/sdh"
    DUMP_DIR="/mnt/postgres/dumps"
    VOL_SIZE="100" # in mb
    
    # Dump variables
    PG_DUMP="/usr/lib/postgresql/8.4/bin/pg_dump"
    S3PUT="/mnt/postgres/s3tools/s3cmd-1.0.0-rc1/s3cmd"
    BASE=$1
    SPLITS="70m"
    DUMP_TIME=`date +"%Y%m%d"`
    DUMP_FILE="$DUMP_DIR/$DUMP_TIME.gz"
    S3ENDPOINT="s3://postgresql-dumps/pilotroi/$BASE/"
    
    echo "***********************************************"
    echo "*    DUMP/ BACKUP PROCESS                     *"
    echo "*    Starting at :" `date` 
    echo "***********************************************"
    
    # Create volume
    echo ""
    echo "Create Volume"
    VOLUME=`ec2-create-volume  --size $VOL_SIZE --region $REGION -z $AVAIL_ZONE | cut -f2`
    while ! ec2-describe-volumes $VOLUME --region $REGION | grep -q available; do sleep 1; done
    echo "Created volume " $VOLUME "with size of "  $VOL_SIZE " Gb"
    
    # Attaching volume
    echo "***********************************************"
    echo "Now attaching volume"
    STATE=`ec2-attach-volume $VOLUME --instance $INSTANCE --device $DEVICE --region $REGION | cut -f5`
    while ! ec2-describe-volumes $VOLUME --region $REGION | grep -q attached; do sleep 1; done
    echo "Volume " $VOLUME "has state : " $STATE
    
    # Building filesystemm and mounting
    echo "***********************************************"
    echo "Now building filesystem"
    while [ ! -e $DEVICE ]; do echo -n .; sleep 1; done
    sudo mkfs.ext3 -F $DEVICE
    if [ ! -d $DUMP_DIR ]
    then
    sudo mkdir $DUMP_DIR
    fi
    sudo mount $DEVICE $DUMP_DIR
    sudo chown postgres:postgres $DUMP_DIR
    sudo chmod 777 $DUMP_DIR
    su - postgres -c "touch file.txt"
    echo "Volume " $VOLUME "mounted on " $DUMP_DIR
    
    
    # Dumping
    echo "**********************************************"
    echo "Dump started at " `date`
    echo "su - postgres -c $PG_DUMP $BASE | gzip | split -b $SPLITS - $DUMP_FILE"
    su - postgres -c "$PG_DUMP $BASE | gzip | split -b $SPLITS - $DUMP_FILE"
    echo "Dump ended at " `date`
    # Sending
    echo "**********************************************"
    echo "Send to S3 started at " `date`
    $S3PUT -p put $DUMP_FILE* $S3ENDPOINT
    echo "Send ended at " `date`
    #echo "**********************************************"
    #echo "Deleting local dump files"
    #rm $DUMP_DIR/$BASE.gz*
    
    
    # Cleaning all
    sudo umount $DUMP_DIR
    echo "$DUMP_DIR unmounted"
    sudo rm -Rf $DUMP_DIR
    
    # Detaching volume
    echo "***********************************************"
    echo "Now detaching volume"
    STATE=`ec2-detach-volume $VOLUME --region $REGION | cut -f5`
    while ! ec2-describe-volumes $VOLUME --region $REGION | grep -q available; do sleep 1; done
    echo "Volume $VOLUME has now state : $STATE and can be deleted"
    ec2-delete-volume $VOLUME --region $REGION
    echo "Volume $VOLUME currently deleting"
    echo "Database dump is finished at : " `date`
    echo "***********************************************"
    echo "Cleanup process"
    echo "Starting at :" `date`
    
    LIMIT=`date --date="5 day ago" +"%Y%m%d"`
    echo $LIMIT
    echo `date '+%F %T'` - Timestamp of 5 days ago: $LIMIT
    echo `date '+%F %T'` - Getting the list of available backups
    TOTAL=0
    for FILENAME in `$S3PUT ls $S3ENDPOINT | cut -d":" -f3`; do
    if [[ $FILENAME =~ ([0-9]*)\.gz* ]]
    then
    echo ${BASH_REMATCH[1]}
    TIMESTAMP=${BASH_REMATCH[1]}
    echo `date '+%F %T'` - Reading metadata of: $FILENAME
    echo -e "\tFilename: $FILENAME"
    echo -e "\tTimestamp: $TIMESTAMP"
    if [[ $TIMESTAMP -le $LIMIT ]]; then
    let "TOTAL=TOTAL+1"
    echo -e "\tResult: Backup deleted\n"
    $S3PUT del "s3:$FILENAME"
    else
    echo -e "\tResult: Backup keeped\n"
    fi
    fi
    done
    echo `date '+%F %T'` - $TOTAL old backups removed
    
    


    It’s working nicely on all my postgres servers. I’m currently finalizing a custom script for retrieving and re-creating a database back from the dump file collection.


    Feel free to contact me for any question.

    Monday, 22 November 2010

    Postgresql dumps and storage on S3

    Hi all,
    I recently had to manage all my backups from Postgresql instances on the cloud. For all these cloud-based backup jobs, I’m using a three way approach. Maybe you think it’s a bit redundant, but I don’t like surprises.
    • Database dump to S3 : daily, depends on criticity …
    • EC2 instance snapshot : daily or weekly, depends … I like to know I can keep several generation of instance image, even if I do not change them quite often now …
    • EBS volume snapshot : hourly or daily, depends on criticity,
    Today, I want to share with you what I did as first backup process : database dump to S3. Of course, you need to have knowledge of Amazon S3 (as well as an account) for that. In the next coming articles, I will show you what I created in order to automate and manage all EC2 instances & volume snapshots.
    For the moment let’s go back to db dump to s3. My process is a simple shell script that will :
    1. Connect to Postgresql,
    2. Start a database dump (database name is passed as script argument),
    3. Split the dump files into several pieces (chunk size is passed as script argument),
    4. Send the dump files into S3.
    Note : your postgresql server (from which you want to dump) does not have to be hosted on AWS/EC2. This process also works with on premises architecture.
    image

    Tools of the trade : pgdump and S3CMD

    image
    I’m using a wonderful tool called s3cmd, you can find it here. This tool allows you to send, retrieve and manage data on Amazon S3. It also offers bucket management, GPG encryption and https transfer. A very good command line tool that will find its place in your EC2 toolbox.
    Installing s3cmd is quite easy and, when using s3cmd –config you will be prompted with your S3 account credentials and other params. You can later retrieve this data into the file called .s3cmd.
    The commands are quite simple :
    • Send file to S3 : s3cmd put file_to_send your_s3_endpoint
    • List buckets : s3cmd ls
    • List content of a bucket : s3cmd ls “Bucket_name” : Bucket_name will have the form : s3://bucket_name
    • Retrieve a file from a bucket : s3cmd get s3://“Bucket_name”/”file_name”.
    As you can see, really easy usage and fits perfectly in a shell script.
    image
    Pg_dump is the regular backup client application for Posgresql database. Its syntax, simplified here, is : pg_dump “dbname” > outfile. You can learn more about pg_dump here. For this current example, I will use the following command :
    • pg_dump db_name | gzip | split -b 50m – dump_file
      • pg_dump : the command,
      • db_name : the db name you want to dump,
      • gzip : create gzipped archives,
      • split : split the dump into several pieces,
      • -b 50m : split size = 50 Mo
      • dump_file : the dump file (the split option will create a collection with extensions like gzaa, gzab …).
    • Add –v if you want a verbose log.

    Process prerequisites

    First, I created an internal account for my Postgresql database. This account has only rights to connect from the database server itself (or localhost). All passwords were disabled for this account, only “trust” is present in pg_hba.conf. Select rights were also granted.
    Then, I created a dedicated directory on the database server to hold the dump files. This directory will only hold the dump files for very limited time, they will be deleted after been pushed on S3 with s3cmd. I recommend to store these temp dump files on a separate and dedicated EBS volume.
    Last, we need a minimum setup on S3 side. Create the appropriate bucket hierarchy you need. Mine is quite simple for this backup process :
    • 1st level : /postgresql-dumps
      • 2nd level : product name : “pilotroi”, the product name of my company (we have several products)
        • 2nd level : /database name, one bucket by database. This is the second parameter I will pass to the shell script. For flexibility, I use the exact same name as for the postgres database I wan to dump. This allows me to build my bucket endpoint like :
          • s3://postgresql-dumps/pilotroi/$BASE/"

    Custom script

    Below is my custom script. A lot of “echo”, hum ? As I said, I don’t like surprises and prefer having verbose logfiles. This script is cronted and needs two parameters :
    1. Database name : the name of the db you need to dump.
    2. Splits : the size of the chunks you want to generate. For instance, 50m is for generating files having a size of 50 Mo max.
    Call the script like that, using two params ($1 and $2) : sh s3_pg_dump.sh client_base 50m
    #!/bin/bash
    
    ################################## 
    #                                # 
    # POSTGRES DUMPS FOR PILOTROI    # 
    # Vincent Teyssier               # 
    # 19/11/2010                     # 
    #                                # 
    ##################################
    
    echo "******************************************************" 
    echo "Database dump is starting at : " `date` 
    echo "******************************************************"
    
    PG_DUMP="/usr/lib/postgresql/8.4/bin/pg_dump" 
    S3PUT="/mnt/postgres/s3tools/s3cmd-1.0.0-rc1/s3cmd"
    
    BASE=$1 
    SPLITS=$2 
    DUMP_FILE="/mnt/postgres/dumps/$BASE.gz" 
    S3ENDPOINT="s3://postgresql-dumps/pilotroi/$BASE/"
    
    echo "*****************************" 
    echo "Parameters : " 
    echo "Base : " $BASE 
    echo "Splits : " $SPLITS 
    echo "S3 Endpoint : " $S3ENDPOINT 
    echo "*****************************"
    
    echo "Dump started at " `date` 
    su - postgres -c "$PG_DUMP $BASE | gzip | split -b $SPLITS - $DUMP_FILE" 
    echo "Dump ended at " `date` 
    echo "*****************************" 
    echo "Send to S3 started at " `date` 
    $S3PUT put $DUMP_FILE* $S3ENDPOINT 
    echo "Send ended at " `date` 
    echo "*****************************" 
    echo "Deleting local dump files" 
    rm /mnt/postgres/dumps/$BASE.gz*
    
    echo "******************************************************" 
    echo "Database dump is finished at : " `date` 
    echo "******************************************************" 
    
    
    
    


     



     



    Process output



    This script file will produce the following output.


    image





    Data is now on S3



    Using S3 Explorer Firefox plugin, you can see all our files are now stored in their dedicated bucket on S3.


    image





    As usual, drop me a message to learn more if needed.

    Thursday, 14 October 2010

    Modified Firefox ElasticFox plugin (handling micro instances)

    Hi all,
    ElasticFox is a wonderful plugin for you guys, AWS and Firefox geeks.
    We all know AWS added a new instance size recently : micro. Micro instances are really small setups with approx 650 Mo RAM and are very useful to build small servers, controllers, dns, ftps …
    Unfortunately I’m afraid there is no “micro” instance size in ElasticFox so far, have a look below.
    image
    That’s why I did my own hack. Note : this is a personal hack, not a new version of ElasticFox. Now you can launch a new instance using “micro” size. This is working perfectly for me (beware using micro instances with Ubuntu Lucid : issues with the fstab as described in http://alestic.com/).
    Please let me know if this hack is usefull and working for you as well.
    You can download this Elasticfox plugin here.
    imageThe new micro instance size

    Monday, 29 March 2010

    Download new Kettle Job Plugin : SendToS3 – Release 2

    Hi all,
    As said in my previous post (below), the release 2 for the Kettle Job Plugin I made is available for download HERE. This release offers a bucket management screen (creation, listing, assign …).
    More to come : after been asked for, I will add some metadata / object attributes to be linked with the file in S3. Very usefull if you need, like me, to manage file collections. Have a look below for an example of object attributes.
    image
    Enjoy,
    Vincent

    Friday, 26 March 2010

    NEW FEATURE : Kettle Job Plugin : SendToS3

    Hi all,
    Here is an overview of a new feature for the Kettle Job plugin “Send files to Amazon S3”. As you can see, I added a screen for bucket management : creation, listing, autorefresh … For those who are new to S3, a bucket is – more or less – like a folder but with specific S3 constraints.
    During the last week, I was asked to add some more features : zip file, file renaming, file timestamping … Seems people are sending a lot of things on S3 now …
    I will find time to add these features during April.
    Still need to clean my code and I will soon push a release on the plugin Google code page.
    image

    Tuesday, 9 March 2010

    Send file to S3 with cool GUI

    Hi all,
    A cool way to manage your S3 assets : http://s3fm.com/. You can create / edit / delete buckets as well as uploading files and downloading also.
    I’m currently writing some code that could be used in Kettle for sending and retrieving files to/from S3. Soon to come, I’m still working on it.
    image
    In this example, I’m sending US public data set (consumer expanditure survey) flat file, available on Amazon, that will be later used for data processing and stats in order to validate a stream.