aboutsummaryrefslogtreecommitdiffstats
path: root/tools/domctl/src/uk
diff options
context:
space:
mode:
Diffstat (limited to 'tools/domctl/src/uk')
-rw-r--r--tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Command.java74
-rw-r--r--tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandDestroy.java69
-rw-r--r--tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandHelp.java58
-rw-r--r--tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandNew.java203
-rw-r--r--tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandStart.java63
-rw-r--r--tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandStop.java64
-rw-r--r--tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Defaults.java153
-rw-r--r--tools/domctl/src/uk/ac/cam/cl/xeno/domctl/InetAddressPattern.java60
-rw-r--r--tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Main.java39
-rw-r--r--tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Settings.java38
-rw-r--r--tools/domctl/src/uk/ac/cam/cl/xeno/domctl/StringPattern.java59
11 files changed, 880 insertions, 0 deletions
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Command.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Command.java
new file mode 100644
index 0000000000..b667e3f274
--- /dev/null
+++ b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Command.java
@@ -0,0 +1,74 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+public abstract class Command
+{
+ public abstract int doCommand(Defaults d, String args[]);
+ public abstract String getName();
+ public abstract String getUsage();
+ public abstract String getHelpText();
+
+ public String getStringParameter(String args[], char key, String def)
+ {
+ String r = getParameter (args, key);
+ return (r == null) ? def : r;
+ }
+
+ public int getIntParameter(String args[], char key, int def)
+ {
+ String r = getParameter (args, key);
+ return (r == null) ? def : (Integer.parseInt (r));
+ }
+
+ public boolean getFlagParameter(String args[], char key)
+ {
+ String r = getParameter (args, key);
+ return (r == null) ? false : true;
+ }
+
+ public String getParameter (String args[], char key)
+ {
+ int i;
+ String result = null;
+ for (i = 0; i < args.length; i ++)
+ {
+ if (args[i].startsWith("-" + key))
+ {
+ if (args[i].length() > 2)
+ {
+ result = args[i].substring(2, args[i].length());
+ }
+ else
+ {
+ result = "";
+ }
+ }
+ }
+ return result;
+ }
+
+ public int reportXIError (String message, String cmd_array[])
+ {
+ int i;
+ System.err.print (message + " using: ");
+ for (i = 0; i < cmd_array.length; i ++) {
+ System.err.print (cmd_array[i] + " ");
+ }
+ System.err.println();
+ return -1;
+ }
+
+ public int reportError (String message)
+ {
+ System.err.println (message);
+ return -1;
+ }
+
+ public void reportCommand (String cmd_array[])
+ {
+ int i;
+ for (i = 0; i < cmd_array.length; i ++) {
+ System.out.print (cmd_array[i] + " ");
+ }
+ System.out.println();
+ }
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandDestroy.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandDestroy.java
new file mode 100644
index 0000000000..025f373c50
--- /dev/null
+++ b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandDestroy.java
@@ -0,0 +1,69 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+import java.io.*;
+import java.net.*;
+
+public class CommandDestroy extends Command
+{
+ public int doCommand(Defaults d, String args[])
+ {
+ Runtime r = Runtime.getRuntime ();
+ int domain_id = getIntParameter(args, 'n', 0);
+ boolean force = getFlagParameter(args, 'f');
+ int rc = 0;
+
+ if (domain_id == 0) {
+ System.err.println ("Expected -n<domain_id>");
+ rc = -1;
+ return rc;
+ }
+
+ try
+ {
+ Process destroy_p;
+ String destroy_cmdarray[] = force ? new String[3] : new String[2];
+ int destroy_rc;
+ int idx = 0;
+ destroy_cmdarray[idx++] = d.XIToolsDir + "xi_destroy";
+ if (force) {
+ destroy_cmdarray[idx++] = "-f";
+ }
+ destroy_cmdarray[idx++] = "" + domain_id;
+
+ if (Settings.TEST) {
+ reportCommand (destroy_cmdarray);
+ } else {
+ destroy_p = r.exec (destroy_cmdarray);
+ destroy_rc = destroy_p.waitFor ();
+
+ if (destroy_rc != 0) {
+ return reportXIError ("Could not destroy domain", destroy_cmdarray);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ System.err.println ("Could not destroy domain (" + e + ")");
+ e.printStackTrace ();
+ rc = -1;
+ }
+
+ return rc;
+ }
+
+ public String getName()
+ {
+ return "destroy";
+ }
+
+ public String getUsage()
+ {
+ return "[-f] [-n<domain_id>]";
+ }
+
+ public String getHelpText()
+ {
+ return
+ "Destory the specified domain. -f forcibly destroys it.";
+ }
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandHelp.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandHelp.java
new file mode 100644
index 0000000000..aef1ee9473
--- /dev/null
+++ b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandHelp.java
@@ -0,0 +1,58 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+public class CommandHelp extends Command
+{
+ public int doCommand(Defaults d, String args[])
+ {
+ if (args.length <= 1)
+ {
+ System.out.println ("Usage:");
+ for (int i = 0; i < Main.commands.length; i ++)
+ {
+ String name = Main.commands[i].getName ();
+ String usage = Main.commands[i].getUsage ();
+ while (name.length() < 12) name = name + " ";
+ System.out.println (" " + name + usage);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < Main.commands.length; i ++)
+ {
+ String name = Main.commands[i].getName ();
+ String usage = Main.commands[i].getUsage ();
+ if (name.equals (args[1]))
+ {
+ doHelpFor (Main.commands[i]);
+ break;
+ }
+ }
+ }
+
+ System.out.println ("");
+ return 0;
+ }
+
+ public int doHelpFor (Command c)
+ {
+ System.out.println ("domctl " + c.getName() + " " + c.getUsage());
+ System.out.println ();
+ System.out.println (c.getHelpText ());
+ return 0;
+ }
+
+ public String getName()
+ {
+ return "help";
+ }
+
+ public String getUsage()
+ {
+ return "";
+ }
+
+ public String getHelpText()
+ {
+ return "This message";
+ }
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandNew.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandNew.java
new file mode 100644
index 0000000000..1dd915686e
--- /dev/null
+++ b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandNew.java
@@ -0,0 +1,203 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+import java.io.*;
+import java.net.*;
+
+public class CommandNew extends Command
+{
+ public int doCommand(Defaults d, String args[])
+ {
+ Runtime r = Runtime.getRuntime ();
+ String name = getStringParameter(args, 'n', d.domainName);
+ int size = getIntParameter(args, 'k', d.domainSizeKB);
+ String image = getStringParameter(args, 'i', d.domainImage);
+ String initrd = getStringParameter (args, 'r', d.domainInitRD);
+ int vifs = getIntParameter(args, 'v', d.domainVIFs);
+ String bargs = getStringParameter (args, 'a', "");
+ String root_dev = getStringParameter (args, 'd', d.rootDevice);
+ String nfs_root_path = getStringParameter (args, 'f', d.NWNFSRoot);
+ String nw_ip = getStringParameter (args, '4', d.NWIP);
+ String nw_gw = getStringParameter (args, 'g', d.NWGW);
+ String nw_mask = getStringParameter (args, 'm', d.NWMask);
+ String nw_nfs_server = getStringParameter (args, 's', d.NWNFSServer);
+ String nw_host = getStringParameter (args, 'h', d.NWHost);
+ String domain_ip = "";
+ int rc = 0;
+ int domain_id;
+ DataInputStream dis;
+ int idx;
+ int i;
+
+
+ try
+ {
+ /* Some initial sanity checks */
+ if (root_dev.equals ("/dev/nfs") && (vifs == 0)) {
+ return reportError ("Cannot use NFS root without VIFs configured");
+ }
+
+ /* Create a new empty domain */
+ Process create_p;
+ String create_cmdarray[] = new String[3];
+ int create_rc;
+ create_cmdarray[0] = d.XIToolsDir + "xi_create";
+ create_cmdarray[1] = "" + size;
+ create_cmdarray[2] = name;
+ if (Settings.TEST) {
+ reportCommand (create_cmdarray);
+ domain_id=1;
+ create_rc=0;
+ } else {
+ create_p = r.exec (create_cmdarray);
+ dis = new DataInputStream (new BufferedInputStream (create_p.getInputStream ()));
+ domain_id = Integer.parseInt (dis.readLine ());
+ create_rc = create_p.waitFor ();
+ }
+
+ if (create_rc != 0) {
+ return reportXIError ("Failed to create domain", create_cmdarray);
+ } else if (domain_id > d.MaxDomainNumber) {
+ return reportError ("Cannot configure more than " +
+ d.MaxDomainNumber + " domains");
+ }
+
+ /* Set up boot parameters to pass to xi_build. */
+ bargs = "";
+
+ if (root_dev.equals ("/dev/nfs")) {
+ if (vifs == 0) {
+ return reportError ("Cannot use NFS root without VIFs configured");
+ }
+ bargs = (bargs +
+ "root=/dev/nfs " +
+ "nfsroot=" + StringPattern.parse(nfs_root_path).resolve(domain_id) +
+ " ");
+ } else {
+ bargs = ("root=" + StringPattern.parse(root_dev).resolve(domain_id) +
+ " ");
+
+ }
+
+ if (vifs > 0) {
+ domain_ip = InetAddressPattern.parse(nw_ip).resolve(domain_id);
+ if (nw_host == null) {
+ try {
+ nw_host = InetAddress.getByName(domain_ip).getHostName();
+ } catch (UnknownHostException uhe) {
+ nw_host = "" + nw_ip;
+ }
+
+ }
+ bargs = ("ip=" + domain_ip +
+ ":" + InetAddressPattern.parse(nw_nfs_server).resolve(domain_id) +
+ ":" + InetAddressPattern.parse(nw_gw).resolve(domain_id) +
+ ":" + InetAddressPattern.parse(nw_mask).resolve(domain_id) +
+ ":" + nw_host +
+ ":eth0:off " + bargs);
+ }
+
+ /* Build the domain */
+ Process build_p;
+ String build_cmdarray[] = new String[6];
+ int build_rc;
+ idx = 0;
+ for (i = 0; i < build_cmdarray.length; i ++)
+ build_cmdarray[i] = "";
+ build_cmdarray[idx ++] = d.XIToolsDir + "xi_build";
+ build_cmdarray[idx ++] = "" + domain_id;
+ build_cmdarray[idx ++] = "" + image;
+ build_cmdarray[idx ++] = "" + vifs;
+ if (initrd != null) build_cmdarray[idx ++] = "initrd=" + initrd;
+ build_cmdarray[idx ++] = "" + bargs;
+ System.out.println ("Build args: " + bargs);
+ if (Settings.TEST) {
+ reportCommand (build_cmdarray);
+ build_rc = 0;
+ } else {
+ build_p = r.exec (build_cmdarray);
+ build_rc = build_p.waitFor ();
+ }
+
+ if (build_rc != 0) {
+ return reportXIError ("Failed to build domain", build_cmdarray);
+ }
+
+
+ /* Set up the first VIF if necessary */
+ if (vifs > 0) {
+ Process vifinit_p;
+ String vifinit_cmdarray[] = new String[4];
+ int vifinit_rc;
+ vifinit_cmdarray[0] = d.XIToolsDir + "xi_vifinit";
+ vifinit_cmdarray[1] = "" + domain_id;
+ vifinit_cmdarray[2] = "0";
+ vifinit_cmdarray[3] = domain_ip;
+ if (Settings.TEST) {
+ reportCommand (vifinit_cmdarray);
+ vifinit_rc = 0;
+ } else {
+ vifinit_p = r.exec (vifinit_cmdarray);
+ vifinit_rc = vifinit_p.waitFor ();
+ }
+
+ if (vifinit_rc != 0) {
+ return reportXIError ("Failed to initialise VIF 0", vifinit_cmdarray);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ System.err.println ("Could not create new domain (" + e + ")");
+ e.printStackTrace ();
+ rc = -1;
+ }
+
+ return rc;
+ }
+
+ public String getName()
+ {
+ return "new";
+ }
+
+ public String getUsage()
+ {
+ return "[-n<domain_name>] [-k<size>] [-i<image>] [-v<num_vifs>] [-r<initrd>] [-d<root_device>] [-f<nfs_root>] [-s<nfs_boot_server>] [-4<ipv4_boot_address>] [-g<ipv4_boot_gateway>] [-m<ipv4_boot_netmask>] [-h<hostname>] [-a<args>]";
+ }
+
+ public String getHelpText()
+ {
+ return
+ "Create a new domain. Note that most of the parameters will assume\n" +
+ "default values: it should not be necessary to specify them all. See\n" +
+ "domctl.xml for the current default settings.\n" +
+ "\n" +
+ "General command line options:\n" +
+ " -n Domain name domain_name\n" +
+ " -k Domain size (kb) domain_size_kb\n" +
+ " -i Domain image name domain_image\n" +
+ " -v Number of VIFs domain_vifs\n" +
+ " -r InitRD (if required) domain_init_rd\n" +
+ " -d Root device (e.g /dev/nfs, /dev/hda3) root_device\n" +
+ " -a Additional boot parameters\n" +
+ "\n" +
+ "Networking options:\n" +
+ " -f NFS root (if /dev/nfs specified) nw_nfs_root\n" +
+ " -s NFS server nw_nfs_server\n" +
+ " -4 Domain IPv4 address nw_ip\n" +
+ " -g Domain gateway nw_gw\n" +
+ " -m Domain net mask nw_mask\n" +
+ " -h Domain hostname nw_host\n" +
+ "\n" +
+ "Parameters to -d, -f, -4, -g, -h can be specified as patterns into\n" +
+ "which the allocated domain ID will be incorporated. e.g. for\n" +
+ "domain 1 patterns would expand as follows:\n" +
+ "\n" +
+ " /dev/hda+ /dev/hda1\n" +
+ " /dev/hda7+ /dev/hda8\n" +
+ " 128.232.8.50+ 128.232.8.51\n" +
+ "\n" +
+ "Additionally, patterns for -4 -g -m can include an = which is\n" +
+ "expanded to the corresponding setting from the calling domain.\n";
+ }
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandStart.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandStart.java
new file mode 100644
index 0000000000..b84b66d306
--- /dev/null
+++ b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandStart.java
@@ -0,0 +1,63 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+import java.io.*;
+import java.net.*;
+
+public class CommandStart extends Command
+{
+ public int doCommand(Defaults d, String args[])
+ {
+ Runtime r = Runtime.getRuntime ();
+ int domain_id = getIntParameter(args, 'n', 0);
+ int rc = 0;
+
+ if (domain_id == 0) {
+ System.err.println ("Expected -n<domain_id>");
+ rc = -1;
+ return rc;
+ }
+
+ try
+ {
+ Process start_p;
+ String start_cmdarray[] = new String[2];
+ int start_rc;
+ start_cmdarray[0] = d.XIToolsDir + "xi_start";
+ start_cmdarray[1] = "" + domain_id;
+
+ if (Settings.TEST) {
+ reportCommand (start_cmdarray);
+ } else {
+ start_p = r.exec (start_cmdarray);
+ start_rc = start_p.waitFor ();
+ if (start_rc != 0) {
+ return reportXIError ("Could not start domain", start_cmdarray);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ System.err.println ("Could not start new domain (" + e + ")");
+ e.printStackTrace ();
+ rc = -1;
+ }
+
+ return rc;
+ }
+
+ public String getName()
+ {
+ return "start";
+ }
+
+ public String getUsage()
+ {
+ return "[-n<domain_id>]";
+ }
+
+ public String getHelpText()
+ {
+ return
+ "Start the specified domain.";
+ }
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandStop.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandStop.java
new file mode 100644
index 0000000000..c6b4cadd6c
--- /dev/null
+++ b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandStop.java
@@ -0,0 +1,64 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+import java.io.*;
+import java.net.*;
+
+public class CommandStop extends Command
+{
+ public int doCommand(Defaults d, String args[])
+ {
+ Runtime r = Runtime.getRuntime ();
+ int domain_id = getIntParameter(args, 'n', 0);
+ int rc = 0;
+
+ if (domain_id == 0) {
+ System.err.println ("Expected -n<domain_id>");
+ rc = -1;
+ return rc;
+ }
+
+ try
+ {
+ Process stop_p;
+ String stop_cmdarray[] = new String[2];
+ int stop_rc;
+ stop_cmdarray[0] = d.XIToolsDir + "xi_stop";
+ stop_cmdarray[1] = "" + domain_id;
+
+ if (Settings.TEST) {
+ reportCommand (stop_cmdarray);
+ } else {
+ stop_p = r.exec (stop_cmdarray);
+ stop_rc = stop_p.waitFor ();
+
+ if (stop_rc != 0) {
+ return reportXIError ("Could not stop domain", stop_cmdarray);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ System.err.println ("Could not stop new domain (" + e + ")");
+ e.printStackTrace ();
+ rc = -1;
+ }
+
+ return rc;
+ }
+
+ public String getName()
+ {
+ return "stop";
+ }
+
+ public String getUsage()
+ {
+ return "[-n<domain_id>]";
+ }
+
+ public String getHelpText()
+ {
+ return
+ "Stop the specified domain.";
+ }
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Defaults.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Defaults.java
new file mode 100644
index 0000000000..bacce11a95
--- /dev/null
+++ b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Defaults.java
@@ -0,0 +1,153 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+import java.net.InetAddress;
+import java.io.*;
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;
+
+public class Defaults
+{
+ String domainName;
+
+ int domainSizeKB;
+ String domainImage;
+ String domainInitRD;
+ int domainVIFs;
+
+ String rootDevice;
+
+ String NWIP;
+ String NWGW;
+ String NWMask;
+ String NWHost;
+
+ String NWNFSServer;
+ String NWNFSRoot;
+
+ int MaxDomainNumber;
+
+ String XIToolsDir;
+
+ /***********************************************************************/
+
+ public Defaults ()
+ {
+ File f = Settings.getDefaultsFile ();
+ System.out.println ("f=" + f);
+
+ try
+ {
+ XMLReader xr = new org.apache.crimson.parser.XMLReaderImpl();
+ Handler handler = new Handler ();
+ xr.setContentHandler (handler);
+ xr.setErrorHandler (handler);
+ xr.parse (new InputSource(new FileReader (f)));
+ }
+ catch (Exception e)
+ {
+ System.err.println ("Could not read defaults file " + f +
+ "\nException: " + e);
+ e.printStackTrace();
+ System.exit(1);
+ }
+
+ System.out.println ("Domain defaults:");
+ System.out.println (" name " + domainName);
+ System.out.println (" size " + domainSizeKB);
+ System.out.println (" vifs " + domainVIFs);
+ System.out.println (" domainImage " + domainImage);
+ System.out.println (" domainInitRD " + domainInitRD);
+ System.out.println (" rootDevice " + rootDevice);
+ System.out.println (" NWIP " + NWIP);
+ System.out.println (" NWGW " + NWGW);
+ System.out.println (" NWMask " + NWMask);
+ System.out.println (" MaxDomainNumber " + MaxDomainNumber);
+ System.out.println (" NWNFSServer " + NWNFSServer);
+ System.out.println (" NWNFSRoot " + NWNFSRoot);
+ System.out.println (" XIToolsDir " + XIToolsDir);
+ }
+
+ /***********************************************************************/
+
+ class Handler extends DefaultHandler
+ {
+ boolean inDomctlDefaults;
+ String lastName;
+
+ public void startDocument ()
+ {
+ }
+
+ public void endDocument ()
+ {
+ }
+
+ public void startElement (String uri, String name,
+ String qname, Attributes atts)
+ {
+ if (qname.equals ("domctl_defaults")) {
+ inDomctlDefaults = true;
+ } else {
+ lastName = qname;
+ }
+ }
+
+ public void endElement (String uri, String name, String qname)
+ {
+ lastName = "";
+ if (qname.equals ("domctl_defaults")) {
+ inDomctlDefaults = false;
+ }
+ }
+
+ public void characters (char ch[], int start, int length)
+ {
+ String s = new String (ch, start, length);
+ if (lastName != null)
+ {
+ if (lastName.equals ("domain_size_kb")) {
+ domainSizeKB = Integer.parseInt (s);
+ } else if (lastName.equals ("domain_image")) {
+ domainImage = s;
+ } else if (lastName.equals ("domain_name")) {
+ domainName = s;
+ } else if (lastName.equals ("domain_init_rd")) {
+ domainInitRD = s;
+ } else if (lastName.equals ("domain_vifs")) {
+ domainVIFs = Integer.parseInt (s);
+ } else if (lastName.equals ("root_device")) {
+ rootDevice = s;
+ } else if (lastName.equals ("nw_ip")) {
+ NWIP = expandDefault (s, Settings.LOCAL_IP);
+ } else if (lastName.equals ("nw_gw")) {
+ NWGW = expandDefault (s, Settings.LOCAL_GW);
+ } else if (lastName.equals ("nw_mask")) {
+ NWMask = expandDefault (s, Settings.LOCAL_MASK);
+ } else if (lastName.equals ("nw_host")) {
+ NWHost = s;
+ } else if (lastName.equals ("nw_nfs_server")) {
+ NWNFSServer = s;
+ } else if (lastName.equals ("nw_nfs_root")) {
+ NWNFSRoot = s;
+ } else if (lastName.equals ("max_domain_number")) {
+ MaxDomainNumber = Integer.parseInt(s);
+ } else if (lastName.equals ("xi_tools_dir")) {
+ XIToolsDir = s;
+ }
+ }
+ }
+ }
+
+ public String expandDefault (String supplied, String self)
+ {
+ if (supplied.startsWith ("=")) {
+ if (supplied.length() > 1) {
+ return self + supplied.substring (1, supplied.length());
+ } else {
+ return self;
+ }
+ } else {
+ return supplied;
+ }
+ }
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/InetAddressPattern.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/InetAddressPattern.java
new file mode 100644
index 0000000000..5786edde71
--- /dev/null
+++ b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/InetAddressPattern.java
@@ -0,0 +1,60 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+import java.net.*;
+
+public class InetAddressPattern
+{
+ InetAddress base;
+ boolean addDom;
+
+ static InetAddressPattern parse (String t)
+ {
+ InetAddressPattern result = new InetAddressPattern ();
+ char[] ca = t.toCharArray ();
+ int idx = 0;
+ int len = ca.length;
+
+ try {
+ if (len == 0) {
+ result.base = null;
+ result.addDom = false;
+ } else if (ca[len - 1] == '+') {
+ result.base = InetAddress.getByName(t.substring(0, len - 1));
+ result.addDom = true;
+ } else {
+ result.base = InetAddress.getByName(t);
+ result.addDom = false;
+ }
+ } catch (UnknownHostException uhe) {
+ result.base = null;
+ result.addDom = false;
+ }
+
+ return result;
+ }
+
+ public String resolve (int domain_id) {
+ byte b[] = base.getAddress ();
+ if (addDom) {
+ if (((int)b[3]) + domain_id > 255) {
+ if (((int)b[2]) + domain_id > 255) {
+ if (((int)b[1]) + domain_id > 255) {
+ b[0] ++;
+ }
+ b[1] ++;
+ }
+ b[2] ++;
+ }
+ b[3] += domain_id;
+ }
+ return "" +
+ (b[0] + (b[0] < 0 ? 256 : 0)) + "." +
+ (b[1] + (b[1] < 0 ? 256 : 0)) + "." +
+ (b[2] + (b[2] < 0 ? 256 : 0)) + "." +
+ (b[3] + (b[3] < 0 ? 256 : 0));
+ }
+
+ public String toString () {
+ return "[" + base + (addDom ? "+dom_id" : "") + "]";
+ }
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Main.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Main.java
new file mode 100644
index 0000000000..49b4fb3c54
--- /dev/null
+++ b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Main.java
@@ -0,0 +1,39 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+public class Main
+{
+ static CommandHelp help = new CommandHelp ();
+ static CommandNew newdom = new CommandNew ();
+ static CommandStart start = new CommandStart ();
+ static CommandStop stop = new CommandStop ();
+ static CommandDestroy destroy = new CommandDestroy ();
+ static Command commands[] = { help, newdom, start, stop, destroy };
+
+ public static void main (String[] args)
+ {
+ Defaults d = new Defaults ();
+ int ec = -1;
+
+ if (args.length == 0) {
+ ec = help.doCommand (d, args);
+ } else {
+ String c = args[0];
+ int i;
+ for (i = 0; i < commands.length; i ++) {
+ if (commands[i].getName().equals(c)) {
+ if (commands[i].getFlagParameter (args, '?')) {
+ ec = help.doHelpFor (commands[i]);
+ } else {
+ ec = commands[i].doCommand (d, args);
+ }
+ break;
+ }
+ }
+ if (i == commands.length) {
+ System.out.println ("Unknown command " + c);
+ }
+ }
+
+ System.exit (ec);
+ }
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Settings.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Settings.java
new file mode 100644
index 0000000000..13d1a2d1df
--- /dev/null
+++ b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Settings.java
@@ -0,0 +1,38 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+import java.util.*;
+import java.io.*;
+import org.xml.sax.*;
+
+public final class Settings
+{
+ public static final String DEFAULTS_FILE = System.getProperty ("DEFAULTS_FILE");
+ public static final String DEFAULTS_PATH = System.getProperty ("DEFAULTS_PATH");
+ public static final String LOCAL_IP = System.getProperty ("LOCAL_IP");
+ public static final String LOCAL_MASK = System.getProperty ("LOCAL_MASK");
+ public static final String LOCAL_GW = System.getProperty ("LOCAL_ROUTE");
+ public static final boolean TEST = (System.getProperty ("TEST") != null);
+
+
+ public static File getDefaultsFile() {
+ StringTokenizer tok = new StringTokenizer (DEFAULTS_PATH, ":");
+ File result = null;
+ File probe;
+
+ while (tok.hasMoreTokens ()) {
+ String probe_dir = tok.nextToken ();
+ probe = new File (probe_dir, DEFAULTS_FILE);
+ if (probe.exists ()) {
+ result = probe;
+ break;
+ }
+ }
+
+ if (result == null) {
+ System.err.println ("Could not find " + DEFAULTS_FILE + " in path " + DEFAULTS_PATH);
+ System.exit (1);
+ }
+
+ return result;
+ }
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/StringPattern.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/StringPattern.java
new file mode 100644
index 0000000000..a0486ba2be
--- /dev/null
+++ b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/StringPattern.java
@@ -0,0 +1,59 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+public class StringPattern
+{
+ String base;
+ int bn;
+ boolean addDom;
+ boolean appendDom;
+
+ static StringPattern parse (String t)
+ {
+ StringPattern result = new StringPattern ();
+ char[] ca = t.toCharArray ();
+ int idx = 0;
+ int len = ca.length;
+
+ if (len == 0) {
+ result.base = "";
+ result.bn = 0;
+ result.addDom = false;
+ } else if (ca[len - 1] == '+') {
+ idx = len - 2;
+ if ((idx >= 0) && (ca[idx] >= '0') && (ca[idx] <= '9')) {
+ while ((idx >= 0) && (ca[idx] >= '0') && (ca[idx] <= '9')) {
+ idx --;
+ }
+ result.base = t.substring(0, idx + 1);
+ result.bn = Integer.parseInt (t.substring (idx + 1, len - 1));
+ result.addDom = true;
+ } else {
+ result.base = t.substring(0, len - 1);
+ result.appendDom = true;
+ }
+ } else {
+ result.base = t;
+ }
+
+ return result;
+ }
+
+ public String resolve (int domain_id) {
+ if (addDom) {
+ return base + (bn + domain_id);
+ } else if (appendDom) {
+ return base + domain_id;
+ } else {
+ return base;
+ }
+ }
+
+ public String toString () {
+ return ("[" +
+ base +
+ (addDom ? "+" + bn : "") +
+ ((addDom || appendDom) ? "+ID" : "") +
+ "]");
+ }
+
+}