diff --git a/src/vmfest/virtualbox/conditions.clj b/src/vmfest/virtualbox/conditions.clj index 99d2545..bebfc0c 100644 --- a/src/vmfest/virtualbox/conditions.clj +++ b/src/vmfest/virtualbox/conditions.clj @@ -5,7 +5,8 @@ InvalidObjectFault InvalidObjectFaultMsg RuntimeFault - RuntimeFaultMsg])) + RuntimeFaultMsg] + [org.virtualbox_4_0 VBoxException])) (defn unsigned-int-to-long [ui] (bit-and (long ui) 0xffffffff)) @@ -39,17 +40,26 @@ (extend-protocol fault java.lang.Exception (as-map [this] - (log/warn (format "Processing exception %s as a java.lang.Exception. Cause %s" (class this) (.getCause this))) + (log/warn + (format "Processing exception %s as a java.lang.Exception. Cause %s" + (class this) + (.getCause this))) {:original-message (.getMessage this) :cause (.getCause this) - :type :exception - }) + :type :exception}) java.net.ConnectException (as-map [this] {:type :connection-error}) com.sun.xml.internal.ws.client.ClientTransportException (as-map [this] {:type :connection-error}) + VBoxException + (as-map [this] + (let [message (.getMessage this) + wrapped (.getWrapped this)] + (merge + (when wrapped (as-map wrapped)) + {:message message}))) RuntimeFaultMsg (as-map [this] (let [message (.getMessage this) @@ -57,7 +67,9 @@ (catch Exception e)) ;; runtime fault interface-id (when info (.getInterfaceID info)) component (when info (.getComponent info)) - result-code (when info (unsigned-int-to-long (int (.getResultCode info)))) ;; originally an unsigned int + result-code (when info + (unsigned-int-to-long + (int (.getResultCode info)))) text (when info (.getText info))] {:type :vbox-runtime :original-message message @@ -92,7 +104,7 @@ (defn wrap-vbox-runtime [e error-condition-map & default-condition-map] (let [condition (condition-from-webservice-exception e) error-type (:original-error-type condition) - condition-map (error-type error-condition-map) ;; the map corresponding to the error type + condition-map (error-type error-condition-map) merged-condition (merge default-condition-map condition-map)] (log-and-raise e merged-condition))) diff --git a/src/vmfest/virtualbox/guest_os_type.clj b/src/vmfest/virtualbox/guest_os_type.clj index 2fb71e1..09afd06 100644 --- a/src/vmfest/virtualbox/guest_os_type.clj +++ b/src/vmfest/virtualbox/guest_os_type.clj @@ -10,23 +10,27 @@ :family-description (.getFamilyDescription o) :id (.getId o) :description (.getDescription o) - :64-bit? (.isIs64Bit o) - :recommended-io-apic? (.isRecommendedIOAPIC o) - :recommended-virt-ex? (.isRecommendedVirtEx o) + :64-bit? (.getIs64Bit o) + :recommended-io-apic? (.getRecommendedIOAPIC o) + :recommended-virt-ex? (.getRecommendedVirtEx o) :recommended-ram (.getRecommendedRAM o) :recommended-vram (.getRecommendedVRAM o) :recommended-hdd (.getRecommendedHDD o) :adapter-type (.getAdapterType o) ;todo: pull the object - :recommended-pae? (.isRecommendedPae o) - :recommended-dvd-storage-controller (.getRecommendedDvdStorageController o) ;todo: pull object - :recommended-dvd-storage-bus (.getRecommendedDvdStorageBus o) ;todo: pull object - :recommended-hd-storage-controller (.getRecommendedHdStorageController o) ;todo: pull object - :recommended-hd-storage-bus (.getRecommendedHdStorageBus o) ;todo: pull object + :recommended-pae? (.getRecommendedPae o) + :recommended-dvd-storage-controller + (.getRecommendedDvdStorageController o) ;todo: pull object + :recommended-dvd-storage-bus + (.getRecommendedDvdStorageBus o) ;todo: pull object + :recommended-hd-storage-controller + (.getRecommendedHdStorageController o) ;todo: pull object + :recommended-hd-storage-bus + (.getRecommendedHdStorageBus o) ;todo: pull object :recommended-firmware (.getRecommendedFirmware o) ;todo: pull object - :recommended-usb-hid? (.isRecommendedUsbHid o) - :recommended-hpet? (.isRecommendedHpet o) - :recommended-usb-tablet? (.isRecommendedUsbTablet o) - :recommended-rtc-use-utc? (.isRecommendedRtcUseUtc o) + :recommended-usb-hid? (.getRecommendedUsbHid o) + :recommended-hpet? (.getRecommendedHpet o) + :recommended-usb-tablet? (.getRecommendedUsbTablet o) + :recommended-rtc-use-utc? (.getRecommendedRtcUseUtc o) }) diff --git a/src/vmfest/virtualbox/machine.clj b/src/vmfest/virtualbox/machine.clj index bb5dc59..3c7bbfc 100644 --- a/src/vmfest/virtualbox/machine.clj +++ b/src/vmfest/virtualbox/machine.clj @@ -6,7 +6,7 @@ [vmfest.virtualbox.model :as model] [vmfest.virtualbox.enums :as enums] [vmfest.virtualbox.session :as session]) - (:import [org.virtualbox_4_0 IMachine IConsole] + (:import [org.virtualbox_4_0 IMachine IConsole VBoxException] [vmfest.virtualbox.model GuestOsType Machine])) (defn map-from-IMachine @@ -30,22 +30,26 @@ :accelerate-2d-video-enabled? (.getAccelerate2DVideoEnabled vb-m) :monitor-count (.getMonitorCount vb-m) :bios-settings (.getBIOSSettings vb-m) ;todo: get object - :firmware-type (enums/firmware-type-to-key (.getFirmwareType vb-m)) ;todo: get object - :pointing-hid-type (enums/pointing-hid-type-to-key (.getPointingHidType vb-m)) ;todo: get object - :keyboard-hid-type (enums/keyboard-hid-type-to-key (.getKeyboardHidType vb-m)) ;todo: get object + :firmware-type (enums/firmware-type-to-key + (.getFirmwareType vb-m)) ;todo: get object + :pointing-hid-type (enums/pointing-hid-type-to-key + (.getPointingHidType vb-m)) ;todo: get object + :keyboard-hid-type (enums/keyboard-hid-type-to-key + (.getKeyboardHidType vb-m)) ;todo: get object :hpet-enabled (.getHpetEnabled vb-m) :snapshot-folder (.getSnapshotFolder vb-m) - :vrdp-server (.getVRDPServer vb-m) ;todo: get object + :vrde-server (.getVRDEServer vb-m) ;todo: get object :medium-attachments (.getMediumAttachments vb-m) ;todo: get - ;objects + ;objects :usb-controller (.getUSBController vb-m) ;todo: get object :audio-adapter (.getAudioAdapter vb-m) ; todo: get object :storage-controllers (.getStorageControllers vb-m) ;todo: get - ;objects + ;objects :settings-file-path (.getSettingsFilePath vb-m) :settings-modified? (try (.getSettingsModified vb-m) (catch Exception e (comment "Do nothing"))) - :session-state (enums/session-state-to-key (.getSessionState vb-m)) ;todo: get object + :session-state (enums/session-state-to-key + (.getSessionState vb-m)) ;todo: get object :session-type (enums/session-type-to-key (.getSessionType vb-m)) :session-pid (.getSessionPid vb-m) :state (enums/machine-state-to-key (.getState vb-m)) ;todo: get object @@ -56,8 +60,10 @@ :snapshot-count (.getSnapshotCount vb-m) :current-state-modified? (.getCurrentStateModified vb-m) :shared-folders (.getSharedFolders vb-m) ;todo: get objects - :clipboard-mode (enums/clipboard-mode-to-key (.getClipboardMode vb-m)) ;todo: get object - :guest-property-notification-patterns (.getGuestPropertyNotificationPatterns vb-m) + :clipboard-mode (enums/clipboard-mode-to-key + (.getClipboardMode vb-m)) ;todo: get object + :guest-property-notification-patterns + (.getGuestPropertyNotificationPatterns vb-m) :teleporter-enabled? (.getTeleporterEnabled vb-m) :teleporter-port (.getTeleporterPort vb-m) :teleporter-address (.getTeleporterAddress vb-m) @@ -65,7 +71,7 @@ :rtc-use-utc? (.getRTCUseUTC vb-m) :io-cache-enabled? (.getIoCacheEnabled vb-m) :io-cache-size (.getIoCacheSize vb-m) - :io-bandwidth-max (.getIoBandwidthMax vb-m) + ; :io-bandwidth-max (.getIoBandwidthMax vb-m) }) (def setters @@ -90,29 +96,35 @@ :snapshot-folder #(.setSnapshotFolder %2 %1) :clipboard-mode #(.setClipboardMode %2 %1) :teleporter-enabled? #(.setTeleporterEnabled %2 %1) - :guest-property-notification-patters #(.setGuestPropertyNotificationPatterns %2 %1) + :guest-property-notification-patters + #(.setGuestPropertyNotificationPatterns %2 %1) :teleporter-port #(.setTeleporterPort %2 %1) :teleporter-address #(.setTeleporterAddress %2 %1) :teleporter-password #(.setTeleporterAddress %2 %1) :rtc-use-utc? #(.setRTCUseUTC %2 %1) :io-cache-enabled? #(.setIoCacheEnabled %2 %1) :io-cache-size #(.setIoCacheSize %2 (long %1)) - :io-bandwidth-max #(.setIoBandwidthMax %2 (long %1))}) + ;; :io-bandwidth-max #(.setIoBandwidthMax %2 (long %1)) + }) (defn set-map [m value-map] (let [get-setter (fn [k] (k setters)) - set-fn (fn [[k v]] - (let [setter (get-setter k)] - (if setter - (setter v m) - (log/error (str "IMachine has no setter defined for " k)))))] + set-fn (fn [[k v]] + (let [setter (get-setter k)] + (if setter + (setter v m) + (log/error + (str "IMachine has no setter defined for " k)))))] (doall (map set-fn value-map)))) (extend-type vmfest.virtualbox.model.Machine model/vbox-object (soak [this vbox] - (virtualbox/find-vb-m vbox (:id this))) + (let [vb-m (virtualbox/find-vb-m vbox (:id this))] + (log/trace + (format "soak: soaking %s into %s" this vb-m)) + vb-m)) (as-map [this] (session/with-vbox (:server this) [_ vbox] (try @@ -120,6 +132,8 @@ (merge this (map-from-IMachine machine (:server this)))) (catch Exception e + (log/error (format "as-map: Machine %s not found. Reason" + (:id this)) e) (merge this {:error "Machine not found" :exception e})))))) @@ -134,77 +148,108 @@ "Starts the virtual machine represented by 'machine'. Optional parameters are: - :session-type 'gui', 'vrdp' or 'sdl'. Default is 'gui' - :env environment as String to be passed to the machine at startup. See IVirtualbox::openRemoteSession for more details" + :session-type 'gui', 'headless' or 'sdl'. Default is 'gui' + :env environment as String to be passed to the machine at startup. +See IVirtualbox::openRemoteSession for more details" [mgr vbox machine-id & opt-kv] (let [opts (apply hash-map opt-kv) - session (.getSessionObject mgr vbox) + session (.getSessionObject mgr) session-type (or (:session-type opts) "gui") env (or (:env opts) "DISPLAY:0.0")] - (try (let [progress (.openRemoteSession vbox session machine-id session-type env)] - (log/debug (str "Starting session for VM " machine-id "...")) + (try (let [vb-m (virtualbox/find-vb-m vbox machine-id) + progress + (.launchVMProcess vb-m session session-type env) + #_(.openRemoteSession vbox session machine-id session-type env)] + (log/debug (str "start: Starting session for VM " machine-id "...")) (.waitForCompletion progress 30000) (let [result-code (.getResultCode progress)] - (if (zero? result-code) - nil - true))) - (catch javax.xml.ws.WebServiceException e + (log/debug (format "start: VM %s started with result code %s" + machine-id + result-code)) + result-code)) + (catch VBoxException e (conditions/wrap-vbox-runtime e - {:E_UNEXPECTED {:message "Virtual Machine not registered."} - :E_INVALIDARG {:message (format "Invalid session type '%s'" session-type)} - :VBOX_E_OBJECT_NOT_FOUND {:message (format "No machine matching id '%s' found." machine-id)} - :VBOX_E_INVALID_OBJECT_STATE {:message "Session already open or opening."} - :VBOX_E_IPTR_ERROR {:message "Launching process for machine failed."} - :VBOX_E_VM_ERROR {:message "Failed to assign machine to session."}})) + {:E_UNEXPECTED + {:message "Virtual Machine not registered."} + :E_INVALIDARG + {:message (format "Invalid session type '%s'" session-type)} + :VBOX_E_OBJECT_NOT_FOUND + {:message (format "No machine matching id '%s' found." machine-id)} + :VBOX_E_INVALID_OBJECT_STATE + {:message "Session already open or opening."} + :VBOX_E_IPTR_ERROR + {:message "Launching process for machine failed."} + :VBOX_E_VM_ERROR + {:message "Failed to assign machine to session."}})) (catch Exception e - (conditions/log-and-raise e {:log-level :error - :message "An error occurred while starting machine"}))))) + (log/error "Cannot start machine" e) + (conditions/log-and-raise + e + {:log-level :error + :message "An error occurred while starting machine"}))))) (defn save-settings [machine] (try (.saveSettings machine) - (catch javax.xml.ws.WebServiceException e + (catch VBoxException e (conditions/wrap-vbox-runtime e - {:VBOX_E_FILE_ERROR {:message "Settings file not accessible while trying to save them"} - :VBOX_E_XML_ERROR {:message "Cannot parse settings XML file"} - :E_ACCESSDENIED {:message "Saving of the settings has been refused"}})) + {:VBOX_E_FILE_ERROR + {:message "Settings file not accessible while trying to save them"} + :VBOX_E_XML_ERROR + {:message "Cannot parse settings XML file"} + :E_ACCESSDENIED + {:message "Saving of the settings has been refused"}})) (catch Exception e - (conditions/log-and-raise e {:log-level :error - :message "An error occurred while saving a machine"})))) + (conditions/log-and-raise + e + {:log-level :error + :message "An error occurred while saving a machine"})))) (defn add-storage-controller [m name bus-type] (let [bus (enums/key-to-storage-bus bus-type)] - (when-not bus (conditions/log-and-raise (RuntimeException.) - {:log-level :error - :message (str "Bus type not found " bus-type)})) + (when-not bus (conditions/log-and-raise + (RuntimeException.) + {:log-level :error + :message (str "Bus type not found " bus-type)})) (try (.addStorageController m name bus) - (catch javax.xml.ws.WebServiceException e + (catch VBoxException e (conditions/wrap-vbox-runtime e - {:VBOX_E_OBJECT_IN_USE {:message "A storage controller with given name exists already."} - :E_INVALIDARG {:message "Invalid controllerType."}}))))) + {:VBOX_E_OBJECT_IN_USE + {:message "A storage controller with given name exists already."} + :E_INVALIDARG + {:message "Invalid controllerType."}}))))) (defn attach-device [m name controller-port device device-type uuid] (let [type (enums/key-to-device-type device-type)] - (when-not type (conditions/log-and-raise (RuntimeException.) - {:log-level :error - :message (str "Device Type not found " device-type)})) + (when-not type (conditions/log-and-raise + (RuntimeException.) + {:log-level :error + :message (str "Device Type not found " device-type)})) (try (.attachDevice m name controller-port device type uuid) - (catch javax.xml.ws.WebServiceException e + (catch VBoxException e (conditions/wrap-vbox-runtime e - {:E_INVALIDARG {:message "SATA device, SATA port, IDE port or IDE slot out of range."} - :VBOX_E_INVALID_OBJECT_STATE {:message "Attempt to attach medium to an unregistered virtual machine."} - :VBOX_E_INVALID_VM_STATE {:message "Invalid machine state."} - :VBOX_E_OBJECT_IN_USE {:message "Hard disk already attached to this or another virtual machine."}}))))) + {:E_INVALIDARG + {:message + "SATA device, SATA port, IDE port or IDE slot out of range."} + :VBOX_E_INVALID_OBJECT_STATE + {:message + "Attempt to attach medium to an unregistered virtual machine."} + :VBOX_E_INVALID_VM_STATE + {:message "Invalid machine state."} + :VBOX_E_OBJECT_IN_USE + {:message + "Hard disk already attached to this or another virtual machine."}} + ))))) (defn set-network-adapter [m port type interface] (try - (when-let [adapter (.getNetworkAdapter m (long port))] + (when-let [adapter (.getNetworkAdapter m (long port))] (condp = type :bridged (do (.attachToBridgedInterface adapter) ;; todo: get this from IHost.getNetworkInterfaces @@ -214,46 +259,58 @@ Optional parameters are: :host-only (.attachToHostOnlyInterface adapter) :vde (.attachToVDE adapter))))) -(defn stop +(defn stop [^IConsole c] (try + (log/trace (format "stop: machine-id: %s" + (.getId (.getMachine c)))) (.powerButton c) - (catch javax.xml.ws.WebServiceException e + (catch VBoxException e + (log/debug "stop: Caught exception" e) (conditions/wrap-vbox-runtime e - {:VBOX_E_INVALID_VM_STATE {:message "Virtual machine not in Running state."} - :VBOX_E_PDM_ERROR {:message "Controlled power off failed."}})))) + {:VBOX_E_INVALID_VM_STATE + {:message "Virtual machine not in Running state."} + :VBOX_E_PDM_ERROR + {:message "Controlled power off failed."}})))) (defn pause [^IConsole c] (try (.pause c) - (catch javax.xml.ws.WebServiceException e + (catch VBoxException e (conditions/wrap-vbox-runtime e - {:VBOX_E_INVALID_VM_STATE {:message "Virtual machine not in Running state."} - :VBOX_E_VM_ERROR {:message "Virtual machine error in suspend operation."}})))) + {:VBOX_E_INVALID_VM_STATE + {:message "Virtual machine not in Running state."} + :VBOX_E_VM_ERROR + {:message "Virtual machine error in suspend operation."}})))) (defn resume [^IConsole c] (try (.resume c) - (catch javax.xml.ws.WebServiceException e + (catch VBoxException e (conditions/wrap-vbox-runtime e - {:VBOX_E_INVALID_VM_STATE {:message "Virtual machine not in Paused state."} - :VBOX_E_VM_ERROR {:message "Virtual machine error in resume operation."}})))) + {:VBOX_E_INVALID_VM_STATE + {:message "Virtual machine not in Paused state."} + :VBOX_E_VM_ERROR + {:message "Virtual machine error in resume operation."}})))) (defn power-down [^Machine c] - (try - (.powerDown c) - (catch javax.xml.ws.WebServiceException e + (try + (let [progress (.powerDown c)] + (.waitForCompletion progress 30000)) + (catch VBoxException e (conditions/wrap-vbox-runtime e {:VBOX_E_INVALID_VM_STATE - {:message "Virtual machine must be Running, Paused or Stuck to be powered down."}})))) + {:message + "Virtual machine must be Running, Paused or Stuck to be powered + down."}})))) (defn detach-device [vb-m medium-attachment] (println medium-attachment) @@ -262,7 +319,9 @@ Optional parameters are: controller-port (.getPort medium-attachment) name (.getController medium-attachment)] (println "medium:" (.getMedium medium-attachment)) - (println "medium name:" name "controller-port:" controller-port "device:" device) + (println "medium name:" name + "controller-port:" controller-port + "device:" device) (println "controller:" (.getController medium-attachment)) (try (.detachDevice vb-m name controller-port device) @@ -282,7 +341,7 @@ Optional parameters are: (defn get-guest-property [^IConsole console key] (try (.getGuestPropertyValue (.getMachine console) key) - (catch javax.xml.ws.WebServiceException e + (catch VBoxException e (conditions/wrap-vbox-runtime e {:VBOX_E_INVALID_VM_STATE {:message "Machine session is not open."}})))) @@ -290,18 +349,21 @@ Optional parameters are: (defn set-guest-property [^IMachine machine key value] (try (.setGuestPropertyValue machine key value) - (catch javax.xml.ws.WebServiceException e + (catch VBoxException e (conditions/wrap-vbox-runtime e {:E_ACCESSDENIED {:message "Property cannot be changed."} - :VBOX_E_INVALID_VM_STATE {:message "Virtual machine is not mutable or session not open."} - :VBOX_E_INVALID_OBJECT_STATE {:message "Cannot set transient property when machine not running."}})))) + :VBOX_E_INVALID_VM_STATE + {:message "Virtual machine is not mutable or session not open."} + :VBOX_E_INVALID_OBJECT_STATE + {:message + "Cannot set transient property when machine not running."}})))) (defn set-extra-data [^IMachine m key value] (try (.setExtraData m key value) (.saveSettings m) - (catch javax.xml.ws.WebServiceException e + (catch VBoxException e (conditions/wrap-vbox-runtime e {:VBOX_E_FILE_ERROR {:message "Sttings file not accessible."} @@ -310,7 +372,7 @@ Optional parameters are: (defn get-extra-data [^IMachine m key] (try (.getExtraData m key) - (catch javax.xml.ws.WebServiceException e + (catch VBoxException e (conditions/wrap-vbox-runtime e {:VBOX_E_FILE_ERROR {:message "Settings file not accessible."} diff --git a/src/vmfest/virtualbox/model.clj b/src/vmfest/virtualbox/model.clj index 3db15ee..53e8b6e 100644 --- a/src/vmfest/virtualbox/model.clj +++ b/src/vmfest/virtualbox/model.clj @@ -9,7 +9,7 @@ (defprotocol vbox-object (as-map [this]) - (soak [this ^IVirtualBox vbox])) + (soak [this vbox])) (defprotocol vbox-remote-object (dry [this server])) diff --git a/src/vmfest/virtualbox/session.clj b/src/vmfest/virtualbox/session.clj index ad65fa9..c3b1881 100644 --- a/src/vmfest/virtualbox/session.clj +++ b/src/vmfest/virtualbox/session.clj @@ -27,7 +27,7 @@ If no home is passed, it will use the default create-session-manager: (String) -> VirtualBoxManager" [& [home]] - (log/debug (str "Creating session manager for home=" (or home "default"))) + (log/trace (str "Creating session manager for home=" (or home "default"))) (VirtualBoxManager/createInstance home)) ;; Before we can interact with the server we need to create a Virtual @@ -42,7 +42,7 @@ VirtualBoxManager object plus the credentials or by a Server object. create-vbox: Session -> IVirtualBox" ([^VirtualBoxManager mgr url username password] - (log/debug + (log/trace (format "creating new vbox with a logon for url=%s and username=%s" url @@ -120,8 +120,7 @@ with a virtualbox. {:log-level :error :message (format - "Called a method that is not available with a direct -session in '%s'" + "Called a method that is not available with a direct session in '%s'" '~body) :type :invalid-method})) (finally (.unlockMachine ~session)))))) diff --git a/src/vmfest/virtualbox/virtualbox.clj b/src/vmfest/virtualbox/virtualbox.clj index 4c3d58d..49a3928 100644 --- a/src/vmfest/virtualbox/virtualbox.clj +++ b/src/vmfest/virtualbox/virtualbox.clj @@ -13,9 +13,14 @@ (defn find-vb-m ([vbox id-or-name] (try - (.findMachine vbox id-or-name) + (log/trace (format "find-vb-m: looking for machine '%s'" id-or-name)) + (let [vb-m (.findMachine vbox id-or-name)] + (log/debug (format "find-vb-m: found machine '%s': %s" + id-or-name + vb-m)) + vb-m) (catch Exception e - (log/warn (format "Machine identified by '%s' not found." + (log/warn (format "find-vb-m: Machine identified by '%s' not found." id-or-name)))))) (defn find-hard-disk diff --git a/test/vmfest/virtualbox/session_test.clj b/test/vmfest/virtualbox/session_test.clj index 0fc6ed7..0157fc3 100644 --- a/test/vmfest/virtualbox/session_test.clj +++ b/test/vmfest/virtualbox/session_test.clj @@ -1,5 +1,5 @@ (ns vmfest.virtualbox.session-test - (:use vmfest.virtualbox.session :reload-all) + (:use vmfest.virtualbox.session :reload) (:use [vmfest.virtualbox.virtualbox :only (find-vb-m)]) (:use clojure.test clojure.contrib.condition) @@ -90,7 +90,7 @@ (deftest ^{:integration true} shared-sessions-can-control-machines - ;; todo + ;(testing "I") ) (deftest ^{:integration true} diff --git a/test/vmfest/virtualbox/virtualbox_test.clj b/test/vmfest/virtualbox/virtualbox_test.clj index 2721851..c22efde 100644 --- a/test/vmfest/virtualbox/virtualbox_test.clj +++ b/test/vmfest/virtualbox/virtualbox_test.clj @@ -1,5 +1,5 @@ (ns vmfest.virtualbox.virtualbox-test - (:use vmfest.virtualbox.virtualbox :reload-all) + (:use vmfest.virtualbox.virtualbox :reload) (:use clojure.test vmfest.virtualbox.session vmfest.virtualbox.session-test)