pystorcli.virtualdrive
StorCLI virtual virtual drive python module
1# -*- coding: utf-8 -*- 2 3# Copyright (c) 2018, Martin Dojcak <martin@dojcak.sk> 4# Copyright (c) 2022, Rafael Leira & Naudit HPCN S.L. <rafael.leira@naudit.es> 5# See LICENSE for details. 6 7'''StorCLI virtual virtual drive python module 8''' 9 10from . import StorCLI 11from . import common 12from . import controller 13from . import drive 14from . import exc 15 16 17class VirtualDriveMetrics(object): 18 """StorCLI VirtualDriveMerics 19 20 Instance of this class represents drive metrics 21 22 Args: 23 vd (:obj:VirtualDrive): virtual drive object 24 25 Properties: 26 state (str): virtual drive state 27 init_progress (str): % progress of initialization on a virtual drive 28 cc_progress (str): % progress of consistency check on a virtual drive 29 migrate_progress (str): % progress of migration on a virtual drive 30 erase_progress (str): % progress of erase on a virtual drive 31 all (dict): all metrics 32 """ 33 34 def __init__(self, vd): 35 """Constructor - create StorCLI VirtualDriveMetrics object 36 37 Args: 38 vd (:obj:VirtualDrive): vitual drive object 39 """ 40 self._vd = vd 41 42 @property 43 def state(self): 44 """(str): virtual drive state (optimal | recovery | offline | degraded | degraded_partially) 45 """ 46 return self._vd.state 47 48 @property 49 @common.stringify 50 def init_progress(self): 51 """Show virtual drive initialization progress in perctentage 52 53 Returns: 54 (str): progress in percentage 55 """ 56 args = [ 57 'show', 58 'init' 59 ] 60 61 progress = self._vd._resposne_operation_status(self._vd._run(args))[ 62 'Progress%'] 63 if progress == '-': 64 return "100" 65 return progress 66 67 @property 68 @common.stringify 69 def cc_progress(self): 70 """Show virtual drive consistency check progress in perctentage 71 72 Returns: 73 (str): progress in percentage 74 """ 75 args = [ 76 'show', 77 'cc' 78 ] 79 80 progress = self._vd._resposne_operation_status(self._vd._run(args))[ 81 'Progress%'] 82 if progress == '-': 83 return "100" 84 return progress 85 86 @property 87 @common.stringify 88 def migrate_progress(self): 89 """Show migrate progress of a virtual drive in percentage 90 91 Returns: 92 (str): progress in percentage 93 """ 94 args = [ 95 'show', 96 'migrate' 97 ] 98 99 progress = self._vd._resposne_operation_status(self._vd._run(args))[ 100 'Progress%'] 101 if progress == '-': 102 return "100" 103 return progress 104 105 @property 106 def all(self): 107 """(:obj:DriveMetrics): all metrics 108 """ 109 metrics = {} 110 111 for attribute in dir(self): 112 if not attribute.startswith('_') and not attribute == 'all': 113 metrics[attribute] = self.__getattribute__(attribute) 114 return metrics 115 116 117class VirtualDrive(object): 118 """StorCLI VirtualDrive 119 120 Instance of this class represents virtual drive (RAID) in StorCLI hierarchy 121 122 Args: 123 ctl_id (str): controller id 124 vd_id (str): virtual drive id 125 binary (str): storcli binary or full path to the binary 126 127 Properties: 128 id (str): virtual drive id 129 facts (dict): raw virtual drive facts 130 metrics (dict): virtual drive metrics 131 raid (str): vitual drive raid level 132 size (str): virtual drive size 133 state (str): virtual drive state 134 strip (str): virtual drive strip size 135 os_exposed (bool): virtual drive exposed to the OS 136 os_name (str): virtual drive device path (/dev/...) 137 ctl_id (str): virtual drive controller 138 ctl (:obj:controller.Controller): virtual drive controller 139 drives (list of :obj:drive.Drive): virtual drive drives 140 name (str): virtual drive name (also setter) 141 bootdrive (str): virtual drive bootdrive (also setter) 142 pdcache (str): current disk cache policy on a virtual drive (also setter) 143 wrcache (str): write cache policy on a virtual drive (also setter) 144 rdcache (str): read cache policy on a virtual drive (also setter) 145 iopolicy (str): I/O policy on a virtual drive (also setter) 146 autobgi (str):virtual drive auto background initialization setting (also setter) 147 148 Methods: 149 init_start (dict): starts the initialization process on a virtual drive 150 init_stop (dict): stops an initialization process running on a virtual drive 151 init_running (bool): check if initialization is running on a virtual drive 152 erase_start (dict): securely erases non-SED virtual drive 153 erase_stop (dict): stops an erase process running on a virtual drive 154 erase_running (bool): check if erase is running on a virtual drive 155 erase_progress (str): % progress of erase on a virtual drive 156 delete (dict): delete virtual drive 157 migrate_start (dict): starts the migration process on a virtual drive 158 migrate_stop (dict): stops an migration process running on a virtual drive 159 migrate_running (bool): check if migrate is running on a virtual drive 160 161 TODO: 162 Implement missing methods: 163 * start cc 164 * stop cc 165 * pause cc 166 * resume cc 167 * cc running 168 """ 169 170 def __init__(self, ctl_id, vd_id, binary='storcli64'): 171 """Constructor - create StorCLI VirtualDrive object 172 173 Args: 174 ctl_id (str): controller id 175 vd_id (str): virtual drive id 176 binary (str): storcli binary or full path to the binary 177 """ 178 self._ctl_id = ctl_id 179 self._vd_id = vd_id 180 self._binary = binary 181 self._storcli = StorCLI(binary) 182 self._name = '/c{0}/v{1}'.format(self._ctl_id, self._vd_id) 183 184 self._exist() 185 186 def _run(self, args, **kwargs): 187 args = args[:] 188 args.insert(0, self._name) 189 return self._storcli.run(args, **kwargs) 190 191 def _exist(self): 192 try: 193 self._run(['show']) 194 except exc.StorCliCmdError: 195 raise exc.StorCliMissingError( 196 self.__class__.__name__, self._name) from None 197 198 @staticmethod 199 def _response_properties(out): 200 return common.response_data(out)['Virtual Drives'][0] 201 202 def _response_properties_all(self, out): 203 return common.response_data(out)['VD{0} Properties'.format(self._vd_id)] 204 205 @staticmethod 206 def _resposne_operation_status(out): 207 return common.response_data(out)['VD Operation Status'][0] 208 209 @property 210 def id(self): 211 """(str): virtual drive id 212 """ 213 return self._vd_id 214 215 @property 216 def facts(self): 217 """(dict): raw virtual drive facts 218 """ 219 args = [ 220 'show', 221 'all' 222 ] 223 return common.response_data(self._run(args)) 224 225 @property 226 def metrics(self): 227 """(:obj:VirtualDriveMetrics): virtual drive metrics 228 """ 229 return VirtualDriveMetrics(self) 230 231 @property 232 @common.lower 233 def raid(self): 234 """(str): virtual drive raid level 235 """ 236 args = [ 237 'show' 238 ] 239 240 return self._response_properties(self._run(args))['TYPE'] 241 242 @property 243 def size(self): 244 """(str): virtual drive size 245 """ 246 args = [ 247 'show' 248 ] 249 return self._response_properties(self._run(args))['Size'] 250 251 @property 252 @common.lower 253 def state(self): 254 """(str): virtual drive state (optimal | recovery | offline | degraded | degraded_partially) 255 """ 256 args = [ 257 'show' 258 ] 259 state = self._response_properties(self._run(args))['State'] 260 if state == 'Optl': 261 return 'optimal' 262 elif state == 'Rec': 263 return 'recovery' 264 elif state == 'OfLn': 265 return 'offline' 266 elif state == 'Pdgd': 267 return 'degraded_partially' 268 return 'degraded' 269 270 @property 271 def strip(self): 272 """(str): virtual drive strip size 273 """ 274 args = [ 275 'show', 276 'all' 277 ] 278 279 size = self._response_properties_all(self._run(args))['Strip Size'] 280 return size.split()[0] 281 282 @property 283 def os_exposed(self): 284 """(bool): virtual drive exposed to the OS 285 """ 286 args = [ 287 'show', 288 'all' 289 ] 290 291 exposed = self._response_properties_all(self._run(args))[ 292 'Exposed to OS'] 293 return bool(exposed == 'Yes') 294 295 @property 296 @common.lower 297 def os_name(self): 298 """(str): virtual drive device path (/dev/...) 299 """ 300 args = [ 301 'show', 302 'all' 303 ] 304 return self._response_properties_all(self._run(args))['OS Drive Name'] 305 306 @property 307 def ctl_id(self): 308 """(str): virtual drive controller id 309 """ 310 return self._ctl_id 311 312 @property 313 def ctl(self): 314 """(:obj:controller.Controller): virtual drive controller 315 """ 316 return controller.Controller(ctl_id=self._ctl_id, binary=self._binary) 317 318 @property 319 def drives(self): 320 """(list of :obj:Drive): drives 321 """ 322 args = [ 323 'show', 324 'all' 325 ] 326 327 drives = [] 328 pds = common.response_data(self._run(args))[ 329 'PDs for VD {0}'.format(self._vd_id)] 330 for pd in pds: 331 drive_encl_id, drive_slot_id = pd['EID:Slt'].split(':') 332 drives.append( 333 drive.Drive( 334 ctl_id=self._ctl_id, 335 encl_id=drive_encl_id, 336 slot_id=drive_slot_id, 337 binary=self._binary 338 ) 339 ) 340 return drives 341 342 @property 343 def name(self): 344 """Get/Set virtual drive name 345 346 The name is restricted to 15 characters. 347 348 Returns: 349 (str): raid name 350 """ 351 args = [ 352 'show', 353 ] 354 355 properties = self._response_properties(self._run(args)) 356 return properties['Name'] 357 358 @name.setter 359 def name(self, value): 360 """ 361 """ 362 args = [ 363 'set', 364 'name={0}'.format(value) 365 ] 366 return common.response_setter(self._run(args)) 367 368 @property 369 def bootdrive(self): 370 """Get/Set virtual drive as Boot Drive 371 372 One of the following options can be set (str): 373 on - enable boot virtual drive 374 off - disable boot virtual dirve 375 376 Returns: 377 (str): on / off 378 """ 379 args = [ 380 '/c{0}'.format(self._ctl_id), 381 'show', 382 'bootdrive' 383 ] 384 385 for vd in common.response_property(self._storcli.run(args)): 386 if vd['Value'] == 'VD:{0}'.format(self._vd_id): 387 return 'on' 388 return 'off' 389 390 @bootdrive.setter 391 def bootdrive(self, value): 392 """ 393 """ 394 args = [ 395 'set', 396 'bootdrive={0}'.format(value) 397 ] 398 return common.response_setter(self._run(args)) 399 400 @property 401 def pdcache(self): 402 """Get/Set PD Cache Setting 403 404 One of the following options can be set (str): 405 on - enables PD Caching 406 off - disables PD Caching 407 default - default PD Caching 408 409 Returns: 410 (str): on / off 411 """ 412 args = [ 413 'show', 414 'all' 415 ] 416 417 properties = self._response_properties_all(self._run(args)) 418 if properties['Disk Cache Policy'] == 'Enabled': 419 return 'on' 420 elif 'Default' in properties['Disk Cache Policy']: 421 return 'default' 422 return 'off' 423 424 @pdcache.setter 425 def pdcache(self, value): 426 """ 427 """ 428 args = [ 429 'set', 430 'pdcache={0}'.format(value) 431 ] 432 return common.response_setter(self._run(args)) 433 434 @property 435 def wrcache(self): 436 """Get/Set Write cache setting 437 438 One of the following options can be set (str): 439 wt - write Through 440 wb - write Back 441 awb - write Back even in case of bad BBU also 442 443 Returns: 444 (str): wt / wb / awb 445 """ 446 args = [ 447 'show', 448 ] 449 450 properties = self._response_properties(self._run(args)) 451 if 'AWB' in properties['Cache']: 452 return 'awb' 453 elif 'WB' in properties['Cache']: 454 return 'wb' 455 return 'wt' 456 457 @wrcache.setter 458 def wrcache(self, value): 459 """ 460 """ 461 args = [ 462 'set', 463 'wrcache={0}'.format(value) 464 ] 465 return common.response_setter(self._run(args)) 466 467 @property 468 def rdcache(self): 469 """Get/Set Read cache setting 470 471 One of the following options can be set (str): 472 ra - Read Ahead 473 nora - No Read Ahead 474 475 Returns: 476 (str): ra / nora 477 """ 478 args = [ 479 'show', 480 ] 481 482 properties = self._response_properties(self._run(args)) 483 if properties['Cache'][0:2] == 'NR': 484 return 'nora' 485 return 'ra' 486 487 @rdcache.setter 488 def rdcache(self, value): 489 """ 490 """ 491 args = [ 492 'set', 493 'rdcache={0}'.format(value) 494 ] 495 return common.response_setter(self._run(args)) 496 497 @property 498 def iopolicy(self): 499 """Get/Set iopolicy setting 500 501 One of the following options can be set (str): 502 cached - IOs are cached 503 direct - IOs are not cached 504 505 Returns: 506 (str): cached / direct 507 """ 508 args = [ 509 'show', 510 ] 511 512 properties = self._response_properties(self._run(args)) 513 if properties['Cache'][-1] == 'D': 514 return 'direct' 515 return 'cached' 516 517 @iopolicy.setter 518 @common.lower 519 def iopolicy(self, value): 520 """ 521 """ 522 args = [ 523 'set', 524 'iopolicy={0}'.format(value) 525 ] 526 return common.response_setter(self._run(args)) 527 528 @property 529 @common.lower 530 def autobgi(self): 531 """Get/Set auto background initialization 532 533 One of the following options can be set (str): 534 on - enables autobgi 535 off - disables autobgi 536 537 Returns: 538 (str): on / off 539 """ 540 args = [ 541 'show', 542 'autobgi' 543 ] 544 return self._resposne_operation_status(self._run(args))['AutoBGI'] 545 546 @autobgi.setter 547 def autobgi(self, value): 548 """ 549 """ 550 args = [ 551 'set', 552 'autobgi={0}'.format(value) 553 ] 554 return common.response_setter(self._run(args)) 555 556 def init_start(self, full=False, force=False): 557 """Starts the initialization of a virtual drive 558 559 Args: 560 full (bool, optional): if specified then it is the full init otherwise it is Fast init 561 force (bool, optional): must be set if there was before some user data 562 563 Returns: 564 (dict): resposne cmd data 565 """ 566 args = [ 567 'start', 568 'init' 569 ] 570 571 if full: 572 args.append('full') 573 if force: 574 args.append('force') 575 return common.response_cmd(self._run(args)) 576 577 def init_stop(self): 578 """Stops the initialization of a virtual drive 579 580 A stopped initialization process cannot be resumed. 581 582 Returns: 583 (dict): resposne cmd data 584 """ 585 args = [ 586 'stop', 587 'init' 588 ] 589 return common.response_cmd(self._run(args)) 590 591 @property 592 def init_running(self): 593 """Check if initialization is running on a virtual drive 594 595 Returns: 596 (bool): true / false 597 """ 598 args = [ 599 'show', 600 'init' 601 ] 602 603 status = self._resposne_operation_status(self._run(args))['Status'] 604 return bool(status == 'In progress') 605 606 def erase_start(self, mode='simple'): 607 """Securely erases non-SED drives with specified erase pattern 608 609 Args: 610 mode (str, optional): 611 simple - Single pass, single pattern write 612 normal - Three pass, three pattern write 613 thorough - Nine pass, repeats the normal write 3 times 614 standard - Applicable only for DFF's 615 PatternA|PatternB - an 8-Bit binary pattern to overwrite the data. 616 617 Returns: 618 (dict): resposne cmd data 619 """ 620 args = [ 621 'start', 622 'erase', 623 '{0}'.format(mode) 624 ] 625 return common.response_cmd(self._run(args)) 626 627 def erase_stop(self): 628 """Stops the erase operation of a virtual drive 629 630 Returns: 631 (dict): resposne cmd data 632 """ 633 args = [ 634 'stop', 635 'erase' 636 ] 637 return common.response_cmd(self._run(args)) 638 639 @property 640 def erase_running(self): 641 """Check if erase is running on a virtual drive 642 643 Returns: 644 (bool): true / false 645 """ 646 args = [ 647 'show', 648 'erase' 649 ] 650 651 status = self._resposne_operation_status(self._run(args))['Status'] 652 return bool(status == 'In progress') 653 654 @property 655 def erase_progress(self): 656 """Show virtual drive erase progress in percentage 657 658 Returns: 659 (str): progress in percentage 660 """ 661 662 args = [ 663 'show', 664 'erase' 665 ] 666 667 progress = self._resposne_operation_status(self._run(args))[ 668 'Progress%'] 669 if progress == '-': 670 return "100" 671 return progress 672 673 def delete(self, force=False): 674 """Deletes a particular virtual drive 675 676 Args: 677 force (bool, optional): If you delete a virtual drive with a valid MBR 678 without erasing the data and then create a new 679 virtual drive using the same set of physical drives 680 and the same RAID level as the deleted virtual drive, 681 the old unerased MBR still exists at block0 of the 682 new virtual drive, which makes it a virtual drive with 683 valid user data. Therefore, you must provide the 684 force option to delete this newly created virtual drive. 685 686 Returns: 687 (dict): resposne cmd data 688 """ 689 args = [ 690 'del' 691 ] 692 693 if force: 694 args.append('force') 695 return common.response_cmd(self._run(args)) 696 697 def migrate_start(self, option, drives, raid=None, force=False): 698 """Starts migartion on the virtual drive 699 700 Args: 701 option (str): 702 add - adds the specified drives to the migrated raid 703 remove - removes the specified drives from the migrated raid 704 drives (str): specifies the list drives which needs to be added 705 or removed in storcli format ([e:]s|[e:]s-x|[e:]s-x,y]) 706 raid - raid level to which migration needs to be done (raid0, raid1, ...) 707 force - if specified, then migration will start even if any drive in the DG is secured 708 709 Returns: 710 (dict): resposne cmd data 711 """ 712 if not raid: 713 raid = self.raid 714 args = [ 715 'start', 716 'migrate', 717 'type={0}'.format(raid), 718 'option={0}'.format(option), 719 'drives={0}'.format(drives) 720 ] 721 if force: 722 args.append('force') 723 return common.response_cmd(self._run(args)) 724 725 @property 726 def migrate_running(self): 727 """Check if migration is running on a virtual drive 728 729 Returns: 730 (bool): true / false 731 """ 732 args = [ 733 'show', 734 'migrate' 735 ] 736 737 status = self._resposne_operation_status(self._run(args))['Status'] 738 return bool(status == 'In progress') 739 740 741class VirtualDrives(object): 742 """StorCLI virtual drives 743 744 Instance of this class is iterable with :obj:VirtualDrive as item 745 746 Args: 747 ctl_id (str): controller id 748 binary (str): storcli binary or full path to the binary 749 750 Properties: 751 has_vds (bool): true if there are vds 752 ids (list of str): list of virtual drives id 753 ctl_id (str): virtual drives controller id 754 ctl (:obj:controller.Controller): virtual drives controller 755 756 757 Methods: 758 has_vd (bool): true if there are virtual drives 759 get_vd (:obj:VirtualDrive): get virtual drive object by id 760 get_named_vd (:obj:VirtualDrive): get virtual drive object by name 761 762 """ 763 764 def __init__(self, ctl_id, binary='storcli64'): 765 """Constructor - create StorCLI VirtualDrives object 766 767 Args: 768 ctl_id (str): controller id 769 binary (str): storcli binary or full path to the binary 770 """ 771 self._ctl_id = ctl_id 772 self._binary = binary 773 self._storecli = StorCLI(binary) 774 775 @property 776 def _vd_ids(self): 777 args = [ 778 '/c{0}'.format(self._ctl_id), 779 'show' 780 ] 781 data = common.response_data(self._storecli.run(args)) 782 if 'VD LIST' in data: 783 return [vd['DG/VD'].split('/')[1] for vd in data['VD LIST']] 784 return [] 785 786 @property 787 def _vds(self): 788 for vd_id in self._vd_ids: 789 yield VirtualDrive(ctl_id=self._ctl_id, vd_id=vd_id, binary=self._binary) 790 791 def __iter__(self): 792 return self._vds 793 794 @property 795 def ids(self): 796 """(list of str): list of virtual drives id 797 """ 798 return self._vd_ids 799 800 @property 801 def ctl_id(self): 802 """(str): virtual drives controller id 803 """ 804 return self._ctl_id 805 806 @property 807 def ctl(self): 808 """(:obj:controller.Controller): virtual drives controller 809 """ 810 return controller.Controller(ctl_id=self._ctl_id, binary=self._binary) 811 812 @property 813 def has_vds(self): 814 """(bool): true if there are virtual drives 815 """ 816 if self.ids: 817 return True 818 return False 819 820 def get_vd(self, vd_id): 821 """Get virtual drive object by id 822 823 Args: 824 vd_id (str): virtual drive id 825 826 Returns: 827 (None): no virtual drive with id 828 (:obj:VirtualDrive): virtual drive object 829 """ 830 for vd in self: 831 if vd.id == vd_id: 832 return vd 833 return None 834 835 def get_named_vd(self, vd_name): 836 """Get virtual drive object by name 837 838 Args: 839 vd_name (str): virtual drive name 840 841 Returns: 842 (None): no virtual drive with name 843 (:obj:VirtualDrive): virtual drive object 844 """ 845 for vd in self: 846 if vd.name == vd_name: 847 return vd 848 return None
18class VirtualDriveMetrics(object): 19 """StorCLI VirtualDriveMerics 20 21 Instance of this class represents drive metrics 22 23 Args: 24 vd (:obj:VirtualDrive): virtual drive object 25 26 Properties: 27 state (str): virtual drive state 28 init_progress (str): % progress of initialization on a virtual drive 29 cc_progress (str): % progress of consistency check on a virtual drive 30 migrate_progress (str): % progress of migration on a virtual drive 31 erase_progress (str): % progress of erase on a virtual drive 32 all (dict): all metrics 33 """ 34 35 def __init__(self, vd): 36 """Constructor - create StorCLI VirtualDriveMetrics object 37 38 Args: 39 vd (:obj:VirtualDrive): vitual drive object 40 """ 41 self._vd = vd 42 43 @property 44 def state(self): 45 """(str): virtual drive state (optimal | recovery | offline | degraded | degraded_partially) 46 """ 47 return self._vd.state 48 49 @property 50 @common.stringify 51 def init_progress(self): 52 """Show virtual drive initialization progress in perctentage 53 54 Returns: 55 (str): progress in percentage 56 """ 57 args = [ 58 'show', 59 'init' 60 ] 61 62 progress = self._vd._resposne_operation_status(self._vd._run(args))[ 63 'Progress%'] 64 if progress == '-': 65 return "100" 66 return progress 67 68 @property 69 @common.stringify 70 def cc_progress(self): 71 """Show virtual drive consistency check progress in perctentage 72 73 Returns: 74 (str): progress in percentage 75 """ 76 args = [ 77 'show', 78 'cc' 79 ] 80 81 progress = self._vd._resposne_operation_status(self._vd._run(args))[ 82 'Progress%'] 83 if progress == '-': 84 return "100" 85 return progress 86 87 @property 88 @common.stringify 89 def migrate_progress(self): 90 """Show migrate progress of a virtual drive in percentage 91 92 Returns: 93 (str): progress in percentage 94 """ 95 args = [ 96 'show', 97 'migrate' 98 ] 99 100 progress = self._vd._resposne_operation_status(self._vd._run(args))[ 101 'Progress%'] 102 if progress == '-': 103 return "100" 104 return progress 105 106 @property 107 def all(self): 108 """(:obj:DriveMetrics): all metrics 109 """ 110 metrics = {} 111 112 for attribute in dir(self): 113 if not attribute.startswith('_') and not attribute == 'all': 114 metrics[attribute] = self.__getattribute__(attribute) 115 return metrics
StorCLI VirtualDriveMerics
Instance of this class represents drive metrics
Args: vd (VirtualDrive): virtual drive object
Properties: state (str): virtual drive state init_progress (str): % progress of initialization on a virtual drive cc_progress (str): % progress of consistency check on a virtual drive migrate_progress (str): % progress of migration on a virtual drive erase_progress (str): % progress of erase on a virtual drive all (dict): all metrics
118class VirtualDrive(object): 119 """StorCLI VirtualDrive 120 121 Instance of this class represents virtual drive (RAID) in StorCLI hierarchy 122 123 Args: 124 ctl_id (str): controller id 125 vd_id (str): virtual drive id 126 binary (str): storcli binary or full path to the binary 127 128 Properties: 129 id (str): virtual drive id 130 facts (dict): raw virtual drive facts 131 metrics (dict): virtual drive metrics 132 raid (str): vitual drive raid level 133 size (str): virtual drive size 134 state (str): virtual drive state 135 strip (str): virtual drive strip size 136 os_exposed (bool): virtual drive exposed to the OS 137 os_name (str): virtual drive device path (/dev/...) 138 ctl_id (str): virtual drive controller 139 ctl (:obj:controller.Controller): virtual drive controller 140 drives (list of :obj:drive.Drive): virtual drive drives 141 name (str): virtual drive name (also setter) 142 bootdrive (str): virtual drive bootdrive (also setter) 143 pdcache (str): current disk cache policy on a virtual drive (also setter) 144 wrcache (str): write cache policy on a virtual drive (also setter) 145 rdcache (str): read cache policy on a virtual drive (also setter) 146 iopolicy (str): I/O policy on a virtual drive (also setter) 147 autobgi (str):virtual drive auto background initialization setting (also setter) 148 149 Methods: 150 init_start (dict): starts the initialization process on a virtual drive 151 init_stop (dict): stops an initialization process running on a virtual drive 152 init_running (bool): check if initialization is running on a virtual drive 153 erase_start (dict): securely erases non-SED virtual drive 154 erase_stop (dict): stops an erase process running on a virtual drive 155 erase_running (bool): check if erase is running on a virtual drive 156 erase_progress (str): % progress of erase on a virtual drive 157 delete (dict): delete virtual drive 158 migrate_start (dict): starts the migration process on a virtual drive 159 migrate_stop (dict): stops an migration process running on a virtual drive 160 migrate_running (bool): check if migrate is running on a virtual drive 161 162 TODO: 163 Implement missing methods: 164 * start cc 165 * stop cc 166 * pause cc 167 * resume cc 168 * cc running 169 """ 170 171 def __init__(self, ctl_id, vd_id, binary='storcli64'): 172 """Constructor - create StorCLI VirtualDrive object 173 174 Args: 175 ctl_id (str): controller id 176 vd_id (str): virtual drive id 177 binary (str): storcli binary or full path to the binary 178 """ 179 self._ctl_id = ctl_id 180 self._vd_id = vd_id 181 self._binary = binary 182 self._storcli = StorCLI(binary) 183 self._name = '/c{0}/v{1}'.format(self._ctl_id, self._vd_id) 184 185 self._exist() 186 187 def _run(self, args, **kwargs): 188 args = args[:] 189 args.insert(0, self._name) 190 return self._storcli.run(args, **kwargs) 191 192 def _exist(self): 193 try: 194 self._run(['show']) 195 except exc.StorCliCmdError: 196 raise exc.StorCliMissingError( 197 self.__class__.__name__, self._name) from None 198 199 @staticmethod 200 def _response_properties(out): 201 return common.response_data(out)['Virtual Drives'][0] 202 203 def _response_properties_all(self, out): 204 return common.response_data(out)['VD{0} Properties'.format(self._vd_id)] 205 206 @staticmethod 207 def _resposne_operation_status(out): 208 return common.response_data(out)['VD Operation Status'][0] 209 210 @property 211 def id(self): 212 """(str): virtual drive id 213 """ 214 return self._vd_id 215 216 @property 217 def facts(self): 218 """(dict): raw virtual drive facts 219 """ 220 args = [ 221 'show', 222 'all' 223 ] 224 return common.response_data(self._run(args)) 225 226 @property 227 def metrics(self): 228 """(:obj:VirtualDriveMetrics): virtual drive metrics 229 """ 230 return VirtualDriveMetrics(self) 231 232 @property 233 @common.lower 234 def raid(self): 235 """(str): virtual drive raid level 236 """ 237 args = [ 238 'show' 239 ] 240 241 return self._response_properties(self._run(args))['TYPE'] 242 243 @property 244 def size(self): 245 """(str): virtual drive size 246 """ 247 args = [ 248 'show' 249 ] 250 return self._response_properties(self._run(args))['Size'] 251 252 @property 253 @common.lower 254 def state(self): 255 """(str): virtual drive state (optimal | recovery | offline | degraded | degraded_partially) 256 """ 257 args = [ 258 'show' 259 ] 260 state = self._response_properties(self._run(args))['State'] 261 if state == 'Optl': 262 return 'optimal' 263 elif state == 'Rec': 264 return 'recovery' 265 elif state == 'OfLn': 266 return 'offline' 267 elif state == 'Pdgd': 268 return 'degraded_partially' 269 return 'degraded' 270 271 @property 272 def strip(self): 273 """(str): virtual drive strip size 274 """ 275 args = [ 276 'show', 277 'all' 278 ] 279 280 size = self._response_properties_all(self._run(args))['Strip Size'] 281 return size.split()[0] 282 283 @property 284 def os_exposed(self): 285 """(bool): virtual drive exposed to the OS 286 """ 287 args = [ 288 'show', 289 'all' 290 ] 291 292 exposed = self._response_properties_all(self._run(args))[ 293 'Exposed to OS'] 294 return bool(exposed == 'Yes') 295 296 @property 297 @common.lower 298 def os_name(self): 299 """(str): virtual drive device path (/dev/...) 300 """ 301 args = [ 302 'show', 303 'all' 304 ] 305 return self._response_properties_all(self._run(args))['OS Drive Name'] 306 307 @property 308 def ctl_id(self): 309 """(str): virtual drive controller id 310 """ 311 return self._ctl_id 312 313 @property 314 def ctl(self): 315 """(:obj:controller.Controller): virtual drive controller 316 """ 317 return controller.Controller(ctl_id=self._ctl_id, binary=self._binary) 318 319 @property 320 def drives(self): 321 """(list of :obj:Drive): drives 322 """ 323 args = [ 324 'show', 325 'all' 326 ] 327 328 drives = [] 329 pds = common.response_data(self._run(args))[ 330 'PDs for VD {0}'.format(self._vd_id)] 331 for pd in pds: 332 drive_encl_id, drive_slot_id = pd['EID:Slt'].split(':') 333 drives.append( 334 drive.Drive( 335 ctl_id=self._ctl_id, 336 encl_id=drive_encl_id, 337 slot_id=drive_slot_id, 338 binary=self._binary 339 ) 340 ) 341 return drives 342 343 @property 344 def name(self): 345 """Get/Set virtual drive name 346 347 The name is restricted to 15 characters. 348 349 Returns: 350 (str): raid name 351 """ 352 args = [ 353 'show', 354 ] 355 356 properties = self._response_properties(self._run(args)) 357 return properties['Name'] 358 359 @name.setter 360 def name(self, value): 361 """ 362 """ 363 args = [ 364 'set', 365 'name={0}'.format(value) 366 ] 367 return common.response_setter(self._run(args)) 368 369 @property 370 def bootdrive(self): 371 """Get/Set virtual drive as Boot Drive 372 373 One of the following options can be set (str): 374 on - enable boot virtual drive 375 off - disable boot virtual dirve 376 377 Returns: 378 (str): on / off 379 """ 380 args = [ 381 '/c{0}'.format(self._ctl_id), 382 'show', 383 'bootdrive' 384 ] 385 386 for vd in common.response_property(self._storcli.run(args)): 387 if vd['Value'] == 'VD:{0}'.format(self._vd_id): 388 return 'on' 389 return 'off' 390 391 @bootdrive.setter 392 def bootdrive(self, value): 393 """ 394 """ 395 args = [ 396 'set', 397 'bootdrive={0}'.format(value) 398 ] 399 return common.response_setter(self._run(args)) 400 401 @property 402 def pdcache(self): 403 """Get/Set PD Cache Setting 404 405 One of the following options can be set (str): 406 on - enables PD Caching 407 off - disables PD Caching 408 default - default PD Caching 409 410 Returns: 411 (str): on / off 412 """ 413 args = [ 414 'show', 415 'all' 416 ] 417 418 properties = self._response_properties_all(self._run(args)) 419 if properties['Disk Cache Policy'] == 'Enabled': 420 return 'on' 421 elif 'Default' in properties['Disk Cache Policy']: 422 return 'default' 423 return 'off' 424 425 @pdcache.setter 426 def pdcache(self, value): 427 """ 428 """ 429 args = [ 430 'set', 431 'pdcache={0}'.format(value) 432 ] 433 return common.response_setter(self._run(args)) 434 435 @property 436 def wrcache(self): 437 """Get/Set Write cache setting 438 439 One of the following options can be set (str): 440 wt - write Through 441 wb - write Back 442 awb - write Back even in case of bad BBU also 443 444 Returns: 445 (str): wt / wb / awb 446 """ 447 args = [ 448 'show', 449 ] 450 451 properties = self._response_properties(self._run(args)) 452 if 'AWB' in properties['Cache']: 453 return 'awb' 454 elif 'WB' in properties['Cache']: 455 return 'wb' 456 return 'wt' 457 458 @wrcache.setter 459 def wrcache(self, value): 460 """ 461 """ 462 args = [ 463 'set', 464 'wrcache={0}'.format(value) 465 ] 466 return common.response_setter(self._run(args)) 467 468 @property 469 def rdcache(self): 470 """Get/Set Read cache setting 471 472 One of the following options can be set (str): 473 ra - Read Ahead 474 nora - No Read Ahead 475 476 Returns: 477 (str): ra / nora 478 """ 479 args = [ 480 'show', 481 ] 482 483 properties = self._response_properties(self._run(args)) 484 if properties['Cache'][0:2] == 'NR': 485 return 'nora' 486 return 'ra' 487 488 @rdcache.setter 489 def rdcache(self, value): 490 """ 491 """ 492 args = [ 493 'set', 494 'rdcache={0}'.format(value) 495 ] 496 return common.response_setter(self._run(args)) 497 498 @property 499 def iopolicy(self): 500 """Get/Set iopolicy setting 501 502 One of the following options can be set (str): 503 cached - IOs are cached 504 direct - IOs are not cached 505 506 Returns: 507 (str): cached / direct 508 """ 509 args = [ 510 'show', 511 ] 512 513 properties = self._response_properties(self._run(args)) 514 if properties['Cache'][-1] == 'D': 515 return 'direct' 516 return 'cached' 517 518 @iopolicy.setter 519 @common.lower 520 def iopolicy(self, value): 521 """ 522 """ 523 args = [ 524 'set', 525 'iopolicy={0}'.format(value) 526 ] 527 return common.response_setter(self._run(args)) 528 529 @property 530 @common.lower 531 def autobgi(self): 532 """Get/Set auto background initialization 533 534 One of the following options can be set (str): 535 on - enables autobgi 536 off - disables autobgi 537 538 Returns: 539 (str): on / off 540 """ 541 args = [ 542 'show', 543 'autobgi' 544 ] 545 return self._resposne_operation_status(self._run(args))['AutoBGI'] 546 547 @autobgi.setter 548 def autobgi(self, value): 549 """ 550 """ 551 args = [ 552 'set', 553 'autobgi={0}'.format(value) 554 ] 555 return common.response_setter(self._run(args)) 556 557 def init_start(self, full=False, force=False): 558 """Starts the initialization of a virtual drive 559 560 Args: 561 full (bool, optional): if specified then it is the full init otherwise it is Fast init 562 force (bool, optional): must be set if there was before some user data 563 564 Returns: 565 (dict): resposne cmd data 566 """ 567 args = [ 568 'start', 569 'init' 570 ] 571 572 if full: 573 args.append('full') 574 if force: 575 args.append('force') 576 return common.response_cmd(self._run(args)) 577 578 def init_stop(self): 579 """Stops the initialization of a virtual drive 580 581 A stopped initialization process cannot be resumed. 582 583 Returns: 584 (dict): resposne cmd data 585 """ 586 args = [ 587 'stop', 588 'init' 589 ] 590 return common.response_cmd(self._run(args)) 591 592 @property 593 def init_running(self): 594 """Check if initialization is running on a virtual drive 595 596 Returns: 597 (bool): true / false 598 """ 599 args = [ 600 'show', 601 'init' 602 ] 603 604 status = self._resposne_operation_status(self._run(args))['Status'] 605 return bool(status == 'In progress') 606 607 def erase_start(self, mode='simple'): 608 """Securely erases non-SED drives with specified erase pattern 609 610 Args: 611 mode (str, optional): 612 simple - Single pass, single pattern write 613 normal - Three pass, three pattern write 614 thorough - Nine pass, repeats the normal write 3 times 615 standard - Applicable only for DFF's 616 PatternA|PatternB - an 8-Bit binary pattern to overwrite the data. 617 618 Returns: 619 (dict): resposne cmd data 620 """ 621 args = [ 622 'start', 623 'erase', 624 '{0}'.format(mode) 625 ] 626 return common.response_cmd(self._run(args)) 627 628 def erase_stop(self): 629 """Stops the erase operation of a virtual drive 630 631 Returns: 632 (dict): resposne cmd data 633 """ 634 args = [ 635 'stop', 636 'erase' 637 ] 638 return common.response_cmd(self._run(args)) 639 640 @property 641 def erase_running(self): 642 """Check if erase is running on a virtual drive 643 644 Returns: 645 (bool): true / false 646 """ 647 args = [ 648 'show', 649 'erase' 650 ] 651 652 status = self._resposne_operation_status(self._run(args))['Status'] 653 return bool(status == 'In progress') 654 655 @property 656 def erase_progress(self): 657 """Show virtual drive erase progress in percentage 658 659 Returns: 660 (str): progress in percentage 661 """ 662 663 args = [ 664 'show', 665 'erase' 666 ] 667 668 progress = self._resposne_operation_status(self._run(args))[ 669 'Progress%'] 670 if progress == '-': 671 return "100" 672 return progress 673 674 def delete(self, force=False): 675 """Deletes a particular virtual drive 676 677 Args: 678 force (bool, optional): If you delete a virtual drive with a valid MBR 679 without erasing the data and then create a new 680 virtual drive using the same set of physical drives 681 and the same RAID level as the deleted virtual drive, 682 the old unerased MBR still exists at block0 of the 683 new virtual drive, which makes it a virtual drive with 684 valid user data. Therefore, you must provide the 685 force option to delete this newly created virtual drive. 686 687 Returns: 688 (dict): resposne cmd data 689 """ 690 args = [ 691 'del' 692 ] 693 694 if force: 695 args.append('force') 696 return common.response_cmd(self._run(args)) 697 698 def migrate_start(self, option, drives, raid=None, force=False): 699 """Starts migartion on the virtual drive 700 701 Args: 702 option (str): 703 add - adds the specified drives to the migrated raid 704 remove - removes the specified drives from the migrated raid 705 drives (str): specifies the list drives which needs to be added 706 or removed in storcli format ([e:]s|[e:]s-x|[e:]s-x,y]) 707 raid - raid level to which migration needs to be done (raid0, raid1, ...) 708 force - if specified, then migration will start even if any drive in the DG is secured 709 710 Returns: 711 (dict): resposne cmd data 712 """ 713 if not raid: 714 raid = self.raid 715 args = [ 716 'start', 717 'migrate', 718 'type={0}'.format(raid), 719 'option={0}'.format(option), 720 'drives={0}'.format(drives) 721 ] 722 if force: 723 args.append('force') 724 return common.response_cmd(self._run(args)) 725 726 @property 727 def migrate_running(self): 728 """Check if migration is running on a virtual drive 729 730 Returns: 731 (bool): true / false 732 """ 733 args = [ 734 'show', 735 'migrate' 736 ] 737 738 status = self._resposne_operation_status(self._run(args))['Status'] 739 return bool(status == 'In progress')
StorCLI VirtualDrive
Instance of this class represents virtual drive (RAID) in StorCLI hierarchy
Args: ctl_id (str): controller id vd_id (str): virtual drive id binary (str): storcli binary or full path to the binary
Properties: id (str): virtual drive id facts (dict): raw virtual drive facts metrics (dict): virtual drive metrics raid (str): vitual drive raid level size (str): virtual drive size state (str): virtual drive state strip (str): virtual drive strip size os_exposed (bool): virtual drive exposed to the OS os_name (str): virtual drive device path (/dev/...) ctl_id (str): virtual drive controller ctl (controller.Controller): virtual drive controller drives (list of drive.Drive): virtual drive drives name (str): virtual drive name (also setter) bootdrive (str): virtual drive bootdrive (also setter) pdcache (str): current disk cache policy on a virtual drive (also setter) wrcache (str): write cache policy on a virtual drive (also setter) rdcache (str): read cache policy on a virtual drive (also setter) iopolicy (str): I/O policy on a virtual drive (also setter) autobgi (str):virtual drive auto background initialization setting (also setter)
Methods: init_start (dict): starts the initialization process on a virtual drive init_stop (dict): stops an initialization process running on a virtual drive init_running (bool): check if initialization is running on a virtual drive erase_start (dict): securely erases non-SED virtual drive erase_stop (dict): stops an erase process running on a virtual drive erase_running (bool): check if erase is running on a virtual drive erase_progress (str): % progress of erase on a virtual drive delete (dict): delete virtual drive migrate_start (dict): starts the migration process on a virtual drive migrate_stop (dict): stops an migration process running on a virtual drive migrate_running (bool): check if migrate is running on a virtual drive
TODO: Implement missing methods: * start cc * stop cc * pause cc * resume cc * cc running
171 def __init__(self, ctl_id, vd_id, binary='storcli64'): 172 """Constructor - create StorCLI VirtualDrive object 173 174 Args: 175 ctl_id (str): controller id 176 vd_id (str): virtual drive id 177 binary (str): storcli binary or full path to the binary 178 """ 179 self._ctl_id = ctl_id 180 self._vd_id = vd_id 181 self._binary = binary 182 self._storcli = StorCLI(binary) 183 self._name = '/c{0}/v{1}'.format(self._ctl_id, self._vd_id) 184 185 self._exist()
Constructor - create StorCLI VirtualDrive object
Args: ctl_id (str): controller id vd_id (str): virtual drive id binary (str): storcli binary or full path to the binary
Get/Set virtual drive as Boot Drive
One of the following options can be set (str): on - enable boot virtual drive off - disable boot virtual dirve
Returns: (str): on / off
Get/Set PD Cache Setting
One of the following options can be set (str): on - enables PD Caching off - disables PD Caching default - default PD Caching
Returns: (str): on / off
Get/Set Write cache setting
One of the following options can be set (str): wt - write Through wb - write Back awb - write Back even in case of bad BBU also
Returns: (str): wt / wb / awb
Get/Set Read cache setting
One of the following options can be set (str): ra - Read Ahead nora - No Read Ahead
Returns: (str): ra / nora
Get/Set iopolicy setting
One of the following options can be set (str): cached - IOs are cached direct - IOs are not cached
Returns: (str): cached / direct
557 def init_start(self, full=False, force=False): 558 """Starts the initialization of a virtual drive 559 560 Args: 561 full (bool, optional): if specified then it is the full init otherwise it is Fast init 562 force (bool, optional): must be set if there was before some user data 563 564 Returns: 565 (dict): resposne cmd data 566 """ 567 args = [ 568 'start', 569 'init' 570 ] 571 572 if full: 573 args.append('full') 574 if force: 575 args.append('force') 576 return common.response_cmd(self._run(args))
Starts the initialization of a virtual drive
Args: full (bool, optional): if specified then it is the full init otherwise it is Fast init force (bool, optional): must be set if there was before some user data
Returns: (dict): resposne cmd data
578 def init_stop(self): 579 """Stops the initialization of a virtual drive 580 581 A stopped initialization process cannot be resumed. 582 583 Returns: 584 (dict): resposne cmd data 585 """ 586 args = [ 587 'stop', 588 'init' 589 ] 590 return common.response_cmd(self._run(args))
Stops the initialization of a virtual drive
A stopped initialization process cannot be resumed.
Returns: (dict): resposne cmd data
607 def erase_start(self, mode='simple'): 608 """Securely erases non-SED drives with specified erase pattern 609 610 Args: 611 mode (str, optional): 612 simple - Single pass, single pattern write 613 normal - Three pass, three pattern write 614 thorough - Nine pass, repeats the normal write 3 times 615 standard - Applicable only for DFF's 616 PatternA|PatternB - an 8-Bit binary pattern to overwrite the data. 617 618 Returns: 619 (dict): resposne cmd data 620 """ 621 args = [ 622 'start', 623 'erase', 624 '{0}'.format(mode) 625 ] 626 return common.response_cmd(self._run(args))
Securely erases non-SED drives with specified erase pattern
Args: mode (str, optional): simple - Single pass, single pattern write normal - Three pass, three pattern write thorough - Nine pass, repeats the normal write 3 times standard - Applicable only for DFF's PatternA|PatternB - an 8-Bit binary pattern to overwrite the data.
Returns: (dict): resposne cmd data
628 def erase_stop(self): 629 """Stops the erase operation of a virtual drive 630 631 Returns: 632 (dict): resposne cmd data 633 """ 634 args = [ 635 'stop', 636 'erase' 637 ] 638 return common.response_cmd(self._run(args))
Stops the erase operation of a virtual drive
Returns: (dict): resposne cmd data
Show virtual drive erase progress in percentage
Returns: (str): progress in percentage
674 def delete(self, force=False): 675 """Deletes a particular virtual drive 676 677 Args: 678 force (bool, optional): If you delete a virtual drive with a valid MBR 679 without erasing the data and then create a new 680 virtual drive using the same set of physical drives 681 and the same RAID level as the deleted virtual drive, 682 the old unerased MBR still exists at block0 of the 683 new virtual drive, which makes it a virtual drive with 684 valid user data. Therefore, you must provide the 685 force option to delete this newly created virtual drive. 686 687 Returns: 688 (dict): resposne cmd data 689 """ 690 args = [ 691 'del' 692 ] 693 694 if force: 695 args.append('force') 696 return common.response_cmd(self._run(args))
Deletes a particular virtual drive
Args: force (bool, optional): If you delete a virtual drive with a valid MBR without erasing the data and then create a new virtual drive using the same set of physical drives and the same RAID level as the deleted virtual drive, the old unerased MBR still exists at block0 of the new virtual drive, which makes it a virtual drive with valid user data. Therefore, you must provide the force option to delete this newly created virtual drive.
Returns: (dict): resposne cmd data
698 def migrate_start(self, option, drives, raid=None, force=False): 699 """Starts migartion on the virtual drive 700 701 Args: 702 option (str): 703 add - adds the specified drives to the migrated raid 704 remove - removes the specified drives from the migrated raid 705 drives (str): specifies the list drives which needs to be added 706 or removed in storcli format ([e:]s|[e:]s-x|[e:]s-x,y]) 707 raid - raid level to which migration needs to be done (raid0, raid1, ...) 708 force - if specified, then migration will start even if any drive in the DG is secured 709 710 Returns: 711 (dict): resposne cmd data 712 """ 713 if not raid: 714 raid = self.raid 715 args = [ 716 'start', 717 'migrate', 718 'type={0}'.format(raid), 719 'option={0}'.format(option), 720 'drives={0}'.format(drives) 721 ] 722 if force: 723 args.append('force') 724 return common.response_cmd(self._run(args))
Starts migartion on the virtual drive
Args: option (str): add - adds the specified drives to the migrated raid remove - removes the specified drives from the migrated raid drives (str): specifies the list drives which needs to be added or removed in storcli format ([e:]s|[e:]s-x|[e:]s-x,y]) raid - raid level to which migration needs to be done (raid0, raid1, ...) force - if specified, then migration will start even if any drive in the DG is secured
Returns: (dict): resposne cmd data
742class VirtualDrives(object): 743 """StorCLI virtual drives 744 745 Instance of this class is iterable with :obj:VirtualDrive as item 746 747 Args: 748 ctl_id (str): controller id 749 binary (str): storcli binary or full path to the binary 750 751 Properties: 752 has_vds (bool): true if there are vds 753 ids (list of str): list of virtual drives id 754 ctl_id (str): virtual drives controller id 755 ctl (:obj:controller.Controller): virtual drives controller 756 757 758 Methods: 759 has_vd (bool): true if there are virtual drives 760 get_vd (:obj:VirtualDrive): get virtual drive object by id 761 get_named_vd (:obj:VirtualDrive): get virtual drive object by name 762 763 """ 764 765 def __init__(self, ctl_id, binary='storcli64'): 766 """Constructor - create StorCLI VirtualDrives object 767 768 Args: 769 ctl_id (str): controller id 770 binary (str): storcli binary or full path to the binary 771 """ 772 self._ctl_id = ctl_id 773 self._binary = binary 774 self._storecli = StorCLI(binary) 775 776 @property 777 def _vd_ids(self): 778 args = [ 779 '/c{0}'.format(self._ctl_id), 780 'show' 781 ] 782 data = common.response_data(self._storecli.run(args)) 783 if 'VD LIST' in data: 784 return [vd['DG/VD'].split('/')[1] for vd in data['VD LIST']] 785 return [] 786 787 @property 788 def _vds(self): 789 for vd_id in self._vd_ids: 790 yield VirtualDrive(ctl_id=self._ctl_id, vd_id=vd_id, binary=self._binary) 791 792 def __iter__(self): 793 return self._vds 794 795 @property 796 def ids(self): 797 """(list of str): list of virtual drives id 798 """ 799 return self._vd_ids 800 801 @property 802 def ctl_id(self): 803 """(str): virtual drives controller id 804 """ 805 return self._ctl_id 806 807 @property 808 def ctl(self): 809 """(:obj:controller.Controller): virtual drives controller 810 """ 811 return controller.Controller(ctl_id=self._ctl_id, binary=self._binary) 812 813 @property 814 def has_vds(self): 815 """(bool): true if there are virtual drives 816 """ 817 if self.ids: 818 return True 819 return False 820 821 def get_vd(self, vd_id): 822 """Get virtual drive object by id 823 824 Args: 825 vd_id (str): virtual drive id 826 827 Returns: 828 (None): no virtual drive with id 829 (:obj:VirtualDrive): virtual drive object 830 """ 831 for vd in self: 832 if vd.id == vd_id: 833 return vd 834 return None 835 836 def get_named_vd(self, vd_name): 837 """Get virtual drive object by name 838 839 Args: 840 vd_name (str): virtual drive name 841 842 Returns: 843 (None): no virtual drive with name 844 (:obj:VirtualDrive): virtual drive object 845 """ 846 for vd in self: 847 if vd.name == vd_name: 848 return vd 849 return None
StorCLI virtual drives
Instance of this class is iterable with VirtualDrive as item
Args: ctl_id (str): controller id binary (str): storcli binary or full path to the binary
Properties: has_vds (bool): true if there are vds ids (list of str): list of virtual drives id ctl_id (str): virtual drives controller id ctl (controller.Controller): virtual drives controller
Methods: has_vd (bool): true if there are virtual drives get_vd (VirtualDrive): get virtual drive object by id get_named_vd (VirtualDrive): get virtual drive object by name
765 def __init__(self, ctl_id, binary='storcli64'): 766 """Constructor - create StorCLI VirtualDrives object 767 768 Args: 769 ctl_id (str): controller id 770 binary (str): storcli binary or full path to the binary 771 """ 772 self._ctl_id = ctl_id 773 self._binary = binary 774 self._storecli = StorCLI(binary)
Constructor - create StorCLI VirtualDrives object
Args: ctl_id (str): controller id binary (str): storcli binary or full path to the binary
821 def get_vd(self, vd_id): 822 """Get virtual drive object by id 823 824 Args: 825 vd_id (str): virtual drive id 826 827 Returns: 828 (None): no virtual drive with id 829 (:obj:VirtualDrive): virtual drive object 830 """ 831 for vd in self: 832 if vd.id == vd_id: 833 return vd 834 return None
Get virtual drive object by id
Args: vd_id (str): virtual drive id
Returns: (None): no virtual drive with id (VirtualDrive): virtual drive object
836 def get_named_vd(self, vd_name): 837 """Get virtual drive object by name 838 839 Args: 840 vd_name (str): virtual drive name 841 842 Returns: 843 (None): no virtual drive with name 844 (:obj:VirtualDrive): virtual drive object 845 """ 846 for vd in self: 847 if vd.name == vd_name: 848 return vd 849 return None
Get virtual drive object by name
Args: vd_name (str): virtual drive name
Returns: (None): no virtual drive with name (VirtualDrive): virtual drive object