Anonymous avatar Anonymous committed 6a6a2b5

Add error reporting to existing API.

Signed-off-by: Austin Seipp <aseipp@pobox.com>;

Comments (0)

Files changed (4)

 
 VixHandle
 hs_vix_connect(const char* host, const char* user, const char* pass, int port,
-	       VixServiceProvider conntype)
+	       VixServiceProvider conntype, VixError* errOut)
 {
-  VixError err;
-  
+  VixError err = VIX_OK;
+
   VixHandle jobHandle  = VIX_INVALID_HANDLE;
   VixHandle hostHandle = VIX_INVALID_HANDLE;
 
 		    &hostHandle,
 		    VIX_PROPERTY_NONE);
   if (VIX_FAILED(err)) {
+    *errOut = err;
     goto abort;
   }
 
+  *errOut = VIX_OK;
   Vix_ReleaseHandle(jobHandle);
   return hostHandle;
 
 
 
 VixHandle
-hs_vix_vm_open(VixHandle host, const char* vmxpath)
+hs_vix_vm_open(VixHandle host, const char* vmxpath, VixError* errOut)
 {
-  VixError err;
+  VixError err = VIX_OK;
   VixHandle jobHandle = VIX_INVALID_HANDLE;
   VixHandle vmHandle  = VIX_INVALID_HANDLE;
 
 		    &vmHandle,
 		    VIX_PROPERTY_NONE);
   if (VIX_FAILED(err)) {
+    *errOut = err;
     goto abort;
   }
-
+  
+  *errOut = VIX_OK;
   Vix_ReleaseHandle(jobHandle);
   return vmHandle;
 
 
 
 int
-hs_vix_vm_poweron(VixHandle hdl, VixVMPowerOpOptions poweropts)
+hs_vix_vm_poweron(VixHandle hdl, VixVMPowerOpOptions poweropts,
+		  VixError* errOut)
 {
   int res = 0;
-  VixError err;
+  VixError err = VIX_OK;
   VixHandle job = VIX_INVALID_HANDLE;
 
   job = VixVM_PowerOn(hdl, poweropts, VIX_INVALID_HANDLE, NULL, NULL);
   res = 1; /* Success */
 
  abort:
+  *errOut = err;
   Vix_ReleaseHandle(job);
   return res;
 }
 
 int
-hs_vix_vm_poweroff(VixHandle hdl)
+hs_vix_vm_poweroff(VixHandle hdl, VixError* errOut)
 {
   int res = 0;
   VixError err;
   res = 1; /* Success */
 
  abort:
+  *errOut = err;
   Vix_ReleaseHandle(job);
   return res;
 }
 
 /** Connecting/disconnecting from remote hosts */
 VixHandle hs_vix_connect(const char*, const char*, const char*, int,
-			 VixServiceProvider);
+			 VixServiceProvider, VixError*);
 void      hs_vix_disconnect(VixHandle);
 
 /** Opening/closing VMs */
-VixHandle hs_vix_vm_open(VixHandle, const char*);
+VixHandle hs_vix_vm_open(VixHandle, const char*, VixError*);
 void      hs_vix_vm_close(VixHandle);
 
 /** Powering on/off */
-int hs_vix_vm_poweron(VixHandle, VixVMPowerOpOptions);
-int hs_vix_vm_poweroff(VixHandle);
+int hs_vix_vm_poweron(VixHandle, VixVMPowerOpOptions, VixError*);
+int hs_vix_vm_poweroff(VixHandle, VixError*);
 
 #endif /* __HS_VIX__ */

src/System/VMware/VIX.hs

     ) where
 
 import Data.Maybe (fromMaybe)
+import Control.Applicative
 import Control.Concurrent
 
 import Foreign
 data VMHandle = VMHandle (MVar C_VixHandle)
 
 -- | Connect to a VMWare system to execute commands.
-connect :: ConnInfo -> IO (Maybe HostHandle)
+connect :: ConnInfo -> IO (Either String HostHandle)
 connect VMwareWorkstationLocal
   = connectLocal c_VIX_SERVICEPROVIDER_VMWARE_WORKSTATION
 connect VMwarePlayer
 connect (VMwareServer1 host port user pass)
   = connectRemote c_VIX_SERVICEPROVIDER_VMWARE_PLAYER host port user pass
 
-connectLocal :: C_VixServiceProvider -> IO (Maybe HostHandle)
-connectLocal typ = do
-  hdl <- c_vix_connect nullPtr nullPtr nullPtr (fromIntegral (0 :: Int)) typ
-  if hdl == c_VIX_INVALID_HANDLE then return Nothing
-   else newMVar hdl >>= return . Just . HostHandle
+connectLocal :: C_VixServiceProvider -> IO (Either String HostHandle)
+connectLocal typ = alloca $ \errOut -> do
+  hdl <- c_vix_connect nullPtr nullPtr nullPtr (fromIntegral (0 :: Int)) typ errOut
+  if hdl == c_VIX_INVALID_HANDLE then do
+    (c_VIX_GET_ERROR_MSG <$> peek errOut) >>= return . Left
+   else newMVar hdl >>= return . Right . HostHandle
 
 connectRemote :: C_VixServiceProvider
               -> Hostname -> Maybe Port -> Username -> Password
-              -> IO (Maybe HostHandle)
+              -> IO (Either String HostHandle)
 connectRemote typ host port user pass =
   let hostname = "https://" ++ host ++ ":" ++ show (fromMaybe 443 port) ++ "/sdk"
+      port'    = fromIntegral (0 :: Int) -- The API doesn't use this. wtf
   in withCString hostname $ \chost ->
      withCString user     $ \cuser ->
-     withCString pass     $ \cpass -> do
-       hdl <- c_vix_connect chost cuser cpass (fromIntegral (0 :: Int)) typ
-       if hdl == c_VIX_INVALID_HANDLE then return Nothing
-        else newMVar hdl >>= return . Just . HostHandle
+     withCString pass     $ \cpass ->
+     alloca               $ \errOut -> do
+       hdl <- c_vix_connect chost cuser cpass port' typ errOut
+       if hdl == c_VIX_INVALID_HANDLE then
+         (c_VIX_GET_ERROR_MSG <$> peek errOut) >>= return . Left
+        else newMVar hdl >>= return . Right . HostHandle
 
 -- | Disconnect from a host.
 disconnect :: HostHandle -> IO ()
 
 
 -- | Open a virtual machine
-openVM :: HostHandle -> FilePath -> IO (Maybe VMHandle)
+openVM :: HostHandle -> FilePath -> IO (Either String VMHandle)
 openVM (HostHandle hdl) vmxpath = withMVar hdl $ \hdl_ ->
+  alloca $ \errOut ->
   withCString vmxpath $ \cvmxpath -> do
-    vhdl <- c_vix_vm_open hdl_ cvmxpath
-    if vhdl == c_VIX_INVALID_HANDLE then return Nothing
-     else newMVar vhdl >>= return . Just . VMHandle
+    vhdl <- c_vix_vm_open hdl_ cvmxpath errOut
+    if vhdl == c_VIX_INVALID_HANDLE then 
+      (c_VIX_GET_ERROR_MSG <$> peek errOut) >>= return . Left
+     else newMVar vhdl >>= return . Right . VMHandle
       
 -- | Close a virtual machine.
 closeVM :: VMHandle -> IO ()

src/System/VMware/VIX/FFI.hsc

     ) where
 
 import Data.Int
+import Data.Word
 import Data.Bits ((.&.))
 import Data.Maybe (fromMaybe)
+import Foreign.Ptr
 import Foreign.C.Types
 import Foreign.C.String
 
 type C_VixHandle           = #{type VixHandle}
 type C_VixServiceProvider  = #{type VixServiceProvider}
 type C_VixVMPowerOpOptions = #{type VixVMPowerOpOptions}
+type C_VixError            = #{type VixError}
 
 --
 -- Constants
 c_VIX_INVALID_HANDLE = #{const VIX_INVALID_HANDLE}
 
 
+--
+-- Functions
+--
+
 -- | Lookup a VIX error code and return the error message for it.
-c_VIX_GET_ERROR_MSG :: CInt -> String
+c_VIX_GET_ERROR_MSG :: Integral a => a -> String
 c_VIX_GET_ERROR_MSG x
   = fromMaybe (error "Could not find VIX error code!")
-  $ lookup (c_VIX_GET_ERROR_CODE x) c_VIX_ERROR_CODES
+  $ lookup (c_VIX_GET_ERROR_CODE $ fromIntegral x) c_VIX_ERROR_CODES
 
 -- | Given a returned 'CInt' from a function, representing the VIX
 -- error code, mask out the required bits to match the right case
 
 
 --
--- Functions
+-- FFI Functions
 --
 
 foreign import ccall unsafe "hs_vix_connect"
   c_vix_connect :: CString -> CString -> CString -> CInt ->
-                   C_VixServiceProvider -> IO C_VixHandle
+                   C_VixServiceProvider -> Ptr C_VixError ->
+                   IO C_VixHandle
 
 foreign import ccall unsafe "hs_vix_disconnect"
   c_vix_disconnect :: C_VixHandle -> IO ()
 
 foreign import ccall unsafe "hs_vix_vm_open"
-  c_vix_vm_open :: C_VixHandle -> CString -> IO C_VixHandle
+  c_vix_vm_open :: C_VixHandle -> CString -> Ptr C_VixError ->
+                   IO C_VixHandle
 
 foreign import ccall unsafe "hs_vix_vm_close"
   c_vix_vm_close :: C_VixHandle -> IO ()
 
 foreign import ccall unsafe "hs_vix_vm_poweron"
-  c_vix_vm_poweron :: C_VixHandle -> C_VixVMPowerOpOptions -> IO CInt
+  c_vix_vm_poweron :: C_VixHandle -> C_VixVMPowerOpOptions ->
+                      Ptr C_VixError -> IO CInt
 
 foreign import ccall unsafe "hs_vix_vm_poweroff"
-  c_vix_vm_poweroff :: C_VixHandle -> IO CInt
+  c_vix_vm_poweroff :: C_VixHandle -> Ptr C_VixError -> IO CInt
 
 
 --
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.