On Fri, Jan 31, 2014 at 11:46 AM, Jose A. Lopes <[email protected]> wrote:
> ... including, user, group, daemonizing code with command line
> options, integration with the Snap HTTP server, and logic.
>
> Signed-off-by: Jose A. Lopes <[email protected]>
> ---
>  .gitignore                     |  1 +
>  Makefile.am                    |  5 +++
>  configure.ac                   |  7 ++++
>  src/AutoConf.hs.in             |  8 +++-
>  src/Ganeti/Constants.hs        | 25 ++++++++---
>  src/Ganeti/Metad.hs            | 94 
> ++++++++++++++++++++++++++++++++++++++++++
>  src/Ganeti/Runtime.hs          |  8 +++-
>  src/ganeti-metad.hs            | 48 +++++++++++++++++++++
>  test/hs/Test/Ganeti/Runtime.hs |  2 +
>  9 files changed, 191 insertions(+), 7 deletions(-)
>  create mode 100644 src/Ganeti/Metad.hs
>  create mode 100644 src/ganeti-metad.hs
>
> diff --git a/.gitignore b/.gitignore
> index ccde486..a02b0df 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -140,6 +140,7 @@
>  /src/ganeti-confd
>  /src/ganeti-kvmd
>  /src/ganeti-luxid
> +/src/ganeti-metad
>  /src/ganeti-mond
>  /src/rpc-test
>
> diff --git a/Makefile.am b/Makefile.am
> index 78a1318..e5d0594 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -595,6 +595,7 @@ endif
>  # Haskell programs to be compiled by "make really-all"
>  HS_COMPILE_PROGS= \
>         src/ganeti-kvmd \
> +       src/ganeti-metad \
>         src/ganeti-mond \
>         src/hconfd \
>         src/hluxid \
> @@ -713,6 +714,7 @@ HS_LIB_SRCS = \
>         src/Ganeti/Logging.hs \
>         src/Ganeti/Luxi.hs \
>         src/Ganeti/Monitoring/Server.hs \
> +       src/Ganeti/Metad.hs \
>         src/Ganeti/Network.hs \
>         src/Ganeti/Objects.hs \
>         src/Ganeti/OpCodes.hs \
> @@ -1072,6 +1074,7 @@ src/ganeti-luxid: src/hluxid
>  nodist_sbin_SCRIPTS += src/ganeti-confd
>  nodist_sbin_SCRIPTS += src/ganeti-luxid
>  nodist_sbin_SCRIPTS += src/ganeti-kvmd
> +nodist_sbin_SCRIPTS += src/ganeti-metad
>  endif
>
>  if ENABLE_MOND
> @@ -1849,6 +1852,8 @@ src/AutoConf.hs: Makefile src/AutoConf.hs.in 
> $(PRINT_PY_CONSTANTS) \
>             -DADMIN_GROUP="$(ADMIN_GROUP)" \
>             -DMASTERD_USER="$(MASTERD_USER)" \
>             -DMASTERD_GROUP="$(MASTERD_GROUP)" \
> +           -DMETAD_USER="$(METAD_USER)" \
> +           -DMETAD_GROUP="$(METAD_GROUP)" \
>             -DRAPI_USER="$(RAPI_USER)" \
>             -DRAPI_GROUP="$(RAPI_GROUP)" \
>             -DCONFD_USER="$(CONFD_USER)" \
> diff --git a/configure.ac b/configure.ac
> index 47df82d..4d9cde4 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -225,6 +225,7 @@ AC_ARG_WITH([user-prefix],
>      [ to change the default)]
>    )],
>    [user_masterd="${withval}masterd";
> +   user_metad="${withval}metad";
>     user_rapi="${withval}rapi";
>     user_confd="${withval}confd";
>     user_kvmd="$user_default";
> @@ -232,6 +233,7 @@ AC_ARG_WITH([user-prefix],
>     user_noded="$user_default";
>     user_mond="$user_default"],
>    [user_masterd="$user_default";
> +   user_metad="$user_default";
>     user_rapi="$user_default";
>     user_confd="$user_default";
>     user_kvmd="$user_default";
> @@ -239,6 +241,7 @@ AC_ARG_WITH([user-prefix],
>     user_noded="$user_default";
>     user_mond="$user_default"])
>  AC_SUBST(MASTERD_USER, $user_masterd)
> +AC_SUBST(METAD_USER, $user_metad)
>  AC_SUBST(RAPI_USER, $user_rapi)
>  AC_SUBST(CONFD_USER, $user_confd)
>  AC_SUBST(KVMD_USER, $user_kvmd)
> @@ -259,6 +262,7 @@ AC_ARG_WITH([group-prefix],
>     group_kvmd="$group_default";
>     group_luxid="${withval}luxid";
>     group_masterd="${withval}masterd";
> +   group_metad="${withval}metad";
>     group_noded="$group_default";
>     group_daemons="${withval}daemons";
>     group_mond="$group_default"],
> @@ -268,6 +272,7 @@ AC_ARG_WITH([group-prefix],
>     group_kvmd="$group_default";
>     group_luxid="$group_default";
>     group_masterd="$group_default";
> +   group_metad="$group_default";
>     group_noded="$group_default";
>     group_daemons="$group_default";
>     group_mond="$group_default"])
> @@ -277,12 +282,14 @@ AC_SUBST(CONFD_GROUP, $group_confd)
>  AC_SUBST(KVMD_GROUP, $group_kvmd)
>  AC_SUBST(LUXID_GROUP, $group_luxid)
>  AC_SUBST(MASTERD_GROUP, $group_masterd)
> +AC_SUBST(METAD_GROUP, $group_metad)
>  AC_SUBST(NODED_GROUP, $group_noded)
>  AC_SUBST(DAEMONS_GROUP, $group_daemons)
>  AC_SUBST(MOND_GROUP, $group_mond)
>
>  # Print the config to the user
>  AC_MSG_NOTICE([Running ganeti-masterd as $group_masterd:$group_masterd])
> +AC_MSG_NOTICE([Running ganeti-metad as $group_metad:$group_metad])
>  AC_MSG_NOTICE([Running ganeti-rapi as $user_rapi:$group_rapi])
>  AC_MSG_NOTICE([Running ganeti-confd as $user_confd:$group_confd])
>  AC_MSG_NOTICE([Running ganeti-luxid as $user_luxid:$group_luxid])
> diff --git a/src/AutoConf.hs.in b/src/AutoConf.hs.in
> index 44720aa..c108873 100644
> --- a/src/AutoConf.hs.in
> +++ b/src/AutoConf.hs.in
> @@ -7,7 +7,7 @@ from @AutoConf.hs.in@.
>
>  {-
>
> -Copyright (C) 2013 Google Inc.
> +Copyright (C) 2013, 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
> @@ -157,6 +157,12 @@ masterdUser = "MASTERD_USER"
>  masterdGroup :: String
>  masterdGroup = "MASTERD_GROUP"
>
> +metadUser :: String
> +metadUser = "METAD_USER"
> +
> +metadGroup :: String
> +metadGroup = "METAD_GROUP"
> +
>  rapiUser :: String
>  rapiUser = "RAPI_USER"
>
> diff --git a/src/Ganeti/Constants.hs b/src/Ganeti/Constants.hs
> index 1a40403..9df4f1f 100644
> --- a/src/Ganeti/Constants.hs
> +++ b/src/Ganeti/Constants.hs
> @@ -200,6 +200,12 @@ masterdUser = Runtime.daemonUser GanetiMasterd
>  masterdGroup :: String
>  masterdGroup = Runtime.daemonGroup (DaemonGroup GanetiMasterd)
>
> +metadUser :: String
> +metadUser = Runtime.daemonUser GanetiMetad
> +
> +metadGroup :: String
> +metadGroup = Runtime.daemonGroup (DaemonGroup GanetiMetad)
> +
>  rapiUser :: String
>  rapiUser = Runtime.daemonUser GanetiRapi
>
> @@ -335,6 +341,9 @@ confd = Runtime.daemonName GanetiConfd
>  masterd :: String
>  masterd = Runtime.daemonName GanetiMasterd
>
> +metad :: String
> +metad = Runtime.daemonName GanetiMetad
> +
>  mond :: String
>  mond = Runtime.daemonName GanetiMond
>
> @@ -365,6 +374,9 @@ defaultConfdPort = 1814
>  defaultMondPort :: Int
>  defaultMondPort = 1815
>
> +defaultMetadPort :: Int
> +defaultMetadPort = 8080
> +
>  defaultNodedPort :: Int
>  defaultNodedPort = 1811
>
> @@ -373,11 +385,14 @@ defaultRapiPort = 5080
>
>  daemonsPorts :: Map String (Protocol, Int)
>  daemonsPorts =
> -  Map.fromList [(confd, (Udp, defaultConfdPort)),
> -                (mond, (Tcp, defaultMondPort)),
> -                (noded, (Tcp, defaultNodedPort)),
> -                (rapi, (Tcp, defaultRapiPort)),
> -                (ssh, (Tcp, 22))]
> +  Map.fromList
> +  [ (confd, (Udp, defaultConfdPort))
> +  , (metad, (Tcp, defaultMetadPort))
> +  , (mond, (Tcp, defaultMondPort))
> +  , (noded, (Tcp, defaultNodedPort))
> +  , (rapi, (Tcp, defaultRapiPort))
> +  , (ssh, (Tcp, 22))
> +  ]
>
>  firstDrbdPort :: Int
>  firstDrbdPort = 11000
> diff --git a/src/Ganeti/Metad.hs b/src/Ganeti/Metad.hs
> new file mode 100644
> index 0000000..535d9a0
> --- /dev/null
> +++ b/src/Ganeti/Metad.hs
> @@ -0,0 +1,94 @@
> +{-| Metadata daemon
> +
> +-}
> +
> +{-
> +
> +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 (start) where
> +
> +import Control.Applicative
> +import Control.Monad.IO.Class (liftIO)
> +import qualified Data.ByteString.Char8 as ByteString (pack, unpack)
> +import Snap.Core
> +import Snap.Http.Server
> +
> +import Ganeti.Daemon
> +import qualified Ganeti.Constants as Constants
> +import qualified Ganeti.Logging as Logging
> +import Ganeti.Runtime (GanetiDaemon(..), ExtraLogReason(..))
> +import qualified Ganeti.Runtime as Runtime
> +
> +type MetaM = Snap ()
> +
> +error404 :: MetaM
> +error404 = do
> +  modifyResponse . setResponseStatus 404 $ ByteString.pack "Not found"
> +  writeBS $ ByteString.pack "Resource not found"
> +
> +handleMetadata :: Method -> String -> String -> String -> MetaM
> +handleMetadata GET  "ganeti" "latest" "meta_data.json" =
> +  liftIO $ Logging.logInfo "ganeti metadata"
> +handleMetadata GET  "ganeti" "latest" "os/parameters.json" =
> +  liftIO $ Logging.logInfo "ganeti OS parameters"
> +handleMetadata GET  "ganeti" "latest" "read" =
> +  liftIO $ Logging.logInfo "ganeti READ"
> +handleMetadata POST "ganeti" "latest" "write" =
> +  liftIO $ Logging.logInfo "ganeti WRITE"
> +handleMetadata _ _ _ _ = error404

This isn't returning any actual data yet, right?

> +
> +routeMetadata :: MetaM
> +routeMetadata =
> +  route [ (providerRoute1, dispatchMetadata)
> +        , (providerRoute2, dispatchMetadata)
> +        ] <|> dispatchMetadata
> +  where provider = "provider"
> +        version  = "version"
> +
> +        providerRoute1 = ByteString.pack $ ':':provider ++ "/" ++ ':':version
> +        providerRoute2 = ByteString.pack $ ':':version
> +
> +        getParamString :: String -> Snap String
> +        getParamString =
> +          fmap (maybe "" ByteString.unpack) . getParam . ByteString.pack
> +
> +        dispatchMetadata =
> +          do m <- rqMethod <$> getRequest
> +             p <- getParamString provider
> +             v <- getParamString version
> +             r <- ByteString.unpack . rqPathInfo <$> getRequest
> +             handleMetadata m p v r
> +
> +defaultHttpConf :: DaemonOptions -> FilePath -> FilePath -> Config Snap ()
> +defaultHttpConf opts accessLog errorLog =
> +  maybe id (setBind . ByteString.pack) (optBindAddress opts) .
> +  setAccessLog (ConfigFileLog accessLog) .
> +  setCompression False .
> +  setErrorLog (ConfigFileLog errorLog) .
> +  setPort (maybe Constants.defaultMetadPort fromIntegral (optPort opts)) .
> +  setVerbose False $
> +  emptyConfig
> +
> +start :: DaemonOptions -> IO ()
> +start opts = do
> +  accessLog <- Runtime.daemonsExtraLogFile GanetiMetad AccessLog
> +  errorLog <- Runtime.daemonsExtraLogFile GanetiMetad ErrorLog
> +  httpServe (defaultHttpConf opts accessLog errorLog) routeMetadata
> diff --git a/src/Ganeti/Runtime.hs b/src/Ganeti/Runtime.hs
> index 7a299a2..eddcee7 100644
> --- a/src/Ganeti/Runtime.hs
> +++ b/src/Ganeti/Runtime.hs
> @@ -4,7 +4,7 @@
>
>  {-
>
> -Copyright (C) 2011, 2012, 2013 Google Inc.
> +Copyright (C) 2011, 2012, 2013, 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
> @@ -60,6 +60,7 @@ import Ganeti.BasicTypes
>  import AutoConf
>
>  data GanetiDaemon = GanetiMasterd
> +                  | GanetiMetad
>                    | GanetiNoded
>                    | GanetiRapi
>                    | GanetiConfd
> @@ -81,6 +82,7 @@ type RuntimeEnts = (M.Map GanetiDaemon UserID, M.Map 
> GanetiGroup GroupID)
>  -- | Returns the daemon name for a given daemon.
>  daemonName :: GanetiDaemon -> String
>  daemonName GanetiMasterd = "ganeti-masterd"
> +daemonName GanetiMetad   = "ganeti-metad"
>  daemonName GanetiNoded   = "ganeti-noded"
>  daemonName GanetiRapi    = "ganeti-rapi"
>  daemonName GanetiConfd   = "ganeti-confd"
> @@ -91,6 +93,7 @@ daemonName GanetiMond    = "ganeti-mond"
>  -- | Returns whether the daemon only runs on the master node.
>  daemonOnlyOnMaster :: GanetiDaemon -> Bool
>  daemonOnlyOnMaster GanetiMasterd = True
> +daemonOnlyOnMaster GanetiMetad   = False
>  daemonOnlyOnMaster GanetiNoded   = False
>  daemonOnlyOnMaster GanetiRapi    = False
>  daemonOnlyOnMaster GanetiConfd   = False
> @@ -101,6 +104,7 @@ daemonOnlyOnMaster GanetiMond    = False
>  -- | Returns the log file base for a daemon.
>  daemonLogBase :: GanetiDaemon -> String
>  daemonLogBase GanetiMasterd = "master-daemon"
> +daemonLogBase GanetiMetad   = "meta-daemon"
>  daemonLogBase GanetiNoded   = "node-daemon"
>  daemonLogBase GanetiRapi    = "rapi-daemon"
>  daemonLogBase GanetiConfd   = "conf-daemon"
> @@ -111,6 +115,7 @@ daemonLogBase GanetiMond    = "monitoring-daemon"
>  -- | Returns the configured user name for a daemon.
>  daemonUser :: GanetiDaemon -> String
>  daemonUser GanetiMasterd = AutoConf.masterdUser
> +daemonUser GanetiMetad   = AutoConf.metadUser
>  daemonUser GanetiNoded   = AutoConf.nodedUser
>  daemonUser GanetiRapi    = AutoConf.rapiUser
>  daemonUser GanetiConfd   = AutoConf.confdUser
> @@ -121,6 +126,7 @@ daemonUser GanetiMond    = AutoConf.mondUser
>  -- | Returns the configured group for a daemon.
>  daemonGroup :: GanetiGroup -> String
>  daemonGroup (DaemonGroup GanetiMasterd) = AutoConf.masterdGroup
> +daemonGroup (DaemonGroup GanetiMetad)   = AutoConf.metadGroup
>  daemonGroup (DaemonGroup GanetiNoded)   = AutoConf.nodedGroup
>  daemonGroup (DaemonGroup GanetiRapi)    = AutoConf.rapiGroup
>  daemonGroup (DaemonGroup GanetiConfd)   = AutoConf.confdGroup
> diff --git a/src/ganeti-metad.hs b/src/ganeti-metad.hs
> new file mode 100644
> index 0000000..28529b6
> --- /dev/null
> +++ b/src/ganeti-metad.hs
> @@ -0,0 +1,48 @@
> +{-| Metadata daemon.
> +
> +-}
> +
> +{-
> +
> +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 Main (main) where
> +
> +import qualified Ganeti.Constants as Constants
> +import Ganeti.Daemon (OptType)
> +import qualified Ganeti.Daemon as Daemon
> +import qualified Ganeti.Metad as Metad
> +import qualified Ganeti.Runtime as Runtime
> +
> +options :: [OptType]
> +options =
> +  [ Daemon.oBindAddress
> +  , Daemon.oDebug
> +  , Daemon.oNoDaemonize
> +  , Daemon.oNoUserChecks
> +  , Daemon.oPort Constants.defaultMetadPort
> +  ]
> +
> +main :: IO ()
> +main =
> +  Daemon.genericMain Runtime.GanetiMetad options
> +    (\_ -> return . Right $ ())
> +    (\_ _ -> return ())
> +    (\opts _ _ -> Metad.start opts)
> diff --git a/test/hs/Test/Ganeti/Runtime.hs b/test/hs/Test/Ganeti/Runtime.hs
> index 605859f..f75fc42 100644
> --- a/test/hs/Test/Ganeti/Runtime.hs
> +++ b/test/hs/Test/Ganeti/Runtime.hs
> @@ -85,6 +85,7 @@ case_UsersGroups = do
>                \         constants.CONFD_USER,\n\
>                \         constants.KVMD_USER,\n\
>                \         constants.LUXID_USER,\n\
> +              \         constants.METAD_USER,\n\
>                \         constants.MOND_USER,\n\
>                \        ]\n\
>                \groups = [constants.MASTERD_GROUP,\n\
> @@ -93,6 +94,7 @@ case_UsersGroups = do
>                \          constants.CONFD_GROUP,\n\
>                \          constants.KVMD_GROUP,\n\
>                \          constants.LUXID_GROUP,\n\
> +              \          constants.METAD_GROUP,\n\
>                \          constants.MOND_GROUP,\n\
>                \          constants.DAEMONS_GROUP,\n\
>                \          constants.ADMIN_GROUP,\n\
> --
> 1.8.5.3
>

Thanks,
Michele

-- 
Google Germany GmbH
Dienerstr. 12
80331 München

Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
Geschäftsführer: Graham Law, Christine Elizabeth Flores

Reply via email to