aboutsummaryrefslogtreecommitdiffstats
path: root/tools/control
diff options
context:
space:
mode:
authorrac61@labyrinth.cl.cam.ac.uk <rac61@labyrinth.cl.cam.ac.uk>2003-07-04 11:21:03 +0000
committerrac61@labyrinth.cl.cam.ac.uk <rac61@labyrinth.cl.cam.ac.uk>2003-07-04 11:21:03 +0000
commit8a7e82b3a364fc789377c42d502cae6c98a44338 (patch)
treef9b41ce26abdd3500f7362dddfd489070d032e73 /tools/control
parent965d3529097e9e06aa6065f4fe29ce118e5c31e2 (diff)
downloadxen-8a7e82b3a364fc789377c42d502cae6c98a44338.tar.gz
xen-8a7e82b3a364fc789377c42d502cae6c98a44338.tar.bz2
xen-8a7e82b3a364fc789377c42d502cae6c98a44338.zip
bitkeeper revision 1.269 (3f05631fUbZceaMD9jXHZuX-gUlgYw)
Start refactoring VD stuff into new package structure Implemented physical disk access stuff for sos22's shiny new interface for same
Diffstat (limited to 'tools/control')
-rw-r--r--tools/control/src/org/xenoserver/cmdline/Main.java12
-rw-r--r--tools/control/src/org/xenoserver/cmdline/ParseGroup.java4
-rw-r--r--tools/control/src/org/xenoserver/cmdline/ParsePartitionsList.java57
-rw-r--r--tools/control/src/org/xenoserver/cmdline/ParsePhysicalGrant.java65
-rw-r--r--tools/control/src/org/xenoserver/cmdline/ParsePhysicalList.java74
-rw-r--r--tools/control/src/org/xenoserver/cmdline/ParsePhysicalRevoke.java51
-rw-r--r--tools/control/src/org/xenoserver/control/CommandPhysicalGrant.java66
-rw-r--r--tools/control/src/org/xenoserver/control/CommandPhysicalList.java98
-rw-r--r--tools/control/src/org/xenoserver/control/CommandPhysicalRevoke.java56
-rw-r--r--tools/control/src/org/xenoserver/control/Extent.java87
-rw-r--r--tools/control/src/org/xenoserver/control/Library.java129
-rw-r--r--tools/control/src/org/xenoserver/control/Mode.java22
-rw-r--r--tools/control/src/org/xenoserver/control/Partition.java191
-rw-r--r--tools/control/src/org/xenoserver/control/PartitionManager.java185
-rw-r--r--tools/control/src/org/xenoserver/control/Settings.java4
-rw-r--r--tools/control/src/org/xenoserver/control/XML.java125
-rw-r--r--tools/control/src/org/xenoserver/control/XMLHelper.java205
17 files changed, 1426 insertions, 5 deletions
diff --git a/tools/control/src/org/xenoserver/cmdline/Main.java b/tools/control/src/org/xenoserver/cmdline/Main.java
index b21aba57b3..624a07c951 100644
--- a/tools/control/src/org/xenoserver/cmdline/Main.java
+++ b/tools/control/src/org/xenoserver/cmdline/Main.java
@@ -17,9 +17,19 @@ public class Main {
new ParseDomainDestroy(),
new ParseDomainList()
};
+ static final CommandParser partitioncommands[] =
+ { new ParsePartitionsList()
+ };
+ static final CommandParser physicalcommands[] =
+ { new ParsePhysicalGrant(),
+ new ParsePhysicalRevoke(),
+ new ParsePhysicalList()
+ };
static final CommandParser commands[] =
{ help,
- new ParseGroup( "domain", domaincommands )
+ new ParseGroup( "domain", domaincommands ),
+ new ParseGroup( "partitions", partitioncommands ),
+ new ParseGroup( "physical", physicalcommands )
};
static final CommandParser parser = new ParseGroup( null, commands );
diff --git a/tools/control/src/org/xenoserver/cmdline/ParseGroup.java b/tools/control/src/org/xenoserver/cmdline/ParseGroup.java
index 1903dc4b2d..02ef3743d3 100644
--- a/tools/control/src/org/xenoserver/cmdline/ParseGroup.java
+++ b/tools/control/src/org/xenoserver/cmdline/ParseGroup.java
@@ -26,7 +26,7 @@ public class ParseGroup extends CommandParser {
String c = (String) args.removeFirst();
for (i = 0; i < commands.length; i++) {
if (commands[i].getName().equals(c)) {
- if (getFlagParameter(args, '?')) {
+ if (!args.isEmpty() && args.getFirst().equals("-?")) {
commands[i].printHelpText(null);
} else {
commands[i].parse(d, args);
@@ -44,12 +44,10 @@ public class ParseGroup extends CommandParser {
}
public String getUsage() {
- // TODO Auto-generated method stub
return null;
}
public String getHelpText() {
- // TODO Auto-generated method stub
return null;
}
diff --git a/tools/control/src/org/xenoserver/cmdline/ParsePartitionsList.java b/tools/control/src/org/xenoserver/cmdline/ParsePartitionsList.java
new file mode 100644
index 0000000000..02a754f23f
--- /dev/null
+++ b/tools/control/src/org/xenoserver/cmdline/ParsePartitionsList.java
@@ -0,0 +1,57 @@
+package org.xenoserver.cmdline;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import org.xenoserver.control.CommandFailedException;
+import org.xenoserver.control.Defaults;
+import org.xenoserver.control.Library;
+import org.xenoserver.control.Partition;
+import org.xenoserver.control.PartitionManager;
+import org.xenoserver.control.Settings;
+import org.xenoserver.control.XML;
+
+public class ParsePartitionsList extends CommandParser {
+
+ public void parse(Defaults d, LinkedList args) throws ParseFailedException, CommandFailedException {
+ XML.load_state( PartitionManager.it, Settings.STATE_INPUT_FILE );
+ Iterator i = PartitionManager.it.iterator();
+ int idx = 1;
+ System.out.println( " maj:min " + " blocks " + "start sect " +
+ " num sects " + "name" );
+ while (i.hasNext()) {
+ Partition p = (Partition) i.next();
+
+ if (p.getIsXeno()) {
+ System.out.print("[ ");
+ } else {
+ System.out.print(" ");
+ }
+ System.out.print(Library.format(idx++, 2, 0) + " ");
+ System.out.print(Library.format(p.getMajor(),3,0) + ":" +
+ Library.format(p.getMinor(),3,1) + " " +
+ Library.format(p.getBlocks(),10,0) + " " +
+ Library.format(p.getStartSect(),10,0) + " " +
+ Library.format(p.getNumSects(),10,0) + " " +
+ Library.format(p.getName(),7,1));
+ if (p.getIsXeno()) {
+ System.out.println("]");
+ } else {
+ System.out.println();
+ }
+ }
+ }
+
+ public String getName() {
+ return "list";
+ }
+
+ public String getUsage() {
+ return "";
+ }
+
+ public String getHelpText() {
+ return "List real partition information";
+ }
+
+}
diff --git a/tools/control/src/org/xenoserver/cmdline/ParsePhysicalGrant.java b/tools/control/src/org/xenoserver/cmdline/ParsePhysicalGrant.java
new file mode 100644
index 0000000000..6792a43e47
--- /dev/null
+++ b/tools/control/src/org/xenoserver/cmdline/ParsePhysicalGrant.java
@@ -0,0 +1,65 @@
+package org.xenoserver.cmdline;
+
+import java.util.LinkedList;
+
+import org.xenoserver.control.CommandFailedException;
+import org.xenoserver.control.CommandPhysicalGrant;
+import org.xenoserver.control.Defaults;
+import org.xenoserver.control.Extent;
+import org.xenoserver.control.Mode;
+import org.xenoserver.control.Partition;
+import org.xenoserver.control.PartitionManager;
+import org.xenoserver.control.Settings;
+import org.xenoserver.control.XML;
+
+public class ParsePhysicalGrant extends CommandParser {
+ public void parse(Defaults d, LinkedList args) throws ParseFailedException, CommandFailedException {
+ int domain_id = getIntParameter(args, 'n', 0);
+ boolean force = getFlagParameter(args, 'f');
+ String partition_name = getStringParameter(args, 'p', "");
+ boolean write = getFlagParameter(args, 'w');
+
+ if (domain_id == 0)
+ throw new ParseFailedException("Expected -n<domain_id>");
+ if (partition_name.equals(""))
+ throw new ParseFailedException("Expected -p<partition_name>");
+
+ Mode mode;
+ if (write)
+ mode = Mode.READ_WRITE;
+ else
+ mode = Mode.READ_ONLY;
+
+ // Initialise the partition manager and look up the partition
+ XML.load_state( PartitionManager.it, Settings.STATE_INPUT_FILE );
+ Partition p = PartitionManager.it.get_partition(partition_name);
+
+ if ( p == null )
+ throw new CommandFailedException("Partition " + partition_name + " does not exist.");
+
+ // Check if this partition belongs to the VDM
+ if (p.getIsXeno() && !force)
+ throw new CommandFailedException("Refusing to grant physical access as the given partition is allocated to the virtual disk manager. Use -f if you are sure.");
+
+ // Convert the partition into a physical extent
+ Extent e = p.toExtent();
+
+ String output = new CommandPhysicalGrant( d, domain_id, e, mode ).execute();
+ if ( output != null )
+ System.out.println( output );
+ }
+
+ public String getName() {
+ return "grant";
+ }
+
+ public String getUsage() {
+ return "[-f] [-w] [-n<domain_id>] [-p<partition_name>]";
+ }
+
+ public String getHelpText() {
+ return "Grant the specified domain access to the given partition. -w grants" +
+ " read-write instead of read-only. -f forcibly grants access.";
+ }
+
+}
diff --git a/tools/control/src/org/xenoserver/cmdline/ParsePhysicalList.java b/tools/control/src/org/xenoserver/cmdline/ParsePhysicalList.java
new file mode 100644
index 0000000000..c08a881a26
--- /dev/null
+++ b/tools/control/src/org/xenoserver/cmdline/ParsePhysicalList.java
@@ -0,0 +1,74 @@
+package org.xenoserver.cmdline;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map.Entry;
+
+import org.xenoserver.control.CommandFailedException;
+import org.xenoserver.control.CommandPhysicalList;
+import org.xenoserver.control.Defaults;
+import org.xenoserver.control.Extent;
+import org.xenoserver.control.Library;
+import org.xenoserver.control.Mode;
+import org.xenoserver.control.Partition;
+import org.xenoserver.control.PartitionManager;
+import org.xenoserver.control.Settings;
+import org.xenoserver.control.XML;
+
+public class ParsePhysicalList extends CommandParser {
+
+ public void parse(Defaults d, LinkedList args) throws ParseFailedException, CommandFailedException {
+ int domain_id = getIntParameter(args, 'n', 0);
+ if (domain_id == 0)
+ throw new ParseFailedException("Expected -n<domain_id>");
+
+ // Initialise the partition manager
+ XML.load_state( PartitionManager.it, Settings.STATE_INPUT_FILE );
+
+ CommandPhysicalList list = new CommandPhysicalList( d, domain_id );
+ String output = list.execute();
+ if ( output != null )
+ System.out.println( output );
+
+ System.out.println( "maj:min " + " blocks " + "start sect " +
+ " num sects " + "name " + "access" );
+ Iterator i = list.extents().entrySet().iterator();
+ while ( i.hasNext() )
+ {
+ Entry entry = (Entry) i.next();
+ Extent e = (Extent) entry.getKey();
+ String mode = entry.getValue().toString();
+ Partition p = PartitionManager.it.get_partition( e );
+ if ( p != null ) {
+ System.out.println(Library.format(p.getMajor(),3,0) + ":" +
+ Library.format(p.getMinor(),3,1) + " " +
+ Library.format(p.getBlocks(),10,0) + " " +
+ Library.format(p.getStartSect(),10,0) + " " +
+ Library.format(p.getNumSects(),10,0) + " " +
+ Library.format(p.getName(),7,1) + " " +
+ Library.format(mode,2,1));
+ } else {
+ System.out.println(Library.format(e.getMajor(),3,0) + ":" +
+ Library.format(e.getMinor(),3,1) + " " +
+ " " + " " +
+ Library.format(e.getOffset(),10,0) + " " +
+ Library.format(e.getSize(),10,0) + " " +
+ " " + " " +
+ Library.format(mode,2,1));
+ }
+ }
+ }
+
+ public String getName() {
+ return "list";
+ }
+
+ public String getUsage() {
+ return "[-n<domain_id>]";
+ }
+
+ public String getHelpText() {
+ return "List all physical access which the given domain has been granted.";
+ }
+
+}
diff --git a/tools/control/src/org/xenoserver/cmdline/ParsePhysicalRevoke.java b/tools/control/src/org/xenoserver/cmdline/ParsePhysicalRevoke.java
new file mode 100644
index 0000000000..8527845cdb
--- /dev/null
+++ b/tools/control/src/org/xenoserver/cmdline/ParsePhysicalRevoke.java
@@ -0,0 +1,51 @@
+package org.xenoserver.cmdline;
+
+import java.util.LinkedList;
+
+import org.xenoserver.control.CommandFailedException;
+import org.xenoserver.control.CommandPhysicalRevoke;
+import org.xenoserver.control.Defaults;
+import org.xenoserver.control.Extent;
+import org.xenoserver.control.Partition;
+import org.xenoserver.control.PartitionManager;
+import org.xenoserver.control.Settings;
+import org.xenoserver.control.XML;
+
+public class ParsePhysicalRevoke extends CommandParser {
+ public void parse(Defaults d, LinkedList args) throws ParseFailedException, CommandFailedException {
+ int domain_id = getIntParameter(args, 'n', 0);
+ String partition_name = getStringParameter(args, 'p', "");
+
+ if (domain_id == 0)
+ throw new ParseFailedException("Expected -n<domain_id>");
+ if (partition_name.equals(""))
+ throw new ParseFailedException("Expected -p<partition_name>");
+
+ // Initialise the partition manager and look up the partition
+ XML.load_state( PartitionManager.it, Settings.STATE_INPUT_FILE );
+ Partition p = PartitionManager.it.get_partition(partition_name);
+
+ if ( p == null )
+ throw new CommandFailedException("Partition " + partition_name + " does not exist.");
+
+ // Convert the partition into a physical extent
+ Extent e = p.toExtent();
+
+ String output = new CommandPhysicalRevoke( d, domain_id, e ).execute();
+ if ( output != null )
+ System.out.println( output );
+ }
+
+ public String getName() {
+ return "revoke";
+ }
+
+ public String getUsage() {
+ return "[-n<domain_id>] [-p<partition_name>]";
+ }
+
+ public String getHelpText() {
+ return "Revoke access to the given partition from the specified domain.";
+ }
+
+}
diff --git a/tools/control/src/org/xenoserver/control/CommandPhysicalGrant.java b/tools/control/src/org/xenoserver/control/CommandPhysicalGrant.java
new file mode 100644
index 0000000000..c7152e46c3
--- /dev/null
+++ b/tools/control/src/org/xenoserver/control/CommandPhysicalGrant.java
@@ -0,0 +1,66 @@
+package org.xenoserver.control;
+
+public class CommandPhysicalGrant extends Command {
+ private Defaults d;
+ private int domain_id;
+ private Extent extent;
+ private Mode mode;
+
+ /**
+ * Constructor for CommandPhysicalGrant.
+ * @param d Defaults object to use.
+ * @param domain_id Domain to grant access for.
+ * @param extent Extent to grant access to.
+ * @param mode Access mode to grant.
+ */
+ public CommandPhysicalGrant(
+ Defaults d,
+ int domain_id,
+ Extent extent,
+ Mode mode) {
+ this.d = d;
+ this.domain_id = domain_id;
+ this.extent = extent;
+ this.mode = mode;
+ }
+
+ public String execute() throws CommandFailedException {
+ Runtime r = Runtime.getRuntime();
+ String output = null;
+
+ try {
+ Process start_p;
+ String start_cmdarray[] = new String[6];
+ int start_rc;
+ start_cmdarray[0] = d.XIToolsDir + "xi_phys_grant";
+ if ( mode == Mode.READ_WRITE )
+ start_cmdarray[1] = "rw";
+ else if ( mode == Mode.READ_ONLY )
+ start_cmdarray[1] = "ro";
+ else
+ throw new CommandFailedException( "Unknown access mode '" + mode + "'" );
+ start_cmdarray[2] = Integer.toString( domain_id );
+ start_cmdarray[3] = Short.toString( extent.getDisk() );
+ start_cmdarray[4] = Long.toString( extent.getOffset() );
+ start_cmdarray[5] = Long.toString( extent.getSize() );
+
+ if (Settings.TEST) {
+ output = reportCommand(start_cmdarray);
+ } else {
+ start_p = r.exec(start_cmdarray);
+ start_rc = start_p.waitFor();
+ if (start_rc != 0) {
+ throw CommandFailedException.XICommandFailed("Could not grant physical access", start_cmdarray);
+ }
+ output = "Granted physical access to domain " + domain_id;
+ }
+ } catch (CommandFailedException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new CommandFailedException("Could not grant physical access (" + e + ")", e);
+ }
+
+ return output;
+ }
+
+}
diff --git a/tools/control/src/org/xenoserver/control/CommandPhysicalList.java b/tools/control/src/org/xenoserver/control/CommandPhysicalList.java
new file mode 100644
index 0000000000..03bed9e15d
--- /dev/null
+++ b/tools/control/src/org/xenoserver/control/CommandPhysicalList.java
@@ -0,0 +1,98 @@
+package org.xenoserver.control;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+/**
+ * Lists details of all extents the given domain has access to.
+ * After execute() has been called, call extents() to get the map of extents
+ * to modes.
+ */
+public class CommandPhysicalList extends Command {
+ private int domain_id;
+ private Defaults d;
+ private Map map = new HashMap();
+
+ /**
+ * Constructor for CommandDomainList.
+ * @param d Defaults object to use.
+ */
+ public CommandPhysicalList(Defaults d, int domain_id) {
+ this.d = d;
+ this.domain_id = domain_id;
+ }
+
+ /**
+ * Retrieves the list of extents.
+ * @return null, call extents() to get the list.
+ */
+ public String execute() throws CommandFailedException {
+ Runtime r = Runtime.getRuntime();
+ int rc = 0;
+ String outline;
+ BufferedReader in;
+ String output = null;
+
+ try {
+ Process start_p;
+ String start_cmdarray[] = new String[2];
+ int start_rc;
+ start_cmdarray[0] = d.XIToolsDir + "xi_phys_probe";
+ start_cmdarray[1] = Integer.toString( domain_id );
+
+ if (Settings.TEST) {
+ output = reportCommand(start_cmdarray);
+ } else {
+ start_p = r.exec(start_cmdarray);
+ start_rc = start_p.waitFor();
+ if (start_rc != 0) {
+ throw CommandFailedException.XICommandFailed("Could not get extent list", start_cmdarray);
+ }
+
+ in =
+ new BufferedReader(new InputStreamReader(start_p.getInputStream()));
+
+ outline = in.readLine();
+ while (outline != null) {
+ Extent extent = new Extent();
+
+ StringTokenizer st = new StringTokenizer(outline);
+ if (st.hasMoreTokens()) {
+ extent.disk = Short.parseShort(st.nextToken(),16);
+ }
+ if (st.hasMoreTokens()) {
+ extent.offset = Long.parseLong(st.nextToken(),16);
+ }
+ if (st.hasMoreTokens()) {
+ extent.size = Long.parseLong(st.nextToken(),16);
+ }
+ if (st.hasMoreTokens()) {
+ String mode = st.nextToken();
+ if ( mode.equals( "rw" ) )
+ map.put( extent, Mode.READ_WRITE );
+ else if ( mode.equals ( "r" ) )
+ map.put( extent, Mode.READ_ONLY );
+ else
+ throw new CommandFailedException("Could not parse access mode " + mode);
+ }
+
+ outline = in.readLine();
+ }
+
+ }
+ } catch (CommandFailedException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new CommandFailedException("Could not get extent list(" + e + ")", e);
+ }
+
+ return output;
+ }
+
+ public Map extents() {
+ return map;
+ }
+}
diff --git a/tools/control/src/org/xenoserver/control/CommandPhysicalRevoke.java b/tools/control/src/org/xenoserver/control/CommandPhysicalRevoke.java
new file mode 100644
index 0000000000..63052b1d4b
--- /dev/null
+++ b/tools/control/src/org/xenoserver/control/CommandPhysicalRevoke.java
@@ -0,0 +1,56 @@
+package org.xenoserver.control;
+
+public class CommandPhysicalRevoke extends Command {
+ private Defaults d;
+ private int domain_id;
+ private Extent extent;
+
+ /**
+ * Constructor for CommandPhysicalRevoke.
+ * @param d Defaults object to use.
+ * @param domain_id Domain to revoke access from.
+ * @param extent Extent to revoke access from.
+ */
+ public CommandPhysicalRevoke(
+ Defaults d,
+ int domain_id,
+ Extent extent) {
+ this.d = d;
+ this.domain_id = domain_id;
+ this.extent = extent;
+ }
+
+ public String execute() throws CommandFailedException {
+ Runtime r = Runtime.getRuntime();
+ String output = null;
+
+ try {
+ Process start_p;
+ String start_cmdarray[] = new String[5];
+ int start_rc;
+ start_cmdarray[0] = d.XIToolsDir + "xi_phys_revoke";
+ start_cmdarray[1] = Integer.toString( domain_id );
+ start_cmdarray[2] = Short.toString( extent.getDisk() );
+ start_cmdarray[3] = Long.toString( extent.getOffset() );
+ start_cmdarray[4] = Long.toString( extent.getSize() );
+
+ if (Settings.TEST) {
+ output = reportCommand(start_cmdarray);
+ } else {
+ start_p = r.exec(start_cmdarray);
+ start_rc = start_p.waitFor();
+ if (start_rc != 0) {
+ throw CommandFailedException.XICommandFailed("Could not revoke physical access", start_cmdarray);
+ }
+ output = "Revoked physical access from domain " + domain_id;
+ }
+ } catch (CommandFailedException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new CommandFailedException("Could not revoke physical access (" + e + ")", e);
+ }
+
+ return output;
+ }
+
+}
diff --git a/tools/control/src/org/xenoserver/control/Extent.java b/tools/control/src/org/xenoserver/control/Extent.java
new file mode 100644
index 0000000000..e4ccff6806
--- /dev/null
+++ b/tools/control/src/org/xenoserver/control/Extent.java
@@ -0,0 +1,87 @@
+/*
+ * Extent.java
+ * 03.03.26 aho creation
+ */
+
+package org.xenoserver.control;
+
+public class
+Extent
+{
+ short disk;
+ long offset; /* offset into disk */
+ long size; /* size of this extent in 512 byte sectors */
+
+ public short
+ getDisk()
+ {
+ return disk;
+ }
+
+ public long
+ getOffset()
+ {
+ return offset;
+ }
+
+ public long
+ getSize()
+ {
+ return size;
+ }
+
+ public int
+ getMajor()
+ {
+ return disk >> 8;
+ }
+
+ public int
+ getMinor()
+ {
+ return disk & 0xFF;
+ }
+
+ public int hashCode() {
+ final int PRIME = 1000003;
+ int result = 0;
+ result = PRIME * result + disk;
+ result = PRIME * result + (int) (offset >>> 32);
+ result = PRIME * result + (int) (offset & 0xFFFFFFFF);
+ result = PRIME * result + (int) (size >>> 32);
+ result = PRIME * result + (int) (size & 0xFFFFFFFF);
+
+ return result;
+ }
+
+ public boolean equals(Object oth) {
+ if (this == oth) {
+ return true;
+ }
+
+ if (oth == null) {
+ return false;
+ }
+
+ if (oth.getClass() != getClass()) {
+ return false;
+ }
+
+ Extent other = (Extent) oth;
+
+ if (this.disk != other.disk) {
+ return false;
+ }
+
+ if (this.offset != other.offset) {
+ return false;
+ }
+
+ if (this.size != other.size) {
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/tools/control/src/org/xenoserver/control/Library.java b/tools/control/src/org/xenoserver/control/Library.java
new file mode 100644
index 0000000000..b384bed19b
--- /dev/null
+++ b/tools/control/src/org/xenoserver/control/Library.java
@@ -0,0 +1,129 @@
+/*
+ * Library.java
+ * 03.03.28 aho creation
+ */
+
+package org.xenoserver.control;
+
+public class
+Library
+{
+ /*
+ * convert a number to a fixed width string
+ */
+ public static String
+ format (long input, int width, int prefix)
+ {
+ String sss = Long.toString(input);
+ String space = " ";
+
+ if (width < sss.length())
+ {
+ width = sss.length();
+ }
+
+ if (prefix == 0)
+ {
+ return space.substring(0, width - sss.length()) + sss;
+ }
+ else
+ {
+ return sss + space.substring(0, width - sss.length());
+ }
+ }
+
+ /*
+ * convert a string to a fixed width string
+ */
+ public static String
+ format (String input, int width, int prefix)
+ {
+ String space = " ";
+
+ if (width < input.length())
+ {
+ width = input.length();
+ }
+
+ if (prefix == 0)
+ {
+ return space.substring(0, width - input.length()) + input;
+ }
+ else
+ {
+ return input + space.substring(0, width - input.length());
+ }
+ }
+
+ /*
+ * convert a number (string format) into
+ * the corresponding integer value.
+ */
+ public static long
+ parse_size(String size)
+ {
+ String substring = size;
+ int suffix = 1;
+ long value = 0;
+
+ if (size == null)
+ {
+ return 0;
+ }
+
+ if ((substring = check(size, 'm')) != null)
+ {
+ suffix = 1024 * 1024;
+ }
+ else if ((substring = check(size, 'M')) != null)
+ {
+ suffix = 1024 * 1024;
+ }
+ else if ((substring = check(size, 'k')) != null)
+ {
+ suffix = 1024;
+ }
+ else if ((substring = check(size, 'K')) != null)
+ {
+ suffix = 1024;
+ }
+ else if ((substring = check(size, 'g')) != null)
+ {
+ suffix = 1024 * 1024 * 1024;
+ }
+ else if ((substring = check(size, 'G')) != null)
+ {
+ suffix = 1024 * 1024 * 1024;
+ }
+ else
+ {
+ substring = size;
+ }
+
+ try
+ {
+ value = Long.decode(substring).longValue() * suffix;
+ }
+ catch (NumberFormatException e)
+ {
+ value = 0;
+ }
+
+ return value;
+ }
+
+ public static String
+ check(String size, char suffix)
+ {
+ int index = size.indexOf(suffix);
+
+ if (index != -1)
+ {
+ return size.substring(0, index);
+ }
+ else
+ {
+ return null;
+ }
+ }
+}
diff --git a/tools/control/src/org/xenoserver/control/Mode.java b/tools/control/src/org/xenoserver/control/Mode.java
new file mode 100644
index 0000000000..5f2ea4d485
--- /dev/null
+++ b/tools/control/src/org/xenoserver/control/Mode.java
@@ -0,0 +1,22 @@
+/*
+ * Mode.java
+ * 03.03.27 aho creation
+ *
+ * until we have jdk1.5, we're left with this mess...
+ */
+
+package org.xenoserver.control;
+
+public class
+Mode
+{
+ private final String name;
+
+ private Mode(String name) { this.name = name; }
+
+ public String toString() { return name; }
+
+ public static final Mode READ_ONLY = new Mode("ro");
+ public static final Mode READ_WRITE = new Mode("rw");
+}
+
diff --git a/tools/control/src/org/xenoserver/control/Partition.java b/tools/control/src/org/xenoserver/control/Partition.java
new file mode 100644
index 0000000000..03237c5fb1
--- /dev/null
+++ b/tools/control/src/org/xenoserver/control/Partition.java
@@ -0,0 +1,191 @@
+/*
+ * Partition.java
+ * 03.03.26 aho creation
+ */
+
+package org.xenoserver.control;
+
+import java.io.*;
+
+public class
+Partition
+{
+ int major;
+ int minor;
+ long blocks;
+ long start_sect;
+ long nr_sects;
+ String name;
+ boolean xeno;
+
+ Partition
+ duplicate ()
+ {
+ Partition p = new Partition();
+
+ p.major = major;
+ p.minor = minor;
+ p.blocks = blocks;
+ p.start_sect = start_sect;
+ p.nr_sects = nr_sects;
+ p.name = name;
+ p.xeno = xeno;
+
+ return p;
+ }
+
+ void
+ dump_xml(PrintWriter out)
+ {
+ out.println (" <partition>\n" +
+ " <major>" + major + "</major>\n" +
+ " <minor>" + minor + "</minor>\n" +
+ " <blocks>" + blocks + "</blocks>\n" +
+ " <start_sect>" + start_sect + "</start_sect>\n" +
+ " <nr_sects>" + nr_sects + "</nr_sects>\n" +
+ " <name>" + name + "</name>\n" +
+ " </partition>");
+ }
+
+ public int
+ getMajor()
+ {
+ return major;
+ }
+
+ public int
+ getMinor()
+ {
+ return minor;
+ }
+
+ public long
+ getBlocks()
+ {
+ return blocks;
+ }
+
+ public long
+ getStartSect()
+ {
+ return start_sect;
+ }
+
+ public long
+ getNumSects()
+ {
+ return nr_sects;
+ }
+
+ public String
+ getName()
+ {
+ return name;
+ }
+
+ public boolean
+ getIsXeno()
+ {
+ return xeno;
+ }
+
+ public int hashCode() {
+ final int PRIME = 1000003;
+ int result = 0;
+ result = PRIME * result + major;
+ result = PRIME * result + minor;
+ result = PRIME * result + (int) (blocks >>> 32);
+ result = PRIME * result + (int) (blocks & 0xFFFFFFFF);
+ result = PRIME * result + (int) (start_sect >>> 32);
+ result = PRIME * result + (int) (start_sect & 0xFFFFFFFF);
+ result = PRIME * result + (int) (nr_sects >>> 32);
+ result = PRIME * result + (int) (nr_sects & 0xFFFFFFFF);
+ if (name != null) {
+ result = PRIME * result + name.hashCode();
+ }
+
+ return result;
+ }
+
+ public boolean equals(Object oth) {
+ if (this == oth) {
+ return true;
+ }
+
+ if (oth == null) {
+ return false;
+ }
+
+ if (oth.getClass() != getClass()) {
+ return false;
+ }
+
+ Partition other = (Partition) oth;
+
+ if (this.major != other.major) {
+ return false;
+ }
+
+ if (this.minor != other.minor) {
+ return false;
+ }
+
+ if (this.blocks != other.blocks) {
+ return false;
+ }
+
+ if (this.start_sect != other.start_sect) {
+ return false;
+ }
+
+ if (this.nr_sects != other.nr_sects) {
+ return false;
+ }
+ if (this.name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else {
+ if (!this.name.equals(other.name)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * @return An Extent covering this partiton.
+ */
+ public Extent toExtent()
+ {
+ Extent e = new Extent();
+ // Build 16-bit disk number.. high 8 bits are the major
+ int disknum = major << 8;
+ // Low 8 bits are the minor, but bottom 5 need to be cleared
+ // as they are the partition number, not the disk number
+ disknum |= ( minor & 0xE0 );
+ e.disk = (short) disknum;
+ e.offset = start_sect;
+ e.size = nr_sects;
+ return e;
+ }
+
+ /**
+ * @param e Extent to compare this partition to.
+ * @return True if this partition covers the same disk area as the given extent.
+ */
+ public boolean matchesExtent( Extent e )
+ {
+ if ( e.getMajor() != major )
+ return false;
+ if ( e.getMinor() != (minor & 0xE0) )
+ return false;
+ if ( e.offset != start_sect )
+ return false;
+ if ( e.size != nr_sects )
+ return false;
+
+ return true;
+ }
+}
diff --git a/tools/control/src/org/xenoserver/control/PartitionManager.java b/tools/control/src/org/xenoserver/control/PartitionManager.java
new file mode 100644
index 0000000000..2609d458ee
--- /dev/null
+++ b/tools/control/src/org/xenoserver/control/PartitionManager.java
@@ -0,0 +1,185 @@
+/*
+ * PartitionManager.java
+ * 03.03.26 aho creation
+ */
+
+package org.xenoserver.control;
+
+import java.io.*;
+import java.util.Iterator;
+import java.util.Vector;
+import java.util.Enumeration;
+
+/**
+ * PartitionManager manages the partitions on the machine. It is a Singleton
+ * which automatically initialises itself on first class reference.
+ */
+public class
+PartitionManager
+{
+ static final String proc_template =
+ "major minor #blocks start_sect nr_sects name";
+
+ public static final PartitionManager it = new PartitionManager(Settings.PARTITIONS_FILE);
+
+ Vector partition_map;
+
+ /*
+ * Initialize partition manager with source file.
+ * Normally we read from /proc/partitions, but we can
+ * specify an alternative file for debugging
+ */
+ private PartitionManager (String filename)
+ {
+ String str;
+ BufferedReader in;
+
+ partition_map = new Vector(100,10);
+
+ try
+ {
+ in = new BufferedReader(new FileReader(filename));
+
+ str = in.readLine(); /* skip headings */
+ if (str.length() < proc_template.length() ||
+ !str.substring(0, proc_template.length()).equals(proc_template))
+ {
+ System.err.println ("Error: Incorrect /proc/partitions.");
+ System.err.println (" Is this Xeno?");
+ System.exit (1);
+ }
+
+ str = in.readLine(); /* skip blank line */
+
+ str = in.readLine();
+ while (str != null)
+ {
+ Partition partition = new Partition();
+
+ partition.major = Integer.parseInt(str.substring(0,5).trim());
+ partition.minor = Integer.parseInt(str.substring(5,10).trim());
+ partition.blocks = Integer.parseInt(str.substring(10,21).trim());
+ partition.start_sect = Integer.parseInt(str.substring(21,32).trim());
+ partition.nr_sects = Integer.parseInt(str.substring(32,43).trim());
+ partition.name = str.substring(43).trim();
+ partition.xeno = false;
+
+ partition_map.add(partition);
+ str = in.readLine();
+ }
+ }
+ catch (IOException io)
+ {
+ System.err.println ("PartitionManager: error reading partition file ["
+ + filename + "]");
+ System.err.println (io);
+ }
+ }
+
+ public Partition
+ get_partition (String name)
+ {
+ Partition partition = null;
+ for (Enumeration e = partition_map.elements() ; e.hasMoreElements() ;)
+ {
+ partition = (Partition) e.nextElement();
+ if (partition.name.equals(name))
+ {
+ return partition;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Finds the partition that matches the given extent, if any.
+ * @param extent The extent to compare to.
+ * @return The first matching partition, or null if none.
+ */
+ public Partition
+ get_partition (Extent extent)
+ {
+ Partition partition = null;
+ for (Enumeration e = partition_map.elements() ; e.hasMoreElements() ;)
+ {
+ partition = (Partition) e.nextElement();
+ if (partition.matchesExtent(extent))
+ {
+ return partition;
+ }
+ }
+ return null;
+ }
+
+ Partition
+ get_partition (int index)
+ {
+ return (Partition) partition_map.get(index);
+ }
+
+ void
+ add_xeno_partition (Partition p)
+ {
+ for (Enumeration e = partition_map.elements() ; e.hasMoreElements() ;)
+ {
+ Partition partition = (Partition) e.nextElement();
+ if (partition.equals(p))
+ {
+ partition.xeno = true;
+ }
+ }
+ }
+
+ /*
+ * dump the xeno partition list as xml
+ */
+ void
+ dump_xml (PrintWriter out)
+ {
+ int loop;
+
+ out.println("<partitions>");
+ for (Enumeration e = partition_map.elements() ; e.hasMoreElements() ;)
+ {
+ Partition partition = (Partition) e.nextElement();
+ if (partition.xeno == true)
+ {
+ partition.dump_xml(out);
+ }
+ }
+
+ out.println("</partitions>");
+
+ return;
+ }
+
+ /**
+ * get the number of partitions
+ */
+
+ int
+ getPartitionCount ()
+ {
+ return partition_map.size();
+ }
+
+ /**
+ * get the details about a particular partition
+ *
+ */
+ Partition
+ getPartition (int index)
+ {
+ Partition partition = (Partition) partition_map.get(index);
+ return partition;
+ }
+
+ /**
+ * Get an iterator over all the partitions.
+ * @return An iterator over Partition objects.
+ */
+ public Iterator iterator()
+ {
+ return partition_map.iterator();
+ }
+}
diff --git a/tools/control/src/org/xenoserver/control/Settings.java b/tools/control/src/org/xenoserver/control/Settings.java
index 74203e618f..c6a1741dda 100644
--- a/tools/control/src/org/xenoserver/control/Settings.java
+++ b/tools/control/src/org/xenoserver/control/Settings.java
@@ -16,7 +16,9 @@ public final class Settings
public static final String LOCAL_GW = System.getProperty ("LOCAL_ROUTE");
public static final boolean TEST = (System.getProperty ("TEST") != null);
public static final String XI_HELPER = System.getProperty ("XI_HELPER", "xi_helper");
-
+ public static final String PARTITIONS_FILE = System.getProperty("PARTITIONS_FILE", "/proc/partitions");
+ public static final String STATE_INPUT_FILE = System.getProperty("STATE_INPUT_FILE", "/var/lib/xen/vdstate.xml");
+ public static final String STATE_OUTPUT_FILE = System.getProperty("STATE_OUTPUT_FILE", "/var/lib/xen/vdstate.xml");
public static File getDefaultsFile() {
StringTokenizer tok = new StringTokenizer (DEFAULTS_PATH, ":");
diff --git a/tools/control/src/org/xenoserver/control/XML.java b/tools/control/src/org/xenoserver/control/XML.java
new file mode 100644
index 0000000000..d8331b9c2b
--- /dev/null
+++ b/tools/control/src/org/xenoserver/control/XML.java
@@ -0,0 +1,125 @@
+/*
+ * XML.java
+ * 03.03.26 aho creation
+ */
+
+package org.xenoserver.control;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+public class
+XML
+{
+ static Document document = null;
+
+ /*
+ * dump partition manager and virtual disk manager state to filename
+ */
+
+ public static void
+ dump_state (PartitionManager pm,/* VirtualDiskManager vdm,*/ String filename)
+ {
+ PrintWriter out;
+
+ try
+ {
+ out = new PrintWriter(new BufferedWriter(new FileWriter(filename)));
+ }
+ catch (IOException e)
+ {
+ System.err.println ("XML.dump_state error [" + filename + "]");
+ System.err.println (e);
+ return;
+ }
+
+ out.println("<?xml version=\"1.0\"?>");
+ out.println("<vdmanager>");
+ pm.dump_xml(out);
+ //vdm.dump_xml(out);
+ out.println("</vdmanager>");
+
+ out.close();
+ return;
+ }
+
+ /*
+ * load partition manager and virtual disk manager state from filename
+ */
+ public static void
+ load_state (PartitionManager pm, /*VirtualDiskManager vdm,*/ String filename)
+ {
+ if (document == null)
+ {
+ load_file (filename);
+ }
+
+ XMLHelper.parse(pm, /*vdm,*/ document);
+ }
+
+ /*
+ * load XML from disk
+ */
+ static void
+ load_file (String filename)
+ {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ // factory.setNamespaceAware(true);
+ // factory.setValidating(true);
+
+ try
+ {
+ File file = new File(filename);
+
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ document = builder.parse(file);
+ }
+ catch (SAXParseException spe) /* error generated by parser */
+ {
+ System.err.println ("xml parser exception on line " +
+ spe.getLineNumber() +
+ " for uri " + spe.getSystemId());
+ System.err.println (spe.getMessage());
+
+ Exception x = spe;
+ if (spe.getException() != null)
+ x = spe.getException();
+ x.printStackTrace();
+ System.exit(1);
+ }
+ catch (SAXException sxe)
+ {
+ Exception e = sxe;
+ if (sxe.getException() != null)
+ e = sxe.getException();
+ e.printStackTrace();
+ System.exit(1);
+ }
+ catch (ParserConfigurationException pce)
+ {
+ pce.printStackTrace();
+ }
+ catch (FileNotFoundException fnfe)
+ {
+ System.err.println ("warning: state file not found [" +
+ filename + "]");
+ }
+ catch (IOException ioe)
+ {
+ ioe.printStackTrace();
+ }
+ return;
+ }
+}
diff --git a/tools/control/src/org/xenoserver/control/XMLHelper.java b/tools/control/src/org/xenoserver/control/XMLHelper.java
new file mode 100644
index 0000000000..5646e5ce21
--- /dev/null
+++ b/tools/control/src/org/xenoserver/control/XMLHelper.java
@@ -0,0 +1,205 @@
+/*
+ * XMLHelper.java
+ * 03.03.27 aho creation
+ */
+
+package org.xenoserver.control;
+
+import java.util.Date;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class
+XMLHelper
+{
+ static void
+ dump_document (Document document)
+ {
+ dump_element(document.getDocumentElement(), 0);
+ }
+
+ static void
+ dump_element (Element element, int indent)
+ {
+ NodeList nl = element.getChildNodes();
+
+ System.out.println ("<" + element.getTagName() + ">");
+ dump_nodelist(nl, indent + 1);
+ System.out.println("</" + element.getTagName() + ">");
+ }
+
+ static void
+ dump_nodelist (NodeList nl, int indent)
+ {
+ for (int loop = 0; loop < nl.getLength(); loop++)
+ {
+ Node node = nl.item(loop);
+ switch (node.getNodeType())
+ {
+ case Node.ELEMENT_NODE :
+ {
+ dump_element((Element)node, indent);
+ break;
+ }
+ case Node.TEXT_NODE :
+ {
+ System.out.println("TEXT: " + node.getNodeValue());
+ break;
+ }
+ default :
+ {
+ System.out.println("NODE: " + node.getNodeType());
+ }
+ }
+ }
+ }
+
+ static Node
+ get_subnode (String name, Node node)
+ {
+ if (node.getNodeType() != Node.ELEMENT_NODE)
+ {
+ System.err.println("Error: Search node not of element type");
+ return null;
+ }
+
+ if (!node.hasChildNodes()) return null;
+
+ NodeList list = node.getChildNodes();
+ for (int i=0; i < list.getLength(); i++)
+ {
+ Node subnode = list.item(i);
+ if (subnode.getNodeType() == Node.ELEMENT_NODE)
+ {
+ if (subnode.getNodeName() == name) return subnode;
+ }
+ }
+ return null;
+ }
+
+ static String
+ get_text (Node node)
+ {
+ StringBuffer result = new StringBuffer();
+ if (node==null || !node.hasChildNodes()) return "";
+
+ NodeList list = node.getChildNodes();
+ for (int i=0; i < list.getLength(); i++)
+ {
+ Node subnode = list.item(i);
+ if (subnode.getNodeType() == Node.TEXT_NODE)
+ {
+ result.append(subnode.getNodeValue());
+ }
+ }
+ return result.toString();
+ }
+
+ static void
+ parse (PartitionManager pm, /*VirtualDiskManager vdm,*/ Document document)
+ {
+ if (document == null) return;
+
+ /* parse partitions */
+ parse_partitions(pm, document.getElementsByTagName("partition"));
+/*
+ / parse virtual disks /
+ NodeList list = document.getElementsByTagName("virtual_disk");
+ for (int i = 0; i < list.getLength(); i++)
+ {
+ Node subnode = list.item(i);
+ String parent = subnode.getParentNode().getNodeName();
+ VirtualDisk vd = parse_virtual_disk(subnode);
+
+ if (parent.equals("free"))
+ {
+ vdm.add_free(vd);
+ }
+ else if (parent.equals("virtual_disks"))
+ {
+ vdm.add_virtual_disk(vd);
+ }
+ else
+ {
+ System.out.println ("XML parse error: unknown parent for virtual_disk "
+ + "[" + parent + "]");
+ }
+ }
+
+ / parse virtual block devices /
+ parse_virtual_block_devices(vdm, document.getElementsByTagName("virtual_block_device"));
+*/
+ return;
+ }
+
+ /* static VirtualDisk
+ parse_virtual_disk(Node node)
+ {
+ VirtualDisk vd;
+ Date date = new Date();
+ NodeList list;
+
+ date.setTime(Long.parseLong(XMLHelper.get_text(XMLHelper.get_subnode("expiry", node))));
+ vd = new VirtualDisk(XMLHelper.get_text(XMLHelper.get_subnode("name", node)),
+ date,
+ XMLHelper.get_text(XMLHelper.get_subnode("key", node)));
+
+ list = XMLHelper.get_subnode("extents", node).getChildNodes();
+ for (int i = 0; i < list.getLength(); i++)
+ {
+ Node enode = list.item(i);
+
+ if (enode.getNodeType() == Node.ELEMENT_NODE &&
+ enode.getNodeName().equals("extent"))
+ {
+ Extent extent = new Extent();
+
+ extent.disk = Integer.parseInt(XMLHelper.get_text(XMLHelper.get_subnode("disk", enode)));
+ extent.size = Long.parseLong(XMLHelper.get_text(XMLHelper.get_subnode("size", enode)));
+ extent.offset = Long.parseLong(XMLHelper.get_text(XMLHelper.get_subnode("offset", enode)));
+ vd.add_extent(extent);
+ }
+ }
+
+ return vd;
+ }*/
+
+ static void
+ parse_partitions (PartitionManager pm, NodeList nl)
+ {
+ Partition partition;
+
+ for (int loop = 0; loop < nl.getLength(); loop++)
+ {
+ Node node = nl.item(loop);
+
+ partition = new Partition();
+ partition.major = Integer.parseInt(XMLHelper.get_text(XMLHelper.get_subnode("major", node)));
+ partition.minor = Integer.parseInt(XMLHelper.get_text(XMLHelper.get_subnode("minor", node)));
+ partition.blocks = Integer.parseInt(XMLHelper.get_text(XMLHelper.get_subnode("blocks", node)));
+ partition.start_sect = Integer.parseInt(XMLHelper.get_text(XMLHelper.get_subnode("start_sect", node)));
+ partition.nr_sects = Integer.parseInt(XMLHelper.get_text(XMLHelper.get_subnode("nr_sects", node)));
+ partition.name = XMLHelper.get_text(XMLHelper.get_subnode("name", node));
+
+ pm.add_xeno_partition(partition);
+ }
+ }
+/*
+ static void
+ parse_virtual_block_devices (VirtualDiskManager vdm, NodeList nl)
+ {
+ VirtualBlockDevice vbd;
+
+ for (int loop = 0; loop < nl.getLength(); loop++)
+ {
+ Node node = nl.item(loop);
+
+ vdm.create_virtual_block_device(XMLHelper.get_text(XMLHelper.get_subnode("key", node)),
+ Integer.parseInt(XMLHelper.get_text(XMLHelper.get_subnode("domain", node))),
+ Integer.parseInt(XMLHelper.get_text(XMLHelper.get_subnode("vbdnum", node))),
+ XMLHelper.get_text(XMLHelper.get_subnode("mode", node)));
+ }
+ }*/
+}