Revision 2724417c

b/src/Ganeti/HTools/Backend/IAlloc.hs
85 85
  let errorMessage = "invalid data for instance '" ++ n ++ "'"
86 86
  let extract x = tryFromObj errorMessage a x
87 87
  disk  <- extract "disk_space_total"
88
  disks <- extract "disks" >>= toArray >>= asObjectList >>=
89
           mapM (flip (tryFromObj errorMessage) "size" . fromJSObject)
88
  jsdisks <- extract "disks" >>= toArray >>= asObjectList
89
  dsizes <- mapM (flip (tryFromObj errorMessage) "size" . fromJSObject) jsdisks
90
  dspindles <- mapM (annotateResult errorMessage .
91
                     flip maybeFromObj "spindles" . fromJSObject) jsdisks
92
  let disks = zipWith Instance.Disk dsizes dspindles
90 93
  mem   <- extract "memory"
91 94
  vcpus <- extract "vcpus"
92 95
  tags  <- extract "tags"
b/src/Ganeti/HTools/Backend/Luxi.hs
173 173
  xauto_balance <- convert "auto_balance" auto_balance
174 174
  xdt <- convert "disk_template" disk_template
175 175
  xsu <- convert "be/spindle_use" su
176
  let inst = Instance.create xname xmem xdisk [xdisk] xvcpus
177
             xrunning xtags xauto_balance xpnode snode xdt xsu []
176
  let inst = Instance.create xname xmem xdisk [Instance.Disk xdisk Nothing]
177
             xvcpus xrunning xtags xauto_balance xpnode snode xdt xsu []
178 178
  return (xname, inst)
179 179

  
180 180
parseInstance _ v = fail ("Invalid instance query result: " ++ show v)
b/src/Ganeti/HTools/Backend/Rapi.hs
122 122
  let owner_name = "Instance '" ++ name ++ "', error while parsing data"
123 123
  let extract s x = tryFromObj owner_name x s
124 124
  disk <- extract "disk_usage" a
125
  disks <- extract "disk.sizes" a
125
  dsizes <- extract "disk.sizes" a
126
  dspindles <- tryArrayMaybeFromObj owner_name a "disk.spindles"
126 127
  beparams <- liftM fromJSObject (extract "beparams" a)
127 128
  omem <- extract "oper_ram" a
128 129
  mem <- case omem of
......
139 140
  auto_balance <- extract "auto_balance" beparams
140 141
  dt <- extract "disk_template" a
141 142
  su <- extract "spindle_use" beparams
143
  let disks = zipWith Instance.Disk dsizes dspindles
142 144
  let inst = Instance.create name mem disk disks vcpus running tags
143 145
             auto_balance pnode snode dt su []
144 146
  return (name, inst)
b/src/Ganeti/HTools/Backend/Text.hs
111 111
      snode = (if sidx == Node.noSecondary
112 112
                 then ""
113 113
                 else Container.nameOf nl sidx)
114
  in printf "%s|%d|%d|%d|%s|%s|%s|%s|%s|%s|%d"
114
  in printf "%s|%d|%d|%d|%s|%s|%s|%s|%s|%s|%d|%s"
115 115
       iname (Instance.mem inst) (Instance.dsk inst)
116 116
       (Instance.vcpus inst) (instanceStatusToRaw (Instance.runSt inst))
117 117
       (if Instance.autoBalance inst then "Y" else "N")
118 118
       pnode snode (diskTemplateToRaw (Instance.diskTemplate inst))
119 119
       (intercalate "," (Instance.allTags inst)) (Instance.spindleUse inst)
120
       -- disk spindles are summed together, as it's done for disk size
121
       (case Instance.getTotalSpindles inst of
122
          Nothing -> "-"
123
          Just x -> show x)
120 124

  
121 125
-- | Generate instance file data from instance objects.
122 126
serializeInstances :: Node.List -> Instance.List -> String
......
244 248
                                               -- instance name and
245 249
                                               -- the instance object
246 250
loadInst ktn [ name, mem, dsk, vcpus, status, auto_bal, pnode, snode
247
             , dt, tags, su ] = do
251
             , dt, tags, su, spindles ] = do
248 252
  pidx <- lookupNode ktn name pnode
249 253
  sidx <- if null snode
250 254
            then return Node.noSecondary
251 255
            else lookupNode ktn name snode
252 256
  vmem <- tryRead name mem
253
  vdsk <- tryRead name dsk
257
  dsize <- tryRead name dsk
254 258
  vvcpus <- tryRead name vcpus
255 259
  vstatus <- instanceStatusFromRaw status
256 260
  auto_balance <- case auto_bal of
......
261 265
  disk_template <- annotateResult ("Instance " ++ name)
262 266
                   (diskTemplateFromRaw dt)
263 267
  spindle_use <- tryRead name su
268
  vspindles <- case spindles of
269
                 "-" -> return Nothing
270
                 _ -> liftM Just (tryRead name spindles)
271
  let disk = Instance.Disk dsize vspindles
264 272
  let vtags = commaSplit tags
265
      newinst = Instance.create name vmem vdsk [vdsk] vvcpus vstatus vtags
273
      newinst = Instance.create name vmem dsize [disk] vvcpus vstatus vtags
266 274
                auto_balance pidx sidx disk_template spindle_use []
267 275
  when (Instance.hasSecondary newinst && sidx == pidx) . fail $
268 276
    "Instance " ++ name ++ " has same primary and secondary node - " ++ pnode
......
272 280
             , dt, tags ] = loadInst ktn [ name, mem, dsk, vcpus, status,
273 281
                                           auto_bal, pnode, snode, dt, tags,
274 282
                                           "1" ]
283

  
284
loadInst ktn [ name, mem, dsk, vcpus, status, auto_bal, pnode, snode
285
             , dt, tags, su ] =
286
  loadInst ktn [ name, mem, dsk, vcpus, status, auto_bal, pnode, snode, dt
287
               , tags, su, "-" ]
288

  
275 289
loadInst _ s = fail $ "Invalid/incomplete instance data: '" ++ show s ++ "'"
276 290

  
277 291
-- | Loads a spec from a field list.
b/src/Ganeti/HTools/Instance.hs
28 28

  
29 29
module Ganeti.HTools.Instance
30 30
  ( Instance(..)
31
  , Disk(..)
31 32
  , AssocList
32 33
  , List
33 34
  , create
......
45 46
  , setBoth
46 47
  , setMovable
47 48
  , specOf
49
  , getTotalSpindles
48 50
  , instBelowISpec
49 51
  , instAboveISpec
50 52
  , instMatchesPolicy
......
65 67
import Ganeti.Utils
66 68

  
67 69
-- * Type declarations
70
data Disk = Disk
71
  { dskSize     :: Int       -- ^ Size in bytes
72
  , dskSpindles :: Maybe Int -- ^ Number of spindles
73
  } deriving (Show, Eq)
68 74

  
69 75
-- | The instance type.
70 76
data Instance = Instance
......
72 78
  , alias        :: String    -- ^ The shortened name
73 79
  , mem          :: Int       -- ^ Memory of the instance
74 80
  , dsk          :: Int       -- ^ Total disk usage of the instance
75
  , disks        :: [Int]     -- ^ Sizes of the individual disks
81
  , disks        :: [Disk]    -- ^ Sizes of the individual disks
76 82
  , vcpus        :: Int       -- ^ Number of VCPUs
77 83
  , runSt        :: T.InstanceStatus -- ^ Original run status
78 84
  , pNode        :: T.Ndx     -- ^ Original primary node
......
165 171
--
166 172
-- Some parameters are not initialized by function, and must be set
167 173
-- later (via 'setIdx' for example).
168
create :: String -> Int -> Int -> [Int] -> Int -> T.InstanceStatus
174
create :: String -> Int -> Int -> [Disk] -> Int -> T.InstanceStatus
169 175
       -> [String] -> Bool -> T.Ndx -> T.Ndx -> T.DiskTemplate -> Int
170 176
       -> [Nic] -> Instance
171 177
create name_init mem_init dsk_init disks_init vcpus_init run_init tags_init
......
259 265
                                 else Ok inst { vcpus = v }
260 266
shrinkByType _ f = Bad $ "Unhandled failure mode " ++ show f
261 267

  
268
-- | Get the number of disk spindles
269
getTotalSpindles :: Instance -> Maybe Int
270
getTotalSpindles inst =
271
  foldr (liftM2 (+) . dskSpindles ) (Just 0) (disks inst)
272

  
262 273
-- | Return the spec of an instance.
263 274
specOf :: Instance -> T.RSpec
264 275
specOf Instance { mem = m, dsk = d, vcpus = c } =
......
270 281
instBelowISpec :: Instance -> T.ISpec -> T.OpResult ()
271 282
instBelowISpec inst ispec
272 283
  | mem inst > T.iSpecMemorySize ispec = Bad T.FailMem
273
  | any (> T.iSpecDiskSize ispec) (disks inst) = Bad T.FailDisk
284
  | any (> T.iSpecDiskSize ispec) (map dskSize $ disks inst) = Bad T.FailDisk
274 285
  | vcpus inst > T.iSpecCpuCount ispec = Bad T.FailCPU
275 286
  | otherwise = Ok ()
276 287

  
......
278 289
instAboveISpec :: Instance -> T.ISpec -> T.OpResult ()
279 290
instAboveISpec inst ispec
280 291
  | mem inst < T.iSpecMemorySize ispec = Bad T.FailMem
281
  | any (< T.iSpecDiskSize ispec) (disks inst) = Bad T.FailDisk
292
  | any (< T.iSpecDiskSize ispec) (map dskSize $ disks inst) = Bad T.FailDisk
282 293
  | vcpus inst < T.iSpecCpuCount ispec = Bad T.FailCPU
283 294
  | otherwise = Ok ()
284 295

  
b/src/Ganeti/HTools/Program/Hspace.hs
395 395
-- having a single disk).
396 396
instFromSpec :: RSpec -> DiskTemplate -> Int -> Instance.Instance
397 397
instFromSpec spx dt su =
398
  Instance.create "new" (rspecMem spx) (rspecDsk spx) [rspecDsk spx]
398
  Instance.create "new" (rspecMem spx) (rspecDsk spx)
399
    [Instance.Disk (rspecDsk spx) (Just su)]
399 400
    (rspecCpu spx) Running [] True (-1) (-1) dt su []
400 401

  
401 402
combineTiered :: Maybe Int -> Cluster.AllocNodes -> Cluster.AllocResult ->
b/test/data/htools/rapi/instances.json
49 49
    "disk.sizes": [
50 50
      128
51 51
    ],
52
    "disk.spindles": [
53
      null
54
    ],
52 55
    "admin_state": "up",
53 56
    "nic.links": [
54 57
      "xen-br0"
......
130 133
      256,
131 134
      128
132 135
    ],
136
    "disk.spindles": [
137
      null,
138
      null
139
    ],
133 140
    "admin_state": "down",
134 141
    "nic.links": [
135 142
      "xen-br0"
......
196 203
    "disk.sizes": [
197 204
      2048
198 205
    ],
206
    "disk.spindles": [
207
      null
208
    ],
199 209
    "admin_state": "down",
200 210
    "nic.links": [
201 211
      "xen-br0"
......
290 300
    "disk.sizes": [
291 301
      256
292 302
    ],
303
    "disk.spindles": [
304
      null
305
    ],
293 306
    "admin_state": "down",
294 307
    "nic.links": [
295 308
      "xen-br0"
......
370 383
    "disk.sizes": [
371 384
      128
372 385
    ],
386
    "disk.spindles": [
387
      null
388
    ],
373 389
    "admin_state": "down",
374 390
    "nic.links": [
375 391
      "xen-br0"
......
434 450
    "disk.sizes": [
435 451
      512
436 452
    ],
453
    "disk.spindles": [
454
      null
455
    ],
437 456
    "admin_state": "down",
438 457
    "nic.links": [
439 458
      "xen-br1"
......
498 517
    "disk.sizes": [
499 518
      128
500 519
    ],
520
    "disk.spindles": [
521
      null
522
    ],
501 523
    "admin_state": "down",
502 524
    "nic.links": [
503 525
      "xen-br0"
......
563 585
    "disk.sizes": [
564 586
      128
565 587
    ],
588
    "disk.spindles": [
589
      null
590
    ],
566 591
    "admin_state": "down",
567 592
    "nic.links": [
568 593
      "xen-br0"
......
627 652
    "disk.sizes": [
628 653
      128
629 654
    ],
655
    "disk.spindles": [
656
      null
657
    ],
630 658
    "admin_state": "down",
631 659
    "nic.links": [
632 660
      "xen-br0"
......
723 751
    "disk.sizes": [
724 752
      512
725 753
    ],
754
    "disk.spindles": [
755
      null
756
    ],
726 757
    "admin_state": "down",
727 758
    "nic.links": [
728 759
      "xen-br0"
......
787 818
    "disk.sizes": [
788 819
      128
789 820
    ],
821
    "disk.spindles": [
822
      null
823
    ],
790 824
    "admin_state": "down",
791 825
    "nic.links": [
792 826
      "xen-br0"
b/test/hs/Test/Ganeti/HTools/Instance.hs
62 62
  sn <- arbitrary
63 63
  vcpus <- choose (0, lim_cpu)
64 64
  dt <- arbitrary
65
  return $ Instance.create name mem dsk [dsk] vcpus run_st [] True pn sn dt 1 []
65
  spindles <- arbitrary
66
  let disk = Instance.Disk dsk spindles
67
  return $ Instance.create
68
    name mem dsk [disk] vcpus run_st [] True pn sn dt 1 []
66 69

  
67 70
-- | Generates an instance smaller than a node.
68 71
genInstanceSmallerThanNode :: Node.Node -> Gen Instance.Instance
b/test/hs/Test/Ganeti/TestHTools.hs
99 99
-- | Create an instance given its spec.
100 100
createInstance :: Int -> Int -> Int -> Instance.Instance
101 101
createInstance mem dsk vcpus =
102
  Instance.create "inst-unnamed" mem dsk [dsk] vcpus Types.Running [] True (-1)
103
    (-1) Types.DTDrbd8 1 []
102
  Instance.create "inst-unnamed" mem dsk [Instance.Disk dsk Nothing] vcpus
103
    Types.Running [] True (-1) (-1) Types.DTDrbd8 1 []
104 104

  
105 105
-- | Create a small cluster by repeating a node spec.
106 106
makeSmallCluster :: Node.Node -> Int -> Node.List

Also available in: Unified diff