92f5644a79f3a5adccfce2f1df598a20a00d9425
[ganeti-local] / src / Ganeti / OpCodes.hs
1 {-# LANGUAGE TemplateHaskell #-}
2
3 {-| Implementation of the opcodes.
4
5 -}
6
7 {-
8
9 Copyright (C) 2009, 2010, 2011, 2012, 2013 Google Inc.
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 02110-1301, USA.
25
26 -}
27
28 module Ganeti.OpCodes
29   ( OpCode(..)
30   , TagObject(..)
31   , tagObjectFrom
32   , encodeTagObject
33   , decodeTagObject
34   , ReplaceDisksMode(..)
35   , DiskIndex
36   , mkDiskIndex
37   , unDiskIndex
38   , opID
39   , allOpIDs
40   , allOpFields
41   , opSummary
42   , CommonOpParams(..)
43   , defOpParams
44   , MetaOpCode(..)
45   , wrapOpCode
46   , setOpComment
47   , setOpPriority
48   ) where
49
50 import Data.Maybe (fromMaybe)
51 import Text.JSON (readJSON, JSON, JSValue, makeObj)
52 import qualified Text.JSON
53
54 import Ganeti.THH
55
56 import Ganeti.OpParams
57 import Ganeti.Types (OpSubmitPriority(..), fromNonEmpty)
58 import Ganeti.Query.Language (queryTypeOpToRaw)
59
60 -- | OpCode representation.
61 --
62 -- We only implement a subset of Ganeti opcodes: those which are actually used
63 -- in the htools codebase.
64 $(genOpCode "OpCode"
65   [ ("OpTestDelay",
66      [ pDelayDuration
67      , pDelayOnMaster
68      , pDelayOnNodes
69      , pDelayRepeat
70      ])
71   , ("OpInstanceReplaceDisks",
72      [ pInstanceName
73      , pEarlyRelease
74      , pIgnoreIpolicy
75      , pReplaceDisksMode
76      , pReplaceDisksList
77      , pRemoteNode
78      , pIallocator
79      ])
80   , ("OpInstanceFailover",
81      [ pInstanceName
82      , pShutdownTimeout
83      , pIgnoreConsistency
84      , pMigrationTargetNode
85      , pIgnoreIpolicy
86      , pIallocator
87      ])
88   , ("OpInstanceMigrate",
89      [ pInstanceName
90      , pMigrationMode
91      , pMigrationLive
92      , pMigrationTargetNode
93      , pAllowRuntimeChgs
94      , pIgnoreIpolicy
95      , pMigrationCleanup
96      , pIallocator
97      , pAllowFailover
98      ])
99   , ("OpTagsGet",
100      [ pTagsObject
101      , pUseLocking
102      ])
103   , ("OpTagsSearch",
104      [ pTagSearchPattern ])
105   , ("OpTagsSet",
106      [ pTagsObject
107      , pTagsList
108      ])
109   , ("OpTagsDel",
110      [ pTagsObject
111      , pTagsList
112      ])
113   , ("OpClusterPostInit", [])
114   , ("OpClusterDestroy", [])
115   , ("OpClusterQuery", [])
116   , ("OpClusterVerify",
117      [ pDebugSimulateErrors
118      , pErrorCodes
119      , pSkipChecks
120      , pIgnoreErrors
121      , pVerbose
122      , pOptGroupName
123      ])
124   , ("OpClusterVerifyConfig",
125      [ pDebugSimulateErrors
126      , pErrorCodes
127      , pIgnoreErrors
128      , pVerbose
129      ])
130   , ("OpClusterVerifyGroup",
131      [ pGroupName
132      , pDebugSimulateErrors
133      , pErrorCodes
134      , pSkipChecks
135      , pIgnoreErrors
136      , pVerbose
137      ])
138   , ("OpClusterVerifyDisks", [])
139   , ("OpGroupVerifyDisks",
140      [ pGroupName
141      ])
142   , ("OpClusterRepairDiskSizes",
143      [ pInstances
144      ])
145   , ("OpClusterConfigQuery",
146      [ pOutputFields
147      ])
148   , ("OpClusterRename",
149      [ pName
150      ])
151   , ("OpClusterSetParams",
152      [ pForce
153      , pHvState
154      , pDiskState
155      , pVgName
156      , pEnabledHypervisors
157      , pClusterHvParams
158      , pClusterBeParams
159      , pOsHvp
160      , pClusterOsParams
161      , pDiskParams
162      , pCandidatePoolSize
163      , pUidPool
164      , pAddUids
165      , pRemoveUids
166      , pMaintainNodeHealth
167      , pPreallocWipeDisks
168      , pNicParams
169      , pNdParams
170      , pIpolicy
171      , pDrbdHelper
172      , pDefaultIAllocator
173      , pMasterNetdev
174      , pMasterNetmask
175      , pReservedLvs
176      , pHiddenOs
177      , pBlacklistedOs
178      , pUseExternalMipScript
179      , pEnabledDiskTemplates
180      ])
181   , ("OpClusterRedistConf", [])
182   , ("OpClusterActivateMasterIp", [])
183   , ("OpClusterDeactivateMasterIp", [])
184   , ("OpQuery",
185      [ pQueryWhat
186      , pUseLocking
187      , pQueryFields
188      , pQueryFilter
189      ])
190   , ("OpQueryFields",
191      [ pQueryWhat
192      , pQueryFields
193      ])
194   , ("OpOobCommand",
195      [ pNodeNames
196      , pOobCommand
197      , pOobTimeout
198      , pIgnoreStatus
199      , pPowerDelay
200      ])
201   , ("OpNodeRemove", [ pNodeName ])
202   , ("OpNodeAdd",
203      [ pNodeName
204      , pHvState
205      , pDiskState
206      , pPrimaryIp
207      , pSecondaryIp
208      , pReadd
209      , pNodeGroup
210      , pMasterCapable
211      , pVmCapable
212      , pNdParams
213     ])
214   , ("OpNodeQuery", dOldQuery)
215   , ("OpNodeQueryvols",
216      [ pOutputFields
217      , pNodes
218      ])
219   , ("OpNodeQueryStorage",
220      [ pOutputFields
221      , pStorageType
222      , pNodes
223      , pStorageName
224      ])
225   , ("OpNodeModifyStorage",
226      [ pNodeName
227      , pStorageType
228      , pStorageName
229      , pStorageChanges
230      ])
231   , ("OpRepairNodeStorage",
232      [ pNodeName
233      , pStorageType
234      , pStorageName
235      , pIgnoreConsistency
236      ])
237   , ("OpNodeSetParams",
238      [ pNodeName
239      , pForce
240      , pHvState
241      , pDiskState
242      , pMasterCandidate
243      , pOffline
244      , pDrained
245      , pAutoPromote
246      , pMasterCapable
247      , pVmCapable
248      , pSecondaryIp
249      , pNdParams
250      , pPowered
251      ])
252   , ("OpNodePowercycle",
253      [ pNodeName
254      , pForce
255      ])
256   , ("OpNodeMigrate",
257      [ pNodeName
258      , pMigrationMode
259      , pMigrationLive
260      , pMigrationTargetNode
261      , pAllowRuntimeChgs
262      , pIgnoreIpolicy
263      , pIallocator
264      ])
265   , ("OpNodeEvacuate",
266      [ pEarlyRelease
267      , pNodeName
268      , pRemoteNode
269      , pIallocator
270      , pEvacMode
271      ])
272   , ("OpInstanceCreate",
273      [ pInstanceName
274      , pForceVariant
275      , pWaitForSync
276      , pNameCheck
277      , pIgnoreIpolicy
278      , pInstBeParams
279      , pInstDisks
280      , pDiskTemplate
281      , pFileDriver
282      , pFileStorageDir
283      , pInstHvParams
284      , pHypervisor
285      , pIallocator
286      , pResetDefaults
287      , pIpCheck
288      , pIpConflictsCheck
289      , pInstCreateMode
290      , pInstNics
291      , pNoInstall
292      , pInstOsParams
293      , pInstOs
294      , pPrimaryNode
295      , pSecondaryNode
296      , pSourceHandshake
297      , pSourceInstance
298      , pSourceShutdownTimeout
299      , pSourceX509Ca
300      , pSrcNode
301      , pSrcPath
302      , pStartInstance
303      , pOpportunisticLocking
304      , pInstTags
305      ])
306   , ("OpInstanceMultiAlloc",
307      [ pIallocator
308      , pMultiAllocInstances
309      , pOpportunisticLocking
310      ])
311   , ("OpInstanceReinstall",
312      [ pInstanceName
313      , pForceVariant
314      , pInstOs
315      , pTempOsParams
316      ])
317   , ("OpInstanceRemove",
318      [ pInstanceName
319      , pShutdownTimeout
320      , pIgnoreFailures
321      ])
322   , ("OpInstanceRename",
323      [ pInstanceName
324      , pNewName
325      , pNameCheck
326      , pIpCheck
327      ])
328   , ("OpInstanceStartup",
329      [ pInstanceName
330      , pForce
331      , pIgnoreOfflineNodes
332      , pTempHvParams
333      , pTempBeParams
334      , pNoRemember
335      , pStartupPaused
336      ])
337   , ("OpInstanceShutdown",
338      [ pInstanceName
339      , pForce
340      , pIgnoreOfflineNodes
341      , pShutdownTimeout'
342      , pNoRemember
343      ])
344   , ("OpInstanceReboot",
345      [ pInstanceName
346      , pShutdownTimeout
347      , pIgnoreSecondaries
348      , pRebootType
349      ])
350   , ("OpInstanceMove",
351      [ pInstanceName
352      , pShutdownTimeout
353      , pIgnoreIpolicy
354      , pMoveTargetNode
355      , pIgnoreConsistency
356      ])
357   , ("OpInstanceConsole",
358      [ pInstanceName ])
359   , ("OpInstanceActivateDisks",
360      [ pInstanceName
361      , pIgnoreDiskSize
362      , pWaitForSyncFalse
363      ])
364   , ("OpInstanceDeactivateDisks",
365      [ pInstanceName
366      , pForce
367      ])
368   , ("OpInstanceRecreateDisks",
369      [ pInstanceName
370      , pRecreateDisksInfo
371      , pNodes
372      , pIallocator
373      ])
374   , ("OpInstanceQuery", dOldQuery)
375   , ("OpInstanceQueryData",
376      [ pUseLocking
377      , pInstances
378      , pStatic
379      ])
380   , ("OpInstanceSetParams",
381      [ pInstanceName
382      , pForce
383      , pForceVariant
384      , pIgnoreIpolicy
385      , pInstParamsNicChanges
386      , pInstParamsDiskChanges
387      , pInstBeParams
388      , pRuntimeMem
389      , pInstHvParams
390      , pOptDiskTemplate
391      , pPrimaryNode
392      , pRemoteNode
393      , pOsNameChange
394      , pInstOsParams
395      , pWaitForSync
396      , pOffline
397      , pIpConflictsCheck
398      ])
399   , ("OpInstanceGrowDisk",
400      [ pInstanceName
401      , pWaitForSync
402      , pDiskIndex
403      , pDiskChgAmount
404      , pDiskChgAbsolute
405      ])
406   , ("OpInstanceChangeGroup",
407      [ pInstanceName
408      , pEarlyRelease
409      , pIallocator
410      , pTargetGroups
411      ])
412   , ("OpGroupAdd",
413      [ pGroupName
414      , pNodeGroupAllocPolicy
415      , pGroupNodeParams
416      , pDiskParams
417      , pHvState
418      , pDiskState
419      , pIpolicy
420      ])
421   , ("OpGroupAssignNodes",
422      [ pGroupName
423      , pForce
424      , pRequiredNodes
425      ])
426   , ("OpGroupQuery", dOldQueryNoLocking)
427   , ("OpGroupSetParams",
428      [ pGroupName
429      , pNodeGroupAllocPolicy
430      , pGroupNodeParams
431      , pDiskParams
432      , pHvState
433      , pDiskState
434      , pIpolicy
435      ])
436   , ("OpGroupRemove",
437      [ pGroupName ])
438   , ("OpGroupRename",
439      [ pGroupName
440      , pNewName
441      ])
442   , ("OpGroupEvacuate",
443      [ pGroupName
444      , pEarlyRelease
445      , pIallocator
446      , pTargetGroups
447      ])
448   , ("OpOsDiagnose",
449      [ pOutputFields
450      , pNames ])
451   , ("OpExtStorageDiagnose",
452      [ pOutputFields
453      , pNames ])
454   , ("OpBackupQuery",
455      [ pUseLocking
456      , pNodes
457      ])
458   , ("OpBackupPrepare",
459      [ pInstanceName
460      , pExportMode
461      ])
462   , ("OpBackupExport",
463      [ pInstanceName
464      , pShutdownTimeout
465      , pExportTargetNode
466      , pShutdownInstance
467      , pRemoveInstance
468      , pIgnoreRemoveFailures
469      , pExportMode
470      , pX509KeyName
471      , pX509DestCA
472      ])
473   , ("OpBackupRemove",
474      [ pInstanceName ])
475   , ("OpTestAllocator",
476      [ pIAllocatorDirection
477      , pIAllocatorMode
478      , pIAllocatorReqName
479      , pIAllocatorNics
480      , pIAllocatorDisks
481      , pHypervisor
482      , pIallocator
483      , pInstTags
484      , pIAllocatorMemory
485      , pIAllocatorVCpus
486      , pIAllocatorOs
487      , pDiskTemplate
488      , pIAllocatorInstances
489      , pIAllocatorEvacMode
490      , pTargetGroups
491      , pIAllocatorSpindleUse
492      , pIAllocatorCount
493      ])
494   , ("OpTestJqueue",
495      [ pJQueueNotifyWaitLock
496      , pJQueueNotifyExec
497      , pJQueueLogMessages
498      , pJQueueFail
499      ])
500   , ("OpTestDummy",
501      [ pTestDummyResult
502      , pTestDummyMessages
503      , pTestDummyFail
504      , pTestDummySubmitJobs
505      ])
506   , ("OpNetworkAdd",
507      [ pNetworkName
508      , pNetworkAddress4
509      , pNetworkGateway4
510      , pNetworkAddress6
511      , pNetworkGateway6
512      , pNetworkMacPrefix
513      , pNetworkAddRsvdIps
514      , pIpConflictsCheck
515      , pInstTags
516      ])
517   , ("OpNetworkRemove",
518      [ pNetworkName
519      , pForce
520      ])
521   , ("OpNetworkSetParams",
522      [ pNetworkName
523      , pNetworkGateway4
524      , pNetworkAddress6
525      , pNetworkGateway6
526      , pNetworkMacPrefix
527      , pNetworkAddRsvdIps
528      , pNetworkRemoveRsvdIps
529      ])
530   , ("OpNetworkConnect",
531      [ pGroupName
532      , pNetworkName
533      , pNetworkMode
534      , pNetworkLink
535      , pIpConflictsCheck
536      ])
537   , ("OpNetworkDisconnect",
538      [ pGroupName
539      , pNetworkName
540      ])
541   , ("OpNetworkQuery", dOldQuery)
542   , ("OpRestrictedCommand",
543      [ pUseLocking
544      , pRequiredNodes
545      , pRestrictedCommand
546      ])
547   ])
548
549 -- | Returns the OP_ID for a given opcode value.
550 $(genOpID ''OpCode "opID")
551
552 -- | A list of all defined/supported opcode IDs.
553 $(genAllOpIDs ''OpCode "allOpIDs")
554
555 instance JSON OpCode where
556   readJSON = loadOpCode
557   showJSON = saveOpCode
558
559 -- | Generates the summary value for an opcode.
560 opSummaryVal :: OpCode -> Maybe String
561 opSummaryVal OpClusterVerifyGroup { opGroupName = s } = Just (fromNonEmpty s)
562 opSummaryVal OpGroupVerifyDisks { opGroupName = s } = Just (fromNonEmpty s)
563 opSummaryVal OpClusterRename { opName = s } = Just (fromNonEmpty s)
564 opSummaryVal OpQuery { opWhat = s } = Just (queryTypeOpToRaw s)
565 opSummaryVal OpQueryFields { opWhat = s } = Just (queryTypeOpToRaw s)
566 opSummaryVal OpNodeRemove { opNodeName = s } = Just (fromNonEmpty s)
567 opSummaryVal OpNodeAdd { opNodeName = s } = Just (fromNonEmpty s)
568 opSummaryVal OpNodeModifyStorage { opNodeName = s } = Just (fromNonEmpty s)
569 opSummaryVal OpRepairNodeStorage  { opNodeName = s } = Just (fromNonEmpty s)
570 opSummaryVal OpNodeSetParams { opNodeName = s } = Just (fromNonEmpty s)
571 opSummaryVal OpNodePowercycle { opNodeName = s } = Just (fromNonEmpty s)
572 opSummaryVal OpNodeMigrate { opNodeName = s } = Just (fromNonEmpty s)
573 opSummaryVal OpNodeEvacuate { opNodeName = s } = Just (fromNonEmpty s)
574 opSummaryVal OpInstanceCreate { opInstanceName = s } = Just s
575 opSummaryVal OpInstanceReinstall { opInstanceName = s } = Just s
576 opSummaryVal OpInstanceRemove { opInstanceName = s } = Just s
577 -- FIXME: instance rename should show both names; currently it shows none
578 -- opSummaryVal OpInstanceRename { opInstanceName = s } = Just s
579 opSummaryVal OpInstanceStartup { opInstanceName = s } = Just s
580 opSummaryVal OpInstanceShutdown { opInstanceName = s } = Just s
581 opSummaryVal OpInstanceReboot { opInstanceName = s } = Just s
582 opSummaryVal OpInstanceReplaceDisks { opInstanceName = s } = Just s
583 opSummaryVal OpInstanceFailover { opInstanceName = s } = Just s
584 opSummaryVal OpInstanceMigrate { opInstanceName = s } = Just s
585 opSummaryVal OpInstanceMove { opInstanceName = s } = Just s
586 opSummaryVal OpInstanceConsole { opInstanceName = s } = Just s
587 opSummaryVal OpInstanceActivateDisks { opInstanceName = s } = Just s
588 opSummaryVal OpInstanceDeactivateDisks { opInstanceName = s } = Just s
589 opSummaryVal OpInstanceRecreateDisks { opInstanceName = s } = Just s
590 opSummaryVal OpInstanceSetParams { opInstanceName = s } = Just s
591 opSummaryVal OpInstanceGrowDisk { opInstanceName = s } = Just s
592 opSummaryVal OpInstanceChangeGroup { opInstanceName = s } = Just s
593 opSummaryVal OpGroupAdd { opGroupName = s } = Just (fromNonEmpty s)
594 opSummaryVal OpGroupAssignNodes { opGroupName = s } = Just (fromNonEmpty s)
595 opSummaryVal OpGroupSetParams { opGroupName = s } = Just (fromNonEmpty s)
596 opSummaryVal OpGroupRemove { opGroupName = s } = Just (fromNonEmpty s)
597 opSummaryVal OpGroupEvacuate { opGroupName = s } = Just (fromNonEmpty s)
598 opSummaryVal OpBackupPrepare { opInstanceName = s } = Just s
599 opSummaryVal OpBackupExport { opInstanceName = s } = Just s
600 opSummaryVal OpBackupRemove { opInstanceName = s } = Just s
601 opSummaryVal OpTagsGet { opKind = k } =
602   Just . fromMaybe "None" $ tagNameOf k
603 opSummaryVal OpTagsSearch { opTagSearchPattern = s } = Just (fromNonEmpty s)
604 opSummaryVal OpTestDelay { opDelayDuration = d } = Just (show d)
605 opSummaryVal OpTestAllocator { opIallocator = s } =
606   -- FIXME: Python doesn't handle None fields well, so we have behave the same
607   Just $ maybe "None" fromNonEmpty s
608 opSummaryVal OpNetworkAdd { opNetworkName = s} = Just (fromNonEmpty s)
609 opSummaryVal OpNetworkRemove { opNetworkName = s} = Just (fromNonEmpty s)
610 opSummaryVal OpNetworkSetParams { opNetworkName = s} = Just (fromNonEmpty s)
611 opSummaryVal OpNetworkConnect { opNetworkName = s} = Just (fromNonEmpty s)
612 opSummaryVal OpNetworkDisconnect { opNetworkName = s} = Just (fromNonEmpty s)
613 opSummaryVal _ = Nothing
614
615 -- | Computes the summary of the opcode.
616 opSummary :: OpCode -> String
617 opSummary op =
618   case opSummaryVal op of
619     Nothing -> op_suffix
620     Just s -> op_suffix ++ "(" ++ s ++ ")"
621   where op_suffix = drop 3 $ opID op
622
623 -- | Generic\/common opcode parameters.
624 $(buildObject "CommonOpParams" "op"
625   [ pDryRun
626   , pDebugLevel
627   , pOpPriority
628   , pDependencies
629   , pComment
630   , pReason
631   ])
632
633 -- | Default common parameter values.
634 defOpParams :: CommonOpParams
635 defOpParams =
636   CommonOpParams { opDryRun     = Nothing
637                  , opDebugLevel = Nothing
638                  , opPriority   = OpPrioNormal
639                  , opDepends    = Nothing
640                  , opComment    = Nothing
641                  , opReason     = []
642                  }
643
644 -- | The top-level opcode type.
645 data MetaOpCode = MetaOpCode { metaParams :: CommonOpParams
646                              , metaOpCode :: OpCode
647                              } deriving (Show, Eq)
648
649 -- | JSON serialisation for 'MetaOpCode'.
650 showMeta :: MetaOpCode -> JSValue
651 showMeta (MetaOpCode params op) =
652   let objparams = toDictCommonOpParams params
653       objop = toDictOpCode op
654   in makeObj (objparams ++ objop)
655
656 -- | JSON deserialisation for 'MetaOpCode'
657 readMeta :: JSValue -> Text.JSON.Result MetaOpCode
658 readMeta v = do
659   meta <- readJSON v
660   op <- readJSON v
661   return $ MetaOpCode meta op
662
663 instance JSON MetaOpCode where
664   showJSON = showMeta
665   readJSON = readMeta
666
667 -- | Wraps an 'OpCode' with the default parameters to build a
668 -- 'MetaOpCode'.
669 wrapOpCode :: OpCode -> MetaOpCode
670 wrapOpCode = MetaOpCode defOpParams
671
672 -- | Sets the comment on a meta opcode.
673 setOpComment :: String -> MetaOpCode -> MetaOpCode
674 setOpComment comment (MetaOpCode common op) =
675   MetaOpCode (common { opComment = Just comment}) op
676
677 -- | Sets the priority on a meta opcode.
678 setOpPriority :: OpSubmitPriority -> MetaOpCode -> MetaOpCode
679 setOpPriority prio (MetaOpCode common op) =
680   MetaOpCode (common { opPriority = prio }) op