module B9.VmBuilder (buildWithVm) where
import Data.List
import Control.Monad
import Control.Applicative
import Control.Monad.IO.Class
import System.Directory (createDirectoryIfMissing, canonicalizePath)
import Text.Printf ( printf )
import Text.Show.Pretty (ppShow)
import B9.B9Monad
import B9.DiskImages
import B9.DiskImageBuilder
import B9.ExecEnv
import B9.B9Config
import B9.Vm
import B9.ArtifactGenerator
import B9.ShellScript
import qualified B9.LibVirtLXC as LXC
buildWithVm :: InstanceId -> [ImageTarget] -> FilePath -> VmScript -> B9 Bool
buildWithVm iid imageTargets instanceDir vmScript = do
vmBuildSupportedImageTypes <- getVmScriptSupportedImageTypes vmScript
buildImages <- createBuildImages imageTargets vmBuildSupportedImageTypes
success <- runVmScript iid imageTargets buildImages instanceDir vmScript
when success (createDestinationImages buildImages imageTargets)
return success
getVmScriptSupportedImageTypes :: VmScript -> B9 [ImageType]
getVmScriptSupportedImageTypes NoVmScript =
return [QCow2, Raw, Vmdk]
getVmScriptSupportedImageTypes _ = do
envType <- getExecEnvType
return (supportedImageTypes envType)
supportedImageTypes :: ExecEnvType -> [ImageType]
supportedImageTypes LibVirtLXC = LXC.supportedImageTypes
createBuildImages :: [ImageTarget] -> [ImageType] -> B9 [Image]
createBuildImages imageTargets vmBuildSupportedImageTypes = do
dbgL "creating build images"
traceL (ppShow imageTargets)
buildImages <- mapM createBuildImage imageTargets
infoL "CREATED BUILD IMAGES"
traceL (ppShow buildImages)
return buildImages
where
createBuildImage (ImageTarget dest imageSource _mnt) = do
buildDir <- getBuildDir
destTypes <- preferredDestImageTypes imageSource
let buildImgType = head (destTypes
`intersect`
preferredSourceImageTypes dest
`intersect`
vmBuildSupportedImageTypes)
srcImg <- resolveImageSource imageSource
let buildImg = changeImageFormat buildImgType
(changeImageDirectory buildDir srcImg)
buildImgAbsolutePath <- liftIO (ensureAbsoluteImageDirExists buildImg)
materializeImageSource imageSource buildImg
return buildImgAbsolutePath
runVmScript :: InstanceId
-> [ImageTarget]
-> [Image]
-> FilePath
-> VmScript
-> B9 Bool
runVmScript _ _ _ _ NoVmScript = return True
runVmScript (IID iid) imageTargets buildImages instanceDir vmScript = do
dbgL (printf "starting vm script with instanceDir '%s'" instanceDir)
traceL (ppShow vmScript)
execEnv <- setUpExecEnv
let (VmScript _ _ script) = vmScript
success <- runInEnvironment execEnv script
if success
then infoL "EXECUTED BUILD SCRIPT"
else errorL "BUILD SCRIPT FAILED"
return success
where
setUpExecEnv :: B9 ExecEnv
setUpExecEnv = do
let (VmScript cpu shares _) = vmScript
let mountedImages = buildImages `zip` (itImageMountPoint <$> imageTargets)
sharesAbs <- createSharedDirs instanceDir shares
return (ExecEnv iid
mountedImages
sharesAbs
(Resources AutomaticRamSize 8 cpu))
createSharedDirs :: FilePath -> [SharedDirectory] -> B9 [SharedDirectory]
createSharedDirs instanceDir sharedDirsIn = mapM createSharedDir sharedDirsIn
where
createSharedDir (SharedDirectoryRO d m) = do
d' <- createAndCanonicalize d
return $ SharedDirectoryRO d' m
createSharedDir (SharedDirectory d m) = do
d' <- createAndCanonicalize d
return $ SharedDirectory d' m
createSharedDir (SharedSources mp) = do
d' <- createAndCanonicalize instanceDir
return $ SharedDirectoryRO d' mp
createAndCanonicalize d = liftIO $ do
createDirectoryIfMissing True d
canonicalizePath d
createDestinationImages :: [Image] -> [ImageTarget] -> B9 ()
createDestinationImages buildImages imageTargets = do
dbgL "converting build- to output images"
let pairsToConvert = buildImages `zip` (itImageDestination `map` imageTargets)
traceL (ppShow pairsToConvert)
mapM_ (uncurry createDestinationImage) pairsToConvert
infoL "CONVERTED BUILD- TO OUTPUT IMAGES"
runInEnvironment :: ExecEnv -> Script -> B9 Bool
runInEnvironment env script = do
t <- getExecEnvType
case t of
LibVirtLXC -> LXC.runInEnvironment env script