On Wed, Aug 05, 2015 at 12:52:18PM +0200, 'BSRK Aditya' via ganeti-devel wrote: > and add it to the data collector list. > > Signed-off-by: BSRK Aditya <[email protected]> > --- > src/Ganeti/DataCollectors.hs | 5 ++ > src/Ganeti/DataCollectors/Diagnose.hs | 147 > +++++++++++++++++++++++++++++++++ > src/Ganeti/DataCollectors/Types.hs | 2 +- > 3 files changed, 153 insertions(+), 1 deletion(-) > create mode 100644 src/Ganeti/DataCollectors/Diagnose.hs > > diff --git a/src/Ganeti/DataCollectors.hs b/src/Ganeti/DataCollectors.hs > index bca6848..9c2cc3b 100644 > --- a/src/Ganeti/DataCollectors.hs > +++ b/src/Ganeti/DataCollectors.hs > @@ -38,6 +38,7 @@ import Data.Map (findWithDefault) > import Data.Monoid (mempty) > > import qualified Ganeti.DataCollectors.CPUload as CPUload > +import qualified Ganeti.DataCollectors.Diagnose as Diagnose > import qualified Ganeti.DataCollectors.Diskstats as Diskstats > import qualified Ganeti.DataCollectors.Drbd as Drbd > import qualified Ganeti.DataCollectors.InstStatus as InstStatus > @@ -57,6 +58,7 @@ collectors = > , drdbCollector > , instStatusCollector > , lvCollector > + , diagnoseCollector > ] > where > f .&&. g = \x y -> f x y && g x y > @@ -82,6 +84,9 @@ collectors = > lvCollector = > DataCollector Lv.dcName Lv.dcCategory Lv.dcKind > (StatelessR Lv.dcReport) Nothing activeConfig updateInterval > + diagnoseCollector = > + DataCollector Diagnose.dcName Diagnose.dcCategory Diagnose.dcKind > + (StatelessR Diagnose.dcReport) Nothing activeConfig updateInterval > cpuLoadCollector = > DataCollector CPUload.dcName CPUload.dcCategory CPUload.dcKind > (StatefulR CPUload.dcReport) (Just CPUload.dcUpdate) activeConfig > diff --git a/src/Ganeti/DataCollectors/Diagnose.hs > b/src/Ganeti/DataCollectors/Diagnose.hs > new file mode 100644 > index 0000000..43c6c30 > --- /dev/null > +++ b/src/Ganeti/DataCollectors/Diagnose.hs > @@ -0,0 +1,147 @@ > +{-| Self-diagnose data collector > + > +-} > + > +{- > + > +Copyright (C) 2013 Google Inc. > +All rights reserved. > + > +Redistribution and use in source and binary forms, with or without > +modification, are permitted provided that the following conditions are > +met: > + > +1. Redistributions of source code must retain the above copyright notice, > +this list of conditions and the following disclaimer. > + > +2. Redistributions in binary form must reproduce the above copyright > +notice, this list of conditions and the following disclaimer in the > +documentation and/or other materials provided with the distribution. > + > +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS > +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED > +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR > +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR > +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, > +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, > +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR > +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF > +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING > +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS > +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + > +-} > + > +module Ganeti.DataCollectors.Diagnose > + ( dcName > + , dcCategory > + , dcKind > + , dcReport > + ) where > + > +import Control.Monad.Trans.Class (lift) > +import System.Directory (doesFileExist) > +import System.FilePath.Posix (isValid, takeFileName, (</>)) > +import System.Posix.Files (getFileStatus, fileOwner, fileGroup, > + fileMode, ownerModes, groupReadMode, > + groupExecuteMode, otherReadMode, > + otherExecuteMode, intersectFileModes, > + unionFileModes, ownerExecuteMode, > + isRegularFile) > +import System.Process (readProcess) > +import Text.JSON (JSValue(..), toJSObject, toJSString, decode, Result(..)) > + > +import Ganeti.BasicTypes (runResultT, ResultT(..), genericResult) > +import Ganeti.Config (loadConfig) > +import Ganeti.Constants (dataCollectorDiagnose, > dataCollectorDiagnoseDirectory) > +import Ganeti.DataCollectors.Types (DCCategory(..), DCKind(..), > DCVersion(..), > + DCReport(..), buildReport) > +import Ganeti.Objects (configCluster, clusterDiagnoseDataCollectorFilename) > +import Ganeti.Path (clusterConfFile) > + > +-- | The name of this data collector. > +dcName :: String > +dcName = dataCollectorDiagnose > + > +-- | The category of this data collector. > +dcCategory :: Maybe DCCategory > +dcCategory = Just DCNode > + > +-- | The kind of this data collector. > +dcKind :: DCKind > +dcKind = DCKStatus > + > +-- | The version of this data collector. > +dcVersion :: DCVersion > +dcVersion = DCVerBuiltin > + > +-- | The version number for the data format of this data collector. > +dcFormatVersion :: Int > +dcFormatVersion = 1 > + > +okWithDetails :: String -> JSValue > +okWithDetails details = JSObject $ toJSObject > + [ ("status", JSString $ toJSString "Ok") > + , ("details", JSString $ toJSString details) > + ] > + > + > +fnToVal :: String -> IO JSValue > +fnToVal fn > + | null fn = return $ okWithDetails > + "No file specified for diagnose data collector" > + | not $ isValid fn = return $ okWithDetails > + "Invalid filename specified for diagnose data collector" > + | takeFileName fn /= fn = return $ okWithDetails > + "Filepaths cannot be specified for diagnose data collector" > + | otherwise = do > + let fp = dataCollectorDiagnoseDirectory </> fn > + exists <- doesFileExist fp > + if exists > + then do > + fs <- getFileStatus fp > + let maxFileMode = ownerModes `unionFileModes` groupReadMode > + `unionFileModes` groupExecuteMode > + `unionFileModes` otherReadMode > + `unionFileModes` otherExecuteMode > + isSubSetOf m1 m2 = m1 `intersectFileModes` m2 == m1 > + case () of _ > + | fileOwner fs /= 0 -> return $ okWithDetails > + "File for diagnose data collector must be owned by > root" > + | fileGroup fs /= 0 -> return $ okWithDetails > + "File for diagnose data collector must have group > root" > + | isSubSetOf (fileMode fs) maxFileMode -> > + return . okWithDetails $ > + "File for diagnose data collector " ++ > + "must have permissions 755 or stricter" > + | isSubSetOf ownerExecuteMode (fileMode fs) -> > + return . okWithDetails $ > + "File for diagnose data collector " ++ > + "must be executable by owner"
This rejects(!) files where the executable bit is set for the owner. This is wrong. In particular, it means, you will never be able to execute the program. Please do at least some very basic testing before wasting everyone's time by sending out patch series that never work, not even in the main intended use case. > + | isSubSetOf groupExecuteMode (fileMode fs) -> > + return . okWithDetails $ > + "File for diagnose data collector " ++ > + "must be executable by group" No, there is no requirement that the group executable bit be set. "Executable by root:root" means that auser with user id root and group root can execute the program. As the file is owned by root, the owner bits will always decide. -- Klaus Aehlig Google Germany GmbH, Dienerstr. 12, 80331 Muenchen Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Geschaeftsfuehrer: Graham Law, Christine Elizabeth Flores
