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
class VirtualDriveMetrics:
 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

VirtualDriveMetrics(vd)
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

Constructor - create StorCLI VirtualDriveMetrics object

Args: vd (VirtualDrive): vitual drive object

state

(str): virtual drive state (optimal | recovery | offline | degraded | degraded_partially)

init_progress

func effective wrapper

cc_progress

func effective wrapper

migrate_progress

func effective wrapper

all

(DriveMetrics): all metrics

class VirtualDrive:
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

VirtualDrive(ctl_id, vd_id, binary='storcli64')
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

id

(str): virtual drive id

facts

(dict): raw virtual drive facts

metrics

(VirtualDriveMetrics): virtual drive metrics

raid

func effective wrapper

size

(str): virtual drive size

state

func effective wrapper

strip

(str): virtual drive strip size

os_exposed

(bool): virtual drive exposed to the OS

os_name

func effective wrapper

ctl_id

(str): virtual drive controller id

ctl

(controller.Controller): virtual drive controller

drives

(list of Drive): drives

name

Get/Set virtual drive name

The name is restricted to 15 characters.

Returns: (str): raid name

bootdrive

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

pdcache

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

wrcache

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

rdcache

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

iopolicy

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

autobgi

func effective wrapper

def init_start(self, full=False, force=False)
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

def init_stop(self)
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

init_running

Check if initialization is running on a virtual drive

Returns: (bool): true / false

def erase_start(self, mode='simple')
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

def erase_stop(self)
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

erase_running

Check if erase is running on a virtual drive

Returns: (bool): true / false

erase_progress

Show virtual drive erase progress in percentage

Returns: (str): progress in percentage

def delete(self, force=False)
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

def migrate_start(self, option, drives, raid=None, force=False)
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

migrate_running

Check if migration is running on a virtual drive

Returns: (bool): true / false

class VirtualDrives:
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

VirtualDrives(ctl_id, binary='storcli64')
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

ids

(list of str): list of virtual drives id

ctl_id

(str): virtual drives controller id

ctl

(controller.Controller): virtual drives controller

has_vds

(bool): true if there are virtual drives

def get_vd(self, vd_id)
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

def get_named_vd(self, vd_name)
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