--- /dev/null
+{-# LANGUAGE OverloadedStrings #-}
+{-| Logical Volumer information parser
+
+This module holds the definition of the parser that extracts status
+information about the logical volumes (LVs) of the system from the output of the
+@lvs@ command.
+
+-}
+{-
+
+Copyright (C) 2013 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.Storage.Lvm.LVParser (lvParser, lvCommand) where
+
+import Control.Applicative ((<*>), (*>), (<*), (<$>), Applicative, )
+import qualified Data.Attoparsec.Text as A
+import qualified Data.Attoparsec.Combinator as AC
+import Data.Attoparsec.Text (Parser)
+import Data.Text (unpack)
+
+import Ganeti.Storage.Lvm.Types
+
+
+-- | The separator of the fields returned by @lvs@
+lvsSeparator :: Char
+lvsSeparator = ';'
+
+-- * Utility functions
+
+-- | Our own space-skipping function, because A.skipSpace also skips
+-- newline characters. It skips ZERO or more spaces, so it does not
+-- fail if there are no spaces.
+skipSpaces :: Parser ()
+skipSpaces = A.skipWhile A.isHorizontalSpace
+
+-- | A parser recognizing a number of bytes, represented as a number preceeded
+-- by a separator and followed by the "B" character.
+bytesP :: Parser Int
+bytesP = A.char lvsSeparator *> A.decimal <* A.char 'B'
+
+-- | A parser recognizing a number discarding the preceeding separator
+intP :: Parser Int
+intP = A.char lvsSeparator *> A.signed A.decimal
+
+-- | A parser recognizing a string starting with and closed by a separator (both
+-- are discarded)
+stringP :: Parser String
+stringP =
+ A.char lvsSeparator *> fmap unpack (A.takeWhile (`notElem`
+ [ lvsSeparator
+ , '\n']
+ ))
+
+-- * Parser implementation
+
+-- | The command providing the data, in the format the parser expects
+lvCommand :: [String]
+lvCommand =
+ [ "lvs"
+ , "--noheadings"
+ , "--units B"
+ , "-- separator ;"
+ , "-o lv_uuid,lv_name,lv_attr,lv_major,lv_minor,lv_kernel_major\
+ \,lv_kernel_minor,lv_size,seg_count,lv_tags,modules,vg_uuid,vg_name,segtype\
+ \,seg_start,seg_start_pe,seg_size,seg_tags,seg_pe_ranges,devices"
+ ]
+
+-- | The parser for one line of the diskstatus file.
+oneLvParser :: Parser LVInfo
+oneLvParser =
+ let uuidP = skipSpaces *> fmap unpack (A.takeWhile (/= lvsSeparator))
+ nameP = stringP
+ attrP = stringP
+ majorP = intP
+ minorP = intP
+ kernelMajorP = intP
+ kernelMinorP = intP
+ sizeP = bytesP
+ segCountP = intP
+ tagsP = stringP
+ modulesP = stringP
+ vgUuidP = stringP
+ vgNameP = stringP
+ segtypeP = stringP
+ segStartP = bytesP
+ segStartPeP = intP
+ segSizeP = bytesP
+ segTagsP = stringP
+ segPeRangesP = stringP
+ devicesP = stringP
+ in
+ LVInfo
+ <$> uuidP <*> nameP <*> attrP <*> majorP <*> minorP <*> kernelMajorP
+ <*> kernelMinorP <*> sizeP <*> segCountP <*> tagsP <*> modulesP
+ <*> vgUuidP <*> vgNameP <*> segtypeP <*> segStartP <*> segStartPeP
+ <*> segSizeP <*> segTagsP <*> segPeRangesP <*> devicesP <* A.endOfLine
+
+-- | The parser for a whole diskstatus file.
+lvParser :: Parser [LVInfo]
+lvParser = oneLvParser `AC.manyTill` A.endOfInput
--- /dev/null
+{-# LANGUAGE TemplateHaskell #-}
+{-| LVM data types
+
+This module holds the definition of the data types describing the status of the
+disks according to LVM (and particularly the lvs tool).
+
+-}
+{-
+
+Copyright (C) 2013 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.Storage.Lvm.Types
+ ( LVInfo(..)
+ ) where
+
+import Ganeti.THH
+
+
+-- | This is the format of the report produced by each data collector.
+$(buildObject "LVInfo" "lvi"
+ [ simpleField "uuid" [t| String |]
+ , simpleField "name" [t| String |]
+ , simpleField "attr" [t| String |]
+ , simpleField "major" [t| Int |]
+ , simpleField "minor" [t| Int |]
+ , simpleField "kernel_major" [t| Int |]
+ , simpleField "kernel_minor" [t| Int |]
+ , simpleField "size" [t| Int |]
+ , simpleField "seg_count" [t| Int |]
+ , simpleField "tags" [t| String |]
+ , simpleField "modules" [t| String |]
+ , simpleField "vg_uuid" [t| String |]
+ , simpleField "vg_name" [t| String |]
+ , simpleField "segtype" [t| String |]
+ , simpleField "seg_start" [t| Int |]
+ , simpleField "seg_start_pe" [t| Int |]
+ , simpleField "seg_size" [t| Int |]
+ , simpleField "seg_tags" [t| String |]
+ , simpleField "seg_pe_ranges" [t| String |]
+ , simpleField "devices" [t| String |]
+ ])