Chris Lacy's Software Engineering Blog
Linux VPN Restart Python Script
Usage: ./vpnRestart <interface id> <vpn id>
For example: ./vpnRestart eth0 myVpn
Tested on Fedora and Ubuntu
#!/usr/bin/env python
import logging
import sys, getopt
import time
import gobject, dbus
from dbus.mainloop.glib import DBusGMainLoop
class DbusHelper:
basePackage = None
systemBus = None
def __init__(self, basePackage):
self.basePackage = basePackage
self.systemBus = dbus.SystemBus()
def createProxy(self, path):
return self.systemBus.get_object(self.basePackage, path)
def createInterface(self, proxy, interfacePackage):
return dbus.Interface(proxy, dbus_interface=interfacePackage)
def createIface(self, proxyPath, interfacePackage):
return self.createInterface(self.createProxy(proxyPath), interfacePackage)
def addReceiver(self, handler, interface, signalName):
self.systemBus.add_signal_receiver(handler,
dbus_interface=interface,
signal_name=signalName)
class DbusPropertiesHelper:
interfacePath = None
propertiesI = None
def __init__(self, proxyPath, dbusHelper, interfacePath):
self.interfacePath = interfacePath
self.propertiesI = dbusHelper.createIface(proxyPath, 'org.freedesktop.DBus.Properties')
def get(self, prop):
return self.propertiesI.Get(self.interfacePath, prop)
class NetworkManagerHelper:
FAILED = 6
DISCONNECTED = 7
interfaceQuery = None
vpnQuery = None
dbusHelper = None
networkManagerI = None
settingsI = None
def __init__(self, interfaceQuery, vpnQuery):
self.interfaceQuery = interfaceQuery
self.vpnQuery = vpnQuery
DBusGMainLoop(set_as_default=True)
self.dbusHelper = DbusHelper('org.freedesktop.NetworkManager')
self.networkManagerI = self.dbusHelper.createIface('/org/freedesktop/NetworkManager', 'org.freedesktop.NetworkManager')
self.settingsI = self.dbusHelper.createIface('/org/freedesktop/NetworkManager/Settings', 'org.freedesktop.NetworkManager.Settings')
def findConnection(self, query):
connection = None
for c in self.getConnections():
ci = self.dbusHelper.createIface(c, 'org.freedesktop.NetworkManager.Settings.Connection')
settings = ci.GetSettings()
if settings['connection']['id'].find(query) != -1:
connection = c
break
return connection
def getConnections(self):
return self.settingsI.ListConnections()
def getConnectionPath(self, uuid):
connection = None
for c in self.getConnections():
settings = settingsI.GetSettings()
if settings['connection']['uuid'] == uuid:
connection = c
break
return connection
def getActiveConnection(self, path):
connection = None
nmdph = DbusPropertiesHelper('/org/freedesktop/NetworkManager', self.dbusHelper, 'org.freedesktop.NetworkManager')
for a in nmdph.get('ActiveConnections'):
acdph = DbusPropertiesHelper(a, self.dbusHelper, 'org.freedesktop.NetworkManager.Connection.Active')
if acdph.get('Connection') == path:
connection = a
break
return connection
def activateVpn(self, connection, specific_object):
self.networkManagerI.ActivateConnection(connection, "/", specific_object)
def isConnectionActive(self, connectionPath):
c = self.getActiveConnection(connectionPath)
return c != None
def activateVpnIf(self):
baseConnectionPath = self.findConnection(self.interfaceQuery)
baseConnected = self.isConnectionActive(baseConnectionPath)
while (baseConnected is False):
logging.debug("waiting for base connection")
time.sleep(10)
baseConnected = self.isConnectionActive(baseConnectionPath)
baseActiveConnection = self.getActiveConnection(baseConnectionPath)
vpnConnectionPath = self.findConnection(self.vpnQuery)
vpnConnected = self.isConnectionActive(vpnConnectionPath)
if (vpnConnected is False):
self.activateVpn(vpnConnectionPath, baseActiveConnection)
connected = self.isConnectionActive(vpnConnectionPath)
def startVpnMonitor(self):
self.activateVpnIf()
self.dbusHelper.addReceiver(self.vpnConnectionHandler, "org.freedesktop.NetworkManager.VPN.Connection", "VpnStateChanged")
gobject.MainLoop().run()
def vpnConnectionHandler(self, *args, **kwargs):
state = args[0]
logging.debug("state %s", state)
if ((state == NetworkManagerHelper.FAILED) or (state == NetworkManagerHelper.DISCONNECTED)):
self.activateVpnIf()
if __name__ == "__main__":
logging.basicConfig(level=logging.ERROR)
if(len(sys.argv) != 3):
print "Usage: vpnRestart "
sys.exit(1)
interfaceQuery = sys.argv[1]
vpnQuery = sys.argv[2]
networkManagerHelper = NetworkManagerHelper(interfaceQuery, vpnQuery)
baseConnectionPath = networkManagerHelper.findConnection(interfaceQuery)
logging.debug(baseConnectionPath)
if(baseConnectionPath is None):
print "Interface id " + interfaceQuery + " not found."
sys.exit(1)
vpnConnectionPath = networkManagerHelper.findConnection(vpnQuery)
logging.debug(vpnConnectionPath)
if(vpnConnectionPath is None):
print "Vpn id " + vpnQuery + " not found."
sys.exit(1)
networkManagerHelper.startVpnMonitor()
Posted at 01:02AM Dec 23, 2011 by chris in General |
interview mistakes 101: overthinking the problem - binary tree flattening
i recently blew an interview with a major company. i had to pseudo-code on a (live) shared doc with my phone in the crook of my neck. problem: flatten a binary tree. it went down hill from there (on this problem). i'm pretty sure (now) that the guy wanted to see this:
private static <T> DoublyLinkedList<T> flatten(BinaryTreeNode<T> btn) {
DoublyLinkedList<T> dll = new DoublyLinkedList<T>();
if(btn != null) {
dll.append(flatten(btn.getLeftChild()));
dll.add(btn.getValue());
dll.append(flatten(btn.getRightChild()));
}
return dll;
}
demonstrate recursion, step through the code, talk about performance
instead, my compiler class shot through my head and i started talking about the strategy and visitor patterns. why would we want to solidify the traversal pattern (left, node, right) or the output (doubly linked list)? he didn't know what the strategy pattern was. i started stumbling and stuttering, knowing we had fixed time. because i had mentioned the strategy pattern i put some temporary code in but ended up ignoring it, and then had difficulty thinking through the recursion (my head was filed with abstractions). so, in my post mortem of the interview i designed the oo solution i would have wanted to see were i the interviewer. you can download it here (which includes the above complete solution), but here are the key parts:
public class BinaryTree<T> {
private BinaryTreeNode<T> root;
public BinaryTree(BinaryTreeNode<T> root) {
this.root = root;
}
public <C> C accept(Visitor<C, T> v, Strategy s) {
s.traverse(root, v);
return v.getResult();
}
}
public interface Visitor<COL, T> {
void visitValue(BinaryTreeNode<T> node);
COL getResult();
}
public interface Strategy {
/**
* @param node may be null
*/
<COL, T> COL traverse(BinaryTreeNode<T> node, Visitor<COL, T> v);
}
public class LmrStrategy implements Strategy {
public static final LmrStrategy SINGLETON = new LmrStrategy();
private LmrStrategy(){}
@Override
public <COL, T> COL traverse(BinaryTreeNode<T> node, Visitor<COL, T> v) {
if(node != null) {
traverse(node.getLeftChild(), v);
v.visitValue(node);
traverse(node.getRightChild(), v);
}
return v.getResult();
}
}
public class RmlStrategy implements Strategy {
public static final RmlStrategy SINGLETON = new RmlStrategy();
private RmlStrategy(){}
@Override
public <COL, T> COL traverse(BinaryTreeNode<T> node, Visitor<COL, T> v) {
if(node != null) {
traverse(node.getRightChild(), v);
v.visitValue(node);
traverse(node.getLeftChild(), v);
}
return v.getResult();
}
}
public class DoublyLinkedListVisitor<T> implements Visitor<DoublyLinkedList<T>, T> {
private DoublyLinkedList<T> dll;
public DoublyLinkedListVisitor() {
dll = new DoublyLinkedList<T>();
}
@Override
public void visitValue(BinaryTreeNode<T> node) {
dll.add(node.getValue());
}
@Override
public DoublyLinkedList<T> getResult() {
return dll;
}
}
public class StringVisitor<T> implements Visitor<String, T> {
private StringBuilder sb;
public StringVisitor() {
sb = new StringBuilder();
}
@Override
public void visitValue(BinaryTreeNode<T> node) {
sb.append(node.getValue());
}
@Override
public String getResult() {
return sb.toString();
}
}
Posted at 01:52PM Sep 14, 2011 by chris in General |
Cyber-Sleuth
cyber security is becoming a hot topic, so i thought i'd write a few notes
- be proactive
- hardened os (OpenBSD)
- minimal installs/applications
- firewalls
- logging and alerting sniffer (snort)
- acl - file, network (selinux)
- forensics
- logs
- live sniffer (tcpdump)
- various tools (lastlog, modified dates)
- make a copy for later inspection, but work to get back up immediately
- hot swap with recent backup
Posted at 01:21AM Jan 24, 2011 by chris in General |
MatchMaker
just put a new web application out - MatchMaker. it's a crowd source dating application. hope you enjoy it. if you don't like the initial warning, you can access it here
Posted at 10:59PM Jan 06, 2011 by chris in General |
hints for grails jquery ajaj
<head>Config.groovy
<gui:resources components="autoComplete"/>
<g:javascript library="jquery" plugin="jquery"/>
</head>
grails.views.javascript.library="jquery"
Posted at 10:47PM Dec 13, 2010 by chris in General |
Pilot's Alphabet Test (Groovy Edition)
package net.chrislacy.pilot
class PilotAlphabetTest {
def MAP = [ 'A':"Alpha", 'B':"Bravo", 'C':"Charlie", 'D':"Delta", 'E':"Echo", 'F':"Foxtrot", 'G':"Golf",
'H':"Hotel", 'I':"India", 'J':"Julliett", 'K':"Kilo", 'L':"Lima", 'M':"Mike", 'N':"November",
'O':"Oscar", 'P':"Papa", 'Q':"Quebec", 'R':"Romeo", 'S':"Sierra", 'T':"Tango", 'U':"Uniform",
'V':"Victor", 'W':"Whiskey", 'X':"X-ray", 'Y':"Yankee", 'Z':"Zulu" ]
def main() {
InputStreamReader c = new InputStreamReader(System.in)
BufferedReader inr = new BufferedReader(c)
def cl = MAP.keySet() as LinkedList
Collections.shuffle(cl, new Random())
cl.each {
println(it)
String answer = MAP.get(it)
if(!inr.readLine().equalsIgnoreCase(answer)) {
println(answer)
}
}
}
}
def pat = new PilotAlphabetTest()
pat.main()
Posted at 03:42PM Nov 30, 2010 by chris in General |
gRest
i've made available the start of a grails application that exposes a database as a RESTful web service. download
Posted at 11:40AM Sep 29, 2010 by chris in General |
coc rest - now with schemas!
- post whatever, in whatever format
- retrieve in whatever format
- add schema before/after if you want (in language of choice - sql, Java, groovy, xml, etc)
- add security if you want (over coc)
- key/value cache with storage back
- translators
- cross kingdom impl to support favorite deploy (war, cgi, etc)
Posted at 02:34PM Aug 26, 2010 by chris in General |
the vm
i predict that a new vm will emerge
- designed for the cloud
- non proprietary
- may abstract jvm and/or .net
- @see xmlvm
- program to any supported api
- all open source apis become immediately available
- will be optimised for: grails, rails, scheme, and/or erlang
Posted at 02:21PM Aug 24, 2010 by chris in General |
802.11s - I am disappoint
I continue to have high hopes for 802.11s and more advanced networking in general. ISPs are no longer needed. All we need are ways to securely and fairly share our connectivity. Imagine you're using your netbook and want to access google, but there's no hotspot nearby. Luckily, there's a guy on his smart phone 100 feet away, and from there he has a signal to a company's wifi (on which he's making the call). That company has a large antenna that reaches google.
I see lots of potential here. You can exchange bandwidth for equal bandwidth, and receive cash if you run a surplus. Municipalities would only need one connection to internet backbone instead of running wires to each residence. Anyone can run a website/server. It's the future.
Posted at 11:35AM Jul 27, 2010 by chris in General |
object translators
in the year 2000, the buzz will be object translators, aka, property editors, aka closures, aka un/marshallers, aka de/serializers, aka reflected methods, etc. and everyone will conform to a standard api
we'll have libraries of translators, too; and we'll define the rules by which a given translator is chosen for conversion between types. and we'll have translators that don't have return values, and translators that take multiple values, etc
and what we'll do, is, we'll pipe data between these translators and translator libraries. REST will be piping data from a web request to a translator that converts http messages to sql (with maybe JSON or XML or AMF in between, plus validation/exception handling and security)
but we'll add these "plus" features (exception handling, security, caching, etc) with aop and additional translators/libraries
Posted at 08:35PM Jun 26, 2010 by chris in General |
finite state machines, domain specific languages, and abstract resources
prediction: we're going to see a convergence around a domain specific language for constructing finite state machines that act on abstract resources. for example, web flow "languages", enterprise service buses, and enterprise integration technologies will eventually share a common tongue. we may see this vertically as well: how many (virtual) machine languages do we need? and since machine languages are themselves programming languages, can we consolidate? do we really need multiple data access technologies (rest, sql, no-sql, hql, jpql)? how many times are we going to re-invent distributed middleware (corba, rmi, rmi-iiop, soap)?
back to finite state machines, though. just as there are enterprise integration patterns, there will be semi-solid "strategies" which take pluggable abstract resources. those resources may be determined by the environment ala osgi di.
Posted at 12:19AM Jun 17, 2010 by chris in General |
Grails AJAJ Autocomplete
Currently only working with grails 1.2-M3 (grails-ui plugin fails in M4)
package net.chrislacy.grails
import grails.converters.JSON
import java.util.concurrent.ConcurrentSkipListSet
class AjajController {
static names = ['Blaire','Carol','Chris','Christy','Conan','Heather','Olivia'] as ConcurrentSkipListSet
def index = {[names:names]}
def autoCompleteMe = {
def query = params.query
def next = query + Character.MAX_VALUE
def foundNames = names.subSet(query, true, next, true).collect{[name:it]}
render([result:foundNames] as JSON)
}
def add = {render names << params.name}
}
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>AJAJ Example</title>
<gui:resources components="['autoComplete']"/>
<g:javascript library="prototype" />
</head>
<body>
<g:formRemote name="add" url="[controller:'ajaj', action:'add']" update="update">
<gui:autoComplete name="name" controller="ajaj" action="autoCompleteMe" minQueryLength="1" />
<g:submitButton style="display:none" name="add"/>
</g:formRemote>
<div id="update">${names}</div>
</body>
</html>
Posted at 08:56PM Nov 26, 2009 by chris in General |
Grails Makes AJAX Too Easy
package net.chrislacy.grails
class AjaxController {
static Set names = new TreeSet()
static {
names << 'Al'
names << 'Barry'
names << 'Carol'
names << 'Chris'
names << 'Conan'
names << 'Olivia'
names << 'Sandy'
names << 'Sam'
}
def index = {
def model =[:]
model.names = names
model
}
def searchAJAX = {
Set foundNames = names.collect(new TreeSet()) {
it.startsWith(params.query) ? it : ''
}
foundNames.remove ''
render(contentType: "text/xml") {
results() {
foundNames.each { n ->
result() {
name(n)
}
}
}
}
}
def add = {
names << params.name
render names
}
}
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Ajax Example</title>
<resource:autoComplete skin="default"/>
<g:javascript library="scriptaculous" />
</head>
<body>
<g:formRemote name="add" url="[controller:'ajax', action:'add']" update="update">
<richui:autoComplete name="name" action="${createLinkTo('dir': 'ajax/searchAJAX')}"/>
</g:formRemote>
<div id="update">${names}</div>
</body>
</html>
Live: http://chrislacy.net/AjaxExample/
Posted at 06:42PM Nov 23, 2009 by chris in General |
SOAP is to CORBA as REST is to _
Remember the SATs?
SOAP is to CORBA as REST is to _
A. Java
B. RPC
C. A Database language like SQL
D. Clean, sleepy snakes
Posted at 09:04PM Apr 05, 2009 by chris in General |