Statistics
| Branch: | Tag: | Revision:

root / htools / Ganeti / Objects.hs @ 497beee2

History | View | Annotate | Download (19.4 kB)

1
{-# LANGUAGE TemplateHaskell #-}
2

    
3
{-| Implementation of the Ganeti config objects.
4

    
5
Some object fields are not implemented yet, and as such they are
6
commented out below.
7

    
8
-}
9

    
10
{-
11

    
12
Copyright (C) 2011, 2012 Google Inc.
13

    
14
This program is free software; you can redistribute it and/or modify
15
it under the terms of the GNU General Public License as published by
16
the Free Software Foundation; either version 2 of the License, or
17
(at your option) any later version.
18

    
19
This program is distributed in the hope that it will be useful, but
20
WITHOUT ANY WARRANTY; without even the implied warranty of
21
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22
General Public License for more details.
23

    
24
You should have received a copy of the GNU General Public License
25
along with this program; if not, write to the Free Software
26
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27
02110-1301, USA.
28

    
29
-}
30

    
31
module Ganeti.Objects
32
  ( VType(..)
33
  , vTypeFromRaw
34
  , HvParams
35
  , OsParams
36
  , PartialNicParams(..)
37
  , FilledNicParams(..)
38
  , fillNicParams
39
  , allNicParamFields
40
  , PartialNic(..)
41
  , FileDriver(..)
42
  , BlockDriver(..)
43
  , DiskMode(..)
44
  , DiskType(..)
45
  , DiskLogicalId(..)
46
  , Disk(..)
47
  , DiskTemplate(..)
48
  , PartialBeParams(..)
49
  , FilledBeParams(..)
50
  , fillBeParams
51
  , allBeParamFields
52
  , AdminState(..)
53
  , adminStateFromRaw
54
  , Instance(..)
55
  , toDictInstance
56
  , PartialNDParams(..)
57
  , FilledNDParams(..)
58
  , fillNDParams
59
  , allNDParamFields
60
  , Node(..)
61
  , NodeRole(..)
62
  , nodeRoleToRaw
63
  , roleDescription
64
  , AllocPolicy(..)
65
  , FilledISpecParams(..)
66
  , PartialISpecParams(..)
67
  , fillISpecParams
68
  , allISpecParamFields
69
  , FilledIPolicy(..)
70
  , PartialIPolicy(..)
71
  , fillIPolicy
72
  , DiskParams
73
  , NodeGroup(..)
74
  , IpFamily(..)
75
  , ipFamilyToVersion
76
  , fillDict
77
  , ClusterHvParams
78
  , OsHvParams
79
  , ClusterBeParams
80
  , ClusterOsParams
81
  , ClusterNicParams
82
  , Cluster(..)
83
  , ConfigData(..)
84
  , TimeStampObject(..)
85
  , UuidObject(..)
86
  , SerialNoObject(..)
87
  , TagsObject(..)
88
  , DictObject(..) -- re-exported from THH
89
  , TagSet -- re-exported from THH
90
  ) where
91

    
92
import Data.List (foldl')
93
import Data.Maybe
94
import qualified Data.Map as Map
95
import qualified Data.Set as Set
96
import Text.JSON (showJSON, readJSON, JSON, JSValue(..))
97
import qualified Text.JSON as J
98

    
99
import qualified Ganeti.Constants as C
100
import Ganeti.JSON
101
import Ganeti.Types
102
import Ganeti.THH
103

    
104
-- * Generic definitions
105

    
106
-- | Fills one map with keys from the other map, if not already
107
-- existing. Mirrors objects.py:FillDict.
108
fillDict :: (Ord k) => Map.Map k v -> Map.Map k v -> [k] -> Map.Map k v
109
fillDict defaults custom skip_keys =
110
  let updated = Map.union custom defaults
111
  in foldl' (flip Map.delete) updated skip_keys
112

    
113
-- | The VTYPES, a mini-type system in Python.
114
$(declareSADT "VType"
115
  [ ("VTypeString",      'C.vtypeString)
116
  , ("VTypeMaybeString", 'C.vtypeMaybeString)
117
  , ("VTypeBool",        'C.vtypeBool)
118
  , ("VTypeSize",        'C.vtypeSize)
119
  , ("VTypeInt",         'C.vtypeInt)
120
  ])
121
$(makeJSONInstance ''VType)
122

    
123
-- | The hypervisor parameter type. This is currently a simple map,
124
-- without type checking on key/value pairs.
125
type HvParams = Container JSValue
126

    
127
-- | The OS parameters type. This is, and will remain, a string
128
-- container, since the keys are dynamically declared by the OSes, and
129
-- the values are always strings.
130
type OsParams = Container String
131

    
132
-- | Class of objects that have timestamps.
133
class TimeStampObject a where
134
  cTimeOf :: a -> Double
135
  mTimeOf :: a -> Double
136

    
137
-- | Class of objects that have an UUID.
138
class UuidObject a where
139
  uuidOf :: a -> String
140

    
141
-- | Class of object that have a serial number.
142
class SerialNoObject a where
143
  serialOf :: a -> Int
144

    
145
-- | Class of objects that have tags.
146
class TagsObject a where
147
  tagsOf :: a -> Set.Set String
148

    
149
-- * Node role object
150

    
151
$(declareSADT "NodeRole"
152
  [ ("NROffline",   'C.nrOffline)
153
  , ("NRDrained",   'C.nrDrained)
154
  , ("NRRegular",   'C.nrRegular)
155
  , ("NRCandidate", 'C.nrMcandidate)
156
  , ("NRMaster",    'C.nrMaster)
157
  ])
158
$(makeJSONInstance ''NodeRole)
159

    
160
-- | The description of the node role.
161
roleDescription :: NodeRole -> String
162
roleDescription NROffline   = "offline"
163
roleDescription NRDrained   = "drained"
164
roleDescription NRRegular   = "regular"
165
roleDescription NRCandidate = "master candidate"
166
roleDescription NRMaster    = "master"
167

    
168
-- * NIC definitions
169

    
170
$(buildParam "Nic" "nicp"
171
  [ simpleField "mode" [t| NICMode |]
172
  , simpleField "link" [t| String  |]
173
  ])
174

    
175
$(buildObject "PartialNic" "nic"
176
  [ simpleField "mac" [t| String |]
177
  , optionalField $ simpleField "ip" [t| String |]
178
  , simpleField "nicparams" [t| PartialNicParams |]
179
  ])
180

    
181
-- * Disk definitions
182

    
183
$(declareSADT "DiskMode"
184
  [ ("DiskRdOnly", 'C.diskRdonly)
185
  , ("DiskRdWr",   'C.diskRdwr)
186
  ])
187
$(makeJSONInstance ''DiskMode)
188

    
189
$(declareSADT "DiskType"
190
  [ ("LD_LV",       'C.ldLv)
191
  , ("LD_DRBD8",    'C.ldDrbd8)
192
  , ("LD_FILE",     'C.ldFile)
193
  , ("LD_BLOCKDEV", 'C.ldBlockdev)
194
  , ("LD_RADOS",    'C.ldRbd)
195
  ])
196
$(makeJSONInstance ''DiskType)
197

    
198
-- | The persistent block driver type. Currently only one type is allowed.
199
$(declareSADT "BlockDriver"
200
  [ ("BlockDrvManual", 'C.blockdevDriverManual)
201
  ])
202
$(makeJSONInstance ''BlockDriver)
203

    
204
-- | Constant for the dev_type key entry in the disk config.
205
devType :: String
206
devType = "dev_type"
207

    
208
-- | The disk configuration type. This includes the disk type itself,
209
-- for a more complete consistency. Note that since in the Python
210
-- code-base there's no authoritative place where we document the
211
-- logical id, this is probably a good reference point.
212
data DiskLogicalId
213
  = LIDPlain String String  -- ^ Volume group, logical volume
214
  | LIDDrbd8 String String Int Int Int String
215
  -- ^ NodeA, NodeB, Port, MinorA, MinorB, Secret
216
  | LIDFile FileDriver String -- ^ Driver, path
217
  | LIDBlockDev BlockDriver String -- ^ Driver, path (must be under /dev)
218
  | LIDRados String String -- ^ Unused, path
219
    deriving (Read, Show, Eq)
220

    
221
-- | Mapping from a logical id to a disk type.
222
lidDiskType :: DiskLogicalId -> DiskType
223
lidDiskType (LIDPlain {}) = LD_LV
224
lidDiskType (LIDDrbd8 {}) = LD_DRBD8
225
lidDiskType (LIDFile  {}) = LD_FILE
226
lidDiskType (LIDBlockDev {}) = LD_BLOCKDEV
227
lidDiskType (LIDRados {}) = LD_RADOS
228

    
229
-- | Builds the extra disk_type field for a given logical id.
230
lidEncodeType :: DiskLogicalId -> [(String, JSValue)]
231
lidEncodeType v = [(devType, showJSON . lidDiskType $ v)]
232

    
233
-- | Custom encoder for DiskLogicalId (logical id only).
234
encodeDLId :: DiskLogicalId -> JSValue
235
encodeDLId (LIDPlain vg lv) = JSArray [showJSON vg, showJSON lv]
236
encodeDLId (LIDDrbd8 nodeA nodeB port minorA minorB key) =
237
  JSArray [ showJSON nodeA, showJSON nodeB, showJSON port
238
          , showJSON minorA, showJSON minorB, showJSON key ]
239
encodeDLId (LIDRados pool name) = JSArray [showJSON pool, showJSON name]
240
encodeDLId (LIDFile driver name) = JSArray [showJSON driver, showJSON name]
241
encodeDLId (LIDBlockDev driver name) = JSArray [showJSON driver, showJSON name]
242

    
243
-- | Custom encoder for DiskLogicalId, composing both the logical id
244
-- and the extra disk_type field.
245
encodeFullDLId :: DiskLogicalId -> (JSValue, [(String, JSValue)])
246
encodeFullDLId v = (encodeDLId v, lidEncodeType v)
247

    
248
-- | Custom decoder for DiskLogicalId. This is manual for now, since
249
-- we don't have yet automation for separate-key style fields.
250
decodeDLId :: [(String, JSValue)] -> JSValue -> J.Result DiskLogicalId
251
decodeDLId obj lid = do
252
  dtype <- fromObj obj devType
253
  case dtype of
254
    LD_DRBD8 ->
255
      case lid of
256
        JSArray [nA, nB, p, mA, mB, k] -> do
257
          nA' <- readJSON nA
258
          nB' <- readJSON nB
259
          p'  <- readJSON p
260
          mA' <- readJSON mA
261
          mB' <- readJSON mB
262
          k'  <- readJSON k
263
          return $ LIDDrbd8 nA' nB' p' mA' mB' k'
264
        _ -> fail "Can't read logical_id for DRBD8 type"
265
    LD_LV ->
266
      case lid of
267
        JSArray [vg, lv] -> do
268
          vg' <- readJSON vg
269
          lv' <- readJSON lv
270
          return $ LIDPlain vg' lv'
271
        _ -> fail "Can't read logical_id for plain type"
272
    LD_FILE ->
273
      case lid of
274
        JSArray [driver, path] -> do
275
          driver' <- readJSON driver
276
          path'   <- readJSON path
277
          return $ LIDFile driver' path'
278
        _ -> fail "Can't read logical_id for file type"
279
    LD_BLOCKDEV ->
280
      case lid of
281
        JSArray [driver, path] -> do
282
          driver' <- readJSON driver
283
          path'   <- readJSON path
284
          return $ LIDBlockDev driver' path'
285
        _ -> fail "Can't read logical_id for blockdev type"
286
    LD_RADOS ->
287
      case lid of
288
        JSArray [driver, path] -> do
289
          driver' <- readJSON driver
290
          path'   <- readJSON path
291
          return $ LIDRados driver' path'
292
        _ -> fail "Can't read logical_id for rdb type"
293

    
294
-- | Disk data structure.
295
--
296
-- This is declared manually as it's a recursive structure, and our TH
297
-- code currently can't build it.
298
data Disk = Disk
299
  { diskLogicalId  :: DiskLogicalId
300
--  , diskPhysicalId :: String
301
  , diskChildren   :: [Disk]
302
  , diskIvName     :: String
303
  , diskSize       :: Int
304
  , diskMode       :: DiskMode
305
  } deriving (Read, Show, Eq)
306

    
307
$(buildObjectSerialisation "Disk"
308
  [ customField 'decodeDLId 'encodeFullDLId $
309
      simpleField "logical_id"    [t| DiskLogicalId   |]
310
--  , simpleField "physical_id" [t| String   |]
311
  , defaultField  [| [] |] $ simpleField "children" [t| [Disk] |]
312
  , defaultField [| "" |] $ simpleField "iv_name" [t| String |]
313
  , simpleField "size" [t| Int |]
314
  , defaultField [| DiskRdWr |] $ simpleField "mode" [t| DiskMode |]
315
  ])
316

    
317
-- * Instance definitions
318

    
319
$(declareSADT "AdminState"
320
  [ ("AdminOffline", 'C.adminstOffline)
321
  , ("AdminDown",    'C.adminstDown)
322
  , ("AdminUp",      'C.adminstUp)
323
  ])
324
$(makeJSONInstance ''AdminState)
325

    
326
$(buildParam "Be" "bep"
327
  [ simpleField "minmem"       [t| Int  |]
328
  , simpleField "maxmem"       [t| Int  |]
329
  , simpleField "vcpus"        [t| Int  |]
330
  , simpleField "auto_balance" [t| Bool |]
331
  ])
332

    
333
$(buildObject "Instance" "inst" $
334
  [ simpleField "name"           [t| String             |]
335
  , simpleField "primary_node"   [t| String             |]
336
  , simpleField "os"             [t| String             |]
337
  , simpleField "hypervisor"     [t| Hypervisor         |]
338
  , simpleField "hvparams"       [t| HvParams           |]
339
  , simpleField "beparams"       [t| PartialBeParams    |]
340
  , simpleField "osparams"       [t| OsParams           |]
341
  , simpleField "admin_state"    [t| AdminState         |]
342
  , simpleField "nics"           [t| [PartialNic]       |]
343
  , simpleField "disks"          [t| [Disk]             |]
344
  , simpleField "disk_template"  [t| DiskTemplate       |]
345
  , optionalField $ simpleField "network_port" [t| Int  |]
346
  ]
347
  ++ timeStampFields
348
  ++ uuidFields
349
  ++ serialFields
350
  ++ tagsFields)
351

    
352
instance TimeStampObject Instance where
353
  cTimeOf = instCtime
354
  mTimeOf = instMtime
355

    
356
instance UuidObject Instance where
357
  uuidOf = instUuid
358

    
359
instance SerialNoObject Instance where
360
  serialOf = instSerial
361

    
362
instance TagsObject Instance where
363
  tagsOf = instTags
364

    
365
-- * IPolicy definitions
366

    
367
$(buildParam "ISpec" "ispec"
368
  [ simpleField C.ispecMemSize     [t| Int |]
369
  , simpleField C.ispecDiskSize    [t| Int |]
370
  , simpleField C.ispecDiskCount   [t| Int |]
371
  , simpleField C.ispecCpuCount    [t| Int |]
372
  , simpleField C.ispecNicCount    [t| Int |]
373
  , simpleField C.ispecSpindleUse  [t| Int |]
374
  ])
375

    
376
-- | Custom partial ipolicy. This is not built via buildParam since it
377
-- has a special 2-level inheritance mode.
378
$(buildObject "PartialIPolicy" "ipolicy"
379
  [ renameField "MinSpecP" $ simpleField "min" [t| PartialISpecParams |]
380
  , renameField "MaxSpecP" $ simpleField "max" [t| PartialISpecParams |]
381
  , renameField "StdSpecP" $ simpleField "std" [t| PartialISpecParams |]
382
  , optionalField . renameField "SpindleRatioP"
383
                    $ simpleField "spindle-ratio"  [t| Double |]
384
  , optionalField . renameField "VcpuRatioP"
385
                    $ simpleField "vcpu-ratio"     [t| Double |]
386
  , optionalField . renameField "DiskTemplatesP"
387
                    $ simpleField "disk-templates" [t| [DiskTemplate] |]
388
  ])
389

    
390
-- | Custom filled ipolicy. This is not built via buildParam since it
391
-- has a special 2-level inheritance mode.
392
$(buildObject "FilledIPolicy" "ipolicy"
393
  [ renameField "MinSpec" $ simpleField "min" [t| FilledISpecParams |]
394
  , renameField "MaxSpec" $ simpleField "max" [t| FilledISpecParams |]
395
  , renameField "StdSpec" $ simpleField "std" [t| FilledISpecParams |]
396
  , simpleField "spindle-ratio"  [t| Double |]
397
  , simpleField "vcpu-ratio"     [t| Double |]
398
  , simpleField "disk-templates" [t| [DiskTemplate] |]
399
  ])
400

    
401
-- | Custom filler for the ipolicy types.
402
fillIPolicy :: FilledIPolicy -> PartialIPolicy -> FilledIPolicy
403
fillIPolicy (FilledIPolicy { ipolicyMinSpec       = fmin
404
                           , ipolicyMaxSpec       = fmax
405
                           , ipolicyStdSpec       = fstd
406
                           , ipolicySpindleRatio  = fspindleRatio
407
                           , ipolicyVcpuRatio     = fvcpuRatio
408
                           , ipolicyDiskTemplates = fdiskTemplates})
409
            (PartialIPolicy { ipolicyMinSpecP       = pmin
410
                            , ipolicyMaxSpecP       = pmax
411
                            , ipolicyStdSpecP       = pstd
412
                            , ipolicySpindleRatioP  = pspindleRatio
413
                            , ipolicyVcpuRatioP     = pvcpuRatio
414
                            , ipolicyDiskTemplatesP = pdiskTemplates}) =
415
  FilledIPolicy { ipolicyMinSpec       = fillISpecParams fmin pmin
416
                , ipolicyMaxSpec       = fillISpecParams fmax pmax
417
                , ipolicyStdSpec       = fillISpecParams fstd pstd
418
                , ipolicySpindleRatio  = fromMaybe fspindleRatio pspindleRatio
419
                , ipolicyVcpuRatio     = fromMaybe fvcpuRatio pvcpuRatio
420
                , ipolicyDiskTemplates = fromMaybe fdiskTemplates
421
                                         pdiskTemplates
422
                }
423
-- * Node definitions
424

    
425
$(buildParam "ND" "ndp"
426
  [ simpleField "oob_program"   [t| String |]
427
  , simpleField "spindle_count" [t| Int    |]
428
  ])
429

    
430
$(buildObject "Node" "node" $
431
  [ simpleField "name"             [t| String |]
432
  , simpleField "primary_ip"       [t| String |]
433
  , simpleField "secondary_ip"     [t| String |]
434
  , simpleField "master_candidate" [t| Bool   |]
435
  , simpleField "offline"          [t| Bool   |]
436
  , simpleField "drained"          [t| Bool   |]
437
  , simpleField "group"            [t| String |]
438
  , simpleField "master_capable"   [t| Bool   |]
439
  , simpleField "vm_capable"       [t| Bool   |]
440
  , simpleField "ndparams"         [t| PartialNDParams |]
441
  , simpleField "powered"          [t| Bool   |]
442
  ]
443
  ++ timeStampFields
444
  ++ uuidFields
445
  ++ serialFields
446
  ++ tagsFields)
447

    
448
instance TimeStampObject Node where
449
  cTimeOf = nodeCtime
450
  mTimeOf = nodeMtime
451

    
452
instance UuidObject Node where
453
  uuidOf = nodeUuid
454

    
455
instance SerialNoObject Node where
456
  serialOf = nodeSerial
457

    
458
instance TagsObject Node where
459
  tagsOf = nodeTags
460

    
461
-- * NodeGroup definitions
462

    
463
-- | The disk parameters type.
464
type DiskParams = Container (Container JSValue)
465

    
466
$(buildObject "NodeGroup" "group" $
467
  [ simpleField "name"         [t| String |]
468
  , defaultField  [| [] |] $ simpleField "members" [t| [String] |]
469
  , simpleField "ndparams"     [t| PartialNDParams |]
470
  , simpleField "alloc_policy" [t| AllocPolicy     |]
471
  , simpleField "ipolicy"      [t| PartialIPolicy  |]
472
  , simpleField "diskparams"   [t| DiskParams      |]
473
  ]
474
  ++ timeStampFields
475
  ++ uuidFields
476
  ++ serialFields
477
  ++ tagsFields)
478

    
479
instance TimeStampObject NodeGroup where
480
  cTimeOf = groupCtime
481
  mTimeOf = groupMtime
482

    
483
instance UuidObject NodeGroup where
484
  uuidOf = groupUuid
485

    
486
instance SerialNoObject NodeGroup where
487
  serialOf = groupSerial
488

    
489
instance TagsObject NodeGroup where
490
  tagsOf = groupTags
491

    
492
-- | IP family type
493
$(declareIADT "IpFamily"
494
  [ ("IpFamilyV4", 'C.ip4Family)
495
  , ("IpFamilyV6", 'C.ip6Family)
496
  ])
497
$(makeJSONInstance ''IpFamily)
498

    
499
-- | Conversion from IP family to IP version. This is needed because
500
-- Python uses both, depending on context.
501
ipFamilyToVersion :: IpFamily -> Int
502
ipFamilyToVersion IpFamilyV4 = C.ip4Version
503
ipFamilyToVersion IpFamilyV6 = C.ip6Version
504

    
505
-- | Cluster HvParams (hvtype to hvparams mapping).
506
type ClusterHvParams = Container HvParams
507

    
508
-- | Cluster Os-HvParams (os to hvparams mapping).
509
type OsHvParams = Container ClusterHvParams
510

    
511
-- | Cluser BeParams.
512
type ClusterBeParams = Container FilledBeParams
513

    
514
-- | Cluster OsParams.
515
type ClusterOsParams = Container OsParams
516

    
517
-- | Cluster NicParams.
518
type ClusterNicParams = Container FilledNicParams
519

    
520
-- | Cluster UID Pool, list (low, high) UID ranges.
521
type UidPool = [(Int, Int)]
522

    
523
-- * Cluster definitions
524
$(buildObject "Cluster" "cluster" $
525
  [ simpleField "rsahostkeypub"           [t| String           |]
526
  , simpleField "highest_used_port"       [t| Int              |]
527
  , simpleField "tcpudp_port_pool"        [t| [Int]            |]
528
  , simpleField "mac_prefix"              [t| String           |]
529
  , simpleField "volume_group_name"       [t| String           |]
530
  , simpleField "reserved_lvs"            [t| [String]         |]
531
  , optionalField $
532
    simpleField "drbd_usermode_helper"    [t| String           |]
533
  , simpleField "master_node"             [t| String           |]
534
  , simpleField "master_ip"               [t| String           |]
535
  , simpleField "master_netdev"           [t| String           |]
536
  , simpleField "master_netmask"          [t| Int              |]
537
  , simpleField "use_external_mip_script" [t| Bool             |]
538
  , simpleField "cluster_name"            [t| String           |]
539
  , simpleField "file_storage_dir"        [t| String           |]
540
  , simpleField "shared_file_storage_dir" [t| String           |]
541
  , simpleField "enabled_hypervisors"     [t| [Hypervisor]     |]
542
  , simpleField "hvparams"                [t| ClusterHvParams  |]
543
  , simpleField "os_hvp"                  [t| OsHvParams       |]
544
  , simpleField "beparams"                [t| ClusterBeParams  |]
545
  , simpleField "osparams"                [t| ClusterOsParams  |]
546
  , simpleField "nicparams"               [t| ClusterNicParams |]
547
  , simpleField "ndparams"                [t| FilledNDParams   |]
548
  , simpleField "diskparams"              [t| DiskParams       |]
549
  , simpleField "candidate_pool_size"     [t| Int              |]
550
  , simpleField "modify_etc_hosts"        [t| Bool             |]
551
  , simpleField "modify_ssh_setup"        [t| Bool             |]
552
  , simpleField "maintain_node_health"    [t| Bool             |]
553
  , simpleField "uid_pool"                [t| UidPool          |]
554
  , simpleField "default_iallocator"      [t| String           |]
555
  , simpleField "hidden_os"               [t| [String]         |]
556
  , simpleField "blacklisted_os"          [t| [String]         |]
557
  , simpleField "primary_ip_family"       [t| IpFamily         |]
558
  , simpleField "prealloc_wipe_disks"     [t| Bool             |]
559
  , simpleField "ipolicy"                 [t| FilledIPolicy    |]
560
 ]
561
 ++ timeStampFields
562
 ++ uuidFields
563
 ++ serialFields
564
 ++ tagsFields)
565

    
566
instance TimeStampObject Cluster where
567
  cTimeOf = clusterCtime
568
  mTimeOf = clusterMtime
569

    
570
instance UuidObject Cluster where
571
  uuidOf = clusterUuid
572

    
573
instance SerialNoObject Cluster where
574
  serialOf = clusterSerial
575

    
576
instance TagsObject Cluster where
577
  tagsOf = clusterTags
578

    
579
-- * ConfigData definitions
580

    
581
$(buildObject "ConfigData" "config" $
582
--  timeStampFields ++
583
  [ simpleField "version"    [t| Int                 |]
584
  , simpleField "cluster"    [t| Cluster             |]
585
  , simpleField "nodes"      [t| Container Node      |]
586
  , simpleField "nodegroups" [t| Container NodeGroup |]
587
  , simpleField "instances"  [t| Container Instance  |]
588
  ]
589
  ++ serialFields)
590

    
591
instance SerialNoObject ConfigData where
592
  serialOf = configSerial