@@ -18,7 +18,7 @@ import System.Environment.Executable (getExecutablePath)
18import Data.Binary (encode, decode)
18import Data.Binary (encode, decode)
19import Data.Digest.Pure.MD5 (md5, MD5Digest)
19import Data.Digest.Pure.MD5 (md5, MD5Digest)
20import qualified Data.ByteString.Char8 as BSSC (pack)
20import qualified Data.ByteString.Char8 as BSSC (pack)
21−import qualified Data.ByteString.Lazy as BSL (ByteString, readFile, putStr, writeFile)
21+import qualified Data.ByteString.Lazy as BSL (ByteString, readFile, putStr)
22import qualified Data.ByteString.Lazy.Char8 as BSLC (unpack)
22import qualified Data.ByteString.Lazy.Char8 as BSLC (unpack)
23import Data.Typeable (Typeable)
23import Data.Typeable (Typeable)
24import Control.Applicative ((<$>))
24import Control.Applicative ((<$>))
@@ -69,7 +69,7 @@ import Control.Distributed.Process
70import Control.Distributed.Process.Closure
70import Control.Distributed.Process.Closure
71 ( remotable
71 ( remotable
73 , SerializableDict(SerializableDict)
73 , SerializableDict(SerializableDict)
74 , staticConst
74 , staticConst
75 , staticApply
75 , staticApply
@@ -104,11 +104,19 @@ data Backend = Backend {
104 -- | Check the MD5 hash of the remote executable
104 -- | Check the MD5 hash of the remote executable
105 , checkMD5 :: VirtualMachine -> IO Bool
105 , checkMD5 :: VirtualMachine -> IO Bool
106 -- | @runOnVM dict vm port p@ starts a CH node on port 'port' and runs 'p'
106 -- | @runOnVM dict vm port p@ starts a CH node on port 'port' and runs 'p'
107− , callOnVM :: forall a. Serializable a => Static (SerializableDict a) -> VirtualMachine -> String -> Closure (Process a) -> IO a
107+ , callOnVM :: forall a. Serializable a
108+ => Static (SerializableDict a)
111+ -> Closure (Backend -> Process a)
108 -- | Create a new CH node and run the specified process in the background.
113 -- | Create a new CH node and run the specified process in the background.
109 -- The CH node will exit when the process exists.
114 -- The CH node will exit when the process exists.
110− , spawnOnVM :: VirtualMachine -> String -> Closure (Process ()) -> IO ()
115+ , spawnOnVM :: VirtualMachine
117+ -> Closure (Backend -> Process ())
119+ } deriving (Typeable)
113data AzureParameters = AzureParameters {
121data AzureParameters = AzureParameters {
114 azureSetup :: AzureSetup
122 azureSetup :: AzureSetup
@@ -170,24 +178,37 @@ apiCopyToVM params vm =
170 SSH.scpSendFile s 0o700 (azureSshLocalPath params) (azureSshRemotePath params)
178 SSH.scpSendFile s 0o700 (azureSshLocalPath params) (azureSshRemotePath params)
172-- | Call a process on a VM
180-- | Call a process on a VM
173−apiCallOnVM :: Serializable a => AzureParameters -> Static (SerializableDict a) -> VirtualMachine -> String -> Closure (Process a) -> IO a
181+apiCallOnVM :: Serializable a
183+ -> Static (SerializableDict a)
186+ -> Closure (Backend -> Process a)
174apiCallOnVM params dict vm port proc =
188apiCallOnVM params dict vm port proc =
175− withSSH2 params vm $ \s -> do
189+ withSSH2 params vm $ \s -> do
176− let exe = "PATH=. " ++ azureSshRemotePath params
190+ let exe = "PATH=. " ++ azureSshRemotePath params
177− ++ " onvm run "
191+ ++ " onvm run "
178− ++ " --host " ++ vmIpAddress vm
192+ ++ " --host " ++ vmIpAddress vm
179− ++ " --port " ++ port
193+ ++ " --port " ++ port
180− ++ " 2>&1"
194+ ++ " 2>&1"
181− (status, r) <- SSH.withChannelBy (SSH.openChannelSession s) id $ \ch -> do
195+ (status, r) <- SSH.withChannelBy (SSH.openChannelSession s) id $ \ch -> do
182− SSH.channelExecute ch exe
196+ SSH.channelExecute ch exe
183− _cnt <- SSH.writeAllChannel ch (encode $ proc `cpBind` cpEncodeToStdout dict)
197+ _cnt <- SSH.writeAllChannel ch (encode proc')
184− SSH.channelSendEOF ch
198+ SSH.channelSendEOF ch
185− SSH.readAllChannel ch
199+ SSH.readAllChannel ch
186− if status == 0
200+ if status == 0
187− then return $ decode r
201+ then return $ decode r
188− else error (BSLC.unpack r)
202+ else error (BSLC.unpack r)
204+ proc' :: Closure (Backend -> Process ())
205+ proc' = proc `cpComp` cpEncodeToStdout dict
190−apiSpawnOnVM :: AzureParameters -> VirtualMachine -> String -> Closure (Process ()) -> IO ()
207+apiSpawnOnVM :: AzureParameters
210+ -> Closure (Backend -> Process ())
191apiSpawnOnVM params vm port proc =
212apiSpawnOnVM params vm port proc =
192 withSSH2 params vm $ \s -> do
213 withSSH2 params vm $ \s -> do
193 let exe = "PATH=. " ++ azureSshRemotePath params
214 let exe = "PATH=. " ++ azureSshRemotePath params
@@ -196,7 +217,6 @@ apiSpawnOnVM params vm port proc =
196 ++ " --port " ++ port
217 ++ " --port " ++ port
197 ++ " --background "
218 ++ " --background "
198 ++ " 2>&1"
219 ++ " 2>&1"
199− BSL.writeFile "closure" (encode proc)
200 (status, r) <- SSH.withChannelBy (SSH.openChannelSession s) id $ \ch -> do
220 (status, r) <- SSH.withChannelBy (SSH.openChannelSession s) id $ \ch -> do
201 SSH.channelExecute ch exe
221 SSH.channelExecute ch exe
202 _cnt <- SSH.writeAllChannel ch (encode proc)
222 _cnt <- SSH.writeAllChannel ch (encode proc)