Statistics
| Branch: | Tag: | Revision:

root / src / Ganeti / OpCodes.hs @ 80adbbe1

History | View | Annotate | Download (16.7 kB)

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
     , pMigrationCleanup
88
     ])
89
  , ("OpInstanceMigrate",
90
     [ pInstanceName
91
     , pMigrationMode
92
     , pMigrationLive
93
     , pMigrationTargetNode
94
     , pAllowRuntimeChgs
95
     , pIgnoreIpolicy
96
     , pMigrationCleanup
97
     , pIallocator
98
     , pAllowFailover
99
     ])
100
  , ("OpTagsGet",
101
     [ pTagsObject
102
     , pUseLocking
103
     ])
104
  , ("OpTagsSearch",
105
     [ pTagSearchPattern ])
106
  , ("OpTagsSet",
107
     [ pTagsObject
108
     , pTagsList
109
     ])
110
  , ("OpTagsDel",
111
     [ pTagsObject
112
     , pTagsList
113
     ])
114
  , ("OpClusterPostInit", [])
115
  , ("OpClusterDestroy", [])
116
  , ("OpClusterQuery", [])
117
  , ("OpClusterVerify",
118
     [ pDebugSimulateErrors
119
     , pErrorCodes
120
     , pSkipChecks
121
     , pIgnoreErrors
122
     , pVerbose
123
     , pOptGroupName
124
     ])
125
  , ("OpClusterVerifyConfig",
126
     [ pDebugSimulateErrors
127
     , pErrorCodes
128
     , pIgnoreErrors
129
     , pVerbose
130
     ])
131
  , ("OpClusterVerifyGroup",
132
     [ pGroupName
133
     , pDebugSimulateErrors
134
     , pErrorCodes
135
     , pSkipChecks
136
     , pIgnoreErrors
137
     , pVerbose
138
     ])
139
  , ("OpClusterVerifyDisks", [])
140
  , ("OpGroupVerifyDisks",
141
     [ pGroupName
142
     ])
143
  , ("OpClusterRepairDiskSizes",
144
     [ pInstances
145
     ])
146
  , ("OpClusterConfigQuery",
147
     [ pOutputFields
148
     ])
149
  , ("OpClusterRename",
150
     [ pName
151
     ])
152
  , ("OpClusterSetParams",
153
     [ pForce
154
     , pHvState
155
     , pDiskState
156
     , pVgName
157
     , pEnabledHypervisors
158
     , pClusterHvParams
159
     , pClusterBeParams
160
     , pOsHvp
161
     , pClusterOsParams
162
     , pDiskParams
163
     , pCandidatePoolSize
164
     , pUidPool
165
     , pAddUids
166
     , pRemoveUids
167
     , pMaintainNodeHealth
168
     , pPreallocWipeDisks
169
     , pNicParams
170
     , pNdParams
171
     , pIpolicy
172
     , pDrbdHelper
173
     , pDefaultIAllocator
174
     , pMasterNetdev
175
     , pMasterNetmask
176
     , pReservedLvs
177
     , pHiddenOs
178
     , pBlacklistedOs
179
     , pUseExternalMipScript
180
     , pEnabledDiskTemplates
181
     , pModifyEtcHosts
182
     ])
183
  , ("OpClusterRedistConf", [])
184
  , ("OpClusterActivateMasterIp", [])
185
  , ("OpClusterDeactivateMasterIp", [])
186
  , ("OpQuery",
187
     [ pQueryWhat
188
     , pUseLocking
189
     , pQueryFields
190
     , pQueryFilter
191
     ])
192
  , ("OpQueryFields",
193
     [ pQueryWhat
194
     , pQueryFields
195
     ])
196
  , ("OpOobCommand",
197
     [ pNodeNames
198
     , pOobCommand
199
     , pOobTimeout
200
     , pIgnoreStatus
201
     , pPowerDelay
202
     ])
203
  , ("OpNodeRemove", [ pNodeName ])
204
  , ("OpNodeAdd",
205
     [ pNodeName
206
     , pHvState
207
     , pDiskState
208
     , pPrimaryIp
209
     , pSecondaryIp
210
     , pReadd
211
     , pNodeGroup
212
     , pMasterCapable
213
     , pVmCapable
214
     , pNdParams
215
    ])
216
  , ("OpNodeQuery", dOldQuery)
217
  , ("OpNodeQueryvols",
218
     [ pOutputFields
219
     , pNodes
220
     ])
221
  , ("OpNodeQueryStorage",
222
     [ pOutputFields
223
     , pStorageType
224
     , pNodes
225
     , pStorageName
226
     ])
227
  , ("OpNodeModifyStorage",
228
     [ pNodeName
229
     , pStorageType
230
     , pStorageName
231
     , pStorageChanges
232
     ])
233
  , ("OpRepairNodeStorage",
234
     [ pNodeName
235
     , pStorageType
236
     , pStorageName
237
     , pIgnoreConsistency
238
     ])
239
  , ("OpNodeSetParams",
240
     [ pNodeName
241
     , pForce
242
     , pHvState
243
     , pDiskState
244
     , pMasterCandidate
245
     , pOffline
246
     , pDrained
247
     , pAutoPromote
248
     , pMasterCapable
249
     , pVmCapable
250
     , pSecondaryIp
251
     , pNdParams
252
     , pPowered
253
     ])
254
  , ("OpNodePowercycle",
255
     [ pNodeName
256
     , pForce
257
     ])
258
  , ("OpNodeMigrate",
259
     [ pNodeName
260
     , pMigrationMode
261
     , pMigrationLive
262
     , pMigrationTargetNode
263
     , pAllowRuntimeChgs
264
     , pIgnoreIpolicy
265
     , pIallocator
266
     ])
267
  , ("OpNodeEvacuate",
268
     [ pEarlyRelease
269
     , pNodeName
270
     , pRemoteNode
271
     , pIallocator
272
     , pEvacMode
273
     ])
274
  , ("OpInstanceCreate",
275
     [ pInstanceName
276
     , pForceVariant
277
     , pWaitForSync
278
     , pNameCheck
279
     , pIgnoreIpolicy
280
     , pInstBeParams
281
     , pInstDisks
282
     , pDiskTemplate
283
     , pFileDriver
284
     , pFileStorageDir
285
     , pInstHvParams
286
     , pHypervisor
287
     , pIallocator
288
     , pResetDefaults
289
     , pIpCheck
290
     , pIpConflictsCheck
291
     , pInstCreateMode
292
     , pInstNics
293
     , pNoInstall
294
     , pInstOsParams
295
     , pInstOs
296
     , pPrimaryNode
297
     , pSecondaryNode
298
     , pSourceHandshake
299
     , pSourceInstance
300
     , pSourceShutdownTimeout
301
     , pSourceX509Ca
302
     , pSrcNode
303
     , pSrcPath
304
     , pStartInstance
305
     , pOpportunisticLocking
306
     , pInstTags
307
     ])
308
  , ("OpInstanceMultiAlloc",
309
     [ pIallocator
310
     , pMultiAllocInstances
311
     , pOpportunisticLocking
312
     ])
313
  , ("OpInstanceReinstall",
314
     [ pInstanceName
315
     , pForceVariant
316
     , pInstOs
317
     , pTempOsParams
318
     ])
319
  , ("OpInstanceRemove",
320
     [ pInstanceName
321
     , pShutdownTimeout
322
     , pIgnoreFailures
323
     ])
324
  , ("OpInstanceRename",
325
     [ pInstanceName
326
     , pNewName
327
     , pNameCheck
328
     , pIpCheck
329
     ])
330
  , ("OpInstanceStartup",
331
     [ pInstanceName
332
     , pForce
333
     , pIgnoreOfflineNodes
334
     , pTempHvParams
335
     , pTempBeParams
336
     , pNoRemember
337
     , pStartupPaused
338
     ])
339
  , ("OpInstanceShutdown",
340
     [ pInstanceName
341
     , pForce
342
     , pIgnoreOfflineNodes
343
     , pShutdownTimeout'
344
     , pNoRemember
345
     ])
346
  , ("OpInstanceReboot",
347
     [ pInstanceName
348
     , pShutdownTimeout
349
     , pIgnoreSecondaries
350
     , pRebootType
351
     ])
352
  , ("OpInstanceMove",
353
     [ pInstanceName
354
     , pShutdownTimeout
355
     , pIgnoreIpolicy
356
     , pMoveTargetNode
357
     , pIgnoreConsistency
358
     ])
359
  , ("OpInstanceConsole",
360
     [ pInstanceName ])
361
  , ("OpInstanceActivateDisks",
362
     [ pInstanceName
363
     , pIgnoreDiskSize
364
     , pWaitForSyncFalse
365
     ])
366
  , ("OpInstanceDeactivateDisks",
367
     [ pInstanceName
368
     , pForce
369
     ])
370
  , ("OpInstanceRecreateDisks",
371
     [ pInstanceName
372
     , pRecreateDisksInfo
373
     , pNodes
374
     , pIallocator
375
     ])
376
  , ("OpInstanceQuery", dOldQuery)
377
  , ("OpInstanceQueryData",
378
     [ pUseLocking
379
     , pInstances
380
     , pStatic
381
     ])
382
  , ("OpInstanceSetParams",
383
     [ pInstanceName
384
     , pForce
385
     , pForceVariant
386
     , pIgnoreIpolicy
387
     , pInstParamsNicChanges
388
     , pInstParamsDiskChanges
389
     , pInstBeParams
390
     , pRuntimeMem
391
     , pInstHvParams
392
     , pOptDiskTemplate
393
     , pPrimaryNode
394
     , pRemoteNode
395
     , pOsNameChange
396
     , pInstOsParams
397
     , pWaitForSync
398
     , pOffline
399
     , pIpConflictsCheck
400
     ])
401
  , ("OpInstanceGrowDisk",
402
     [ pInstanceName
403
     , pWaitForSync
404
     , pDiskIndex
405
     , pDiskChgAmount
406
     , pDiskChgAbsolute
407
     ])
408
  , ("OpInstanceChangeGroup",
409
     [ pInstanceName
410
     , pEarlyRelease
411
     , pIallocator
412
     , pTargetGroups
413
     ])
414
  , ("OpGroupAdd",
415
     [ pGroupName
416
     , pNodeGroupAllocPolicy
417
     , pGroupNodeParams
418
     , pDiskParams
419
     , pHvState
420
     , pDiskState
421
     , pIpolicy
422
     ])
423
  , ("OpGroupAssignNodes",
424
     [ pGroupName
425
     , pForce
426
     , pRequiredNodes
427
     ])
428
  , ("OpGroupQuery", dOldQueryNoLocking)
429
  , ("OpGroupSetParams",
430
     [ pGroupName
431
     , pNodeGroupAllocPolicy
432
     , pGroupNodeParams
433
     , pDiskParams
434
     , pHvState
435
     , pDiskState
436
     , pIpolicy
437
     ])
438
  , ("OpGroupRemove",
439
     [ pGroupName ])
440
  , ("OpGroupRename",
441
     [ pGroupName
442
     , pNewName
443
     ])
444
  , ("OpGroupEvacuate",
445
     [ pGroupName
446
     , pEarlyRelease
447
     , pIallocator
448
     , pTargetGroups
449
     ])
450
  , ("OpOsDiagnose",
451
     [ pOutputFields
452
     , pNames ])
453
  , ("OpExtStorageDiagnose",
454
     [ pOutputFields
455
     , pNames ])
456
  , ("OpBackupQuery",
457
     [ pUseLocking
458
     , pNodes
459
     ])
460
  , ("OpBackupPrepare",
461
     [ pInstanceName
462
     , pExportMode
463
     ])
464
  , ("OpBackupExport",
465
     [ pInstanceName
466
     , pShutdownTimeout
467
     , pExportTargetNode
468
     , pShutdownInstance
469
     , pRemoveInstance
470
     , pIgnoreRemoveFailures
471
     , pExportMode
472
     , pX509KeyName
473
     , pX509DestCA
474
     ])
475
  , ("OpBackupRemove",
476
     [ pInstanceName ])
477
  , ("OpTestAllocator",
478
     [ pIAllocatorDirection
479
     , pIAllocatorMode
480
     , pIAllocatorReqName
481
     , pIAllocatorNics
482
     , pIAllocatorDisks
483
     , pHypervisor
484
     , pIallocator
485
     , pInstTags
486
     , pIAllocatorMemory
487
     , pIAllocatorVCpus
488
     , pIAllocatorOs
489
     , pDiskTemplate
490
     , pIAllocatorInstances
491
     , pIAllocatorEvacMode
492
     , pTargetGroups
493
     , pIAllocatorSpindleUse
494
     , pIAllocatorCount
495
     ])
496
  , ("OpTestJqueue",
497
     [ pJQueueNotifyWaitLock
498
     , pJQueueNotifyExec
499
     , pJQueueLogMessages
500
     , pJQueueFail
501
     ])
502
  , ("OpTestDummy",
503
     [ pTestDummyResult
504
     , pTestDummyMessages
505
     , pTestDummyFail
506
     , pTestDummySubmitJobs
507
     ])
508
  , ("OpNetworkAdd",
509
     [ pNetworkName
510
     , pNetworkAddress4
511
     , pNetworkGateway4
512
     , pNetworkAddress6
513
     , pNetworkGateway6
514
     , pNetworkMacPrefix
515
     , pNetworkAddRsvdIps
516
     , pIpConflictsCheck
517
     , pInstTags
518
     ])
519
  , ("OpNetworkRemove",
520
     [ pNetworkName
521
     , pForce
522
     ])
523
  , ("OpNetworkSetParams",
524
     [ pNetworkName
525
     , pNetworkGateway4
526
     , pNetworkAddress6
527
     , pNetworkGateway6
528
     , pNetworkMacPrefix
529
     , pNetworkAddRsvdIps
530
     , pNetworkRemoveRsvdIps
531
     ])
532
  , ("OpNetworkConnect",
533
     [ pGroupName
534
     , pNetworkName
535
     , pNetworkMode
536
     , pNetworkLink
537
     , pIpConflictsCheck
538
     ])
539
  , ("OpNetworkDisconnect",
540
     [ pGroupName
541
     , pNetworkName
542
     ])
543
  , ("OpNetworkQuery", dOldQuery)
544
  , ("OpRestrictedCommand",
545
     [ pUseLocking
546
     , pRequiredNodes
547
     , pRestrictedCommand
548
     ])
549
  ])
550

    
551
-- | Returns the OP_ID for a given opcode value.
552
$(genOpID ''OpCode "opID")
553

    
554
-- | A list of all defined/supported opcode IDs.
555
$(genAllOpIDs ''OpCode "allOpIDs")
556

    
557
instance JSON OpCode where
558
  readJSON = loadOpCode
559
  showJSON = saveOpCode
560

    
561
-- | Generates the summary value for an opcode.
562
opSummaryVal :: OpCode -> Maybe String
563
opSummaryVal OpClusterVerifyGroup { opGroupName = s } = Just (fromNonEmpty s)
564
opSummaryVal OpGroupVerifyDisks { opGroupName = s } = Just (fromNonEmpty s)
565
opSummaryVal OpClusterRename { opName = s } = Just (fromNonEmpty s)
566
opSummaryVal OpQuery { opWhat = s } = Just (queryTypeOpToRaw s)
567
opSummaryVal OpQueryFields { opWhat = s } = Just (queryTypeOpToRaw s)
568
opSummaryVal OpNodeRemove { opNodeName = s } = Just (fromNonEmpty s)
569
opSummaryVal OpNodeAdd { opNodeName = s } = Just (fromNonEmpty s)
570
opSummaryVal OpNodeModifyStorage { opNodeName = s } = Just (fromNonEmpty s)
571
opSummaryVal OpRepairNodeStorage  { opNodeName = s } = Just (fromNonEmpty s)
572
opSummaryVal OpNodeSetParams { opNodeName = s } = Just (fromNonEmpty s)
573
opSummaryVal OpNodePowercycle { opNodeName = s } = Just (fromNonEmpty s)
574
opSummaryVal OpNodeMigrate { opNodeName = s } = Just (fromNonEmpty s)
575
opSummaryVal OpNodeEvacuate { opNodeName = s } = Just (fromNonEmpty s)
576
opSummaryVal OpInstanceCreate { opInstanceName = s } = Just s
577
opSummaryVal OpInstanceReinstall { opInstanceName = s } = Just s
578
opSummaryVal OpInstanceRemove { opInstanceName = s } = Just s
579
-- FIXME: instance rename should show both names; currently it shows none
580
-- opSummaryVal OpInstanceRename { opInstanceName = s } = Just s
581
opSummaryVal OpInstanceStartup { opInstanceName = s } = Just s
582
opSummaryVal OpInstanceShutdown { opInstanceName = s } = Just s
583
opSummaryVal OpInstanceReboot { opInstanceName = s } = Just s
584
opSummaryVal OpInstanceReplaceDisks { opInstanceName = s } = Just s
585
opSummaryVal OpInstanceFailover { opInstanceName = s } = Just s
586
opSummaryVal OpInstanceMigrate { opInstanceName = s } = Just s
587
opSummaryVal OpInstanceMove { opInstanceName = s } = Just s
588
opSummaryVal OpInstanceConsole { opInstanceName = s } = Just s
589
opSummaryVal OpInstanceActivateDisks { opInstanceName = s } = Just s
590
opSummaryVal OpInstanceDeactivateDisks { opInstanceName = s } = Just s
591
opSummaryVal OpInstanceRecreateDisks { opInstanceName = s } = Just s
592
opSummaryVal OpInstanceSetParams { opInstanceName = s } = Just s
593
opSummaryVal OpInstanceGrowDisk { opInstanceName = s } = Just s
594
opSummaryVal OpInstanceChangeGroup { opInstanceName = s } = Just s
595
opSummaryVal OpGroupAdd { opGroupName = s } = Just (fromNonEmpty s)
596
opSummaryVal OpGroupAssignNodes { opGroupName = s } = Just (fromNonEmpty s)
597
opSummaryVal OpGroupSetParams { opGroupName = s } = Just (fromNonEmpty s)
598
opSummaryVal OpGroupRemove { opGroupName = s } = Just (fromNonEmpty s)
599
opSummaryVal OpGroupEvacuate { opGroupName = s } = Just (fromNonEmpty s)
600
opSummaryVal OpBackupPrepare { opInstanceName = s } = Just s
601
opSummaryVal OpBackupExport { opInstanceName = s } = Just s
602
opSummaryVal OpBackupRemove { opInstanceName = s } = Just s
603
opSummaryVal OpTagsGet { opKind = k } =
604
  Just . fromMaybe "None" $ tagNameOf k
605
opSummaryVal OpTagsSearch { opTagSearchPattern = s } = Just (fromNonEmpty s)
606
opSummaryVal OpTestDelay { opDelayDuration = d } = Just (show d)
607
opSummaryVal OpTestAllocator { opIallocator = s } =
608
  -- FIXME: Python doesn't handle None fields well, so we have behave the same
609
  Just $ maybe "None" fromNonEmpty s
610
opSummaryVal OpNetworkAdd { opNetworkName = s} = Just (fromNonEmpty s)
611
opSummaryVal OpNetworkRemove { opNetworkName = s} = Just (fromNonEmpty s)
612
opSummaryVal OpNetworkSetParams { opNetworkName = s} = Just (fromNonEmpty s)
613
opSummaryVal OpNetworkConnect { opNetworkName = s} = Just (fromNonEmpty s)
614
opSummaryVal OpNetworkDisconnect { opNetworkName = s} = Just (fromNonEmpty s)
615
opSummaryVal _ = Nothing
616

    
617
-- | Computes the summary of the opcode.
618
opSummary :: OpCode -> String
619
opSummary op =
620
  case opSummaryVal op of
621
    Nothing -> op_suffix
622
    Just s -> op_suffix ++ "(" ++ s ++ ")"
623
  where op_suffix = drop 3 $ opID op
624

    
625
-- | Generic\/common opcode parameters.
626
$(buildObject "CommonOpParams" "op"
627
  [ pDryRun
628
  , pDebugLevel
629
  , pOpPriority
630
  , pDependencies
631
  , pComment
632
  , pReason
633
  ])
634

    
635
-- | Default common parameter values.
636
defOpParams :: CommonOpParams
637
defOpParams =
638
  CommonOpParams { opDryRun     = Nothing
639
                 , opDebugLevel = Nothing
640
                 , opPriority   = OpPrioNormal
641
                 , opDepends    = Nothing
642
                 , opComment    = Nothing
643
                 , opReason     = []
644
                 }
645

    
646
-- | The top-level opcode type.
647
data MetaOpCode = MetaOpCode { metaParams :: CommonOpParams
648
                             , metaOpCode :: OpCode
649
                             } deriving (Show, Eq)
650

    
651
-- | JSON serialisation for 'MetaOpCode'.
652
showMeta :: MetaOpCode -> JSValue
653
showMeta (MetaOpCode params op) =
654
  let objparams = toDictCommonOpParams params
655
      objop = toDictOpCode op
656
  in makeObj (objparams ++ objop)
657

    
658
-- | JSON deserialisation for 'MetaOpCode'
659
readMeta :: JSValue -> Text.JSON.Result MetaOpCode
660
readMeta v = do
661
  meta <- readJSON v
662
  op <- readJSON v
663
  return $ MetaOpCode meta op
664

    
665
instance JSON MetaOpCode where
666
  showJSON = showMeta
667
  readJSON = readMeta
668

    
669
-- | Wraps an 'OpCode' with the default parameters to build a
670
-- 'MetaOpCode'.
671
wrapOpCode :: OpCode -> MetaOpCode
672
wrapOpCode = MetaOpCode defOpParams
673

    
674
-- | Sets the comment on a meta opcode.
675
setOpComment :: String -> MetaOpCode -> MetaOpCode
676
setOpComment comment (MetaOpCode common op) =
677
  MetaOpCode (common { opComment = Just comment}) op
678

    
679
-- | Sets the priority on a meta opcode.
680
setOpPriority :: OpSubmitPriority -> MetaOpCode -> MetaOpCode
681
setOpPriority prio (MetaOpCode common op) =
682
  MetaOpCode (common { opPriority = prio }) op