1from pydantic import BaseModel, Field, PositiveInt 2from enum import Enum 3import pathlib 4from typing import Optional, List 5from fastapi import Depends, FastAPI, HTTPException, status, Response, Path, Body, Query 6 7 8class Token(BaseModel): 9 access_token: str 10 token_type: str 11 12 13class TokenData(BaseModel): 14 username: Optional[str] = None 15 16 17class User(BaseModel): 18 username: str 19 directorName: Optional[str] = None 20 21 22class UserInDB(User): 23 hashed_password: str 24 25 26class bareosBool(str, Enum): 27 yes = "yes" 28 no = "no" 29 30 def __str__(self): 31 return self.name 32 33 def __bool__(self): 34 return self.name == "yes" 35 36 37class bareosFlag(str, Enum): 38 """ 39 Same as bareosBool but with different internal handling 40 """ 41 42 yes = "yes" 43 no = "no" 44 45 def __str__(self): 46 return self.name 47 48 def __bool__(self): 49 return self.name == "yes" 50 51 52class bareosTime(str): 53 # TODO: define this, stuff like "20 days" or "1 months" 54 def __str__(self): 55 return self.name 56 57 58class bareosReplaceOption(str, Enum): 59 """ 60 Replace option used by restore command 61 """ 62 63 always = "always" 64 never = "never" 65 ifolder = "ifolder" 66 ifnewer = "ifnewer" 67 68 def __str__(self): 69 return self.name 70 71 72class bareosSpeed(str): 73 # TODO: define this 74 def __str__(self): 75 return self.name 76 77 78class bareosSize(str): 79 # TODO: define this. Samples: 300, 10G 80 def __str__(self): 81 return self.name 82 83 84class bareosACL(str): 85 # TODO: define this. 86 def __str__(self): 87 return self.name 88 89 90class jobStatus(str, Enum): 91 """ 92 Allowed job status chars 93 """ 94 95 A = "A" 96 B = "B" 97 C = "C" 98 D = "D" 99 E = "E" 100 F = "F" 101 I = "I" 102 L = "L" 103 M = "M" 104 R = "R" 105 S = "S" 106 T = "T" 107 W = "W" 108 a = "a" 109 c = "c" 110 d = "d" 111 e = "e" 112 f = "f" 113 i = "i" 114 j = "j" 115 l = "l" 116 m = "m" 117 p = "p" 118 q = "q" 119 s = "s" 120 t = "t" 121 122 def __str__(self): 123 return self.name 124 125 126class jobLevelChr(str, Enum): 127 """ 128 Allowed job level chars 129 """ 130 131 F = "F" 132 I = "I" 133 D = "D" 134 S = "S" 135 C = "C" 136 V = "V" 137 O = "O" 138 d = "d" 139 A = "A" 140 B = "B" 141 f = "f" 142 143 def __str__(self): 144 return self.name 145 146 147class jobLevel(str, Enum): 148 """ 149 Allowed job level full description strings 150 """ 151 152 Base = "Base" 153 Full = "Full" 154 Incremental = "Incremental" 155 Differential = "Differential" 156 Since = "Since" 157 VerifyCatalog = "Verify Catalog" 158 InitCatalog = "Init Catalog" 159 VolumetoCatalog = "Volume to Catalog" 160 161 def __str__(self): 162 return self.name 163 164 165class aclCollection(BaseModel): 166 """ 167 Possible ACL options 168 """ 169 170 jobacl: Optional[bareosACL] = Field(None, title="") 171 clientacl: Optional[bareosACL] = Field(None, title="") 172 storageacl: Optional[bareosACL] = Field(None, title="") 173 scheduleacl: Optional[bareosACL] = Field(None, title="") 174 poolacl: Optional[bareosACL] = Field(None, title="") 175 commandacl: Optional[bareosACL] = Field(None, title="") 176 filesetacl: Optional[bareosACL] = Field(None, title="") 177 catalogacl: Optional[bareosACL] = Field(None, title="") 178 whereacl: Optional[bareosACL] = Field(None, title="") 179 pluginoptionsacl: Optional[bareosACL] = Field(None, title="") 180 181 182class tlsSettings(BaseModel): 183 """ 184 Options for TLS settings 185 """ 186 187 tlsauthenticate: Optional[bareosBool] = Field(None, title="") 188 tlsenable: Optional[bareosBool] = Field(None, title="") 189 tlsrequire: Optional[bareosBool] = Field(None, title="") 190 tlscipherlist: Optional[pathlib.Path] = Field(None, title="") 191 tlsdhfile: Optional[pathlib.Path] = Field(None, title="") 192 tlsverifypeer: Optional[bareosBool] = Field(None, title="") 193 tlscacertificatefile: Optional[pathlib.Path] = Field(None, title="") 194 tlscacertificatedir: Optional[pathlib.Path] = Field(None, title="") 195 tlscertificaterevocationlist: Optional[pathlib.Path] = Field(None, title="") 196 tlscertificate: Optional[pathlib.Path] = Field(None, title="") 197 tlskey: Optional[pathlib.Path] = Field(None, title="") 198 tlsallowedcn: Optional[List[str]] = Field(None, title="") 199 200 201class volumeQuery(BaseModel): 202 """ 203 Allowed query fields for volume queries 204 """ 205 206 volume: Optional[str] = Field( 207 None, title="volume name to query", example="myvolume" 208 ) 209 jobid: Optional[int] = Field( 210 None, title="Search for volumes used by a certain job", example="1", gt=1 211 ) 212 ujobid: Optional[str] = Field( 213 None, 214 title="Search for volumes used by a certain job given by full job-name", 215 example="DefaultJob.2020-08-20_12.56.27_25", 216 ) 217 pool: Optional[str] = Field( 218 None, title="Query volumes from the given pool", example="Full" 219 ) 220 221 222class volumeLabelDef(BaseModel): 223 """ 224 Options for volume label operation 225 """ 226 227 volume: str = Field(..., title="Name for the new volume", example="Full-1742") 228 pool: str = Field(..., title="New volume will get into this pool", example="Full") 229 storage: Optional[str] = Field(None, title="Storage for this volume") 230 slot: Optional[int] = Field(None, title="Slot for this volume", ge=0) 231 drive: Optional[int] = Field(None, title="Drive number", ge=0) 232 # TODO: handle [ barcodes ] [ encrypt ] flags 233 234 235class volumeRelabelDef(BaseModel): 236 """ 237 Options for volume relabel operation 238 """ 239 240 volume: str = Field(..., title="New Name for Volume", example="Full-001742") 241 storage: str = Field(..., title="Volume's storage", example="File") 242 pool: str = Field( 243 ..., 244 title="Volume's pool, can stay here or be moved to this pool", 245 example="Full", 246 ) 247 encrypt: Optional[bareosFlag] = Field(None, title="Encrypt volume", example="yes") 248 249 250class volumeProperties(BaseModel): 251 """ 252 Volume properties that can be set for _update volume_ operation 253 """ 254 255 pool: Optional[str] = Field(None, title="New pool for this volume", example="Full") 256 slot: Optional[int] = Field(None, title="New slot for this volume", ge=0) 257 volstatus: Optional[str] = Field( 258 None, title="New status for this volume", example="Archive" 259 ) 260 volretention: Optional[bareosTime] = Field( 261 None, title="Volume retention time", example="1 month" 262 ) 263 actiononpurge: Optional[str] = Field(None, title="Action to execute on purge") 264 recycle: Optional[bareosBool] = Field(None, title="Set recycle flag") 265 inchanger: Optional[bareosBool] = Field(None, title="Set inchanger flag") 266 maxvolbytes: Optional[bareosSize] = Field( 267 None, title="Set max byte size for this volume", example="20G" 268 ) 269 maxvolfiles: Optional[int] = Field( 270 None, title="Set max number of files for this volume", ge=0, example="10000" 271 ) 272 maxvoljobs: Optional[int] = Field( 273 None, title="Set max number of jobs for this volume", ge=0, example="20" 274 ) 275 enabled: Optional[bareosBool] = Field(None, title="Enable / disable volume") 276 recyclepool: Optional[str] = Field( 277 None, title="Define recyclepool for this volume", example="Scratch" 278 ) 279 280 281class volumeMove(BaseModel): 282 # parameters used for move 283 storage: str = Field(..., title="Storage to use for move operation") 284 srcslots: str = Field(..., title="Source slot selection") 285 dstslots: str = Field(..., title="Destination slot selection") 286 287 288class volumeExport(BaseModel): 289 storage: str = Field(..., title="Storage to use for move operation") 290 srcslots: str = Field(..., title="Source slot selection") 291 dstslots: Optional[str] = Field(None, title="Destination slot selection") 292 volume: Optional[str] = Field( 293 None, title="Volume selection", example="A00020L4|A00007L4|A00005L4" 294 ) 295 scan: Optional[bareosFlag] = Field(None, title="scan volume") 296 297 298class volumeImport(BaseModel): 299 storage: str = Field(..., title="Storage to use for import operation") 300 srcslots: Optional[str] = Field(..., title="Source slot selection") 301 dstslots: Optional[str] = Field(None, title="Destination slot selection") 302 volume: Optional[str] = Field(None, title="Volume name") 303 scan: Optional[bareosFlag] = Field(None, title="scan volume") 304 305 306class poolResource(BaseModel): 307 name: str = Body(..., title="Pool name") 308 description: Optional[str] = Field(None, title="") 309 pooltype: Optional[str] = Field(None, title="") 310 labelformat: Optional[str] = Field(None, title="") 311 labeltype: Optional[str] = Field(None, title="") 312 cleaningprefix: Optional[str] = Field(None, title="") 313 usecatalog: Optional[bareosBool] = Field(None, title="") 314 purgeoldestvolume: Optional[bareosBool] = Field(None, title="") 315 actiononpurge: Optional[str] = Field(None, title="") 316 recycleoldestvolume: Optional[bareosBool] = Field(None, title="") 317 recyclecurrentvolume: Optional[bareosBool] = Field(None, title="") 318 maximumvolumes: Optional[int] = Field(None, title="", ge=1) 319 maximumvolumejobs: Optional[int] = Field(None, title="", ge=1) 320 maximumvolumefiles: Optional[int] = Field(None, title="", ge=1) 321 maximumvolumebytes: Optional[int] = Field(None, title="") 322 catalogfiles: Optional[bareosBool] = Field(None, title="") 323 volumeretention: Optional[bareosTime] = Field(None, title="") 324 volumeuseduration: Optional[bareosTime] = Field(None, title="") 325 migrationtime: Optional[bareosTime] = Field(None, title="") 326 migrationhighbytes: Optional[int] = Field(None, title="") 327 migrationlowbytes: Optional[int] = Field(None, title="") 328 nextpool: Optional[str] = Field(None, title="") 329 storage: Optional[List[str]] = Field(None, title="") 330 autoprune: Optional[bareosBool] = Field(None, title="") 331 recycle: Optional[bareosBool] = Field(None, title="") 332 recyclepool: Optional[str] = Field(None, title="") 333 scratchpool: Optional[str] = Field(None, title="") 334 catalog: Optional[str] = Field(None, title="") 335 fileretention: Optional[bareosTime] = Field(None, title="") 336 jobretention: Optional[bareosTime] = Field(None, title="") 337 minimumblocksize: Optional[int] = Field(None, title="") 338 maximumblocksize: Optional[int] = Field(None, title="") 339 340 341class scheduleResource(BaseModel): 342 name: str = Body(..., title="Schedule name") 343 description: Optional[str] = Body(None, title="Schedule Description") 344 runCommand: Optional[List[str]] = Body( 345 None, 346 title="A list of run statements", 347 example=["Full 1st Sat at 12:00", "Incremental Sun-Fri at 11:00"], 348 ) 349 enabled: Optional[bareosBool] = Body( 350 None, title="Schedule enabled? Yes, if unset", example="no" 351 ) 352 353 354class profileResource(aclCollection): 355 name: str = Field(..., title="resource name") 356 description: Optional[str] = Field(None, title="Description") 357 358 359class userResource(profileResource): 360 profile: Optional[List[str]] = Field( 361 None, title="List of profile names for this user" 362 ) 363 364 365class jobRange(BaseModel): 366 days: Optional[int] = Field( 367 None, title="Query jobs run max days ago", gt=1, example=7 368 ) 369 hours: Optional[int] = Field( 370 None, title="Query jobs run max hours ago", gt=1, example=12 371 ) 372 since_jobid: Optional[int] = Field( 373 None, title="Run all jobs since the given job by id", ge=1 374 ) 375 unitl_jobid: Optional[int] = Field( 376 None, title="Run all jobs until the given job by id", ge=1 377 ) 378 379 380# class bareosTimeSpec(BaseModel): 381# # TODO: better specification / Regex? 382# timeSpec: str = Field(None, title="Bareos universal time specification") 383 384 385class jobControl(BaseModel): 386 job: str = Field(..., title="Job name to run", example="myjob") 387 client: str = Field(None, title="Client to run job on", example="myclient-fd") 388 fileset: Optional[str] = Field( 389 None, title="Fileset to use", example="server-fileset" 390 ) 391 level: Optional[jobLevel] = Field(None, title="Job level to query", example="Full") 392 storage: Optional[str] = Field(None, title="Storage to use") 393 when: Optional[str] = Field( 394 None, title="When to run job, Bareos universal timespec" 395 ) 396 pool: Optional[str] = Field(None, title="Pool to use", example="LTO-Pool") 397 pluginoptions: Optional[str] = Field( 398 None, title="Overwrite eventual plugin options" 399 ) 400 accurate: Optional[bareosBool] = Field(None, title="Set / unset accurate option") 401 comment: Optional[str] = Field(None, title="Comment") 402 spooldata: Optional[bareosBool] = Field(None, title="Spooling") 403 priority: Optional[str] = Field( 404 None, title="Priority, higher number means lower prio" 405 ) 406 catalog: Optional[str] = Field(None, title="Catalog to use for this job") 407 # migrationjob in help run list but not in documentation 408 migrationjob: Optional[str] = Field(None) 409 backupformat: Optional[str] = Field( 410 None, 411 title="The backup format used for protocols which support multiple formats.", 412 ) 413 nextpool: Optional[str] = Field( 414 None, 415 title="A Next Pool override used for Migration/Copy and Virtual Backup Jobs.", 416 ) 417 # since in help run list but not in documentation 418 since: Optional[str] = Field( 419 None, 420 title="Set since time for differential / incremental jobs. Bareos universal timespec", 421 ) 422 verifyjob: Optional[str] = Field(None) 423 verifylist: Optional[str] = Field(None) 424 migrationjob: Optional[str] = Field(None) 425 426 427class restoreJobControl(BaseModel): 428 client: str = Field(..., title="Restore data from this client") 429 where: Optional[pathlib.Path] = Field( 430 None, title="Filesystem prefix. Use _/_ for original location", example="/" 431 ) 432 storage: Optional[str] = Field(None, title="") 433 bootstrap: Optional[str] = Field(None, title="") 434 restorejob: Optional[str] = Field(None, title="") 435 comment: Optional[str] = Field(None, title="") 436 jobid: Optional[int] = Field( 437 None, title="Restore all files backuped by a given jobid", ge=1 438 ) 439 fileset: Optional[str] = Field(None, title="") 440 replace: Optional[bareosReplaceOption] = Field( 441 None, title="Set file-replace options", example="ifnewer" 442 ) 443 pluginoptions: Optional[str] = Field(None, title="") 444 regexwhere: Optional[str] = Field(None, title="") 445 restoreclient: Optional[str] = Field(None, title="Restore data to this client") 446 backupformat: Optional[str] = Field(None, title="") 447 pool: Optional[str] = Field(None, title="") 448 file: Optional[str] = Field(None, title="") 449 # can't use pathlib.Path here, as it strips trailing /, which is required by Bareos to accept a path 450 directory: Optional[str] = Field(None, title="") 451 before: Optional[str] = Field(None, title="") 452 strip_prefix: Optional[str] = Field(None, title="") 453 add_prefix: Optional[str] = Field(None, title="") 454 add_suffix: Optional[str] = Field(None, title="") 455 select: Optional[str] = Field(None, title="use select=date") 456 selectAllDone: Optional[bareosBool] = Field( 457 None, title="Run restore job with _select all done_ option" 458 ) 459 460 461class jobResource(BaseModel): 462 # TODO: complete field description 'title' and find meaningful examples 463 messages: str = Field(..., title="Message resource identifier", example="Standard") 464 name: str = Field(..., title="Name for this resource", example="DefaultJob") 465 pool: str = Field(..., title="Pool for this job", example="Full") 466 jobdefs: str = Field(..., title="Jobdefs to use", example="DefaultJob") 467 type: str = Field(..., title="Job type", example="Backup") 468 accurate: Optional[bareosBool] = Field( 469 None, 470 title="Accurate setting, will be default 'no' if unset here", 471 example="yes", 472 ) 473 addprefix: Optional[str] = Field(None, title="") 474 addsuffix: Optional[str] = Field(None, title="") 475 allowduplicatejobs: Optional[bareosBool] = Field(None, title="") 476 allowhigherduplicates: Optional[bareosBool] = Field(None, title="") 477 allowmixedpriority: Optional[bareosBool] = Field(None, title="") 478 alwaysincremental: Optional[bareosBool] = Field(None, title="") 479 alwaysincrementaljobretention: Optional[bareosTime] = Field( 480 None, title="", example="20 days" 481 ) 482 alwaysincrementalkeepnumber: Optional[int] = Field(None, title="", ge=1, example=5) 483 cancellowerlevelduplicates: Optional[bareosBool] = Field(None, title="") 484 cancelqueuedduplicates: Optional[bareosBool] = Field(None, title="") 485 cancelrunningduplicates: Optional[bareosBool] = Field(None, title="") 486 catalog: Optional[str] = Field(None, title="") 487 client: Optional[str] = Field(None, title="") 488 clientrunafterjob: Optional[str] = Field(None, title="") 489 clientrunbeforejob: Optional[str] = Field(None, title="") 490 description: Optional[str] = Field(None, title="") 491 differentialbackuppool: Optional[str] = Field(None, title="") 492 differentialmaxruntime: Optional[bareosTime] = Field(None, title="") 493 dirpluginoptions: List[str] = Field(None, title="") 494 enabled: Optional[bareosBool] = Field(None, title="") 495 fdpluginoptions: List[str] = Field(None, title="") 496 filehistorysize: Optional[int] = Field(None, title="", gt=1) 497 fileset: Optional[str] = Field(None, title="") 498 fullbackuppool: Optional[str] = Field(None, title="") 499 fullmaxruntime: Optional[bareosTime] = Field(None, title="") 500 incrementalbackuppool: Optional[str] = Field(None, title="") 501 incrementalmaxruntime: Optional[bareosTime] = Field(None, title="") 502 jobtoverify: Optional[str] = Field(None, title="") 503 level: Optional[jobLevel] = Field(None, title="Job Level", example="Full") 504 maxconcurrentcopies: Optional[int] = Field(None, title="", gt=1) 505 maxdiffinterval: Optional[bareosTime] = Field(None, title="") 506 maxfullconsolidations: Optional[int] = Field(None, title="", gt=1) 507 maxfullinterval: Optional[bareosTime] = Field(None, title="") 508 maximumbandwidth: Optional[bareosSpeed] = Field(None, title="") 509 maximumconcurrentjobs: Optional[int] = Field(None, title="") 510 maxrunschedtime: Optional[bareosTime] = Field(None, title="") 511 maxruntime: Optional[bareosTime] = Field(None, title="") 512 maxstartdelay: Optional[bareosTime] = Field(None, title="") 513 maxvirtualfullinterval: Optional[bareosTime] = Field(None, title="") 514 maxwaittime: Optional[bareosTime] = Field(None, title="") 515 nextpool: Optional[str] = Field(None, title="") 516 prefermountedvolumes: Optional[bareosBool] = Field(None, title="") 517 prefixlinks: Optional[bareosBool] = Field(None, title="") 518 priority: Optional[int] = Field(None, title="", gt=1) 519 protocol: Optional[str] = Field(None, title="") 520 prunefiles: Optional[bareosBool] = Field(None, title="") 521 prunejobs: Optional[bareosBool] = Field(None, title="") 522 prunevolumes: Optional[bareosBool] = Field(None, title="") 523 purgemigrationjob: Optional[bareosBool] = Field(None, title="") 524 regexwhere: Optional[str] = Field(None, title="") 525 replace: Optional[str] = Field(None, title="") 526 rerunfailedlevels: Optional[bareosBool] = Field(None, title="") 527 rescheduleinterval: Optional[bareosTime] = Field(None, title="") 528 rescheduleonerror: Optional[bareosBool] = Field(None, title="") 529 rescheduletimes: Optional[int] = Field(None, title="", gt=1) 530 runafterfailedjob: Optional[str] = Field(None, title="") 531 runafterjob: Optional[str] = Field(None, title="") 532 runbeforejob: Optional[str] = Field(None, title="") 533 runonincomingconnectinterval: Optional[bareosTime] = Field(None, title="") 534 run: List[str] = Field(None, title="") 535 savefilehistory: Optional[bareosBool] = Field(None, title="") 536 schedule: Optional[str] = Field(None, title="") 537 sdpluginoptions: List[str] = Field(None, title="") 538 selectionpattern: Optional[str] = Field(None, title="") 539 selectiontype: Optional[str] = Field(None, title="", example="OldestVolume") 540 spoolattributes: Optional[bareosBool] = Field(None, title="") 541 spooldata: Optional[bareosBool] = Field(None, title="") 542 spoolsize: Optional[int] = Field(None, title="", gt=1) 543 storage: List[str] = Field(None, title="") 544 stripprefix: Optional[str] = Field(None, title="") 545 virtualfullbackuppool: Optional[str] = Field(None, title="") 546 where: Optional[pathlib.Path] = Field(None, title="") 547 writebootstrap: Optional[pathlib.Path] = Field(None, title="") 548 writeverifylist: Optional[pathlib.Path] = Field(None, title="") 549 550 551class jobDefs(jobResource): 552 jobdefs: Optional[str] = Field(None, title="Jobdefs to use", example="DefaultJob") 553 554 555class clientResource(tlsSettings): 556 name: str 557 address: str 558 password: str 559 description: Optional[str] = Field(None, title="A client description") 560 passive: Optional[bareosBool] = Field( 561 None, 562 title="Passive clients will wait for Director and SD to open any connection", 563 ) 564 port: Optional[int] = Field(None, gt=1, le=65535) 565 protocol: Optional[str] = Field(None) 566 authtype: Optional[str] = Field(None) 567 lanaddress: Optional[str] = Field(None) 568 username: Optional[str] = Field(None) 569 catalog: Optional[str] = Field(None) 570 connectionfromdirectortoclient: Optional[bareosBool] = Field(None) 571 connectionfromclienttodirector: Optional[bareosBool] = Field(None) 572 enabled: Optional[bareosBool] = Field(None) 573 hardquota: Optional[int] = Field(None) 574 softquota: Optional[int] = Field(None) 575 softquotagraceperiod: Optional[str] = Field(None) 576 strictquotas: Optional[bareosBool] = Field(None) 577 quotaincludefailedjobs: Optional[bareosBool] = Field(None) 578 fileretention: Optional[str] = Field(None) 579 jobretention: Optional[str] = Field(None) 580 heartbeatinterval: Optional[str] = Field(None) 581 autoprune: Optional[bareosBool] = Field(None) 582 maximumconcurrentjobs: Optional[PositiveInt] = Field(None) 583 maximumbandwidthperjob: Optional[str] = Field(None) 584 ndmploglevel: Optional[PositiveInt] = Field(None) 585 ndmpblocksize: Optional[PositiveInt] = Field(None) 586 ndmpuselmdb: Optional[bareosBool] = Field(None) 587 588 589class deviceResource(tlsSettings): 590 device: str = Field(..., title="") 591 mediatype: str = Field(..., title="") 592 description: Optional[str] = Field(None, title="") 593 protocol: Optional[str] = Field(None, title="") 594 authtype: Optional[str] = Field(None, title="") 595 lanaddress: Optional[str] = Field(None, title="") 596 port: Optional[int] = Field(None, title="", ge=1) 597 username: Optional[str] = Field(None, title="") 598 autochanger: Optional[bareosBool] = Field(None, title="") 599 enabled: Optional[bareosBool] = Field(None, title="") 600 allowcompression: Optional[bareosBool] = Field(None, title="") 601 heartbeatinterval: Optional[bareosTime] = Field(None, title="") 602 cachestatusinterval: Optional[bareosTime] = Field(None, title="") 603 maximumconcurrentjobs: Optional[int] = Field(None, title="", ge=1) 604 maximumconcurrentreadjobs: Optional[int] = Field(None, title="", ge=1) 605 pairedstorage: Optional[str] = Field(None, title="") 606 maximumbandwidthperjob: Optional[bareosSpeed] = Field(None, title="") 607 collectstatistics: Optional[bareosBool] = Field(None, title="") 608 ndmpchangerdevice: Optional[str] = Field(None, title="") 609 610 611class storageResource(deviceResource): 612 name: str = Field(..., title="") 613 address: str = Field(..., title="") 614 password: str = Field(..., title="") 615 616 617class consoleResource(userResource, tlsSettings): 618 password: str = Field(..., title="Console password") 619 620 621class jobQuery(BaseModel): 622 job: Optional[str] = Field(None, title="Job name to query", example="myjob") 623 client: Optional[str] = Field(None, title="Client to query", example="myclient-fd") 624 jobstatus: Optional[jobStatus] = Field( 625 None, title="Job status to query", example="T" 626 ) 627 joblevel: Optional[jobLevelChr] = Field( 628 None, title="Job level to query", example="F" 629 ) 630 volume: Optional[str] = Field( 631 None, title="Query jobs on the given volume", example="Full-0017" 632 ) 633 days: Optional[int] = Field( 634 None, title="Query jobs run max days ago", gt=1, example=7 635 ) 636 hours: Optional[int] = Field( 637 None, title="Query jobs run max hours ago", gt=1, example=12 638 ) 639