@@ -24,7 +24,7 @@ import System.Environment (getEnv)
24import System.FilePath ((</>), takeFileName)
24import System.FilePath ((</>), takeFileName)
25import System.Environment.Executable (getExecutablePath)
25import System.Environment.Executable (getExecutablePath)
26import System.IO (stdout, hFlush)
26import System.IO (stdout, hFlush)
27−import Data.Binary (encode, decode)
27+import Data.Binary (Binary(get, put), encode, decode)
28import Data.Digest.Pure.MD5 (md5, MD5Digest)
28import Data.Digest.Pure.MD5 (md5, MD5Digest)
29import qualified Data.ByteString as BSS
29import qualified Data.ByteString as BSS
30 ( ByteString
30 ( ByteString
@@ -43,7 +43,7 @@ import qualified Data.ByteString.Lazy as BSL
44import qualified Data.ByteString.Lazy.Char8 as BSLC (unpack)
44import qualified Data.ByteString.Lazy.Char8 as BSLC (unpack)
45import Data.Typeable (Typeable)
45import Data.Typeable (Typeable)
46−import Control.Applicative ((<$>))
46+import Control.Applicative ((<$>), (<*>))
47import Control.Monad (void, unless)
47import Control.Monad (void, unless)
48import Control.Monad.Reader (MonadReader, ReaderT, runReaderT, ask)
48import Control.Monad.Reader (MonadReader, ReaderT, runReaderT, ask)
49import Control.Exception (Exception, catches, Handler(Handler), throwIO)
49import Control.Exception (Exception, catches, Handler(Handler), throwIO)
@@ -125,6 +125,19 @@ data AzureParameters = AzureParameters {
125 , azureSshLocalPath :: FilePath
125 , azureSshLocalPath :: FilePath
128+instance Binary AzureParameters where
130+ put (azureSetup params)
131+ put (azureSshUserName params)
132+ put (azureSshPublicKey params)
133+ put (azureSshPrivateKey params)
134+ put (azureSshPassphrase params)
135+ put (azureSshKnownHosts params)
136+ put (azureSshRemotePath params)
137+ put (azureSshLocalPath params)
139+ AzureParameters <$> get <*> get <*> get <*> get <*> get <*> get <*> get <*> get
128-- | Create default azure parameters
141-- | Create default azure parameters
129defaultAzureParameters :: String -- ^ Azure subscription ID
142defaultAzureParameters :: String -- ^ Azure subscription ID
130 -> FilePath -- ^ Path to X509 certificate
143 -> FilePath -- ^ Path to X509 certificate
@@ -155,8 +168,8 @@ initializeBackend params cloudService =
155 findVMs = apiFindVMs params cloudService
168 findVMs = apiFindVMs params cloudService
156 , copyToVM = apiCopyToVM params
169 , copyToVM = apiCopyToVM params
157 , checkMD5 = apiCheckMD5 params
170 , checkMD5 = apiCheckMD5 params
158− , callOnVM = apiCallOnVM params
171+ , callOnVM = apiCallOnVM params cloudService
159− , spawnOnVM = apiSpawnOnVM params
172+ , spawnOnVM = apiSpawnOnVM params cloudService
162-- | Find virtual machines
175-- | Find virtual machines
@@ -175,21 +188,26 @@ apiCopyToVM params vm =
176-- | Call a process on a VM
189-- | Call a process on a VM
177apiCallOnVM :: AzureParameters
190apiCallOnVM :: AzureParameters
178 -> VirtualMachine
192 -> VirtualMachine
179 -> String
193 -> String
180 -> ProcessPair a
194 -> ProcessPair a
182−apiCallOnVM params vm port ppair =
196+apiCallOnVM params cloudService vm port ppair =
183 withSSH2 params vm $ \s -> do
197 withSSH2 params vm $ \s -> do
184 let exe = "PATH=. " ++ azureSshRemotePath params
198 let exe = "PATH=. " ++ azureSshRemotePath params
185 ++ " onvm run "
199 ++ " onvm run "
186 ++ " --host " ++ vmIpAddress vm
200 ++ " --host " ++ vmIpAddress vm
187 ++ " --port " ++ port
201 ++ " --port " ++ port
202+ ++ " --cloud-service " ++ cloudService
188 ++ " 2>&1"
203 ++ " 2>&1"
204+ let paramsEnc = encode params
189 (status, r) <- SSH.withChannelBy (SSH.openChannelSession s) id $ \ch -> do
205 (status, r) <- SSH.withChannelBy (SSH.openChannelSession s) id $ \ch -> do
190 SSH.channelExecute ch exe
206 SSH.channelExecute ch exe
191− _ <- SSH.writeChannel ch (encodeInt32 (BSL.length rprocEnc))
207+ SSH.writeChannel ch (encodeInt32 (BSL.length rprocEnc))
208+ SSH.writeAllChannel ch rprocEnc
209+ SSH.writeChannel ch (encodeInt32 (BSL.length paramsEnc))
192− _ <- SSH.writeAllChannel ch rprocEnc
210+ SSH.writeAllChannel ch paramsEnc
193 runLocalProcess (ppairLocal ppair) ch
211 runLocalProcess (ppairLocal ppair) ch
194 if status == 0
212 if status == 0
195 then return r
213 then return r
@@ -199,22 +217,28 @@ apiCallOnVM params vm port ppair =
199 rprocEnc = encode (ppairRemote ppair)
217 rprocEnc = encode (ppairRemote ppair)
201apiSpawnOnVM :: AzureParameters
219apiSpawnOnVM :: AzureParameters
202 -> VirtualMachine
221 -> VirtualMachine
203 -> String
222 -> String
204 -> Closure (Backend -> Process ())
223 -> Closure (Backend -> Process ())
206−apiSpawnOnVM params vm port proc =
225+apiSpawnOnVM params cloudService vm port proc =
207 withSSH2 params vm $ \s -> do
226 withSSH2 params vm $ \s -> do
227+ -- TODO: reduce duplication with apiCallOnVM
208 let exe = "PATH=. " ++ azureSshRemotePath params
228 let exe = "PATH=. " ++ azureSshRemotePath params
209 ++ " onvm run "
229 ++ " onvm run "
210 ++ " --host " ++ vmIpAddress vm
230 ++ " --host " ++ vmIpAddress vm
211 ++ " --port " ++ port
231 ++ " --port " ++ port
232+ ++ " --cloud-service " ++ cloudService
212 ++ " --background "
233 ++ " --background "
213 ++ " 2>&1"
234 ++ " 2>&1"
235+ let paramsEnc = encode params
214 (status, r) <- SSH.withChannelBy (SSH.openChannelSession s) id $ \ch -> do
236 (status, r) <- SSH.withChannelBy (SSH.openChannelSession s) id $ \ch -> do
215 SSH.channelExecute ch exe
237 SSH.channelExecute ch exe
216− _ <- SSH.writeChannel ch (encodeInt32 (BSL.length procEnc))
238+ SSH.writeChannel ch (encodeInt32 (BSL.length procEnc))
239+ SSH.writeAllChannel ch procEnc
240+ SSH.writeChannel ch (encodeInt32 (BSL.length paramsEnc))
217− _ <- SSH.writeAllChannel ch procEnc
241+ SSH.writeAllChannel ch paramsEnc
218 SSH.channelSendEOF ch
242 SSH.channelSendEOF ch
219 SSH.readAllChannel ch
243 SSH.readAllChannel ch
220 unless (status == 0) $ error (BSLC.unpack r)
244 unless (status == 0) $ error (BSLC.unpack r)