diff options
author | rac61@labyrinth.cl.cam.ac.uk <rac61@labyrinth.cl.cam.ac.uk> | 2003-07-04 11:21:03 +0000 |
---|---|---|
committer | rac61@labyrinth.cl.cam.ac.uk <rac61@labyrinth.cl.cam.ac.uk> | 2003-07-04 11:21:03 +0000 |
commit | 8a7e82b3a364fc789377c42d502cae6c98a44338 (patch) | |
tree | f9b41ce26abdd3500f7362dddfd489070d032e73 /tools/control | |
parent | 965d3529097e9e06aa6065f4fe29ce118e5c31e2 (diff) | |
download | xen-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')
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))); + } + }*/ +} |