LGTM, thanks

On Thu, Apr 3, 2014 at 4:46 PM, Jose A. Lopes <[email protected]> wrote:

> ... as an intermediate step before moving the responsbility of
> computing the final OS parameter configuration from the configuration
> server to the web server.  This will allow the metadata daemon to
> store a more general configuration and thus reuse that configuration
> for replying to more general queries.
>
> Signed-off-by: Jose A. Lopes <[email protected]>
> ---
>  Makefile.am                      |   1 +
>  src/Ganeti/Metad/Config.hs       | 131
> +++++++++++++++++++++++++++++++++++++++
>  src/Ganeti/Metad/ConfigServer.hs | 109 +-------------------------------
>  3 files changed, 134 insertions(+), 107 deletions(-)
>  create mode 100644 src/Ganeti/Metad/Config.hs
>
> diff --git a/Makefile.am b/Makefile.am
> index 9a44cce..22b72a8 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -773,6 +773,7 @@ HS_LIB_SRCS = \
>         src/Ganeti/Logging.hs \
>         src/Ganeti/Logging/Lifted.hs \
>         src/Ganeti/Luxi.hs \
> +       src/Ganeti/Metad/Config.hs \
>         src/Ganeti/Metad/ConfigServer.hs \
>         src/Ganeti/Metad/Server.hs \
>         src/Ganeti/Metad/Types.hs \
> diff --git a/src/Ganeti/Metad/Config.hs b/src/Ganeti/Metad/Config.hs
> new file mode 100644
> index 0000000..83dbdf5
> --- /dev/null
> +++ b/src/Ganeti/Metad/Config.hs
> @@ -0,0 +1,131 @@
> +{-
> +
> +Copyright (C) 2014 Google Inc.
> +
> +This program is free software; you can redistribute it and/or modify
> +it under the terms of the GNU General Public License as published by
> +the Free Software Foundation; either version 2 of the License, or
> +(at your option) any later version.
> +
> +This program is distributed in the hope that it will be useful, but
> +WITHOUT ANY WARRANTY; without even the implied warranty of
> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +General Public License for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with this program; if not, write to the Free Software
> +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> +02110-1301, USA.
> +
> +-}
> +module Ganeti.Metad.Config where
> +
> +import Control.Arrow (second)
> +import qualified Data.List as List (isPrefixOf)
> +import qualified Data.Map as Map
> +import Text.JSON
> +import qualified Text.JSON as JSON
> +
> +import Ganeti.Constants as Constants
> +import Ganeti.Metad.Types
> +
> +-- | Merges two instance configurations into one.
> +--
> +-- In the case where instance IPs (i.e., map keys) are repeated, the
> +-- old instance configuration is thrown away by 'Map.union' and
> +-- replaced by the new configuration.  As a result, the old private
> +-- and secret OS parameters are completely lost.
> +mergeConfig :: InstanceParams -> InstanceParams -> InstanceParams
> +mergeConfig cfg1 cfg2 = cfg2 `Map.union` cfg1
> +
> +-- | Extracts the OS parameters (public, private, secret) from a JSON
> +-- object.
> +--
> +-- This function checks whether the OS parameters are in fact a JSON
> +-- object.
> +getOsParams :: String -> String -> JSObject JSValue -> Result (JSObject
> JSValue)
> +getOsParams key msg jsonObj =
> +  case lookup key (fromJSObject jsonObj) of
> +    Nothing -> Error $ "Could not find " ++ msg ++ " OS parameters"
> +    Just (JSObject x) -> Ok x
> +    _ -> Error "OS params is not a JSON object"
> +
> +getPublicOsParams :: JSObject JSValue -> Result (JSObject JSValue)
> +getPublicOsParams = getOsParams "osparams" "public"
> +
> +getPrivateOsParams :: JSObject JSValue -> Result (JSObject JSValue)
> +getPrivateOsParams = getOsParams "osparams_private" "private"
> +
> +getSecretOsParams :: JSObject JSValue -> Result (JSObject JSValue)
> +getSecretOsParams = getOsParams "osparams_secret" "secret"
> +
> +-- | Merges the OS parameters (public, private, secret) in a single
> +-- data structure containing all parameters and their visibility.
> +--
> +-- Example:
> +--   { "os-image": ["http://example.com/disk.img";, "public"],
> +--     "os-password": ["mypassword", "secret"] }
> +makeInstanceParams
> +  :: JSObject JSValue -> JSObject JSValue -> JSObject JSValue -> JSValue
> +makeInstanceParams pub priv sec =
> +  JSObject . JSON.toJSObject $
> +    addVisibility "public" pub ++
> +    addVisibility "private" priv ++
> +    addVisibility "secret" sec
> +  where
> +    key = JSString . JSON.toJSString
> +
> +    addVisibility param params =
> +      map (second (JSArray . (:[key param]))) (JSON.fromJSObject params)
> +
> +-- | Finds the IP address of the instance communication NIC in the
> +-- instance's NICs.
> +getInstanceCommunicationIp :: JSObject JSValue -> Result String
> +getInstanceCommunicationIp jsonObj =
> +  getNics >>= getInstanceCommunicationNic >>= getIp
> +  where
> +    getIp nic =
> +      case lookup "ip" (fromJSObject nic) of
> +        Nothing -> Error "Could not find instance communication IP"
> +        Just (JSString ip) -> Ok (JSON.fromJSString ip)
> +        _ -> Error "Instance communication IP is not a string"
> +
> +    getInstanceCommunicationNic [] =
> +      Error "Could not find instance communication NIC"
> +    getInstanceCommunicationNic (JSObject nic:nics) =
> +      case lookup "name" (fromJSObject nic) of
> +        Just (JSString name)
> +          | Constants.instanceCommunicationNicPrefix
> +            `List.isPrefixOf` JSON.fromJSString name ->
> +            Ok nic
> +        _ -> getInstanceCommunicationNic nics
> +    getInstanceCommunicationNic _ =
> +      Error "Found wrong data in instance NICs"
> +
> +    getNics =
> +      case lookup "nics" (fromJSObject jsonObj) of
> +        Nothing -> Error "Could not find OS parameters key 'nics'"
> +        Just (JSArray nics) -> Ok nics
> +        _ -> Error "Instance nics is not an array"
> +
> +-- | Extracts the OS parameters from the instance's parameters and
> +-- returns a data structure containing all the OS parameters and their
> +-- visibility indexed by the instance's IP address which is used in
> +-- the instance communication NIC.
> +getInstanceParams :: JSValue -> Result (String, InstanceParams)
> +getInstanceParams json =
> +    case json of
> +      JSObject jsonObj -> do
> +        name <- case lookup "name" (fromJSObject jsonObj) of
> +                  Nothing -> Error "Could not find instance name"
> +                  Just (JSString x) -> Ok (JSON.fromJSString x)
> +                  _ -> Error "Name is not a string"
> +        ip <- getInstanceCommunicationIp jsonObj
> +        publicOsParams <- getPublicOsParams jsonObj
> +        privateOsParams <- getPrivateOsParams jsonObj
> +        secretOsParams <- getSecretOsParams jsonObj
> +        let instanceParams =
> +              makeInstanceParams publicOsParams privateOsParams
> secretOsParams
> +        Ok (name, Map.fromList [(ip, instanceParams)])
> +      _ ->
> +        Error "Expecting a dictionary"
> diff --git a/src/Ganeti/Metad/ConfigServer.hs
> b/src/Ganeti/Metad/ConfigServer.hs
> index c1db6bb..9610cca 100644
> --- a/src/Ganeti/Metad/ConfigServer.hs
> +++ b/src/Ganeti/Metad/ConfigServer.hs
> @@ -25,18 +25,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor,
> Boston, MA
>  -}
>  module Ganeti.Metad.ConfigServer where
>
> -import Control.Arrow (second)
>  import Control.Concurrent
>  import Control.Exception (try, finally)
>  import Control.Monad (unless)
> -import qualified Data.List as List
> -import qualified Data.Map as Map
>  import Text.JSON
> -import qualified Text.JSON as JSON
>  import System.FilePath ((</>))
>  import System.IO.Error (isEOFError)
>
> -import Ganeti.Constants as Constants
>  import Ganeti.Path as Path
>  import Ganeti.Daemon (DaemonOptions)
>  import qualified Ganeti.Logging as Logging
> @@ -44,6 +39,7 @@ import Ganeti.Runtime (GanetiDaemon(..))
>  import Ganeti.UDSServer (Client, ConnectConfig(..), Server)
>  import qualified Ganeti.UDSServer as UDSServer
>
> +import Ganeti.Metad.Config as Config
>  import Ganeti.Metad.Types (InstanceParams)
>
>  metadSocket :: IO FilePath
> @@ -51,107 +47,6 @@ metadSocket =
>    do dir <- Path.socketDir
>       return $ dir </> "ganeti-metad"
>
> --- | Merges two instance configurations into one.
> ---
> --- In the case where instance IPs (i.e., map keys) are repeated, the
> --- old instance configuration is thrown away by 'Map.union' and
> --- replaced by the new configuration.  As a result, the old private
> --- and secret OS parameters are completely lost.
> -mergeConfig :: InstanceParams -> InstanceParams -> InstanceParams
> -mergeConfig cfg1 cfg2 = cfg2 `Map.union` cfg1
> -
> --- | Extracts the OS parameters (public, private, secret) from a JSON
> --- object.
> ---
> --- This function checks whether the OS parameters are in fact a JSON
> --- object.
> -getOsParams :: String -> String -> JSObject JSValue -> Result (JSObject
> JSValue)
> -getOsParams key msg jsonObj =
> -  case lookup key (fromJSObject jsonObj) of
> -    Nothing -> Error $ "Could not find " ++ msg ++ " OS parameters"
> -    Just (JSObject x) -> Ok x
> -    _ -> Error "OS params is not a JSON object"
> -
> -getPublicOsParams :: JSObject JSValue -> Result (JSObject JSValue)
> -getPublicOsParams = getOsParams "osparams" "public"
> -
> -getPrivateOsParams :: JSObject JSValue -> Result (JSObject JSValue)
> -getPrivateOsParams = getOsParams "osparams_private" "private"
> -
> -getSecretOsParams :: JSObject JSValue -> Result (JSObject JSValue)
> -getSecretOsParams = getOsParams "osparams_secret" "secret"
> -
> --- | Finds the IP address of the instance communication NIC in the
> --- instance's NICs.
> -getInstanceCommunicationIp :: JSObject JSValue -> Result String
> -getInstanceCommunicationIp jsonObj =
> -  getNics >>= getInstanceCommunicationNic >>= getIp
> -  where
> -    getIp nic =
> -      case lookup "ip" (fromJSObject nic) of
> -        Nothing -> Error "Could not find instance communication IP"
> -        Just (JSString ip) -> Ok (JSON.fromJSString ip)
> -        _ -> Error "Instance communication IP is not a string"
> -
> -    getInstanceCommunicationNic [] =
> -      Error "Could not find instance communication NIC"
> -    getInstanceCommunicationNic (JSObject nic:nics) =
> -      case lookup "name" (fromJSObject nic) of
> -        Just (JSString name)
> -          | Constants.instanceCommunicationNicPrefix
> -            `List.isPrefixOf` JSON.fromJSString name ->
> -            Ok nic
> -        _ -> getInstanceCommunicationNic nics
> -    getInstanceCommunicationNic _ =
> -      Error "Found wrong data in instance NICs"
> -
> -    getNics =
> -      case lookup "nics" (fromJSObject jsonObj) of
> -        Nothing -> Error "Could not find OS parameters key 'nics'"
> -        Just (JSArray nics) -> Ok nics
> -        _ -> Error "Instance nics is not an array"
> -
> --- | Merges the OS parameters (public, private, secret) in a single
> --- data structure containing all parameters and their visibility.
> ---
> --- Example:
> ---   { "os-image": ["http://example.com/disk.img";, "public"],
> ---     "os-password": ["mypassword", "secret"] }
> -makeInstanceParams
> -  :: JSObject JSValue -> JSObject JSValue -> JSObject JSValue -> JSValue
> -makeInstanceParams pub priv sec =
> -  JSObject . JSON.toJSObject $
> -    addVisibility "public" pub ++
> -    addVisibility "private" priv ++
> -    addVisibility "secret" sec
> -  where
> -    key = JSString . JSON.toJSString
> -
> -    addVisibility param params =
> -      map (second (JSArray . (:[key param]))) (JSON.fromJSObject params)
> -
> --- | Extracts the OS parameters from the instance's parameters and
> --- returns a data structure containing all the OS parameters and their
> --- visibility indexed by the instance's IP address which is used in
> --- the instance communication NIC.
> -getInstanceParams :: JSValue -> Result (String, InstanceParams)
> -getInstanceParams json =
> -    case json of
> -      JSObject jsonObj -> do
> -        name <- case lookup "name" (fromJSObject jsonObj) of
> -                  Nothing -> Error "Could not find instance name"
> -                  Just (JSString x) -> Ok (JSON.fromJSString x)
> -                  _ -> Error "Name is not a string"
> -        ip <- getInstanceCommunicationIp jsonObj
> -        publicOsParams <- getPublicOsParams jsonObj
> -        privateOsParams <- getPrivateOsParams jsonObj
> -        secretOsParams <- getSecretOsParams jsonObj
> -        let instanceParams =
> -              makeInstanceParams publicOsParams privateOsParams
> secretOsParams
> -        Ok (name, Map.fromList [(ip, instanceParams)])
> -      _ ->
> -        Error "Expecting a dictionary"
> -
>  -- | Update the configuration with the received instance parameters.
>  updateConfig :: MVar InstanceParams -> String -> IO ()
>  updateConfig config str =
> @@ -159,7 +54,7 @@ updateConfig config str =
>      Error err ->
>        Logging.logDebug $ show err
>      Ok x ->
> -      case getInstanceParams x of
> +      case Config.getInstanceParams x of
>          Error err ->
>            Logging.logError $ "Could not get instance parameters: " ++ err
>          Ok (name, instanceParams) -> do
> --
> 1.9.1.423.g4596e3a
>
>

Reply via email to