Tuesday, 23 August 2011

toggling /etc/hosts file via a simple gui

Like many folks who play at web development, I have local running instances of all my websites to enable offline development and/or testing.

To switch between the two, I have a launcher to a little gui I've written.

The Interface
The Dialog raised on request.

works great.

the code is below.

Incidentally, as /etc/hosts required root permissions, I call the write using gksu. KDE users would need to change this.

Here's the full code.
#! /usr/bin/env python

'''
This script modifies the /etc/hosts file so that I utilise this machines
web server rather than doing a dns lookup and going to the online 
sites.
It's for testing purposes. 

my /etc/hosts file has this text present.

127.0.0.1   localhost 
127.0.0.1   rowinggolfer.org 
127.0.0.1   openmolar.com 
127.0.0.1   academydental.com 
127.0.1.1    slim-maroon

and when I want to use the "cloud" servers, the sites listed in variable SITES
are commented out.

'''

from PyQt4 import QtGui, QtCore
import re, subprocess, sys, tempfile

SITES = ["rowinggolfer.org", "academydental.com", "openmolar.com",]


class Dialog(QtGui.QDialog):
    def __init__(self, parent=None):
        QtGui.QDialog.__init__(self, parent)
    
        self.setWindowTitle("toggle /etc/hosts file")
        
        self.local_rb = QtGui.QRadioButton("Using localhost")
        self.global_rb = QtGui.QRadioButton("Using remote host(s)")
        
        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.local_rb)
        layout.addWidget(self.global_rb)
        
        self.global_rb.setChecked(True)
        self.local_rb.setChecked(self.check_state)
        
        self.local_rb.toggled.connect(self.apply_changes)
    
    def sizeHint(self):
        return QtCore.QSize(200,50)
    
    @property
    def check_state(self):
        '''
        checks /etc/hosts to see if it is set to use the local instance of 
        apache2 for the SITES
        '''
        local = False
        
        f = open("/etc/hosts", "r")
        for line in f:
            for site in SITES:
                if re.match("127\.0\.0\.1[ \t]*%s"% site, line):
                    local = True
        
        return local
        
    def apply_changes(self, use_local):
        host = "localhost" if use_local else "remote host(s)"
        
        message = '''modify <em>/etc/hosts</em> so that 
            <b>%s</b> is used for the following sites?<ul>{sites}</ul>'''% host
        
        sites = ""
        for site in SITES:
            sites += "<li>%s</li>"% site
            
        message = message.replace("{sites}", sites)
        
        result = QtGui.QMessageBox.question(self, "confirm", message,
        QtGui.QMessageBox.Ok|QtGui.QMessageBox.Cancel,
        QtGui.QMessageBox.Ok) == QtGui.QMessageBox.Ok
        
        if result:
            self.write_file(use_local)
        
        
        success = use_local == self.check_state
        
        if success:
            QtGui.QMessageBox.inforamtion(self, "success", 
                "changes applied sucessfully")
        
        self.local_rb.toggled.disconnect(self.apply_changes)
        self.local_rb.setChecked(self.check_state)
        self.local_rb.toggled.connect(self.apply_changes)
        
        
        
    def write_file(self, local):
    
        def repl(arg):
            if local:
                return re.sub("\n#*", "\n", arg.group())
            else:
                return arg.group().replace("\n", "\n#")
    
        f = open("/etc/hosts", "r")
        data = f.read()
        f.close()
        if not local:
            for site in SITES:
                data = re.sub(  "(\n127\.0\.0\.1[ \t]*%s)"% site, 
                                repl, data)
        else:
            for site in SITES:
                data = re.sub(  "\n#*127\.0\.0\.1[ \t]*(%s)"% site, 
                                repl, data)
    
        t = tempfile.NamedTemporaryFile("w", delete=False)
        t.write(data)
        t.close()
        
        p = subprocess.Popen(["gksu", "mv", t.name, "/etc/hosts"]) 
        assert p.wait()==0
        
        
if __name__ == "__main__":
    app = QtGui.QApplication([])
    dl = Dialog()
    dl.exec_()
    
    

Monday, 22 August 2011

A VPS from Bitfolk

I've had a VPS from amazon up and running for a few months, but I simply couldn't get my head around their billing tariffs. I am sure they are great and really flexible, but they weren't working out as a good deal for me.
(on average I was paying $75 a month). On top of that, on Friday, I was having trouble logging in (probably my own fault).


So I finally got around to switching provider.
and as http://bitfolk.com/ are well known to the UK floss community as a sponsor of http://oggcamp.org/ , and patronised by the internet's very own "Alan (popey) Pope".

Bitfolk have been an absolute joy to deal with, I had my server up and running within a couple of hours of my enquiry.

I have now moved both www.openmolar.com and www.rowinggolfer.org onto that server and they seem fast and stable.
 How much for this incredible service? Under 20% of the cost of the amazon box (which is now cancelled), and easy to understand.


Thanks Bitfolk, and a 5 star rating from yours truly.

Tuesday, 16 August 2011

Screencasting on linux

There are lots of good screen capturing options for linux.

On #oggcastplanet on irc.freenode.net,  K4k asked about streaming the output, with a webcam shot of the speaker somewhere on the screen.

here's one way to do that.

1st, start the webcam in a non-intrusive frame. mplayer fits the bill here.

~$ mplayer -cache 128 -tv driver=v4l2:width=320:height=240 -vo xv tv:// 

when that window appears, resize it, place it where you find least intrusive, and set it to remain "on top".

in another terminal, do this

~$ ffmpeg -f oss -i /dev/dsp -f x11grab -s xga -r 15 -i :0.0 out.mp4

then record your screencast.

hit q in the second terminal when you are finished.

If this works.. replace out.mp4 with whatever format or stream you wish to create.

Below is the video I created with this method (on ubuntu 10.04).

video

Thursday, 11 August 2011

Customised Business Software or Software Customised Businesses?

So I am reading Bookeeping for Dummies at the moment (because double-entry booking is a complete mystery to me).

This paragraph caught my eye, when the author discusses software.




Chapter 6
Surveying Computer Options.



...... we must mention the fact that in a significant number of business situations no accounting software package does exactly what you did before in the same way. Every accounting package is a compromise because it offers the features that someone else decided are important for the majority of businesses. The decision you may have to make is whether to modify your business processes to fall into line with the new accounting software or have some bespoke modification to the accounting package you decide to buy. The simplest and cheapest solution is to fall into line with your chosen accounting software.


Get the gist?
The choice is.. change how you do things, or make the software do what you need it to, and the author suggests the former.

I believe it is a shame that ANYONE holds this view. Would we buy shoes that don't fit our feet? Why then do we have to use software that doesn't fit our needs?

Get an open source solution that is the closest fit, then get it modified.