Add 'ReqInstDisks' request type and allow Confd to query for the disks
of an instance. The helper function 'getInstDisks' returns the list
of instances on the given node along with their disks and is
used by the function 'addInstNameToLv'.

Update the test's data file 'instance-prim-sec' and rename it to
'instance-disks' as it doesn't return the primary and secondary
instances of a node any more, but it returns the instances and their
disks.

Signed-off-by: Ilias Tsitsimpis <[email protected]>
---
 Makefile.am                                  |   2 +-
 src/Ganeti/Confd/ClientFunctions.hs          |  45 ++++++--
 src/Ganeti/Confd/Server.hs                   |  11 ++
 src/Ganeti/Confd/Types.hs                    |   1 +
 src/Ganeti/Constants.hs                      |   3 +
 src/Ganeti/DataCollectors/InstStatus.hs      |   2 +-
 src/Ganeti/DataCollectors/Lv.hs              |  45 ++++----
 test/data/instance-disks.txt                 | 152 +++++++++++++++++++++++++++
 test/data/instance-prim-sec.txt              |  88 ----------------
 test/hs/shelltests/htools-mon-collector.test |   2 +-
 10 files changed, 230 insertions(+), 121 deletions(-)
 create mode 100644 test/data/instance-disks.txt
 delete mode 100644 test/data/instance-prim-sec.txt

diff --git a/Makefile.am b/Makefile.am
index 5be9d1c..01cbfe9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1419,7 +1419,7 @@ TEST_FILES = \
        test/data/cluster_config_2.10.json \
        test/data/cluster_config_2.11.json \
        test/data/instance-minor-pairing.txt \
-       test/data/instance-prim-sec.txt \
+       test/data/instance-disks.txt \
        test/data/ip-addr-show-dummy0.txt \
        test/data/ip-addr-show-lo-ipv4.txt \
        test/data/ip-addr-show-lo-ipv6.txt \
diff --git a/src/Ganeti/Confd/ClientFunctions.hs 
b/src/Ganeti/Confd/ClientFunctions.hs
index 03f8e43..3def032 100644
--- a/src/Ganeti/Confd/ClientFunctions.hs
+++ b/src/Ganeti/Confd/ClientFunctions.hs
@@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
 module Ganeti.Confd.ClientFunctions
   ( getInstances
+  , getInstDisks
   ) where
 
 import qualified Text.JSON as J
@@ -42,12 +43,40 @@ getInstances
   :: String
   -> Maybe String
   -> Maybe Int
-  -> IO (BT.Result ([Ganeti.Objects.Instance], [Ganeti.Objects.Instance]))
+  -> BT.ResultT String IO ([Ganeti.Objects.Instance], 
[Ganeti.Objects.Instance])
 getInstances node srvAddr srvPort = do
-  client <- getConfdClient srvAddr srvPort
-  reply <- query client ReqNodeInstances $ PlainQuery node
-  return $
-    case fmap (J.readJSON . confdReplyAnswer) reply of
-      Just (J.Ok instances) -> BT.Ok instances
-      Just (J.Error msg) -> BT.Bad msg
-      Nothing -> BT.Bad "No answer from the Confd server"
+  client <- liftIO $ getConfdClient srvAddr srvPort
+  reply <- liftIO $ query client ReqNodeInstances $ PlainQuery node
+  case fmap (J.readJSON . confdReplyAnswer) reply of
+    Just (J.Ok instances) -> return instances
+    Just (J.Error msg) -> fail msg
+    Nothing -> fail "No answer from the Confd server"
+
+-- | Get the list of disks that belong to a given instance
+-- The server address and the server port parameters are mainly intended
+-- for testing purposes. If they are Nothing, the default values will be used.
+getDisks
+  :: Ganeti.Objects.Instance
+  -> Maybe String
+  -> Maybe Int
+  -> BT.ResultT String IO [Ganeti.Objects.Disk]
+getDisks inst srvAddr srvPort = do
+  client <- liftIO $ getConfdClient srvAddr srvPort
+  reply <- liftIO $ query client ReqInstDisks . PlainQuery . instUuid $ inst
+  case fmap (J.readJSON . confdReplyAnswer) reply of
+    Just (J.Ok disks) -> return disks
+    Just (J.Error msg) -> fail msg
+    Nothing -> fail "No answer from the Confd server"
+
+-- | Get the list of instances on the given node along with their disks
+-- The server address and the server port parameters are mainly intended
+-- for testing purposes. If they are Nothing, the default values will be used.
+getInstDisks
+  :: String
+  -> Maybe String
+  -> Maybe Int
+  -> BT.ResultT String IO [(Ganeti.Objects.Instance, [Ganeti.Objects.Disk])]
+getInstDisks node srvAddr srvPort =
+  getInstances node srvAddr srvPort >>=
+    return . uncurry (++) >>=
+    mapM (\i -> getDisks i srvAddr srvPort >>= return . (,) i)
diff --git a/src/Ganeti/Confd/Server.hs b/src/Ganeti/Confd/Server.hs
index f51b9fb..7e497b7 100644
--- a/src/Ganeti/Confd/Server.hs
+++ b/src/Ganeti/Confd/Server.hs
@@ -221,6 +221,17 @@ buildResponse cdata req@(ConfdRequest { confdRqType = 
ReqNodeInstances }) = do
       instances = getNodeInstances cfg node_uuid
   return (ReplyStatusOk, J.showJSON instances)
 
+-- | Return the list of disks for an instance given the instance uuid.
+buildResponse cdata req@(ConfdRequest { confdRqType = ReqInstDisks }) = do
+  let cfg = fst cdata
+  inst_uuid <-
+    case confdRqQuery req of
+      PlainQuery str -> return str
+      _ -> fail $ "Invalid query type " ++ show (confdRqQuery req)
+  case getInstDisksByName cfg inst_uuid of
+    Ok disks -> return (ReplyStatusOk, J.showJSON disks)
+    Bad e -> fail $ "Could not retrieve disks: " ++ show e
+
 -- | Creates a ConfdReply from a given answer.
 serializeResponse :: Result StatusAnswer -> ConfdReply
 serializeResponse r =
diff --git a/src/Ganeti/Confd/Types.hs b/src/Ganeti/Confd/Types.hs
index 03aded6..ab8f840 100644
--- a/src/Ganeti/Confd/Types.hs
+++ b/src/Ganeti/Confd/Types.hs
@@ -63,6 +63,7 @@ $(declareILADT "ConfdRequestType"
   , ("ReqInstIpsList",      6)
   , ("ReqNodeDrbd",         7)
   , ("ReqNodeInstances",    8)
+  , ("ReqInstDisks",        9)
   ])
 $(makeJSONInstance ''ConfdRequestType)
 
diff --git a/src/Ganeti/Constants.hs b/src/Ganeti/Constants.hs
index f9c3ef1..f9bb1c2 100644
--- a/src/Ganeti/Constants.hs
+++ b/src/Ganeti/Constants.hs
@@ -4056,6 +4056,9 @@ confdReqNodeDrbd = Types.confdRequestTypeToRaw ReqNodeDrbd
 confdReqNodeInstances :: Int
 confdReqNodeInstances = Types.confdRequestTypeToRaw ReqNodeInstances
 
+confdReqInstDisks :: Int
+confdReqInstDisks = Types.confdRequestTypeToRaw ReqInstDisks
+
 confdReqs :: FrozenSet Int
 confdReqs =
   ConstantUtils.mkSet .
diff --git a/src/Ganeti/DataCollectors/InstStatus.hs 
b/src/Ganeti/DataCollectors/InstStatus.hs
index ed898d9..936c5b3 100644
--- a/src/Ganeti/DataCollectors/InstStatus.hs
+++ b/src/Ganeti/DataCollectors/InstStatus.hs
@@ -180,7 +180,7 @@ computeGlobalStatus instStatusList =
 buildInstStatusReport :: Maybe String -> Maybe Int -> IO DCReport
 buildInstStatusReport srvAddr srvPort = do
   node <- getHostName
-  answer <- getInstances node srvAddr srvPort
+  answer <- runResultT $ getInstances node srvAddr srvPort
   inst <- exitIfBad "Can't get instance info from ConfD" answer
   d <- getInferredDomInfo
   reportData <-
diff --git a/src/Ganeti/DataCollectors/Lv.hs b/src/Ganeti/DataCollectors/Lv.hs
index d296b0f..7dde006 100644
--- a/src/Ganeti/DataCollectors/Lv.hs
+++ b/src/Ganeti/DataCollectors/Lv.hs
@@ -122,20 +122,21 @@ getLvInfo inputFile = do
         ++ show contexts ++ "\n" ++ errorMessage
     A.Done _ lvinfoD -> return lvinfoD
 
--- | Get the list of instances on the current node (both primary and secondary)
+-- | Get the list of instances on the current node along with their disks,
 -- either from a provided file or by querying Confd.
-getInstanceList :: Options -> IO ([Instance], [Instance])
-getInstanceList opts = do
+getInstDiskList :: Options -> IO [(Instance, [Disk])]
+getInstDiskList opts = do
   let srvAddr = optConfdAddr opts
       srvPort = optConfdPort opts
       instFile = optInstances opts
-      fromConfdUnchecked :: IO (BT.Result ([Instance], [Instance]))
-      fromConfdUnchecked = getHostName >>= \n -> getInstances n srvAddr srvPort
-      fromConfd :: IO (BT.Result ([Instance], [Instance]))
+      fromConfdUnchecked :: IO (BT.Result [(Instance, [Disk])])
+      fromConfdUnchecked = getHostName >>=
+        \n -> BT.runResultT $ getInstDisks n srvAddr srvPort
+      fromConfd :: IO (BT.Result [(Instance, [Disk])])
       fromConfd =
         liftM (either (BT.Bad . show) id) (E.try fromConfdUnchecked :: 
-          IO (Either IOError (BT.Result ([Instance], [Instance]))))
-      fromFile :: FilePath -> IO (BT.Result ([Instance], [Instance]))
+          IO (Either IOError (BT.Result [(Instance, [Disk])])))
+      fromFile :: FilePath -> IO (BT.Result [(Instance, [Disk])])
       fromFile inputFile = do
         contents <-
           ((E.try $ readFile inputFile) :: IO (Either IOError String))
@@ -145,28 +146,28 @@ getInstanceList opts = do
   exitIfBad "Unable to obtain the list of instances" instances
 
 -- | Adds the name of the instance to the information about one logical volume.
-addInstNameToOneLv :: [Instance] -> LVInfo -> LVInfo
-addInstNameToOneLv instances lvInfo =
-  let vg_name = lviVgName lvInfo
-      lv_name = lviName lvInfo
-      instanceHasDisk = any (includesLogicalId vg_name lv_name) . instDisks
-      rightInstance = find instanceHasDisk instances
-    in 
-      case rightInstance of
-        Nothing -> lvInfo
-        Just i -> lvInfo { lviInstance = Just $ instName i }
+addInstNameToOneLv :: [(Instance, [Disk])] -> LVInfo -> LVInfo
+addInstNameToOneLv instDiskList lvInfo =
+ let vg_name = lviVgName lvInfo
+     lv_name = lviName lvInfo
+     instanceHasDisk = any (includesLogicalId vg_name lv_name) . snd
+     rightInstance = find instanceHasDisk instDiskList
+   in
+     case rightInstance of
+       Nothing -> lvInfo
+       Just (i, _) -> lvInfo { lviInstance = Just $ instName i }
 
 -- | Adds the name of the instance to the information about logical volumes.
-addInstNameToLv :: [Instance] -> [LVInfo] -> [LVInfo]
-addInstNameToLv instances = map (addInstNameToOneLv instances)
+addInstNameToLv :: [(Instance, [Disk])] -> [LVInfo] -> [LVInfo]
+addInstNameToLv instDisksList = map (addInstNameToOneLv instDisksList)
 
 -- | This function computes the JSON representation of the LV status.
 buildJsonReport :: Options -> IO J.JSValue
 buildJsonReport opts = do
   let inputFile = optInputFile opts
   lvInfo <- getLvInfo inputFile
-  (prim, sec) <- getInstanceList opts
-  return . J.showJSON $ addInstNameToLv (prim ++ sec) lvInfo
+  instDiskList <- getInstDiskList opts
+  return . J.showJSON $ addInstNameToLv instDiskList lvInfo
 
 -- | This function computes the DCReport for the logical volumes.
 buildDCReport :: Options -> IO DCReport
diff --git a/test/data/instance-disks.txt b/test/data/instance-disks.txt
new file mode 100644
index 0000000..67568c2
--- /dev/null
+++ b/test/data/instance-disks.txt
@@ -0,0 +1,152 @@
+[[{"admin_state": "up",
+   "beparams": {},
+   "ctime": 1372838883.9710441,
+   "disk_template": "drbd",
+   "disks": [
+     {
+       "children": [
+         {
+           "dev_type": "plain",
+           "logical_id": [
+             "xenvg",
+             "df9ff3f6-a833-48ff-8bd5-bff2eaeab759.disk0_data"
+           ],
+           "params": {},
+           "physical_id": [
+             "xenvg",
+             "df9ff3f6-a833-48ff-8bd5-bff2eaeab759.disk0_data"
+           ],
+           "size": 1024,
+           "uuid": "eaff6322-1bfb-4d59-b306-4535730917cc",
+           "serial_no": 1,
+           "ctime": 1372838946.2599809,
+           "mtime": 1372838946.2599809
+         },
+         {
+           "dev_type": "plain",
+           "logical_id": [
+             "xenvg",
+             "df9ff3f6-a833-48ff-8bd5-bff2eaeab759.disk0_meta"
+           ],
+           "params": {},
+           "physical_id": [
+             "xenvg",
+             "df9ff3f6-a833-48ff-8bd5-bff2eaeab759.disk0_meta"
+           ],
+           "size": 128,
+           "uuid": "bf512e95-2a49-4cb3-8d1f-30a503f6bf1b",
+           "serial_no": 1,
+           "ctime": 1372838946.2599809,
+           "mtime": 1372838946.2599809
+         }
+       ],
+       "dev_type": "drbd",
+       "iv_name": "disk/0",
+       "logical_id": [
+         "60e687a0-21fc-4577-997f-ccd08925fa65",
+         "c739c7f3-79d8-4e20-ac68-662e16577d2e",
+         11000,
+         0,
+         0,
+         "9bdb15fb7ab6bb4610a313d654ed4d0d2433713e"
+       ],
+       "mode": "rw",
+       "params": {},
+       "physical_id": [
+         "172.16.241.3",
+         11000,
+         "172.16.241.2",
+         11000,
+         0,
+         "9bdb15fb7ab6bb4610a313d654ed4d0d2433713e"
+       ],
+       "size": 1024,
+       "uuid": "5d61e205-bf89-4ba8-a319-589b7bb7419e",
+       "serial_no": 1,
+       "ctime": 1372838946.2599809,
+       "mtime": 1372838946.2599809
+     }
+   ],
+   "disks_active": true,
+   "hvparams": {},
+   "hypervisor": "xen-pvm",
+   "mtime": 1372838946.2599809,
+   "name": "instance1.example.com",
+   "nics": [
+     {
+       "mac": "aa:00:00:1d:ba:63",
+       "nicparams": {},
+       "uuid": "7b7f4249-fab8-4b3f-b446-d7a2aff37644"
+     }
+   ],
+   "os": "busybox",
+   "osparams": {},
+   "osparams_private": {},
+   "primary_node": "60e687a0-21fc-4577-997f-ccd08925fa65",
+   "serial_no": 2,
+   "uuid": "aec390cb-5eae-44e6-bcc2-ec14d31347f0"
+ },
+ [{
+   "children": [
+     {
+       "dev_type": "plain",
+       "logical_id": [
+         "xenvg",
+         "df9ff3f6-a833-48ff-8bd5-bff2eaeab759.disk0_data"
+         ],
+       "params": {},
+       "physical_id": [
+         "xenvg",
+         "df9ff3f6-a833-48ff-8bd5-bff2eaeab759.disk0_data"
+         ],
+       "size": 1024,
+       "uuid": "eaff6322-1bfb-4d59-b306-4535730917cc",
+       "serial_no": 1,
+       "ctime": 1372838946.2599809,
+       "mtime": 1372838946.2599809
+       },
+     {
+       "dev_type": "plain",
+       "logical_id": [
+         "xenvg",
+         "df9ff3f6-a833-48ff-8bd5-bff2eaeab759.disk0_meta"
+         ],
+       "params": {},
+       "physical_id": [
+         "xenvg",
+         "df9ff3f6-a833-48ff-8bd5-bff2eaeab759.disk0_meta"
+         ],
+       "size": 128,
+       "uuid": "bf512e95-2a49-4cb3-8d1f-30a503f6bf1b",
+       "serial_no": 1,
+       "mtime": 1372838946.2599809,
+       "ctime": 1372838946.2599809
+       }
+     ],
+   "dev_type": "drbd",
+   "iv_name": "disk/0",
+   "logical_id": [
+     "60e687a0-21fc-4577-997f-ccd08925fa65",
+     "c739c7f3-79d8-4e20-ac68-662e16577d2e",
+     11000,
+     0,
+     0,
+     "9bdb15fb7ab6bb4610a313d654ed4d0d2433713e"
+     ],
+   "mode": "rw",
+   "params": {},
+   "physical_id": [
+     "172.16.241.3",
+     11000,
+     "172.16.241.2",
+     11000,
+     0,
+     "9bdb15fb7ab6bb4610a313d654ed4d0d2433713e"
+     ],
+   "size": 1024,
+   "uuid": "5d61e205-bf89-4ba8-a319-589b7bb7419e",
+   "serial_no": 1,
+   "ctime": 1372838946.2599809,
+   "mtime": 1372838946.2599809
+  }]]
+]
diff --git a/test/data/instance-prim-sec.txt b/test/data/instance-prim-sec.txt
deleted file mode 100644
index b27fd5c..0000000
--- a/test/data/instance-prim-sec.txt
+++ /dev/null
@@ -1,88 +0,0 @@
-[[{"admin_state": "up",
-   "beparams": {},
-   "ctime": 1372838883.9710441,
-   "disk_template": "drbd",
-   "disks": [
-     {
-       "children": [
-         {
-           "dev_type": "plain",
-           "logical_id": [
-             "xenvg",
-             "df9ff3f6-a833-48ff-8bd5-bff2eaeab759.disk0_data"
-           ],
-           "params": {},
-           "physical_id": [
-             "xenvg",
-             "df9ff3f6-a833-48ff-8bd5-bff2eaeab759.disk0_data"
-           ],
-           "size": 1024,
-           "uuid": "eaff6322-1bfb-4d59-b306-4535730917cc",
-           "serial_no": 1,
-           "ctime": 1372838946.2599809,
-           "mtime": 1372838946.2599809
-         },
-         {
-           "dev_type": "plain",
-           "logical_id": [
-             "xenvg",
-             "df9ff3f6-a833-48ff-8bd5-bff2eaeab759.disk0_meta"
-           ],
-           "params": {},
-           "physical_id": [
-             "xenvg",
-             "df9ff3f6-a833-48ff-8bd5-bff2eaeab759.disk0_meta"
-           ],
-           "size": 128,
-           "uuid": "bf512e95-2a49-4cb3-8d1f-30a503f6bf1b",
-           "serial_no": 1,
-           "ctime": 1372838946.2599809,
-           "mtime": 1372838946.2599809
-         }
-       ],
-       "dev_type": "drbd",
-       "iv_name": "disk/0",
-       "logical_id": [
-         "60e687a0-21fc-4577-997f-ccd08925fa65",
-         "c739c7f3-79d8-4e20-ac68-662e16577d2e",
-         11000,
-         0,
-         0,
-         "9bdb15fb7ab6bb4610a313d654ed4d0d2433713e"
-       ],
-       "mode": "rw",
-       "params": {},
-       "physical_id": [
-         "172.16.241.3",
-         11000,
-         "172.16.241.2",
-         11000,
-         0,
-         "9bdb15fb7ab6bb4610a313d654ed4d0d2433713e"
-       ],
-       "size": 1024,
-       "uuid": "5d61e205-bf89-4ba8-a319-589b7bb7419e",
-       "serial_no": 1,
-       "ctime": 1372838946.2599809,
-       "mtime": 1372838946.2599809
-     }
-   ],
-   "disks_active": true,
-   "hvparams": {},
-   "hypervisor": "xen-pvm",
-   "mtime": 1372838946.2599809,
-   "name": "instance1.example.com",
-   "nics": [
-     {
-       "mac": "aa:00:00:1d:ba:63",
-       "nicparams": {},
-       "uuid": "7b7f4249-fab8-4b3f-b446-d7a2aff37644"
-     }
-   ],
-   "os": "busybox",
-   "osparams": {},
-   "osparams_private": {},
-   "primary_node": "60e687a0-21fc-4577-997f-ccd08925fa65",
-   "serial_no": 2,
-   "uuid": "aec390cb-5eae-44e6-bcc2-ec14d31347f0"
- }], []]
diff --git a/test/hs/shelltests/htools-mon-collector.test 
b/test/hs/shelltests/htools-mon-collector.test
index 6fcecbd..f4d120e 100644
--- a/test/hs/shelltests/htools-mon-collector.test
+++ b/test/hs/shelltests/htools-mon-collector.test
@@ -104,6 +104,6 @@ Failed reading: versionInfo
 >>>= !0
 
 # Test that lv parses correctly a standard test file
-./test/hs/hpc-mon-collector lv -f $PYTESTDATA_DIR/lvs_lv.txt -i 
$PYTESTDATA_DIR/instance-prim-sec.txt
+./test/hs/hpc-mon-collector lv -f $PYTESTDATA_DIR/lvs_lv.txt -i 
$PYTESTDATA_DIR/instance-disks.txt
 >>>/"instance":"instance1.example.com"/
 >>>= 0
-- 
1.9.1

Reply via email to