Index: /trunk/src/VBox/Frontends/VBoxShell/vboxshell.py
===================================================================
--- /trunk/src/VBox/Frontends/VBoxShell/vboxshell.py	(revision 21639)
+++ /trunk/src/VBox/Frontends/VBoxShell/vboxshell.py	(revision 21640)
@@ -258,6 +258,11 @@
             print session.QueryErrorObject(rc)
 
-def getMachines(ctx):
-    return ctx['global'].getArray(ctx['vb'], 'machines')
+def getMachines(ctx, invalidate = False):
+    if ctx['vb'] is not None:
+        if ctx['_machlist'] is None or invalidate:
+            ctx['_machlist'] = ctx['global'].getArray(ctx['vb'], 'machines')
+        return ctx['_machlist']
+    else:
+        return []
 
 def asState(var):
@@ -389,5 +394,5 @@
 
 def listCmd(ctx, args):
-    for m in getMachines(ctx):
+    for m in getMachines(ctx, True):
         print "Machine '%s' [%s], state=%s" %(m.name,m.id,m.sessionState)
     return 0
@@ -420,7 +425,7 @@
     os = ctx['vb'].getGuestOSType(mach.OSTypeId)
     print " One can use setvar <mach> <var> <value> to change variable, using name in []."
-    print "  Name [name]: " + mach.name
-    print "  ID [n/a]: " + mach.id
-    print "  OS Type [n/a]: " + os.description
+    print "  Name [name]: %s" %(mach.name)
+    print "  ID [n/a]: %s" %(mach.id)
+    print "  OS Type [n/a]: %s" %(os.description)
     print
     print "  CPUs [CPUCount]: %d" %(mach.CPUCount)
@@ -435,5 +440,5 @@
     print "  ACPI [BIOSSettings.ACPIEnabled]: %s" %(asState(bios.ACPIEnabled))
     print "  APIC [BIOSSettings.IOAPICEnabled]: %s" %(asState(bios.IOAPICEnabled))
-    print "  PAE [PAEEnabled]: %s" %(asState(mach.PAEEnabled))
+    print "  PAE [PAEEnabled]: %s" %(asState(int(mach.PAEEnabled)))
     print "  Hardware virtualization [HWVirtExEnabled]: " + asState(mach.HWVirtExEnabled)
     print "  VPID support [HWVirtExVPIDEnabled]: " + asState(mach.HWVirtExVPIDEnabled)
@@ -457,36 +462,36 @@
         print "    Controller: %s port: %d device: %d:" % (disk.controller, disk.port, disk.device)
         hd = disk.hardDisk
-        print "    id: " + hd.id
-        print "    location: " +  hd.location
-        print "    name: " +  hd.name
-        print "    format: " +  hd.format
+        print "    id: %s" %(hd.id)
+        print "    location: %s" %(hd.location)
+        print "    name: %s"  %(hd.name)
+        print "    format: %s"  %(hd.format)
         print
 
     dvd = mach.DVDDrive
-    if dvd.getHostDrive() is not None:
+    if dvd.getHostDrive():
         hdvd = dvd.getHostDrive()
         print "  DVD:"
-        print "    Host disk:",hdvd.name
+        print "    Host disk: %s" %(hdvd.name)
         print
 
-    if dvd.getImage() is not None:
+    if dvd.getImage():
         vdvd = dvd.getImage()
         print "  DVD:"
-        print "    Image at:",vdvd.location
-        print "    Size:",vdvd.size
+        print "    Image at: %s" %(vdvd.location)
+        print "    Size: %s" %(vdvd.size)
         print
 
     floppy = mach.floppyDrive
-    if floppy.getHostDrive() is not None:
+    if floppy.getHostDrive():
         hfloppy = floppy.getHostDrive()
         print "  Floppy:"
-        print "    Host disk:",hfloppy.name
+        print "    Host disk: %s" %(hfloppy.name)
         print
 
-    if floppy.getImage() is not None:
+    if floppy.getImage():
         vfloppy = floppy.getImage()
         print "  Floppy:"
-        print "    Image at:",vfloppy.location
-        print "    Size:",vfloppy.size
+        print "    Image at: %s" %(vfloppy.location)
+        print "    Size: %s" %(vfloppy.size)
         print
 
@@ -769,4 +774,54 @@
 
     time.sleep(float(args[1]))
+    return 0
+
+
+def connectCmd(ctx, args):
+    if (len(args) > 4):
+        print "usage: connect [url] [username] [passwd]"
+        return 0
+
+    if ctx['vb'] is not None:
+        print "Already connected, disconnect first..."
+        return 0
+
+    if (len(args) > 1):
+        url = args[1]
+    else:
+        url = None
+
+    if (len(args) > 2):
+        user = args[1]
+    else:
+        user = ""
+
+    if (len(args) > 3):
+        passwd = args[2]
+    else:
+        passwd = ""
+
+    vbox = ctx['global'].platform.connect(url, user, passwd)
+    ctx['vb'] = vbox
+    print "Running VirtualBox version %s" %(vbox.version)
+    ctx['perf'] = ctx['global'].getPerfCollector(ctx['vb'])
+    return 0
+
+def disconnectCmd(ctx, args):
+    if (len(args) != 1):
+        print "usage: disconnect"
+        return 0
+
+    if ctx['vb'] is None:
+        print "Not connected yet."
+        return 0
+
+    try:
+        ctx['global'].platform.disconnect()
+    except:
+        ctx['vb'] = None
+        raise
+
+    ctx['vb'] = None
+    return 0
 
 aliases = {'s':'start',
@@ -852,10 +907,21 @@
         traceback.print_exc()
 
-def interpret(ctx):
+def interpret(ctx):    
+    if ctx['remote']:
+        commands['connect'] = ["Connect to remote VBox instance", connectCmd, 0]
+        commands['disconnect'] = ["Disconnect from remote VBox instance", disconnectCmd, 0]
+    
     vbox = ctx['vb']
-    print "Running VirtualBox version %s" %(vbox.version)
-    ctx['perf'] = ctx['global'].getPerfCollector(ctx['vb'])
-
-    checkUserExtensions(ctx, commands, vbox.homeFolder)
+
+    if vbox is not None:
+        print "Running VirtualBox version %s" %(vbox.version)
+        ctx['perf'] = ctx['global'].getPerfCollector(ctx['vb'])
+        home = vbox.homeFolder
+    else:
+        ctx['perf'] = None
+        home = os.path.join(os.path.expanduser("~"), ".VirtualBox")
+
+    print "h", home
+    checkUserExtensions(ctx, commands, home)
 
     autoCompletion(commands, ctx)
@@ -923,5 +989,6 @@
            'remote':g_virtualBoxManager.remote, 
            'type':g_virtualBoxManager.type,
-           'run':runCommandCb
+           'run':runCommandCb,
+           '_machlist':None
            }
     interpret(ctx)
Index: /trunk/src/VBox/Main/glue/vboxapi.py
===================================================================
--- /trunk/src/VBox/Main/glue/vboxapi.py	(revision 21639)
+++ /trunk/src/VBox/Main/glue/vboxapi.py	(revision 21640)
@@ -379,4 +379,5 @@
     def __init__(self, params):
         sys.path.append(VboxSdkDir+'/bindings/webservice/python/lib')
+        # not really needed, but just fail early if misconfigured
         import VirtualBox_services
         import VirtualBox_wrappers
@@ -390,12 +391,32 @@
             self.password = ""
             self.url = None
+        self.vbox = None        
+
+    def getSessionObject(self, vbox):        
+        return self.wsmgr.getSessionObject(vbox)
+
+    def getVirtualBox(self):
+        return connect(self.url, self.user, self.password)
+
+    def connect(self, url, user, passwd):
+        if self.vbox is not None:
+             disconnect()
+        from VirtualBox_wrappers import IWebsessionManager2
+        self.url = url
+        if user is None:
+            user = ""
+        self.user = user
+        if passwd is None:
+            passwd = ""
+        self.password = passwd
         self.wsmgr = IWebsessionManager2(self.url)
-
-    def getSessionObject(self, vbox):
-        return self.wsmgr.getSessionObject(vbox)
-
-    def getVirtualBox(self):
         self.vbox = self.wsmgr.logon(self.user, self.password)
         return self.vbox
+
+    def disconnect(self):
+        if self.vbox is not None and self.wsmgr is not None:
+                self.wsmgr.logoff(self.vbox)
+                self.vbox = None
+                self.wsmgr = None
 
     def getConstants(self):
@@ -426,9 +447,7 @@
     def deinit(self):
         try:
-            if self.vbox is not None:
-                self.wsmg.logoff(self.vbox)
-                self.vbox = None
+           disconnect()
         except:
-            pass
+           pass
 
     def getPerfCollector(self, vbox):
@@ -451,14 +470,19 @@
         try:
             exec "self.platform = Platform"+style+"(platparams)"
-            self.vbox = self.platform.getVirtualBox()
-            self.mgr = SessionManager(self)
+            
             self.constants = VirtualBoxReflectionInfo()
             self.type = self.platform.getType()
             self.remote = self.platform.getRemote()
             self.style = style            
+
+            self.mgr = SessionManager(self)
+            self.vbox = self.platform.getVirtualBox()
         except Exception,e:
             print "init exception: ",e
             traceback.print_exc()
-            raise e
+            if self.remote:
+                self.vbox = None
+            else:
+                raise e
 
     def getArray(self, obj, field):
Index: /trunk/src/VBox/Main/webservice/websrv-python.xsl
===================================================================
--- /trunk/src/VBox/Main/webservice/websrv-python.xsl	(revision 21639)
+++ /trunk/src/VBox/Main/webservice/websrv-python.xsl	(revision 21640)
@@ -55,4 +55,5 @@
     <xsl:when test="$type='uuid'">UUID</xsl:when>
     <xsl:when test="$type='$unknown'">IUnknown</xsl:when>
+    <xsl:when test="$type='$dispatched'">IUnknown</xsl:when>
     <xsl:otherwise><xsl:value-of select="$type" /></xsl:otherwise>
   </xsl:choose>
@@ -139,10 +140,30 @@
 </xsl:template>
 
+
+<xsl:template name="computeExtends">
+  <xsl:param name="base" />
+  
+  <xsl:choose>
+    <xsl:when test="($base = '$unknown') or ($base = '$dispatched')">
+      <xsl:value-of select="'IUnknown'"/>
+    </xsl:when>
+     <xsl:otherwise>
+      <xsl:value-of select="$base"/>
+    </xsl:otherwise>
+  </xsl:choose>
+</xsl:template>
+
 <xsl:template name="interface">
+   <xsl:variable name="base">
+     <xsl:call-template name="computeExtends">
+       <xsl:with-param name="base" select="@extends" />
+     </xsl:call-template>
+   </xsl:variable>
    <xsl:variable name="ifname"><xsl:value-of select="@name" /></xsl:variable>
-class <xsl:value-of select="$ifname"/>:
+
+class <xsl:value-of select="$ifname"/>(<xsl:value-of select="$base" />):
    def __init__(self, mgr, handle, isarray = False):
        self.mgr = mgr
-       if handle is None or handle == "":
+       if handle is None:
            raise Exception("bad handle: "+str(handle))
        self.handle = handle
@@ -191,8 +212,11 @@
    def __getattr__(self,name):
       hndl = <xsl:value-of select="$ifname" />._Attrs_.get(name, None)
-      if (hndl != None and hndl[0] != None):
-         return hndl[0](self)
+      if hndl != None:
+         if hndl[0] != None:
+           return hndl[0](self)
+         else:
+          raise AttributeError
       else:
-         raise AttributeError
+         return <xsl:value-of select="$base" />.__getattr__(self, name)
 
    def __setattr__(self, name, val):
@@ -272,8 +296,18 @@
    <xsl:variable name="ifname"><xsl:value-of select="@name" /></xsl:variable>
 class <xsl:value-of select="$ifname"/>:
-    def __init__(self, mgr, handle):<xsl:for-each select="attribute">
-       self.mgr = mgr
-       self.<xsl:value-of select="@name"/> = handle._<xsl:value-of select="@name"/>
+    def __init__(self, mgr, handle, isarray = False):
+       self.mgr = mgr
+       self.isarray = isarray
+       if isarray:
+          self.handle = handle
+       else:
+<xsl:for-each select="attribute">
+          self.<xsl:value-of select="@name"/> = <xsl:call-template name="emitConvertedType">
+              <xsl:with-param name="ifname" select="$ifname" />
+              <xsl:with-param name="methodname" select="''" />
+              <xsl:with-param name="type" select="@type" />
+             </xsl:call-template>(self.mgr, handle._<xsl:value-of select="@name"/>)
        </xsl:for-each>
+          pass
 
    <!-- also do getters/setters -->
@@ -285,4 +319,25 @@
        raise Error, 'setters not supported'
     </xsl:for-each>
+
+    def __next(self):
+      if self.isarray:
+          return self.handle.__next()
+      raise TypeError, "iteration over non-sequence"
+
+    def __size(self):
+      if self.isarray:         
+          return self.handle.__size()
+      raise TypeError, "iteration over non-sequence"
+
+    def __len__(self):
+      if self.isarray:
+          return self.handle.__len__()
+      raise TypeError, "iteration over non-sequence"
+
+    def __getitem__(self, index):
+      if self.isarray:
+          return <xsl:value-of select="$ifname" />(self.mgr, self.handle[index])
+      raise TypeError, "iteration over non-sequence"       
+
 </xsl:template>
 
@@ -435,4 +490,5 @@
   def __init__(self, mgr, handle, isarray = False):
       self.handle = handle
+      self.mgr = mgr
       self.isarray = isarray
  
@@ -454,9 +510,9 @@
   def __getitem__(self, index):
       if self.isarray:
-          return String(self.handle[index])
+          return String(self.mgr, self.handle[index])
       raise TypeError, "iteration over non-sequence"       
 
   def __str__(self):
-      return self.handle
+      return str(self.handle)
 
   def __eq__(self,other):
@@ -478,8 +534,12 @@
       return True
 
+  def __add__(self,other):
+      return str(self.handle)+str(other)
+
 
 class UUID:
   def __init__(self, mgr, handle, isarray = False):
       self.handle = handle
+      self.mgr = mgr
       self.isarray = isarray
  
@@ -501,5 +561,5 @@
   def __getitem__(self, index):
       if self.isarray:
-          return UUID(self.handle[index])
+          return UUID(self.mgr, self.handle[index])
       raise TypeError, "iteration over non-sequence"       
 
@@ -526,6 +586,9 @@
 
 class Boolean:
-  def __init__(self, mgr, handle, isarray = False):
-       self.handle = handle
+  def __init__(self, mgr, handle, isarray = False):       
+       self.handle = handle
+       if self.handle == "false":
+          self.handle = None
+       self.mgr = mgr
        self.isarray = isarray
  
@@ -547,7 +610,37 @@
       return True
 
+  def __int__(self):
+       return 1 if self.handle else 0
+
+  def __long__(self):
+       return 1 if self.handle else 0
+
+  def __nonzero__(self):
+       return True if self.handle else False
+
+  def __next(self):
+      if self.isarray:
+          return self.handle.__next()
+      raise TypeError, "iteration over non-sequence"
+
+  def __size(self):
+      if self.isarray:         
+          return self.handle.__size()
+      raise TypeError, "iteration over non-sequence"
+
+  def __len__(self):
+      if self.isarray:
+          return self.handle.__len__()
+      raise TypeError, "iteration over non-sequence"
+
+  def __getitem__(self, index):
+      if self.isarray:
+          return Boolean(self.mgr, self.handle[index])
+      raise TypeError, "iteration over non-sequence"       
+
 class UnsignedInt:
   def __init__(self, mgr, handle, isarray = False):
        self.handle = handle
+       self.mgr = mgr
        self.isarray = isarray
  
@@ -558,22 +651,25 @@
        return int(self.handle)
 
-  def __next(self):
-      if self.isarray:
-          return self.handle.__next()
-      raise TypeError, "iteration over non-sequence"
-
-  def __size(self):
-      if self.isarray:         
-          return self.handle.__size()
-      raise TypeError, "iteration over non-sequence"
-
-  def __len__(self):
-      if self.isarray:
-          return self.handle.__len__()
-      raise TypeError, "iteration over non-sequence"
-
-  def __getitem__(self, index):
-      if self.isarray:
-          return UnsignedInt(self.handle[index])
+  def __long__(self):
+       return long(self.handle)
+
+  def __next(self):
+      if self.isarray:
+          return self.handle.__next()
+      raise TypeError, "iteration over non-sequence"
+
+  def __size(self):
+      if self.isarray:         
+          return self.handle.__size()
+      raise TypeError, "iteration over non-sequence"
+
+  def __len__(self):
+      if self.isarray:
+          return self.handle.__len__()
+      raise TypeError, "iteration over non-sequence"
+
+  def __getitem__(self, index):
+      if self.isarray:
+          return UnsignedInt(self.mgr, self.handle[index])
       raise TypeError, "iteration over non-sequence"       
 
@@ -582,24 +678,25 @@
   def __init__(self, mgr, handle, isarray = False):
        self.handle = handle
-       self.isarray = isarray
-
-  def __next(self):
-      if self.isarray:
-          return self.handle.__next()
-      raise TypeError, "iteration over non-sequence"
-
-  def __size(self):
-      if self.isarray:         
-          return self.handle.__size()
-      raise TypeError, "iteration over non-sequence"
-
-  def __len__(self):
-      if self.isarray:
-          return self.handle.__len__()
-      raise TypeError, "iteration over non-sequence"
-
-  def __getitem__(self, index):
-      if self.isarray:
-          return Int(self.handle[index])
+       self.mgr = mgr
+       self.isarray = isarray
+
+  def __next(self):
+      if self.isarray:
+          return self.handle.__next()
+      raise TypeError, "iteration over non-sequence"
+
+  def __size(self):
+      if self.isarray:         
+          return self.handle.__size()
+      raise TypeError, "iteration over non-sequence"
+
+  def __len__(self):
+      if self.isarray:
+          return self.handle.__len__()
+      raise TypeError, "iteration over non-sequence"
+
+  def __getitem__(self, index):
+      if self.isarray:
+          return Int(self.mgr, self.handle[index])
       raise TypeError, "iteration over non-sequence"       
  
@@ -610,7 +707,11 @@
        return int(self.handle)
 
+  def __long__(self):
+       return long(self.handle)
+
 class UnsignedShort:
   def __init__(self, mgr, handle, isarray = False):
        self.handle = handle
+       self.mgr = mgr
        self.isarray = isarray
  
@@ -621,7 +722,32 @@
        return int(self.handle)
 
+  def __long__(self):
+       return long(self.handle)
+
+  def __next(self):
+      if self.isarray:
+          return self.handle.__next()
+      raise TypeError, "iteration over non-sequence"
+
+  def __size(self):
+      if self.isarray:         
+          return self.handle.__size()
+      raise TypeError, "iteration over non-sequence"
+
+  def __len__(self):
+      if self.isarray:
+          return self.handle.__len__()
+      raise TypeError, "iteration over non-sequence"
+
+  def __getitem__(self, index):
+      if self.isarray:
+          return UnsignedShort(self.mgr, self.handle[index])
+      raise TypeError, "iteration over non-sequence"       
+
 class Short:
   def __init__(self, mgr, handle, isarray = False):
        self.handle = handle
+       self.mgr = mgr
+       self.isarray = isarray
  
   def __str__(self):
@@ -631,7 +757,32 @@
        return int(self.handle)
 
+  def __long__(self):
+       return long(self.handle)
+
+  def __next(self):
+      if self.isarray:
+          return self.handle.__next()
+      raise TypeError, "iteration over non-sequence"
+
+  def __size(self):
+      if self.isarray:         
+          return self.handle.__size()
+      raise TypeError, "iteration over non-sequence"
+
+  def __len__(self):
+      if self.isarray:
+          return self.handle.__len__()
+      raise TypeError, "iteration over non-sequence"
+
+  def __getitem__(self, index):
+      if self.isarray:
+          return Short(self.mgr, self.handle[index])
+      raise TypeError, "iteration over non-sequence"
+
 class UnsignedLong:
   def __init__(self, mgr, handle, isarray = False):
        self.handle = handle
+       self.mgr = mgr
+       self.isarray = isarray
  
   def __str__(self):
@@ -641,8 +792,33 @@
        return int(self.handle)
 
+  def __long__(self):
+       return long(self.handle)
+
+  def __next(self):
+      if self.isarray:
+          return self.handle.__next()
+      raise TypeError, "iteration over non-sequence"
+
+  def __size(self):
+      if self.isarray:         
+          return self.handle.__size()
+      raise TypeError, "iteration over non-sequence"
+
+  def __len__(self):
+      if self.isarray:
+          return self.handle.__len__()
+      raise TypeError, "iteration over non-sequence"
+
+  def __getitem__(self, index):
+      if self.isarray:
+          return UnsignedLong(self.mgr, self.handle[index])
+      raise TypeError, "iteration over non-sequence"
+
 class Long:
   def __init__(self, mgr, handle, isarray = False):
        self.handle = handle
- 
+       self.mgr = mgr
+       self.isarray = isarray
+
   def __str__(self):
        return str(self.handle)
@@ -651,7 +827,32 @@
        return int(self.handle)
 
+  def __long__(self):
+       return int(self.handle)
+
+  def __next(self):
+      if self.isarray:
+          return self.handle.__next()
+      raise TypeError, "iteration over non-sequence"
+
+  def __size(self):
+      if self.isarray:         
+          return self.handle.__size()
+      raise TypeError, "iteration over non-sequence"
+
+  def __len__(self):
+      if self.isarray:
+          return self.handle.__len__()
+      raise TypeError, "iteration over non-sequence"
+
+  def __getitem__(self, index):
+      if self.isarray:
+          return Long(self.mgr, self.handle[index])
+      raise TypeError, "iteration over non-sequence"
+
 class Double:
   def __init__(self, mgr, handle, isarray = False):
        self.handle = handle
+       self.mgr = mgr
+       self.isarray = isarray
  
   def __str__(self):
@@ -661,8 +862,33 @@
        return int(self.handle)
 
+  def __float__(self):
+       return float(self.handle)
+
+  def __next(self):
+      if self.isarray:
+          return self.handle.__next()
+      raise TypeError, "iteration over non-sequence"
+
+  def __size(self):
+      if self.isarray:         
+          return self.handle.__size()
+      raise TypeError, "iteration over non-sequence"
+
+  def __len__(self):
+      if self.isarray:
+          return self.handle.__len__()
+      raise TypeError, "iteration over non-sequence"
+
+  def __getitem__(self, index):
+      if self.isarray:
+          return Double(self.mgr, self.handle[index])
+      raise TypeError, "iteration over non-sequence"
+
 class Float:
   def __init__(self, mgr, handle, isarray = False):
        self.handle = handle
-       
+       self.mgr = mgr       
+       self.isarray = isarray
+
   def __str__(self):
        return str(self.handle)
@@ -671,4 +897,26 @@
        return int(self.handle)
 
+  def __float__(self):
+       return float(self.handle)
+
+  def __next(self):
+      if self.isarray:
+          return self.handle.__next()
+      raise TypeError, "iteration over non-sequence"
+
+  def __size(self):
+      if self.isarray:         
+          return self.handle.__size()
+      raise TypeError, "iteration over non-sequence"
+
+  def __len__(self):
+      if self.isarray:
+          return self.handle.__len__()
+      raise TypeError, "iteration over non-sequence"
+
+  def __getitem__(self, index):
+      if self.isarray:
+          return Float(self.mgr, self.handle[index])
+      raise TypeError, "iteration over non-sequence"
 
 class IUnknown:
@@ -677,4 +925,7 @@
        self.mgr = mgr
        self.isarray = isarray
+
+  def __nonzero__(self):
+       return True if self.handle != "" else False
 
   def __next(self):
@@ -700,4 +951,11 @@
   def __str__(self):
        return str(self.handle)
+
+  def __getattr__(self,attr):
+       if self.__class__.__dict__.get(attr) != None:
+           return self.__class__.__dict__.get(attr)
+       if self.__dict__.get(attr) != None:
+           return self.__dict__.get(attr)
+       raise AttributeError
 
 </xsl:text>
