Statistics
| Branch: | Tag: | Revision:

root / src / Ganeti / OpCodes.hs @ edcad688

History | View | Annotate | Download (27.7 kB)

1
{-# LANGUAGE ExistentialQuantification, TemplateHaskell #-}
2
{-# OPTIONS_GHC -fno-warn-orphans #-}
3

    
4
{-| Implementation of the opcodes.
5

    
6
-}
7

    
8
{-
9

    
10
Copyright (C) 2009, 2010, 2011, 2012, 2013 Google Inc.
11

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

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

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

    
27
-}
28

    
29
module Ganeti.OpCodes
30
  ( pyClasses
31
  , OpCode(..)
32
  , ReplaceDisksMode(..)
33
  , DiskIndex
34
  , mkDiskIndex
35
  , unDiskIndex
36
  , opID
37
  , allOpIDs
38
  , allOpFields
39
  , opSummary
40
  , CommonOpParams(..)
41
  , defOpParams
42
  , MetaOpCode(..)
43
  , resolveDependencies
44
  , wrapOpCode
45
  , setOpComment
46
  , setOpPriority
47
  ) where
48

    
49
import Text.JSON (readJSON, JSObject, JSON, JSValue(..), makeObj, fromJSObject)
50
import qualified Text.JSON
51

    
52
import Ganeti.THH
53

    
54
import qualified Ganeti.Hs2Py.OpDoc as OpDoc
55
import Ganeti.OpParams
56
import Ganeti.PyValueInstances ()
57
import Ganeti.Types
58
import Ganeti.Query.Language (queryTypeOpToRaw)
59

    
60
import Data.List (intercalate)
61
import Data.Map (Map)
62

    
63
import qualified Ganeti.Constants as C
64

    
65
instance PyValue DiskIndex where
66
  showValue = showValue . unDiskIndex
67

    
68
instance PyValue IDiskParams where
69
  showValue _ = error "OpCodes.showValue(IDiskParams): unhandled case"
70

    
71
instance PyValue RecreateDisksInfo where
72
  showValue RecreateDisksAll = "[]"
73
  showValue (RecreateDisksIndices is) = showValue is
74
  showValue (RecreateDisksParams is) = showValue is
75

    
76
instance PyValue a => PyValue (SetParamsMods a) where
77
  showValue SetParamsEmpty = "[]"
78
  showValue _ = error "OpCodes.showValue(SetParamsMods): unhandled case"
79

    
80
instance PyValue a => PyValue (NonNegative a) where
81
  showValue = showValue . fromNonNegative
82

    
83
instance PyValue a => PyValue (NonEmpty a) where
84
  showValue = showValue . fromNonEmpty
85

    
86
-- FIXME: should use the 'toRaw' function instead of being harcoded or
87
-- perhaps use something similar to the NonNegative type instead of
88
-- using the declareSADT
89
instance PyValue ExportMode where
90
  showValue ExportModeLocal = show C.exportModeLocal
91
  showValue ExportModeRemote = show C.exportModeLocal
92

    
93
instance PyValue CVErrorCode where
94
  showValue = cVErrorCodeToRaw
95

    
96
instance PyValue VerifyOptionalChecks where
97
  showValue = verifyOptionalChecksToRaw
98

    
99
instance PyValue INicParams where
100
  showValue = error "instance PyValue INicParams: not implemented"
101

    
102
instance PyValue a => PyValue (JSObject a) where
103
  showValue obj =
104
    "{" ++ intercalate ", " (map showPair (fromJSObject obj)) ++ "}"
105
    where showPair (k, v) = show k ++ ":" ++ showValue v
106

    
107
instance PyValue JSValue where
108
  showValue (JSObject obj) = showValue obj
109
  showValue x = show x
110

    
111
type JobIdListOnly = [(Bool, Either String JobId)]
112

    
113
type InstanceMultiAllocResponse =
114
  ([(Bool, Either String JobId)], NonEmptyString)
115

    
116
type QueryFieldDef =
117
  (NonEmptyString, NonEmptyString, TagKind, NonEmptyString)
118

    
119
type QueryResponse =
120
  ([QueryFieldDef], [[(QueryResultCode, JSValue)]])
121

    
122
type QueryFieldsResponse = [QueryFieldDef]
123

    
124
-- | OpCode representation.
125
--
126
-- We only implement a subset of Ganeti opcodes: those which are actually used
127
-- in the htools codebase.
128
$(genOpCode "OpCode"
129
  [ ("OpClusterPostInit",
130
     [t| Bool |],
131
     OpDoc.opClusterPostInit,
132
     [],
133
     [])
134
  , ("OpClusterDestroy",
135
     [t| NonEmptyString |],
136
     OpDoc.opClusterDestroy,
137
     [],
138
     [])
139
  , ("OpClusterQuery",
140
     [t| JSObject JSValue |],
141
     OpDoc.opClusterQuery,
142
     [],
143
     [])
144
  , ("OpClusterVerify",
145
     [t| JobIdListOnly |],
146
     OpDoc.opClusterVerify,
147
     [ pDebugSimulateErrors
148
     , pErrorCodes
149
     , pSkipChecks
150
     , pIgnoreErrors
151
     , pVerbose
152
     , pOptGroupName
153
     ],
154
     [])
155
  , ("OpClusterVerifyConfig",
156
     [t| Bool |],
157
     OpDoc.opClusterVerifyConfig,
158
     [ pDebugSimulateErrors
159
     , pErrorCodes
160
     , pIgnoreErrors
161
     , pVerbose
162
     ],
163
     [])
164
  , ("OpClusterVerifyGroup",
165
     [t| Bool |],
166
     OpDoc.opClusterVerifyGroup,
167
     [ pGroupName
168
     , pDebugSimulateErrors
169
     , pErrorCodes
170
     , pSkipChecks
171
     , pIgnoreErrors
172
     , pVerbose
173
     ],
174
     "group_name")
175
  , ("OpClusterVerifyDisks",
176
     [t| JobIdListOnly |],
177
     OpDoc.opClusterVerifyDisks,
178
     [],
179
     [])
180
  , ("OpGroupVerifyDisks",
181
     [t| (Map String String, [String], Map String [[String]]) |],
182
     OpDoc.opGroupVerifyDisks,
183
     [ pGroupName
184
     ],
185
     "group_name")
186
  , ("OpClusterRepairDiskSizes",
187
     [t| [(NonEmptyString, NonNegative Int, NonEmptyString, NonNegative Int)]|],
188
     OpDoc.opClusterRepairDiskSizes,
189
     [ pInstances
190
     ],
191
     [])
192
  , ("OpClusterConfigQuery",
193
     [t| [JSValue] |],
194
     OpDoc.opClusterConfigQuery,
195
     [ pOutputFields
196
     ],
197
     [])
198
  , ("OpClusterRename",
199
      [t| NonEmptyString |],
200
      OpDoc.opClusterRename,
201
     [ pName
202
     ],
203
     "name")
204
  , ("OpClusterSetParams",
205
     [t| () |],
206
     OpDoc.opClusterSetParams,
207
     [ pForce
208
     , pHvState
209
     , pDiskState
210
     , pVgName
211
     , pEnabledHypervisors
212
     , pClusterHvParams
213
     , pClusterBeParams
214
     , pOsHvp
215
     , pClusterOsParams
216
     , pDiskParams
217
     , pCandidatePoolSize
218
     , pUidPool
219
     , pAddUids
220
     , pRemoveUids
221
     , pMaintainNodeHealth
222
     , pPreallocWipeDisks
223
     , pNicParams
224
     , withDoc "Cluster-wide node parameter defaults" pNdParams
225
     , withDoc "Cluster-wide ipolicy specs" pIpolicy
226
     , pDrbdHelper
227
     , pDefaultIAllocator
228
     , pMasterNetdev
229
     , pMasterNetmask
230
     , pReservedLvs
231
     , pHiddenOs
232
     , pBlacklistedOs
233
     , pUseExternalMipScript
234
     , pEnabledDiskTemplates
235
     , pModifyEtcHosts
236
     , pClusterFileStorageDir
237
     , pClusterSharedFileStorageDir
238
     ],
239
     [])
240
  , ("OpClusterRedistConf",
241
     [t| () |],
242
     OpDoc.opClusterRedistConf,
243
     [],
244
     [])
245
  , ("OpClusterActivateMasterIp",
246
     [t| () |],
247
     OpDoc.opClusterActivateMasterIp,
248
     [],
249
     [])
250
  , ("OpClusterDeactivateMasterIp",
251
     [t| () |],
252
     OpDoc.opClusterDeactivateMasterIp,
253
     [],
254
     [])
255
  , ("OpQuery",
256
     [t| QueryResponse |],
257
     OpDoc.opQuery,
258
     [ pQueryWhat
259
     , pUseLocking
260
     , pQueryFields
261
     , pQueryFilter
262
     ],
263
     "what")
264
  , ("OpQueryFields",
265
     [t| QueryFieldsResponse |],
266
     OpDoc.opQueryFields,
267
     [ pQueryWhat
268
     , pQueryFieldsFields
269
     ],
270
     "what")
271
  , ("OpOobCommand",
272
     [t| [[(QueryResultCode, JSValue)]] |],
273
     OpDoc.opOobCommand,
274
     [ pNodeNames
275
     , withDoc "List of node UUIDs to run the OOB command against" pNodeUuids
276
     , pOobCommand
277
     , pOobTimeout
278
     , pIgnoreStatus
279
     , pPowerDelay
280
     ],
281
     [])
282
  , ("OpRestrictedCommand",
283
     [t| [(Bool, String)] |],
284
     OpDoc.opRestrictedCommand,
285
     [ pUseLocking
286
     , withDoc
287
       "Nodes on which the command should be run (at least one)"
288
       pRequiredNodes
289
     , withDoc
290
       "Node UUIDs on which the command should be run (at least one)"
291
       pRequiredNodeUuids
292
     , pRestrictedCommand
293
     ],
294
     [])
295
  , ("OpNodeRemove",
296
     [t| () |],
297
      OpDoc.opNodeRemove,
298
     [ pNodeName
299
     , pNodeUuid
300
     ],
301
     "node_name")
302
  , ("OpNodeAdd",
303
     [t| () |],
304
      OpDoc.opNodeAdd,
305
     [ pNodeName
306
     , pHvState
307
     , pDiskState
308
     , pPrimaryIp
309
     , pSecondaryIp
310
     , pReadd
311
     , pNodeGroup
312
     , pMasterCapable
313
     , pVmCapable
314
     , pNdParams
315
     ],
316
     "node_name")
317
  , ("OpNodeQuery",
318
     [t| [[JSValue]] |],
319
     OpDoc.opNodeQuery,
320
     [ pOutputFields
321
     , withDoc "Empty list to query all nodes, node names otherwise" pNames
322
     , pUseLocking
323
     ],
324
     [])
325
  , ("OpNodeQueryvols",
326
     [t| [JSValue] |],
327
     OpDoc.opNodeQueryvols,
328
     [ pOutputFields
329
     , withDoc "Empty list to query all nodes, node names otherwise" pNodes
330
     ],
331
     [])
332
  , ("OpNodeQueryStorage",
333
     [t| [[JSValue]] |],
334
     OpDoc.opNodeQueryStorage,
335
     [ pOutputFields
336
     , pStorageTypeOptional
337
     , withDoc
338
       "Empty list to query all, list of names to query otherwise"
339
       pNodes
340
     , pStorageName
341
     ],
342
     [])
343
  , ("OpNodeModifyStorage",
344
     [t| () |],
345
     OpDoc.opNodeModifyStorage,
346
     [ pNodeName
347
     , pNodeUuid
348
     , pStorageType
349
     , pStorageName
350
     , pStorageChanges
351
     ],
352
     "node_name")
353
  , ("OpRepairNodeStorage",
354
      [t| () |],
355
      OpDoc.opRepairNodeStorage,
356
     [ pNodeName
357
     , pNodeUuid
358
     , pStorageType
359
     , pStorageName
360
     , pIgnoreConsistency
361
     ],
362
     "node_name")
363
  , ("OpNodeSetParams",
364
     [t| [(NonEmptyString, JSValue)] |],
365
     OpDoc.opNodeSetParams,
366
     [ pNodeName
367
     , pNodeUuid
368
     , pForce
369
     , pHvState
370
     , pDiskState
371
     , pMasterCandidate
372
     , withDoc "Whether to mark the node offline" pOffline
373
     , pDrained
374
     , pAutoPromote
375
     , pMasterCapable
376
     , pVmCapable
377
     , pSecondaryIp
378
     , pNdParams
379
     , pPowered
380
     ],
381
     "node_name")
382
  , ("OpNodePowercycle",
383
     [t| Maybe NonEmptyString |],
384
     OpDoc.opNodePowercycle,
385
     [ pNodeName
386
     , pNodeUuid
387
     , pForce
388
     ],
389
     "node_name")
390
  , ("OpNodeMigrate",
391
     [t| JobIdListOnly |],
392
     OpDoc.opNodeMigrate,
393
     [ pNodeName
394
     , pNodeUuid
395
     , pMigrationMode
396
     , pMigrationLive
397
     , pMigrationTargetNode
398
     , pMigrationTargetNodeUuid
399
     , pAllowRuntimeChgs
400
     , pIgnoreIpolicy
401
     , pIallocator
402
     ],
403
     "node_name")
404
  , ("OpNodeEvacuate",
405
     [t| JobIdListOnly |],
406
     OpDoc.opNodeEvacuate,
407
     [ pEarlyRelease
408
     , pNodeName
409
     , pNodeUuid
410
     , pRemoteNode
411
     , pRemoteNodeUuid
412
     , pIallocator
413
     , pEvacMode
414
     ],
415
     "node_name")
416
  , ("OpInstanceCreate",
417
     [t| [NonEmptyString] |],
418
     OpDoc.opInstanceCreate,
419
     [ pInstanceName
420
     , pForceVariant
421
     , pWaitForSync
422
     , pNameCheck
423
     , pIgnoreIpolicy
424
     , pOpportunisticLocking
425
     , pInstBeParams
426
     , pInstDisks
427
     , pOptDiskTemplate
428
     , pFileDriver
429
     , pFileStorageDir
430
     , pInstHvParams
431
     , pHypervisor
432
     , pIallocator
433
     , pResetDefaults
434
     , pIpCheck
435
     , pIpConflictsCheck
436
     , pInstCreateMode
437
     , pInstNics
438
     , pNoInstall
439
     , pInstOsParams
440
     , pInstOs
441
     , pPrimaryNode
442
     , pPrimaryNodeUuid
443
     , pSecondaryNode
444
     , pSecondaryNodeUuid
445
     , pSourceHandshake
446
     , pSourceInstance
447
     , pSourceShutdownTimeout
448
     , pSourceX509Ca
449
     , pSrcNode
450
     , pSrcNodeUuid
451
     , pSrcPath
452
     , pBackupCompress
453
     , pStartInstance
454
     , pInstTags
455
     ],
456
     "instance_name")
457
  , ("OpInstanceMultiAlloc",
458
     [t| InstanceMultiAllocResponse |],
459
     OpDoc.opInstanceMultiAlloc,
460
     [ pOpportunisticLocking
461
     , pIallocator
462
     , pMultiAllocInstances
463
     ],
464
     [])
465
  , ("OpInstanceReinstall",
466
     [t| () |],
467
     OpDoc.opInstanceReinstall,
468
     [ pInstanceName
469
     , pInstanceUuid
470
     , pForceVariant
471
     , pInstOs
472
     , pTempOsParams
473
     ],
474
     "instance_name")
475
  , ("OpInstanceRemove",
476
     [t| () |],
477
     OpDoc.opInstanceRemove,
478
     [ pInstanceName
479
     , pInstanceUuid
480
     , pShutdownTimeout
481
     , pIgnoreFailures
482
     ],
483
     "instance_name")
484
  , ("OpInstanceRename",
485
     [t| NonEmptyString |],
486
     OpDoc.opInstanceRename,
487
     [ pInstanceName
488
     , pInstanceUuid
489
     , withDoc "New instance name" pNewName
490
     , pNameCheck
491
     , pIpCheck
492
     ],
493
     [])
494
  , ("OpInstanceStartup",
495
     [t| () |],
496
     OpDoc.opInstanceStartup,
497
     [ pInstanceName
498
     , pInstanceUuid
499
     , pForce
500
     , pIgnoreOfflineNodes
501
     , pTempHvParams
502
     , pTempBeParams
503
     , pNoRemember
504
     , pStartupPaused
505
     ],
506
     "instance_name")
507
  , ("OpInstanceShutdown",
508
     [t| () |],
509
     OpDoc.opInstanceShutdown,
510
     [ pInstanceName
511
     , pInstanceUuid
512
     , pForce
513
     , pIgnoreOfflineNodes
514
     , pShutdownTimeout'
515
     , pNoRemember
516
     ],
517
     "instance_name")
518
  , ("OpInstanceReboot",
519
     [t| () |],
520
     OpDoc.opInstanceReboot,
521
     [ pInstanceName
522
     , pInstanceUuid
523
     , pShutdownTimeout
524
     , pIgnoreSecondaries
525
     , pRebootType
526
     ],
527
     "instance_name")
528
  , ("OpInstanceReplaceDisks",
529
     [t| () |],
530
     OpDoc.opInstanceReplaceDisks,
531
     [ pInstanceName
532
     , pInstanceUuid
533
     , pEarlyRelease
534
     , pIgnoreIpolicy
535
     , pReplaceDisksMode
536
     , pReplaceDisksList
537
     , pRemoteNode
538
     , pRemoteNodeUuid
539
     , pIallocator
540
     ],
541
     "instance_name")
542
  , ("OpInstanceFailover",
543
     [t| () |],
544
     OpDoc.opInstanceFailover,
545
     [ pInstanceName
546
     , pInstanceUuid
547
     , pShutdownTimeout
548
     , pIgnoreConsistency
549
     , pMigrationTargetNode
550
     , pMigrationTargetNodeUuid
551
     , pIgnoreIpolicy
552
     , pMigrationCleanup
553
     , pIallocator
554
     ],
555
     "instance_name")
556
  , ("OpInstanceMigrate",
557
     [t| () |],
558
     OpDoc.opInstanceMigrate,
559
     [ pInstanceName
560
     , pInstanceUuid
561
     , pMigrationMode
562
     , pMigrationLive
563
     , pMigrationTargetNode
564
     , pMigrationTargetNodeUuid
565
     , pAllowRuntimeChgs
566
     , pIgnoreIpolicy
567
     , pMigrationCleanup
568
     , pIallocator
569
     , pAllowFailover
570
     ],
571
     "instance_name")
572
  , ("OpInstanceMove",
573
     [t| () |],
574
     OpDoc.opInstanceMove,
575
     [ pInstanceName
576
     , pInstanceUuid
577
     , pShutdownTimeout
578
     , pIgnoreIpolicy
579
     , pMoveTargetNode
580
     , pMoveTargetNodeUuid
581
     , pMoveCompress
582
     , pIgnoreConsistency
583
     ],
584
     "instance_name")
585
  , ("OpInstanceConsole",
586
     [t| JSObject JSValue |],
587
     OpDoc.opInstanceConsole,
588
     [ pInstanceName
589
     , pInstanceUuid
590
     ],
591
     "instance_name")
592
  , ("OpInstanceActivateDisks",
593
     [t| [(NonEmptyString, NonEmptyString, NonEmptyString)] |],
594
     OpDoc.opInstanceActivateDisks,
595
     [ pInstanceName
596
     , pInstanceUuid
597
     , pIgnoreDiskSize
598
     , pWaitForSyncFalse
599
     ],
600
     "instance_name")
601
  , ("OpInstanceDeactivateDisks",
602
     [t| () |],
603
     OpDoc.opInstanceDeactivateDisks,
604
     [ pInstanceName
605
     , pInstanceUuid
606
     , pForce
607
     ],
608
     "instance_name")
609
  , ("OpInstanceRecreateDisks",
610
     [t| () |],
611
     OpDoc.opInstanceRecreateDisks,
612
     [ pInstanceName
613
     , pInstanceUuid
614
     , pRecreateDisksInfo
615
     , withDoc "New instance nodes, if relocation is desired" pNodes
616
     , withDoc "New instance node UUIDs, if relocation is desired" pNodeUuids
617
     , pIallocator
618
     ],
619
     "instance_name")
620
  , ("OpInstanceQuery",
621
     [t| [[JSValue]] |],
622
     OpDoc.opInstanceQuery,
623
     [ pOutputFields
624
     , pUseLocking
625
     , withDoc
626
       "Empty list to query all instances, instance names otherwise"
627
       pNames
628
     ],
629
     [])
630
  , ("OpInstanceQueryData",
631
     [t| JSObject (JSObject JSValue) |],
632
     OpDoc.opInstanceQueryData,
633
     [ pUseLocking
634
     , pInstances
635
     , pStatic
636
     ],
637
     [])
638
  , ("OpInstanceSetParams",
639
      [t| [(NonEmptyString, JSValue)] |],
640
      OpDoc.opInstanceSetParams,
641
     [ pInstanceName
642
     , pInstanceUuid
643
     , pForce
644
     , pForceVariant
645
     , pIgnoreIpolicy
646
     , pInstParamsNicChanges
647
     , pInstParamsDiskChanges
648
     , pInstBeParams
649
     , pRuntimeMem
650
     , pInstHvParams
651
     , pOptDiskTemplate
652
     , pPrimaryNode
653
     , pPrimaryNodeUuid
654
     , withDoc "Secondary node (used when changing disk template)" pRemoteNode
655
     , withDoc
656
       "Secondary node UUID (used when changing disk template)"
657
       pRemoteNodeUuid
658
     , pOsNameChange
659
     , pInstOsParams
660
     , pWaitForSync
661
     , withDoc "Whether to mark the instance as offline" pOffline
662
     , pIpConflictsCheck
663
     , pHotplug
664
     ],
665
     "instance_name")
666
  , ("OpInstanceGrowDisk",
667
     [t| () |],
668
     OpDoc.opInstanceGrowDisk,
669
     [ pInstanceName
670
     , pInstanceUuid
671
     , pWaitForSync
672
     , pDiskIndex
673
     , pDiskChgAmount
674
     , pDiskChgAbsolute
675
     ],
676
     "instance_name")
677
  , ("OpInstanceChangeGroup",
678
     [t| JobIdListOnly |],
679
     OpDoc.opInstanceChangeGroup,
680
     [ pInstanceName
681
     , pInstanceUuid
682
     , pEarlyRelease
683
     , pIallocator
684
     , pTargetGroups
685
     ],
686
     "instance_name")
687
  , ("OpGroupAdd",
688
     [t| () |],
689
     OpDoc.opGroupAdd,
690
     [ pGroupName
691
     , pNodeGroupAllocPolicy
692
     , pGroupNodeParams
693
     , pDiskParams
694
     , pHvState
695
     , pDiskState
696
     , withDoc "Group-wide ipolicy specs" pIpolicy
697
     ],
698
     "group_name")
699
  , ("OpGroupAssignNodes",
700
     [t| () |],
701
     OpDoc.opGroupAssignNodes,
702
     [ pGroupName
703
     , pForce
704
     , withDoc "List of nodes to assign" pRequiredNodes
705
     , withDoc "List of node UUIDs to assign" pRequiredNodeUuids
706
     ],
707
     "group_name")
708
  , ("OpGroupQuery",
709
     [t| [[JSValue]] |],
710
     OpDoc.opGroupQuery,
711
     [ pOutputFields
712
     , withDoc "Empty list to query all groups, group names otherwise" pNames
713
     ],
714
     [])
715
  , ("OpGroupSetParams",
716
     [t| [(NonEmptyString, JSValue)] |],
717
     OpDoc.opGroupSetParams,
718
     [ pGroupName
719
     , pNodeGroupAllocPolicy
720
     , pGroupNodeParams
721
     , pDiskParams
722
     , pHvState
723
     , pDiskState
724
     , withDoc "Group-wide ipolicy specs" pIpolicy
725
     ],
726
     "group_name")
727
  , ("OpGroupRemove",
728
     [t| () |],
729
     OpDoc.opGroupRemove,
730
     [ pGroupName
731
     ],
732
     "group_name")
733
  , ("OpGroupRename",
734
     [t| NonEmptyString |],
735
     OpDoc.opGroupRename,
736
     [ pGroupName
737
     , withDoc "New group name" pNewName
738
     ],
739
     [])
740
  , ("OpGroupEvacuate",
741
     [t| JobIdListOnly |],
742
     OpDoc.opGroupEvacuate,
743
     [ pGroupName
744
     , pEarlyRelease
745
     , pIallocator
746
     , pTargetGroups
747
     ],
748
     "group_name")
749
  , ("OpOsDiagnose",
750
     [t| [[JSValue]] |],
751
     OpDoc.opOsDiagnose,
752
     [ pOutputFields
753
     , withDoc "Which operating systems to diagnose" pNames
754
     ],
755
     [])
756
  , ("OpExtStorageDiagnose",
757
     [t| [[JSValue]] |],
758
     OpDoc.opExtStorageDiagnose,
759
     [ pOutputFields
760
     , withDoc "Which ExtStorage Provider to diagnose" pNames
761
     ],
762
     [])
763
  , ("OpBackupQuery",
764
     [t| JSObject (Either Bool [NonEmptyString]) |],
765
     OpDoc.opBackupQuery,
766
     [ pUseLocking
767
     , withDoc "Empty list to query all nodes, node names otherwise" pNodes
768
     ],
769
     [])
770
  , ("OpBackupPrepare",
771
     [t| Maybe (JSObject JSValue) |],
772
     OpDoc.opBackupPrepare,
773
     [ pInstanceName
774
     , pInstanceUuid
775
     , pExportMode
776
     ],
777
     "instance_name")
778
  , ("OpBackupExport",
779
     [t| (Bool, [Bool]) |],
780
     OpDoc.opBackupExport,
781
     [ pInstanceName
782
     , pInstanceUuid
783
     , pBackupCompress
784
     , pShutdownTimeout
785
     , pExportTargetNode
786
     , pExportTargetNodeUuid
787
     , pShutdownInstance
788
     , pRemoveInstance
789
     , pIgnoreRemoveFailures
790
     , defaultField [| ExportModeLocal |] pExportMode
791
     , pX509KeyName
792
     , pX509DestCA
793
     ],
794
     "instance_name")
795
  , ("OpBackupRemove",
796
     [t| () |],
797
     OpDoc.opBackupRemove,
798
     [ pInstanceName
799
     , pInstanceUuid
800
     ],
801
     "instance_name")
802
  , ("OpTagsGet",
803
     [t| [NonEmptyString] |],
804
     OpDoc.opTagsGet,
805
     [ pTagsObject
806
     , pUseLocking
807
     , withDoc "Name of object to retrieve tags from" pTagsName
808
     ],
809
     "name")
810
  , ("OpTagsSearch",
811
     [t| [(NonEmptyString, NonEmptyString)] |],
812
     OpDoc.opTagsSearch,
813
     [ pTagSearchPattern
814
     ],
815
     "pattern")
816
  , ("OpTagsSet",
817
     [t| () |],
818
     OpDoc.opTagsSet,
819
     [ pTagsObject
820
     , pTagsList
821
     , withDoc "Name of object where tag(s) should be added" pTagsName
822
     ],
823
     [])
824
  , ("OpTagsDel",
825
     [t| () |],
826
     OpDoc.opTagsDel,
827
     [ pTagsObject
828
     , pTagsList
829
     , withDoc "Name of object where tag(s) should be deleted" pTagsName
830
     ],
831
     [])
832
  , ("OpTestDelay",
833
     [t| () |],
834
     OpDoc.opTestDelay,
835
     [ pDelayDuration
836
     , pDelayOnMaster
837
     , pDelayOnNodes
838
     , pDelayOnNodeUuids
839
     , pDelayRepeat
840
     ],
841
     "duration")
842
  , ("OpTestAllocator",
843
     [t| String |],
844
     OpDoc.opTestAllocator,
845
     [ pIAllocatorDirection
846
     , pIAllocatorMode
847
     , pIAllocatorReqName
848
     , pIAllocatorNics
849
     , pIAllocatorDisks
850
     , pHypervisor
851
     , pIallocator
852
     , pInstTags
853
     , pIAllocatorMemory
854
     , pIAllocatorVCpus
855
     , pIAllocatorOs
856
     , pDiskTemplate
857
     , pIAllocatorInstances
858
     , pIAllocatorEvacMode
859
     , pTargetGroups
860
     , pIAllocatorSpindleUse
861
     , pIAllocatorCount
862
     ],
863
     "iallocator")
864
  , ("OpTestJqueue",
865
     [t| Bool |],
866
     OpDoc.opTestJqueue,
867
     [ pJQueueNotifyWaitLock
868
     , pJQueueNotifyExec
869
     , pJQueueLogMessages
870
     , pJQueueFail
871
     ],
872
     [])
873
  , ("OpTestDummy",
874
     [t| () |],
875
     OpDoc.opTestDummy,
876
     [ pTestDummyResult
877
     , pTestDummyMessages
878
     , pTestDummyFail
879
     , pTestDummySubmitJobs
880
     ],
881
     [])
882
  , ("OpNetworkAdd",
883
     [t| () |],
884
     OpDoc.opNetworkAdd,
885
     [ pNetworkName
886
     , pNetworkAddress4
887
     , pNetworkGateway4
888
     , pNetworkAddress6
889
     , pNetworkGateway6
890
     , pNetworkMacPrefix
891
     , pNetworkAddRsvdIps
892
     , pIpConflictsCheck
893
     , withDoc "Network tags" pInstTags
894
     ],
895
     "network_name")
896
  , ("OpNetworkRemove",
897
     [t| () |],
898
     OpDoc.opNetworkRemove,
899
     [ pNetworkName
900
     , pForce
901
     ],
902
     "network_name")
903
  , ("OpNetworkSetParams",
904
     [t| () |],
905
     OpDoc.opNetworkSetParams,
906
     [ pNetworkName
907
     , pNetworkGateway4
908
     , pNetworkAddress6
909
     , pNetworkGateway6
910
     , pNetworkMacPrefix
911
     , withDoc "Which external IP addresses to reserve" pNetworkAddRsvdIps
912
     , pNetworkRemoveRsvdIps
913
     ],
914
     "network_name")
915
  , ("OpNetworkConnect",
916
     [t| () |],
917
     OpDoc.opNetworkConnect,
918
     [ pGroupName
919
     , pNetworkName
920
     , pNetworkMode
921
     , pNetworkLink
922
     , pIpConflictsCheck
923
     ],
924
     "network_name")
925
  , ("OpNetworkDisconnect",
926
     [t| () |],
927
     OpDoc.opNetworkDisconnect,
928
     [ pGroupName
929
     , pNetworkName
930
     ],
931
     "network_name")
932
  , ("OpNetworkQuery",
933
     [t| [[JSValue]] |],
934
     OpDoc.opNetworkQuery,
935
     [ pOutputFields
936
     , pUseLocking
937
     , withDoc "Empty list to query all groups, group names otherwise" pNames
938
     ],
939
     [])
940
  ])
941

    
942
-- | Returns the OP_ID for a given opcode value.
943
$(genOpID ''OpCode "opID")
944

    
945
-- | A list of all defined/supported opcode IDs.
946
$(genAllOpIDs ''OpCode "allOpIDs")
947

    
948
instance JSON OpCode where
949
  readJSON = loadOpCode
950
  showJSON = saveOpCode
951

    
952
-- | Generates the summary value for an opcode.
953
opSummaryVal :: OpCode -> Maybe String
954
opSummaryVal OpClusterVerifyGroup { opGroupName = s } = Just (fromNonEmpty s)
955
opSummaryVal OpGroupVerifyDisks { opGroupName = s } = Just (fromNonEmpty s)
956
opSummaryVal OpClusterRename { opName = s } = Just (fromNonEmpty s)
957
opSummaryVal OpQuery { opWhat = s } = Just (queryTypeOpToRaw s)
958
opSummaryVal OpQueryFields { opWhat = s } = Just (queryTypeOpToRaw s)
959
opSummaryVal OpNodeRemove { opNodeName = s } = Just (fromNonEmpty s)
960
opSummaryVal OpNodeAdd { opNodeName = s } = Just (fromNonEmpty s)
961
opSummaryVal OpNodeModifyStorage { opNodeName = s } = Just (fromNonEmpty s)
962
opSummaryVal OpRepairNodeStorage  { opNodeName = s } = Just (fromNonEmpty s)
963
opSummaryVal OpNodeSetParams { opNodeName = s } = Just (fromNonEmpty s)
964
opSummaryVal OpNodePowercycle { opNodeName = s } = Just (fromNonEmpty s)
965
opSummaryVal OpNodeMigrate { opNodeName = s } = Just (fromNonEmpty s)
966
opSummaryVal OpNodeEvacuate { opNodeName = s } = Just (fromNonEmpty s)
967
opSummaryVal OpInstanceCreate { opInstanceName = s } = Just s
968
opSummaryVal OpInstanceReinstall { opInstanceName = s } = Just s
969
opSummaryVal OpInstanceRemove { opInstanceName = s } = Just s
970
-- FIXME: instance rename should show both names; currently it shows none
971
-- opSummaryVal OpInstanceRename { opInstanceName = s } = Just s
972
opSummaryVal OpInstanceStartup { opInstanceName = s } = Just s
973
opSummaryVal OpInstanceShutdown { opInstanceName = s } = Just s
974
opSummaryVal OpInstanceReboot { opInstanceName = s } = Just s
975
opSummaryVal OpInstanceReplaceDisks { opInstanceName = s } = Just s
976
opSummaryVal OpInstanceFailover { opInstanceName = s } = Just s
977
opSummaryVal OpInstanceMigrate { opInstanceName = s } = Just s
978
opSummaryVal OpInstanceMove { opInstanceName = s } = Just s
979
opSummaryVal OpInstanceConsole { opInstanceName = s } = Just s
980
opSummaryVal OpInstanceActivateDisks { opInstanceName = s } = Just s
981
opSummaryVal OpInstanceDeactivateDisks { opInstanceName = s } = Just s
982
opSummaryVal OpInstanceRecreateDisks { opInstanceName = s } = Just s
983
opSummaryVal OpInstanceSetParams { opInstanceName = s } = Just s
984
opSummaryVal OpInstanceGrowDisk { opInstanceName = s } = Just s
985
opSummaryVal OpInstanceChangeGroup { opInstanceName = s } = Just s
986
opSummaryVal OpGroupAdd { opGroupName = s } = Just (fromNonEmpty s)
987
opSummaryVal OpGroupAssignNodes { opGroupName = s } = Just (fromNonEmpty s)
988
opSummaryVal OpGroupSetParams { opGroupName = s } = Just (fromNonEmpty s)
989
opSummaryVal OpGroupRemove { opGroupName = s } = Just (fromNonEmpty s)
990
opSummaryVal OpGroupEvacuate { opGroupName = s } = Just (fromNonEmpty s)
991
opSummaryVal OpBackupPrepare { opInstanceName = s } = Just s
992
opSummaryVal OpBackupExport { opInstanceName = s } = Just s
993
opSummaryVal OpBackupRemove { opInstanceName = s } = Just s
994
opSummaryVal OpTagsGet { opKind = s } = Just (show s)
995
opSummaryVal OpTagsSearch { opTagSearchPattern = s } = Just (fromNonEmpty s)
996
opSummaryVal OpTestDelay { opDelayDuration = d } = Just (show d)
997
opSummaryVal OpTestAllocator { opIallocator = s } =
998
  -- FIXME: Python doesn't handle None fields well, so we have behave the same
999
  Just $ maybe "None" fromNonEmpty s
1000
opSummaryVal OpNetworkAdd { opNetworkName = s} = Just (fromNonEmpty s)
1001
opSummaryVal OpNetworkRemove { opNetworkName = s} = Just (fromNonEmpty s)
1002
opSummaryVal OpNetworkSetParams { opNetworkName = s} = Just (fromNonEmpty s)
1003
opSummaryVal OpNetworkConnect { opNetworkName = s} = Just (fromNonEmpty s)
1004
opSummaryVal OpNetworkDisconnect { opNetworkName = s} = Just (fromNonEmpty s)
1005
opSummaryVal _ = Nothing
1006

    
1007
-- | Computes the summary of the opcode.
1008
opSummary :: OpCode -> String
1009
opSummary op =
1010
  case opSummaryVal op of
1011
    Nothing -> op_suffix
1012
    Just s -> op_suffix ++ "(" ++ s ++ ")"
1013
  where op_suffix = drop 3 $ opID op
1014

    
1015
-- | Generic\/common opcode parameters.
1016
$(buildObject "CommonOpParams" "op"
1017
  [ pDryRun
1018
  , pDebugLevel
1019
  , pOpPriority
1020
  , pDependencies
1021
  , pComment
1022
  , pReason
1023
  ])
1024

    
1025
-- | Default common parameter values.
1026
defOpParams :: CommonOpParams
1027
defOpParams =
1028
  CommonOpParams { opDryRun     = Nothing
1029
                 , opDebugLevel = Nothing
1030
                 , opPriority   = OpPrioNormal
1031
                 , opDepends    = Nothing
1032
                 , opComment    = Nothing
1033
                 , opReason     = []
1034
                 }
1035

    
1036
-- | Resolve relative dependencies to absolute ones, given the job ID.
1037
resolveDependsCommon :: (Monad m) => CommonOpParams -> JobId -> m CommonOpParams
1038
resolveDependsCommon p@(CommonOpParams { opDepends = Just deps}) jid = do
1039
  deps' <- mapM (`absoluteJobDependency` jid) deps
1040
  return p { opDepends = Just deps' }
1041
resolveDependsCommon p _ = return p
1042

    
1043
-- | The top-level opcode type.
1044
data MetaOpCode = MetaOpCode { metaParams :: CommonOpParams
1045
                             , metaOpCode :: OpCode
1046
                             } deriving (Show, Eq)
1047

    
1048
-- | Resolve relative dependencies to absolute ones, given the job Id.
1049
resolveDependencies :: (Monad m) => MetaOpCode -> JobId -> m MetaOpCode
1050
resolveDependencies mopc jid = do
1051
  mpar <- resolveDependsCommon (metaParams mopc) jid
1052
  return (mopc { metaParams = mpar })
1053

    
1054
-- | JSON serialisation for 'MetaOpCode'.
1055
showMeta :: MetaOpCode -> JSValue
1056
showMeta (MetaOpCode params op) =
1057
  let objparams = toDictCommonOpParams params
1058
      objop = toDictOpCode op
1059
  in makeObj (objparams ++ objop)
1060

    
1061
-- | JSON deserialisation for 'MetaOpCode'
1062
readMeta :: JSValue -> Text.JSON.Result MetaOpCode
1063
readMeta v = do
1064
  meta <- readJSON v
1065
  op <- readJSON v
1066
  return $ MetaOpCode meta op
1067

    
1068
instance JSON MetaOpCode where
1069
  showJSON = showMeta
1070
  readJSON = readMeta
1071

    
1072
-- | Wraps an 'OpCode' with the default parameters to build a
1073
-- 'MetaOpCode'.
1074
wrapOpCode :: OpCode -> MetaOpCode
1075
wrapOpCode = MetaOpCode defOpParams
1076

    
1077
-- | Sets the comment on a meta opcode.
1078
setOpComment :: String -> MetaOpCode -> MetaOpCode
1079
setOpComment comment (MetaOpCode common op) =
1080
  MetaOpCode (common { opComment = Just comment}) op
1081

    
1082
-- | Sets the priority on a meta opcode.
1083
setOpPriority :: OpSubmitPriority -> MetaOpCode -> MetaOpCode
1084
setOpPriority prio (MetaOpCode common op) =
1085
  MetaOpCode (common { opPriority = prio }) op