Index: /trunk/src/VBox/Frontends/VBoxShell/vboxshell.py
===================================================================
--- /trunk/src/VBox/Frontends/VBoxShell/vboxshell.py	(revision 28605)
+++ /trunk/src/VBox/Frontends/VBoxShell/vboxshell.py	(revision 28606)
@@ -233,5 +233,5 @@
     mgr = ctx['mgr']
     vb = ctx['vb']
-    mach = vb.createMachine(name, kind, base, "")
+    mach = vb.createMachine(name, kind, base, "", False)
     mach.saveSettings()
     print "created machine with UUID",mach.id
@@ -245,13 +245,5 @@
     id = mach.id
     print "removing machine ",mach.name,"with UUID",id
-    session = ctx['global'].openMachineSession(id)
-    try:
-       mach = session.machine
-       for d in ctx['global'].getArray(mach, 'mediumAttachments'):
-          mach.detachDevice(d.controller, d.port, d.device)
-    except:
-       traceback.print_exc()
-    mach.saveSettings()
-    ctx['global'].closeMachineSession(session)
+    cmdClosedVm(ctx, mach, detachVmDevice, ["ALL"])
     mach = vb.unregisterMachine(id)
     if mach:
@@ -502,4 +494,18 @@
     session.close()
 
+
+def cmdClosedVm(ctx,mach,cmd,args=[],save=True):
+    session = ctx['global'].openMachineSession(mach.id)
+    mach = session.machine
+    try:
+         cmd(ctx, mach, args)
+    except Exception, e:
+        print 'failed: ',e
+        if g_verbose:
+            traceback.print_exc()
+    if save:
+         mach.saveSettings()
+    session.close()
+
 def machById(ctx,id):
     mach = None
@@ -556,4 +562,8 @@
     return "<unknown>"
 
+def enumFromString(ctx,enum,str):
+    all = ctx['ifaces'].all_values(enum)
+    return all.get(str, None)
+
 def listCmd(ctx, args):
     for m in getMachines(ctx, True):
@@ -575,4 +585,5 @@
     print " One can use setvar <mach> <var> <value> to change variable, using name in []."
     print "  Name [name]: %s" %(mach.name)
+    print "  Description [description]: %s" %(mach.description)
     print "  ID [n/a]: %s" %(mach.id)
     print "  OS Type [via OSTypeId]: %s" %(os.description)
@@ -618,5 +629,5 @@
         print "  Controllers:"
     for controller in controllers:
-        print "    '%s' %s bus: %d" % (controller.name, asEnumElem(ctx,"StorageControllerType", controller.controllerType), controller.bus)
+        print "    '%s': bus %s type %s" % (controller.name, asEnumElem(ctx,"StorageBus", controller.bus), asEnumElem(ctx,"StorageControllerType", controller.controllerType))
 
     attaches = ctx['global'].getArray(mach, 'mediumAttachments')
@@ -671,7 +682,7 @@
     return 0
 
-def createCmd(ctx, args):
+def createVmCmd(ctx, args):
     if (len(args) < 3 or len(args) > 4):
-        print "usage: create name ostype <basefolder>"
+        print "usage: createvm name ostype <basefolder>"
         return 0
     name = args[1]
@@ -722,5 +733,5 @@
     return 0
 
-def removeCmd(ctx, args):
+def removeVmCmd(ctx, args):
     mach = argsToMach(ctx,args)
     if mach == None:
@@ -801,4 +812,13 @@
     return 0
 
+def portalsettings(ctx,mach,args):
+    enabled = args[0]
+    mach.teleporterEnabled = enabled
+    if enabled:
+        port = args[1]
+        passwd = args[2]
+        mach.teleporterPort = port
+        mach.teleporterPassword = passwd
+
 def openportalCmd(ctx, args):
     if (len(args) < 3):
@@ -814,11 +834,5 @@
         passwd = ""
     if not mach.teleporterEnabled or mach.teleporterPort != port or passwd:
-        session = ctx['global'].openMachineSession(mach.id)
-        mach1 = session.machine
-        mach1.teleporterEnabled = True
-        mach1.teleporterPort = port
-        mach1.teleporterPassword = passwd
-        mach1.saveSettings()
-        session.close()
+        cmdClosedVm(ctx, mach, portalsettings, [True, port, passwd])
     startVm(ctx, mach, "gui")
     return 0
@@ -832,9 +846,5 @@
         return 0
     if mach.teleporterEnabled:
-        session = ctx['global'].openMachineSession(mach.id)
-        mach1 = session.machine
-        mach1.teleporterEnabled = False
-        mach1.saveSettings()
-        session.close()
+        cmdClosedVm(ctx, mach, portalsettings, [False])
     return 0
 
@@ -849,4 +859,14 @@
     return 0
 
+def plugcpu(ctx,mach,args):
+    plug = args[0]
+    cpu = args[1]
+    if plug:
+        print "Adding CPU %d..." %(cpu)
+        mach.hotPlugCPU(cpu)
+    else:
+        print "Removing CPU %d..." %(cpu)
+        mach.hotUnplugCPU(cpu)
+
 def plugcpuCmd(ctx, args):
     if (len(args) < 2):
@@ -858,15 +878,5 @@
     if str(mach.sessionState) != str(ctx['ifaces'].SessionState_Open):
         if mach.CPUHotPlugEnabled:
-            session = ctx['global'].openMachineSession(mach.id)
-            try:
-                mach1 = session.machine
-                cpu = int(args[2])
-                print "Adding CPU %d..." %(cpu)
-                mach1.hotPlugCPU(cpu)
-                mach1.saveSettings()
-            except:
-                session.close()
-                raise
-            session.close()
+            cmdClosedVm(ctx, mach, plugcpu, [True, int(args[2])])
     else:
         cmdExistingVm(ctx, mach, 'plugcpu', args[2])
@@ -882,18 +892,13 @@
     if str(mach.sessionState) != str(ctx['ifaces'].SessionState_Open):
         if mach.CPUHotPlugEnabled:
-            session = ctx['global'].openMachineSession(mach.id)
-            try:
-                mach1 = session.machine
-                cpu = int(args[2])
-                print "Removing CPU %d..." %(cpu)
-                mach1.hotUnplugCPU(cpu)
-                mach1.saveSettings()
-            except:
-                session.close()
-                raise
-            session.close()
+            cmdClosedVm(ctx, mach, plugcpu, [False, int(args[2])])
     else:
         cmdExistingVm(ctx, mach, 'unplugcpu', args[2])
     return 0
+
+def setvar(ctx,mach,args):
+    expr = 'mach.'+args[0]+' = '+args[1]
+    print "Executing",expr
+    exec expr
 
 def setvarCmd(ctx, args):
@@ -904,18 +909,12 @@
     if mach == None:
         return 0
-    session = ctx['global'].openMachineSession(mach.id)
-    mach = session.machine
-    expr = 'mach.'+args[2]+' = '+args[3]
-    print "Executing",expr
-    try:
-        exec expr
-    except Exception, e:
-        print 'failed: ',e
-        if g_verbose:
-            traceback.print_exc()
-    mach.saveSettings()
-    session.close()
-    return 0
-
+    cmdClosedVm(ctx, mach, setvar, args[2:])
+    return 0
+
+def setvmextra(ctx,mach,args):
+    key = args[0]
+    value = args[1]
+    print "%s: setting %s to %s" %(mach.name, key, value)
+    mach.setExtraData(key, value)
 
 def setExtraDataCmd(ctx, args):
@@ -935,9 +934,5 @@
     if mach == None:
         return 0
-    session = ctx['global'].openMachineSession(mach.id)
-    mach = session.machine
-    mach.setExtraData(key, value)
-    mach.saveSettings()
-    session.close()
+    cmdClosedVm(ctx, mach, setvmextra, [key, value])
     return 0
 
@@ -966,5 +961,5 @@
         keys = [ key ]
     for k in keys:
-        printExtraKey(args[1], k, ctx['vb'].getExtraData(k))
+        printExtraKey(args[1], k, obj.getExtraData(k))
 
     return 0
@@ -1537,4 +1532,8 @@
    return 0
 
+def controldevice(ctx,mach,args):
+    [ctr,port,slot,type,id] = args
+    mach.attachDevice(ctr, port, slot,type,id)
+
 def attachHddCmd(ctx,args):
    if (len(args) < 4):
@@ -1554,29 +1553,17 @@
    ctr = args[3]
    (port,slot) = args[4].split(":")
-
-   session = ctx['global'].openMachineSession(mach.id)
-   mach = session.machine
-   try:
-      mach.attachDevice(ctr, port, slot, ctx['global'].constants.DeviceType_HardDisk, hdd.id)
-   except Exception, e:
-      print 'failed: ',e
-   mach.saveSettings()
-   session.close()
+   cmdClosedVm(ctx, mach, lambda ctx,mach,args: mach.attachDevice(ctr, port, slot, ctx['global'].constants.DeviceType_HardDisk,hdd.id))
    return 0
 
+def detachVmDevice(ctx,mach,args):
+    atts = ctx['global'].getArray(mach, 'mediumAttachments')
+    hid = args[0]
+    for a in atts:
+        if a.medium:
+            if hid == "ALL" or a.medium.id == hid:
+                mach.detachDevice(a.controller, a.port, a.device)
+
 def detachMedium(ctx,mid,medium):
-   session = ctx['global'].openMachineSession(mid)
-   mach = session.machine
-   try:
-      atts = ctx['global'].getArray(mach, 'mediumAttachments')
-      hid = medium.id
-      for a in atts:
-         if a.medium and a.medium.id == hid:
-            mach.detachDevice(a.controller, a.port, a.device)
-   except Exception, e:
-      session.close()
-      raise e
-   mach.saveSettings()
-   session.close()
+    cmdClosedVm(ctx, mach, detachVmDevice, [medium.id])
 
 def detachHddCmd(ctx,args):
@@ -1657,5 +1644,4 @@
    return 0
 
-
 def unregisterIsoCmd(ctx,args):
    if (len(args) != 2):
@@ -1712,13 +1698,5 @@
    ctr = args[3]
    (port,slot) = args[4].split(":")
-
-   session = ctx['global'].openMachineSession(mach.id)
-   mach = session.machine
-   try:
-      mach.attachDevice(ctr, port, slot, ctx['global'].constants.DeviceType_DVD, dvd.id)
-   except Exception, e:
-      print 'failed: ',e
-   mach.saveSettings()
-   session.close()
+   cmdClosedVm(ctx, mach, lambda ctx,mach,args: mach.attachDevice(ctr, port, slot, ctx['global'].constants.DeviceType_DVD,dvd.id))
    return 0
 
@@ -1742,5 +1720,4 @@
    return 0
 
-
 def mountIsoCmd(ctx,args):
    if (len(args) < 5):
@@ -1782,4 +1759,47 @@
 
    return 0
+
+def attachCtr(ctx,mach,args):
+    [name, bus, type] = args
+    ctr = mach.addStorageController(name, bus)
+    if type != None:
+        ctr.controllerType = type
+
+def attachCtrCmd(ctx,args):
+   if (len(args) < 4):
+      print "usage: attachCtr vm cname bus <type>"
+      return 0
+
+   if len(args) > 4:
+       type = enumFromString(ctx,'StorageControllerType', args[4])
+       if type == None:
+           print "Controller type %s unknown" %(args[4])
+           return 0
+   else:
+       type = None
+
+   mach = ctx['machById'](args[1])
+   if mach is None:
+        return 0
+   bus = enumFromString(ctx,'StorageBus', args[3])
+   if bus is None:
+       print "Bus type %s unknown" %(args[3])
+       return 0
+   name = args[2]
+   cmdClosedVm(ctx, mach, attachCtr, [name, bus, type])
+   return 0
+
+def detachCtrCmd(ctx,args):
+   if (len(args) < 3):
+      print "usage: detachCtr vm name"
+      return 0
+
+   mach = ctx['machById'](args[1])
+   if mach is None:
+        return 0
+   ctr = args[2]
+   cmdClosedVm(ctx, mach, lambda ctx,mach,args: mach.removeStorageController(ctr))
+   return 0
+
 
 aliases = {'s':'start',
@@ -1794,6 +1814,6 @@
 commands = {'help':['Prints help information', helpCmd, 0],
             'start':['Start virtual machine by name or uuid: start Linux', startCmd, 0],
-            'create':['Create virtual machine', createCmd, 0],
-            'remove':['Remove virtual machine', removeCmd, 0],
+            'createVm':['Create virtual machine: createVm macvm MacOS', createVmCmd, 0],
+            'removeVm':['Remove virtual machine', removeVmCmd, 0],
             'pause':['Pause virtual machine', pauseCmd, 0],
             'resume':['Resume virtual machine', resumeCmd, 0],
@@ -1845,4 +1865,6 @@
             'mountIso': ['Mount CD/DVD to the running VM: mountIso win /os.iso "IDE Controller" 0:1', mountIsoCmd, 0],
             'unmountIso': ['Unmount CD/DVD from running VM: unmountIso win "IDE Controller" 0:1', unmountIsoCmd, 0],
+            'attachCtr': ['Attach storage controller to the VM: attachCtr win Ctr0 IDE ICH6', attachCtrCmd, 0],
+            'detachCtr': ['Detach HDD from the VM: detachCtr win Ctr0', detachCtrCmd, 0],
             'listMediums': ['List mediums known to this VBox instance', listMediumsCmd, 0]
             }
