Advertise with Googlier.com Allan Feid - perl https://allanfeid.com/category/tags/perl en Cluster Management with FreePanel https://allanfeid.com/content/cluster-management-freepanel <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><p>I haven't had much time to continue work on <a href="http://freepanel.org" title="FreePanel Wiki">FreePanel</a>, but the Perl modules I've written have proven to be useful in cluster management. Take a look at the following diagram as an example scenario:</p> <div align="center"><img src="/sites/default/files/cluster_diagram.png" title="Web Cluster Example" alt="Web Cluster Example" /></div> <p>There's two key points to take away from that diagram.</p> <ul><li>physical servers are load balanced using a single VIP (Virtual IP)</li> <li>the servers share access to a single storage mount</li> </ul><p>The idea behind load balancing is that requests go to the individual servers based on which can handle the traffic. A hardware appliance takes care of the actual load balancing work, but this could be done using some software just as easily.</p> <h2>So what does this have to do with FreePanel?</h2> <p>If you're constantly needing to add additional domains to your cluster, doing this manually becomes tiresome, especially when in most cases your application needs the same Apache configuration per domain. Take the below basic Virtual Host config:</p> <pre> <virtualhost> ServerAdmin webmaster@example.com ServerName example.com ServerAlias www.example.com ErrorLog /home/sites/logs/example.com.error CustomLog /home/sites/logs/example.com.access combined DocumentRoot /home/sites/example.com/web <directory></directory> Options Indexes FollowSymLinks AllowOverride None Order allow,deny Allow from all </virtualhost></pre><p>Each of your 50 or so hosted applications needs a similar configuration, just with a different domain name. That's where FreePanel can make your life easier. Take the above example and we'll form a template that can be used with FreePanel's Apache module.</p> <pre> <virtualhost>&gt; ServerAdmin webmaster@<domain> ServerName <domain> ServerAlias www.<domain> ErrorLog /home/sites/logs/<domain>.error CustomLog /home/sites/logs/<domain>.access combined DocumentRoot /home/sites/<domain>/web <directory>/web/&gt; Options Indexes FollowSymLinks AllowOverride None Order allow,deny Allow from all </directory></domain></domain></domain></domain></domain></domain></virtualhost></pre><p>As you can expect, this module can parse the template file and replace certain items with what arguments are being passed. We'll take a look at the addSite method of <a href="http://github.com/crazed/freepanel/blob/master/run/FreePanel/Admin/Apache.pm" title="FreePanel::Admin::Apache on github">FreePanel::Admin::Apache</a>.</p> <pre> sub addSite { my ($self, $domain, $ip_addr) = @_; $self-&gt;logger("function: addSite($domain, $ip_addr) called.", $self-&gt;FUNC_CALL); my $vhost_dir = $self-&gt;getVhostDir(); my $vhost_templ = $self-&gt;getVhostTemplate(); my $check = $self-&gt;getValidateObj(); if ($check-&gt;is_active($domain, $vhost_dir)) { $self-&gt;logger("vhost config already exists for $domain.", $self-&gt;ERROR); return 0; } open (VHOST, '&gt;', $vhost_dir."/$domain"); open (VHOST_T, ') { s/<domain>/$domain/; s/<ip_addr>/$ip_addr/; print VHOST; } } else { while (<vhost_t>) { s/<domain>/$domain/; s/<ip_addr>/\*/; print VHOST; } } close VHOST_T; close VHOST; return 1; } </ip_addr></domain></vhost_t></ip_addr></domain></pre><p>Nothing really that crazy going on here, it just opens up the template file -- defined in your config file -- then replaces <code class="prettyprint">&lt;DOMAIN&gt;</code> and <code class="prettyprint">&lt;IP_ADDR&gt;</code> with the values you pass. This file is written out to a directory -- also defined in the config file -- and if no IP address is passed, we default to use *. This could be easily modified to include additional values, but I won't go into that now.</p> <h2>Okay, how do I use it?</h2> <pre> #!/usr/bin/perl use strict; use FreePanel::Admin::Apache; if ($#ARGV [ip address]\n"; exit; } my $domain = $ARGV[0]; my $ip_addr = $ARGV[1]; my $apache = new FreePanel::Admin::Apache; $apache-&gt;addWebDir($domain) or die "Error adding web directory for $domain"; $apache-&gt;logger("web directory for $domain has been created.", $apache-&gt;INFO); if ($ip_addr) { $apache-&gt;addSite($domain, $ip_addr) or die "Error creating vhost with $ip_addr for $domain"; $apache-&gt;logger("vhost config created for $domain using $ip_addr.", $apache-&gt;INFO); } else { $apache-&gt;addSite($domain) or die "Error creating vhost for $domain"; $apache-&gt;logger("vhost config craeted for $domain.", $apache-&gt;INFO); } # restart apache, still implementing FreePanel::Admin::Apache-&gt;restart system('apachectl restart'); </pre><p>With the above you have a basic script for adding new domains fairly quickly. This will also allow you to keep track of what has been added and when since everything you do using FreePanel is logged to a file you chose. Here's a sample log output:</p> <pre> 03-07-2010 11:59:36 :: [ DEBUG ] function: addWebDir(example.com) 03-07-2010 11:59:36 :: [ INFO ] web directory for example.com has been created. 03-07-2010 11:59:36 :: [ DEBUG ] function: addSite(example.com) called. 03-07-2010 11:59:36 :: [ INFO ] vhost config craeted for example.com. </pre><p>Your level of logging is also defined by the configuration file. So with this basic script you get a log keeping track of what sites have been added and when as well as taking on the tedious work of copying a configuration file and switching a few values to meet the new domain's needs. There's a bit of documentation lacking, but some will soon be added to the <a href="http://freepanel.org" title="FreePanel.org">FreePanel Wiki</a>.</p> <h2>A case study: three web servers (clustered) using SSL for all domains</h2> <p>Recently, I was dealing with a client that had three web servers all behind a load balancer (Cisco CSS). This was a basic CRM software that required SSL for each virtual host (domain). This was troublesome because you need a unique IP address for each SSL site, and since all of their clients were using SSL, this meant every single domain had to have its own IP. This also means that each virtual host will be listening on a private IP behind the CSS. What this means is you will see something like this:</p> <p><strong>Web01:</strong></p> <pre> <virtualhost> ServerAdmin webmaster@example.com ServerName example.com ... </virtualhost></pre><p><strong>Web02:</strong></p> <pre> <virtualhost> ServerAdmin webmaster@example.com ServerName example.com ... </virtualhost></pre><p><strong>Web03:</strong></p> <pre> <virtualhost> ServerAdmin webmaster@example.com ServerName example.com ... </virtualhost></pre><p>Being a lazy systems admin, I certainly did not want to manually create three configurations each time I wanted to add a new domain. So I used <code class="prettyprint">FreePanel::Admin::Apache</code> and some ssh keys to carry out the creation of each. Using the <code class="prettyprint">addSite</code> method, I passed the last octet of each domain rather than the full IP, and had the template using something similar to this:</p> <pre> <virtualhost>&gt; </virtualhost></pre><p>Of course, changing the first three octets based on which server this template was being used on. I had a simple script similar to the one above that took the input for domain name and IP address, and a main script which I ran from an admin box. The main script was in charge of creating SSH connections and launching the helper script on each server with the proper arguments. This main script also remotely restarted Apache after creating each site.</p> <p>While this example certainly isn't very elegant as password-less root SSH keys were required, it did however prove to be a very useful use-case for our Apache module. Solutions to problems such as this are why I work on FreePanel, because we all know that lazy syadmins are usually the best sysadmins.</p> </div></div></div><section class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above view-mode-rss"><h2 class="field-label">Tags:&nbsp;</h2><ul class="field-items"><li class="field-item even"><a href="/category/tags/script" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">script</a></li><li class="field-item odd"><a href="/category/tags/perl" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">perl</a></li><li class="field-item even"><a href="/category/tags/freepanel" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">FreePanel</a></li><li class="field-item odd"><a href="/category/tags/sysadmin" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">sysadmin</a></li></ul></section> Fri, 05 Mar 2010 17:16:09 +0000 Allan Feid 62 at https://allanfeid.com Perl: wrapper for virt-install to provide iSCSI storage pool creation https://allanfeid.com/content/perl-wrapper-virt-install-provide-iscsi-storage-pool-creation <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><p>So I've been working on a setup for virtualization, where currently I'm using <a href="/content/serving-iscsi-targets-your-zpool" title="Serving iSCSI targets from your zpool">one large iSCSI target</a> from an OpenSolaris machine. It occurred to me that there is a downside to this. I cannot use zfs snapshots for individual machines and backups/restores will be more difficult. I also did not want to be hassled with having to connect the iscsi targets using <code class="prettyprint">iscsiadm</code> every time I spin up a new VM.</p> <p>Luckily libvirt <a href="http://libvirt.org/storage.html#StorageBackendISCSI" title="libvirt storage pool management">provides iSCSI storage pool methods</a> which will connect the targets and manage them for you. This makes life much easier for me, however, <code class="prettyprint">virt-install</code> does not have the functionality to install on these. Me being more proficient in Perl, I decided to take up the task of creating a simple wrapper. To use it, first you need this template XML file called "disk.xml."</p> <pre> <pool type="iscsi"><name>$NAME</name> <pre class="prettyprint"><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;host name="$PORTAL"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;device path="$TARGET"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </code></pre> <target><path>/dev/disk/by-path</path></target></pool></pre><p>Here's my script that I call <code class="prettyprint">virt-iscsi-install</code>, and it's pretty easy to use. Not the greatest solution as it does not do much for error checking, but for now this is what I'll be using. I may consider venturing into some Python and patch virt-install to include similar functionality as the libvirt library is well documented and not hard to understand.</p> <pre> #!/usr/bin/perl use Sys::Virt; use Getopt::Long; usage() if ( ! GetOptions( 'name|n=s' =&gt; \$name, 'ram|r=s' =&gt; \$ram, 'target|t=s' =&gt; \$target, 'portal|p=s' =&gt; \$portal, 'mirror|m=s' =&gt; \$mirror )) ; #print "name: $name\nram: $ram\ntarget: $target\nportal: $portal\n"; sub usage { print "usage: $0 --name <name> --ram <ram> --target ". "<iscsi target=""> --portal <iscsi portal=""> --mirror <install mirror="">\n"; exit; } my $path = createPool($target,$portal,$name); print "Volume: $path\n"; print "Launching virt-install..\n"; system ("virt-install -n $name -r $ram --location $mirror --file $path --vnc --bridge=br0"); sub createPool { my ($target, $portal, $name) = @_; my $vmm = Sys::Virt-&gt;new(address =&gt; 'qemu:///system'); open my $fh, ') { s/\$NAME/$name/; s/\$TARGET/$target/; s/\$PORTAL/$portal/; $xml = "$xml $_"; } close $fh; #print $xml; my $pool = $vmm-&gt;define_storage_pool($xml); $pool-&gt;create(); if (!$pool-&gt;get_autostart) { print "setting pool to auto-start\n"; $pool-&gt;set_autostart(1); } my @volNames = $pool-&gt;list_volumes; foreach my $vol (@volNames) { return $vol-&gt;get_path; } } </install></iscsi></iscsi></ram></name></pre></div></div></div><section class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above view-mode-rss"><h2 class="field-label">Tags:&nbsp;</h2><ul class="field-items"><li class="field-item even"><a href="/category/tags/script" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">script</a></li><li class="field-item odd"><a href="/category/tags/perl" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">perl</a></li><li class="field-item even"><a href="/category/tags/libvirt" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">libvirt</a></li></ul></section> Wed, 03 Mar 2010 16:42:28 +0000 Allan Feid 60 at https://allanfeid.com Announcing FreePanel https://allanfeid.com/content/announcing-freepanel <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><p>What's been keeping me busy? Well I've been working for a managed hosting company (DataPipe) and that has been the biggest source of time suck for me. Outside of that I've been working on some Perl modules to make administrating load balanced servers as easy as possible. For now, read the source if you want to know more:</p> <p><a href="http://github.com/crazed/freepanel/" title="FreePanel on GitHub">FreePanel</a></p> </div></div></div><section class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above view-mode-rss"><h2 class="field-label">Tags:&nbsp;</h2><ul class="field-items"><li class="field-item even"><a href="/projects" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">project</a></li><li class="field-item odd"><a href="/category/tags/perl" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">perl</a></li><li class="field-item even"><a href="/category/tags/freepanel" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">FreePanel</a></li><li class="field-item odd"><a href="/category/tags/sysadmin" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">sysadmin</a></li></ul></section> Fri, 15 Jan 2010 17:40:38 +0000 Allan Feid 54 at https://allanfeid.com Parse Airodump-NG Output with Perl https://allanfeid.com/content/parse-airodump-ng-output-perl <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded">I had to enumerate all the wireless access points around school today. So I booted up BackTrack 4 on my Eee PC and ran airodump-ng to create a list of ESSIDs, their corresponding BSSIDs, and the channels they were running on. <!--break--> Start off by running airodump-ng to save the data: <pre>airodump-ng ath0 -w enum</pre> That saves all the data to enum-01.txt, .csv, and .cap files. The .txt file itself is difficult to read, so I wanted to make a perl script to parse the data to a much more readable format. This is what I came up with: <pre> #!/usr/bin/perl -w my @data; my @bssid; my @fts; my @lts; my @channel; my @speed; my @privacy; my @cipher; my @authentication; my @power; my @num_beacons; my @num_ivs; my @lan_ip; my @idlen; my @essid; # read the airodump file open FILE, "<? echo htmlspecialchars("<enum.txt"); ?>" or die $!; while (<? echo htmlspecialchars("<FILE>"); ?>) { # lines are put in default $_ var, split reads this by default @data = split(/,\s*/); push(@bssid, $data[0]); push(@fts, $data[1]); push(@lts, $data[2]); push(@channel, $data[3]); push(@speed, $data[4]); push(@privacy, $data[5]); push(@cipher, $data[6]); push(@authentication, $data[7]); push(@power, $data[8]); push(@num_beacons, $data[9]); push(@num_ivs, $data[10]); push(@lan_ip, $data[11]); push(@idlen, $data[12]); push(@essid, $data[13]); } close(FILE); # get unique essids my $essid_search; # easier to remember/type than $essid[$i]; my @unique_essids; # array of unique essids my $unique_essid; # var used in foreach loop as the current unique essid my $check_unique; # bool, if true (1) essid is unique foreach ($i = 0; $i <= scalar(@essid); $i++) { $essid_search = $essid[$i]; # if blank essid go to next if (!$essid_search) { next; } # loop through and see if it's a unique essid $check_unique = 1; foreach $unique_essid (@unique_essids) { if ($essid_search eq $unique_essid) { $check_unique = 0; last; } } # if unique, add it to @unique_essids if ($check_unique == 1) { push(@unique_essids, $essid_search); } } # look at all the essid, then print out corresponding bssid and channel my $essid_match; foreach $essid_match (@unique_essids) { print "Matching for $essid_match\n"; print "-----------------------------------------------------\n"; print "\tBSSID\t\t\tCHANNEL\tPRIVACY\n"; print "-----------------------------------------------------\n"; for ($i = 0; $i <= scalar(@essid); $i++) { if (($essid[$i]) && ($essid[$i] eq $essid_match)) { print "\t".$bssid[$i]."\t".$channel[$i]."\t".$privacy[$i]."\n"; } } print "=====================================================\n\n\n"; } </pre> Nothing fancy going on here and you'll have to change the open FILE section to correlate to the name of your capture file. This also ignores blank ESSIDs, as for my project I did not need them. Either way quick and easy and much better looking. I'll probably expand on this for future use but this is where I'll leave it for now.</div></div></div><section class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above view-mode-rss"><h2 class="field-label">Tags:&nbsp;</h2><ul class="field-items"><li class="field-item even"><a href="/category/tags/script" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">script</a></li><li class="field-item odd"><a href="/category/tags/wireless" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">wireless</a></li><li class="field-item even"><a href="/category/tags/perl" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">perl</a></li><li class="field-item odd"><a href="/category/tags/airodump-ng" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">airodump-ng</a></li></ul></section> Wed, 01 Apr 2009 03:32:51 +0000 Allan Feid 38 at https://allanfeid.com