1
2
3
4 """
5 @copyright: Copyright (C) 2008, 2010 Oracle and/or its affiliates. All rights reserved.
6
7 @license: See the file COPYING for redistribution information.
8
9 @summary: This module contains all the Oracle Storage Connect API
10 interfaces.
11 """
12
13 __docformat__ = 'epytext en'
14
15 import sys
16 import os
17 import time
18 import socket
19 import gettext
20 import subprocess
21
22 import OSCCache
23 import OSCPluginUtils
24 from os.path import exists
25 from PyEnum import PyEnum
26
27 __all__ = ["IPlugin",
28
29 "IStorageArrayPlugin",
30 "IFileSystemPlugin",
31
32 "IPluginException",
33
34 "NoSuchOperationEx",
35 "OperationFailedEx",
36 "MissingKeyEx",
37 "ValueFormatEx",
38 "StorageArrayLicenseEx",
39 "TargetDiscoveryEx",
40 "LoginFailedEx",
41 "LogoutFailedEx",
42 "RefreshFailedEx",
43 "ListFailedEx",
44 "CreateSnapFailedEx",
45 "ListSnapFailedEx",
46 "SnapRestoreNotSafeEx",
47 "CloneFailedEx",
48 "InvalidStorageArrayEx",
49 "InvalidValueEx",
50 "StorageElementBusyEx",
51 "PermissionDeniedEx",
52 "OperationPreReqNotMetEx",
53 "StorageNameRequiredEx",
54 "InvalidFSTypeEx",
55 "FileSystemBusyEx",
56 "CommandMissingEx",
57 "FileSystemAlreadyMountedEx",
58
59 "ABILITY_TYPES",
60 "SE_STATES",
61 "SE_STATES_TEXT",
62 "FS_STATES",
63 "FS_STATES_TEXT",
64 "BACKING_DEVICE_TYPES",
65 "BACKING_DEVICE_TYPES_TEXT",
66 ]
67
68 _ = gettext.gettext
69
70 default_cache = OSCCache.OSCDefaultCache()
71
72 ABILITY_TYPES = PyEnum("UNSUPPORTED = 0x00",
73 "OFFLINE = 0x01",
74 "ONLINE = 0x02",
75 "NO = 0x04",
76 "YES = 0x08",
77 "INVALID = 0xFF",
78 )
79 """
80 Enum representing the possible values a plugin/storage server
81 capability can be set to.
82 """
83
84 SE_STATES = PyEnum("UNKNOWN = 0x00",
85 "OFFLINE = 0x01",
86 "BUSY_CREATE = 0x02",
87 "BUSY_CLONE = 0x03",
88 "BUSY_COPY = 0x04",
89 "BUSY_CHILDREN = 0x05",
90 "ERROR = 0x06",
91 "ONLINE = 0x07",
92 )
93 """
94 Enum representing all the possible Storage Element states.
95 """
96
97 SE_STATES_TEXT = {SE_STATES.UNKNOWN: "Unknown",
98 SE_STATES.OFFLINE: "Offline",
99 SE_STATES.BUSY_CREATE: "Busy (Creating)",
100 SE_STATES.BUSY_CLONE: "Busy (Cloning)",
101 SE_STATES.BUSY_COPY: "Busy (Copying)",
102 SE_STATES.BUSY_CHILDREN: "Busy (Have children)",
103 SE_STATES.ERROR: "Error",
104 SE_STATES.ONLINE: "Online",
105 }
106 """
107 Dictionary used to lookup the text description associated with the
108 state of a Storage Element.
109 """
110
111 FS_STATES = PyEnum("UNKNOWN = 0x00",
112 "UNMOUNTED = 0x01",
113 "MOUNTED = 0x02",
114 "MOUNTED_READONLY = 0x03",
115 "ERROR = 0x04",
116 )
117 """
118 Enum representing all the possible File System states.
119 """
120
121 FS_STATES_TEXT = {FS_STATES.UNKNOWN: "Unknown",
122 FS_STATES.UNMOUNTED: "Not mounted",
123 FS_STATES.MOUNTED: "Mounted",
124 FS_STATES.MOUNTED_READONLY: "Mounted Read Only",
125 FS_STATES.ERROR: "Error",
126 }
127 """
128 Dictionary used to lookup the text description associated with the
129 state of a File System.
130 """
131
132 BACKING_DEVICE_TYPES = PyEnum("UNSUPPORTED = 0x00",
133 "DEVICE_SINGLE = 0x01",
134 "DEVICE_MULTI = 0x02",
135 "PLUGIN_SINGLE = 0x03",
136 "PLUGIN_MULTI = 0x04",
137 "INVALID = 0x05",
138 )
139 """
140 Enum representing all the possible File System states.
141 """
142
143 BACKING_DEVICE_TYPES_TEXT = {BACKING_DEVICE_TYPES.UNSUPPORTED: "File system creation is not supported",
144 BACKING_DEVICE_TYPES.DEVICE_SINGLE: "Single block device",
145 BACKING_DEVICE_TYPES.DEVICE_MULTI: "Multiple block devices",
146 BACKING_DEVICE_TYPES.PLUGIN_SINGLE: "Single plugin defined value",
147 BACKING_DEVICE_TYPES.PLUGIN_MULTI: "Multiple plugin defined values",
148 BACKING_DEVICE_TYPES.INVALID: "Invalid",
149 }
150 """
151 Dictionary used to lookup the text description associated with the
152 state of a File System.
153 """
156 """
157 The base interface for various Storage Connect plug-in interfaces.
158
159 The class tree of the Storage Connect API is as follows:
160 G{classtree: IPlugin}
161
162 @note: All logging should be done through the L{logger <IPlugin.logger>}
163 instance set in the L{IPlugin<IPlugin>} class.
164 """
165
166 name = "IPlugin"
167 """
168 @cvar: Class name.
169 @type: C{str}
170 """
171
172 plugin_api_version = ["1", "2", "7"]
173 """
174 @cvar: The over arching API version for the plugin interface.
175 @type: C{list} of C{str}
176 """
177
178 required_api_vers = None
179 """
180 @cvar: The minimum API version required by the plugin.
181 @type: C{list} of C{str}
182 """
183
184 logger = None
185 """
186 @cvar: Logging instance to be used by the plugin.
187 @type: C{logging} object
188 """
189
190 iscsiadm = "/sbin/iscsiadm"
191 """
192 @cvar: Location of the iscsiadm executable.
193 @type: C{str}
194 """
195
196 plugin_type = "inv"
197 """
198 @cvar: Specific type of plugin.
199 @type: C{str}
200 """
201
202 plugin_name = ""
203 """
204 @cvar: The name of the plugin - Name used to populate the user
205 interface drop down list.
206 @type: C{str}
207 """
208
209 vendor_name = ""
210 """
211 @cvar: Name of the Vendor supplying the plugin.
212 @type: C{str}
213 """
214
215 plugin_version = ""
216 """
217 @cvar: Version of the plugin.
218 @type: C{str}
219 """
220
221 ss_extra_info_help = "None"
222 """
223 @cvar: The help text that will be displayed for the extra info
224 to the user when creating the Storage Server.
225 @type: C{str}
226 """
227
228 se_extra_info_help = "None"
229 """
230 @cvar: The help text that will be displayed for the extra info
231 to the user when creating a Storage Element.
232 @type: C{str}
233 """
234
235 fs_extra_info_help = "None"
236 """
237 @cvar: The help text that will be displayed for the extra info
238 to the user when creating a File System.
239 @type: C{str}
240 """
241
242 file_extra_info_help = "None"
243 """
244 @cvar: The help text that will be displayed for the extra info
245 to the user when creating a File.
246 @type: C{str}
247 """
248
249 plugin_ability = {"snapshot": ABILITY_TYPES.INVALID,
250 "custom_snap_name": ABILITY_TYPES.INVALID,
251 "snap_is_sync": ABILITY_TYPES.INVALID,
252 "clone": ABILITY_TYPES.INVALID,
253 "custom_clone_name": ABILITY_TYPES.INVALID,
254 "clone_is_sync": ABILITY_TYPES.INVALID,
255 "resize": ABILITY_TYPES.INVALID,
256 "resize_is_sync": ABILITY_TYPES.INVALID,
257 "splitclone": ABILITY_TYPES.INVALID,
258 "splitclone_is_sync": ABILITY_TYPES.INVALID,
259 "splitclone_while_open": ABILITY_TYPES.INVALID,
260 "snapclone": ABILITY_TYPES.INVALID,
261 "snapclone_is_sync": ABILITY_TYPES.INVALID,
262 "require_storage_name": ABILITY_TYPES.INVALID,
263 "backing_device_type": BACKING_DEVICE_TYPES.INVALID,
264 "access_control": ABILITY_TYPES.INVALID,
265 "max_access_entries": 0,
266 }
267 """
268 @cvar: Capabilities that this specific plugin support.
269 L{Version<plugin_api_version>} of the API have the following
270 fields::
271
272 Name Comment
273 --------------------------------------------------------------------
274 "snapshot": # Set to ONLINE/OFFLINE if the plugin
275 # can create snapshots, NO if not.
276 "custom_snap_name": # Set this to YES if a custom name can
277 # be given to the snapshot.
278 "snap_is_sync": # Set this to YES if creating the
279 # snapshot is synchronously.
280 "clone": # Set to ONLINE/OFFLINE if the plugin
281 # can create clones, NO if not.
282 "custom_clone_name": # Set this to YES if a custom name can
283 # be given to the new clone.
284 "clone_is_sync": # Set this to YES if creating the
285 # clone is synchronously.
286 "resize": # Set to ONLINE/OFFLINE if the plugin
287 # can resize Storage Elements, NO
288 # if not.
289 "resize_is_sync": # Set this to YES if resizing the
290 # Storage Element is synchronously.
291 "splitclone": # Set to ONLINE/OFFLINE if the plugin
292 # can split clones, NO if not.
293 "splitclone_is_sync": # Set this to YES if splitting the
294 # clones is synchronously.
295 "splitclone_while_open": # Set this to YES if the plugin allows
296 # the clones to open when splitting.
297 "snapclone": # Set to ONLINE/OFFLINE if the plugin
298 # can create a clone from a snapshot,
299 # NO if not.
300 "snapclone_is_sync": # Set this to YES if cloning from a
301 # snapshot is synchronously.
302 "require_storage_name": # Set this to YES if the plugin require
303 # the user to supply a Storage Name
304 # (normally used by storage
305 # concentrators and appliances)
306 "backing_device_type": # This is for File System plugins ONLY,
307 # it defines what type of backing device
308 # the file system use when creating a
309 # file system.
310 "access_control": # Set this to YES if the plugin support
311 # access control groups.
312 "max_access_entries": # Set this to the maximum number any one
313 # access group can contain.
314 @type: C{dict}
315 """
316
317 dev_path_prefix = "/dev/mapper"
318 """
319 @cvar: This is the device path prefix that plug-ins should use when filling
320 in the path in the L{SERecord<__SERecord_fields__>}.
321 @type: C{str}
322 """
323
324 dev_name_regex = "^[0-9a-zA-Z]+"
325 """
326 @cvar: This is the device name regex that plug-ins should use when scanning
327 through the devices to fill in the path in
328 L{SERecord<__SERecord_fields__>}.
329 @type: C{str}
330 """
331
332 SANStorage = "SAN"
333 """
334 @cvar: Used to designate that the plugin can handle all types of SCSI
335 storage (FC, FCoE, SAS, SATA, etc.) except iSCSI.
336 @type: C{str}
337 """
338
339 iSCSIStorage = "iSCSI"
340 """
341 @cvar: Used to designate that the plugin can handle iSCSI storage.
342 @type: C{str}
343 """
344
345 FileSysStorage = "FileSys"
346 """
347 @cvar: Used to designate that the plugin handle File System storage.
348 @type: C{str}
349 """
350
351 NetworkFileSystem = "NetworkFS"
352 """
353 @cvar: Used to designate that the plugin is for a network file system.
354 @type: C{str}
355 """
356
357 LocalFileSystem = "LocalFS"
358 """
359 @cvar: Used to designate that the plugin is for a local file system.
360 @type: C{str}
361 """
362
363 __access_grp__ = {"grp_name": "",
364 "grp_entries": [""],
365 "grp_modes": [""],
366 }
367 """
368 @ivar: Access group. All the known fields and if the key is mandatory
369 are listed in L{Access Group fields<__access_grp_fields__>}.
370 @type: C{dict}
371 """
372
373 __access_grp_fields__ = {"grp_name": (str, True),
374 "grp_entries": (list, True),
375 "grp_modes": (list, False),
376 }
377 """
378 @cvar: Field list for the access group. L{Version<plugin_api_version>} of
379 the API have the following fields::
380
381 Name Type Comment
382 --------------------------------------------------------------------
383 "grp_name": str # Name of the access group.
384 "grp_entries": list # This is the access control entries
385 # for the group. For example,
386 # SAN would have a list of WWNs,
387 # iSCSI, a list of initiator names
388 # and for network file systems, a
389 # list of host names.
390 "grp_modes": list # Optional list of modes associated
391 # with the access group, for
392 # example the export mode for a
393 # network file system.
394 @type: C{dict}
395 """
396
397 __vol_group__ = {"vol_name": "",
398 "vol_total_sz": 0,
399 "vol_used_sz": 0,
400 "vol_free_sz": 0,
401 "vol_alloc_sz": 0,
402 "vol_desc": "",
403 }
404 """
405 @ivar: Volume group. All the known fields and if the key is mandatory
406 are listed in L{Volume group fields<__vol_group_fields__>}.
407 @type: C{dict}
408 """
409
410 __vol_group_fields__ = {"vol_name": (str, True),
411 "vol_total_sz": (int, True),
412 "vol_used_sz": (int, True),
413 "vol_free_sz": (int, True),
414 "vol_alloc_sz": (int, False),
415 "vol_desc": (str, False),
416 }
417 """
418 @cvar: Field list for the volume group. L{Version<plugin_api_version>} of
419 the API have the following fields::
420
421 Name Type Comment
422 --------------------------------------------------------------------
423 "vol_name": str # Name of the volume group.
424 "vol_total_sz": int # Total size of the volume group.
425 "vol_used_sz": int # Currently used space.
426 "vol_free_sz": int # Currently available space.
427 "vol_alloc_sz": int # Currently allocated space.
428 "vol_desc": str # Volume group description.
429 @type: C{dict}
430 """
431
432 __qos_vals__ = {"priority": 0,
433 "value": "",
434 }
435 """
436 @ivar: Quality-of-Service. All the known fields and if the key is mandatory
437 are listed in L{QoS fields<__qos_vals_fields__>}.
438 @type: C{dict}
439 """
440
441 __qos_vals_fields__ = {"priority": (int, True),
442 "value": (str, True),
443 }
444 """
445 @cvar: Field list for the qos_vals. L{Version<plugin_api_version>} of the
446 API have the following fields::
447
448 Name Type Comment
449 --------------------------------------------------------------------
450 "priority": int # Priority of the QoS value,
451 # zero (0) being the highest
452 # priority. It is not required for
453 # the values to follow numerically
454 "value": str # Quality-of-Service name as known
455 # by the Storage Server.
456 @type: C{dict}
457 """
458
459 __SSRecord__ = {"name": "",
460 "uuid": "",
461 "storage_server_id": "",
462 "storage_type": "",
463 "access_host": "",
464 "access_port": "",
465 "username": "",
466 "passwd": "",
467 "chap": False,
468 "admin_host": "",
469 "admin_user": "",
470 "admin_passwd": "",
471 "netdevs": [""],
472 "storage_name": "",
473 "status": "",
474 "total_sz": 0,
475 "used_sz": 0,
476 "free_sz": 0,
477 "alloc_sz": 0,
478 "access_grps": [__access_grp__],
479 "vol_groups": [__vol_group__],
480 "storage_id": [""],
481 "storage_desc": "",
482 "extra_info": "",
483 }
484 """
485 @cvar: Storage Server record. All the known fields and if the key is
486 mandatory are listed in L{SSRecord<__SSRecord_fields__>}.
487 @type: C{dict}
488 """
489
490 __SSRecord_fields__ = {"name": (str, True),
491 "uuid": (str, True),
492 "storage_server_id": (str, False),
493 "storage_type": (str, True),
494 "access_host": (str, False),
495 "access_port": (str, False),
496 "username": (str, False),
497 "passwd": (str, False),
498 "chap": (bool, False),
499 "admin_host": (str, True),
500 "admin_user": (str, True),
501 "admin_passwd": (str, True),
502 "netdevs": (list, False),
503 "storage_name": (str, False),
504 "status": (str, True),
505 "total_sz": (int, True),
506 "used_sz": (int, True),
507 "free_sz": (int, True),
508 "alloc_sz": (int, False),
509 "access_grps": (list, True),
510 "vol_groups": (list, False),
511 "storage_id": (list, False),
512 "storage_desc": (str, True),
513 "extra_info": (str, False),
514 }
515 """
516 @cvar: Field list for the Storage Server record.
517 L{Version<plugin_api_version>} of the API have the following fields::
518
519 Name Type Comment
520 --------------------------------------------------------------------
521 "name": str # Name of the Storage Server as
522 # shown in the Oracle VM Manager.
523 "uuid": str # UUID string of the Storage Server
524 # Record.
525 "storage_server_id": str # Storage Server unique identifier.
526 # This is for use solely by the
527 # plug-in to uniquely identify
528 # the Storage Server.
529 "storage_type": str # Storage type: SAN, iSCSI or
530 # FileSys.
531 "access_host": str # Host/IP address used to access the
532 # storage.
533 "access_port": str # Port number to access the storage.
534 "username": str # Storage server username.
535 "passwd": str # Storage server password.
536 "chap": bool # Does storage server require CHAP?
537 "admin_host": str # Host/IP address to admin the
538 # storage.
539 "admin_user": str # Storage administrator user name.
540 "admin_passwd": str # Storage administrator password.
541 "netdevs": list # Network device(s) used to access
542 # the storage.
543 "storage_name": str # Actual name of the Storage Server.
544 "status": str # Status of the Storage Server.
545 "total_sz": int # Total size in bytes.
546 "used_sz": int # Actual space already used.
547 "free_sz": int # Available space in bytes.
548 "alloc_sz": int # Allocated/reserved space in bytes.
549 "access_grps": list # List of access groups. See
550 # __access_grp_fields__
551 "vol_groups": list # List of vol_groups. See
552 # __vol_group_fields__
553 "storage_id": str # Storage identifier (iSCSI target
554 # name).
555 "storage_desc": str # Storage description.
556 "extra_info": str # Extra info (open format).
557
558 NOTE: Depending on the storage types some fields would not be in the
559 dict for instance SAN would not have the username, passwd etc.
560 also if the start method does not return a updated record with
561 the storage_id set it would not be passed in subsequent
562 operations.
563 @type: C{dict}
564 """
565 __SERecord__ = {"se_type": "",
566 "ss_uuid": __SSRecord__["uuid"],
567 "name": "",
568 "uuid": "",
569 "page83_id": "",
570 "id": "",
571 "vendor": "",
572 "product_id": "",
573 "path": [""],
574 "array_path": "",
575 "size": 0,
576 "status": "",
577 "vol_group_name": "",
578 "access_grp_names": [""],
579 "qos": "",
580 "state": SE_STATES.UNKNOWN,
581 "extra_info": "",
582 }
583 """
584 @cvar: Storage Element record. All the known fields and if the key is
585 mandatory are listed in L{SERecord<__SERecord_fields__>}.
586 @type: C{dict}
587 """
588
589 __SERecord_fields__ = {"se_type": (str, True),
590 "ss_uuid": (str, True),
591 "name": (str, True),
592 "uuid": (str, True),
593 "page83_id": (str, True),
594 "id": (str, False),
595 "vendor": (str, False),
596 "product_id": (str, False),
597 "path": (list, True),
598 "array_path": (str, False),
599 "size": (int, True),
600 "status": (str, True),
601 "vol_group_name": (str, False),
602 "access_grp_names": (list, True),
603 "qos": (str, False),
604 "state": (SE_STATES, True),
605 "extra_info": (str, False),
606 }
607 """
608 @cvar: Field list for the Storage Element record.
609 L{Version<plugin_api_version>} of the API have the following fields::
610
611 Name Type Comment
612 --------------------------------------------------------------------
613 "se_type": str # See __SETypes__.
614 "ss_uuid": str # UUID for the owning SSRecord.
615 "name": str # User friendly name.
616 "uuid": str # UUID string for the device.
617 "page83_id": str # SCSI Page 83 unique LUN ID.
618 "id": str # ID for the SE (LUN/Snap ID).
619 "vendor": str # Vendor as seen by a SCSI INQ.
620 "product_id": str # Product as seen by a SCSI INQ.
621 "path": list # System path(s) to the device.
622 "array_path": str # Path on the array for the device.
623 "size": int # Size in bytes.
624 "status": str # Returned status of the SE.
625 "vol_group_name": str # Volume group this SE belongs to.
626 "access_grp_names": list # List of access group names.
627 "qos": str # Quality-of-Service for the SE.
628 "state": SE_STATES # Current state of the SE.
629 "extra_info": str # Extra info (open format).
630
631 NOTE: Depending on the storage types some fields would not be in the
632 dict for instance SAN would not have the username, passwd etc.
633 @type: C{dict}
634 """
635
636 LUNType = "LUN"
637 """
638 @cvar: Used to designate that the SE record represent a LUN.
639 @type: C{str}
640 """
641
642 GhostLUNType = "GhostLUN"
643 """
644 @cvar: Used to designate that the SE record represent a Ghost LUN.
645 @type: C{str}
646 """
647
648 SnapType = "Snapshot"
649 """
650 @cvar: Used to designate that the SE record represent a Snapshot.
651 @type: C{str}
652 """
653
654 SnapCloneType = "SnapClone"
655 """
656 @cvar: Used to designate that the SE record represent a clone from a
657 snapshot.
658 @type: C{str}
659 """
660
661 __SETypes__ = [LUNType,
662 GhostLUNType,
663 SnapType,
664 SnapCloneType,
665 ]
666 """
667 @cvar: Known Storage Element types. A
668 L{SERecord<__SERecord_fields__>} must be of these types.
669 L{Version <plugin_api_version>} of the API define the following
670 types::
671
672 Type Comment
673 --------------------------------------------------------------------
674 LUNType # Normal block device LUN.
675 GhostLUNType # Ghost LUN.
676 SnapType # Snapshot created for a LUN, File system or File.
677 SnapCloneType # Clone created from a snapshot. This is a special
678 # case since it can become a full LUN in the
679 # future. We need to keep track as on most arrays
680 # the snap is locked until the snap clone is
681 # deleted or split from the snapshot.
682 @type: C{list}
683 """
684
685 __FSRecord__ = {"access_path": "",
686 "ss_uuid": __SSRecord__["uuid"],
687 "name": "",
688 "mount_options": [""],
689 "array_path": "",
690 "uuid": "",
691 "size": 0,
692 "status": "",
693 "state": FS_STATES.UNKNOWN,
694 "access_grp_names": [""],
695 "qos": "",
696 "backing_device": "",
697 "extra_info": "",
698 }
699 """
700 @cvar: File System record. All the known fields and if the key is
701 mandatory are listed in L{FSRecord<__FSRecord_fields__>}.
702 @type: C{dict}
703 """
704
705 __FSRecord_fields__ = {"access_path": (str, False),
706 "ss_uuid": (str, True),
707 "name": (str, True),
708 "mount_options": (list, False),
709 "array_path": (str, False),
710 "uuid": (str, True),
711 "size": (int, True),
712 "status": (str, True),
713 "state": (FS_STATES, True),
714 "access_grp_names": (list, True),
715 "qos": (str, False),
716 "backing_device": (str, False),
717 "extra_info": (str, False),
718 }
719 """
720 @cvar: Field list for the File System record. L{Version<plugin_api_version>}
721 of the API have the following fields::
722
723 Name Type Comment
724 --------------------------------------------------------------------
725 "access_path": str # Access path for the file system,
726 # this is only used for networked
727 # file systems.
728 "ss_uuid": str # UUID of the SS Record owning this
729 # file system.
730 "name": str # User friendly name of the file
731 # system.
732 "mount_options": list # List of default mount options for
733 # the file system.
734 "array_path": str # Path on storage server for the
735 # file system.
736 "uuid": str # UUID of the the file system.
737 "size": int # Size, returned, supplied for
738 # resizing.
739 "status": str # Status of the file system for
740 # display.
741 "state": FS_STATES # State of the file system.
742 "access_grp_names": list # List of access group names the
743 # file system is (or will be)
744 # exported to.
745 "qos": str # Quality-of-Service for the FS.
746 "backing_device": str/list # This is used to specify what type
747 # of device the File System
748 # requires.
749 "extra_info": str # Extra info (open format extra
750 # info).
751
752 NOTE: Depending on the file system type some fields would not be in
753 the dict.
754 @type: C{dict}
755 """
756
757 __BackingDeviceRecord__ = {"name": "",
758 "total_sz": 0,
759 "free_sz": 0,
760 "value": "",
761 "description": "",
762 }
763 """
764 @cvar: Backing device record. All the known fields and if the key is
765 mandatory are listed in L{BackingDeviceRecord<__BackingDeviceRecord_fields__>}.
766 @type: C{dict}
767 """
768
769 __BackingDeviceRecord_fields__ = {"name": (str, True),
770 "total_sz": (int, True),
771 "free_sz": (int, True),
772 "value": (list, True),
773 "description": (str, False),
774 }
775 """
776 @cvar: Field list for the backing device records.
777 L{Version<plugin_api_version>} of the API have the following
778 fields::
779
780 Name Type Comment
781 --------------------------------------------------------------------
782 "name": str # Name of the backing device.
783 "total_sz": int # Total size of the backing device.
784 "free_sz": int # Available free size in the backing
785 # device.
786 "value": str # Value that need to be passed back
787 # to the plugin to use this backing
788 # device.
789 "description": str # User friendly description for the
790 # backing device that will be.
791 @type: C{dict}
792 """
793
794 __MountRecord__ = {"uuid": "",
795 "fs_uuid": __FSRecord__["uuid"],
796 "mount_point": "",
797 "options": [""],
798 "shared_path": "",
799 "status": "",
800 "extra_info": "",
801 }
802 """
803 @cvar: Mount point record. All the known fields and if the key is
804 mandatory are listed in L{MountRecord<__MountRecord_fields__>}.
805 @type: C{dict}
806 """
807
808 __MountRecord_fields__ = {"uuid": (str, True),
809 "fs_uuid": (str, True),
810 "mount_point": (str, True),
811 "options": (list, False),
812 "status": (str, True),
813 "extra_info": (str, False),
814 }
815 """
816 @cvar: Field list for the Mount point records.
817 L{Version<plugin_api_version>} of the API have the following
818 fields::
819
820 Name Type Comment
821 --------------------------------------------------------------------
822 "uuid": str # UUID of this mount point.
823 "fs_uuid": str # UUID of the File System owning
824 # this mount point.
825 "mount_point": str # Path file system should be or is
826 # mounted on.
827 "options": list # List of mount options for this
828 # specific mount point.
829 "status": str # Status of the mount point for
830 # display.
831 "extra_info": str # Extra info (open format extra
832 # info).
833 @type: C{dict}
834 """
835
836 __FileRecord__ = {"fr_type": "",
837 "file_path": "",
838 "ondisk_sz": 0,
839 "file_sz": 0,
840 "fs_uuid": __FSRecord__["uuid"],
841 "name_pattern": "",
842 "snap_name": "",
843 "extra_info": "",
844 }
845 """
846 @cvar: File record. All the known fields and if the key is
847 mandatory are listed in L{FileRecord<__FileRecord_fields__>}.
848 @type: C{dict}
849 """
850
851 __FileRecord_fields__ = {"fr_type": (str, True),
852 "file_path": (str, True),
853 "ondisk_sz": (int, True),
854 "file_sz": (int, True),
855 "fs_uuid": (str, True),
856 "name_pattern": (str, False),
857 "snap_name": (str, False),
858 "extra_info": (str, False),
859 }
860 """
861 @cvar: Field list for the File System record. L{Version<plugin_api_version>}
862 of the API have the following fields::
863
864 Name Type Comment
865 --------------------------------------------------------------------
866 "fr_type": str # See __FRTypes__.
867 "file_path": str # Absolute path to the file.
868 "fs_uuid": str # UUID of the file system containing
869 # the file.
870 "name_pattern": str # This would optionally contain the
871 # pattern the file or directory
872 # name should match when listing.
873 "snap_name": str # Name of the snap.
874 "extra_info": str # Extra info (open format).
875
876 NOTE: Depending on the file system type some fields would not be in
877 the dict.
878 @type: C{dict}
879 """
880
881 FileType = "File"
882 """
883 @cvar: Used to designate that the FR record represent a file.
884 @type: C{str}
885 """
886
887 DirType = "Directory"
888 """
889 @cvar: Used to designate that the FR record represent a directory.
890 @type: C{str}
891 """
892
893 SymLinkType = "SymbolicLink"
894 """
895 @cvar: Used to designate that the FR record represent a symbolic link.
896 @type: C{str}
897 """
898
899 CharDevType = "CharDevice"
900 """
901 @cvar: Used to designate that the FR record represent a character device.
902 @type: C{str}
903 """
904
905 BlkDevType = "BlockDevice"
906 """
907 @cvar: Used to designate that the FR record represent a block device.
908 @type: C{str}
909 """
910
911 FifoType = "FIFOFile"
912 """
913 @cvar: Used to designate that the FR record represent a FIFO file.
914 @type: C{str}
915 """
916
917 SockFileType = "SocketFile"
918 """
919 @cvar: Used to designate that the FR record represent a socket file.
920 @type: C{str}
921 """
922
923 __FRTypes__ = [FileType,
924 DirType,
925 SymLinkType,
926 CharDevType,
927 BlkDevType,
928 FifoType,
929 SockFileType,
930 SnapType,
931 SnapCloneType,
932 ]
933 """
934 @cvar: Known File record types. A
935 L{FileRecord<__FileRecord_fields__>} must be of these types.
936 L{Version<plugin_api_version>} of the API define the following
937 types::
938
939 Type Comment
940 --------------------------------------------------------------------
941 FileType # Normal file.
942 DirType # Directory.
943 SymLinkType # Symbolic link.
944 CharDevType # Character device file.
945 BlkDevType # Block device file.
946 FifoType # FIFO pipe file.
947 SocketType # Socket file.
948 SnapType # Snapshot / RefLink created of the file.
949 SnapCloneType # Clone created from a snapshot. This is a special
950 # case since in some file systems the Snapshot
951 # must stay around as long as there is a clone
952 # based on it. It is only used when the file
953 # system have this restriction.
954 @type: C{list}
955 """
956
957 __osc_install_dir__ = "/opt/storage-connect"
958 """
959 @cvar: The Oracle Storage Connect installation directory.
960 @type: C{str}
961 """
962
963 __plugin_top_dir__ = "%s/plugins" % __osc_install_dir__
964 """
965 @cvar: Top directory under which all Storage Connect plugins will be
966 installed.
967 @type: C{str}
968 """
969
970 __plugin_types__ = ["isa", "ifs"]
971 """
972 @cvar: Known Oracle Storage Connect plugin types.
973 @type: C{list}
974 """
975
976 __plugin_temp_dir__ = "/var/tmp/storage-connect"
977 """
978 @cvar: Directory where temporrary files woud be created under.
979 @type: C{str}
980 """
981
982 __generic_plugin__ = False
983 """
984 @cvar: Flag if this is a generic Plugin - Vendor implemented plugins
985 should NOT change this!
986 @type: C{bool}
987 """
988
989 __cluster_required__ = False
990 """
991 @cvar: Flag if this Plugin requires the cluster to be up - Vendor
992 implemented plugins should NOT change this!
993 @type: C{bool}
994 """
995
996 cache = default_cache
997 """
998 @cvar: Caching that can be used by the plugin.
999 @type: C{cache} object
1000 """
1001
1002 - def __new__(cls, *args, **kwargs):
1003 """
1004 Override the method to enforce that no Storage Connect classes be
1005 instantiated.
1006 """
1007 raise TypeError("Storage Connect classes cannot be instantiated")
1008
1009 @staticmethod
1011 """
1012 Create a dict from a string in the form of attr=value[,...].
1013
1014 @param key_val_s: String containing key value pairs in key=val[,...] form.
1015 @type key_val_s: C{str}
1016
1017 @param result_dict: Optional dictionary to update with the parsed string.
1018 @type result_dict: C{dict}
1019
1020 @return: C{dict} with all the parsed key value pairs in the string.
1021 @rtype: C{dict}
1022 """
1023 for kv_vals in key_val_s.split(","):
1024 kv_pair = kv_vals.split("=")
1025 if len(kv_pair) == 2:
1026 result_dict[kv_pair[0]] = kv_pair[1]
1027
1028 else:
1029
1030
1031
1032 raise ValueFormatEx("Invalid format expecting an "
1033 "attr=value[,...] string",
1034 "extra_info")
1035
1036 return result_dict
1037
1038 @staticmethod
1040 """
1041 This method will create a string in the form of key=value[,...] from a
1042 dict.
1043
1044 @param key_val_d: C{dict} containing all the values to inserted in the
1045 string.
1046 @type key_val_d: C{dict}
1047
1048 @return: String in with all keys in the dict in the format of
1049 key=value[,...]
1050 @rtype: C{str}
1051 """
1052 kv_str = ""
1053 for kv_key in key_val_d:
1054 kv_str = kv_str + "%s=%s," % (kv_key, key_val_d[kv_key])
1055
1056 return kv_str[:-1]
1057
1058 @staticmethod
1059 - def copy(src, dst):
1060 """
1061 This will do a block copy from the source to the destination
1062
1063 @param src: Source for the block copy operation.
1064 @type src: C{str}
1065
1066 @param dst: Destination for the block copy operation.
1067 @type dst: C{str}
1068 """
1069 IPlugin.logger.debug("ENTER: copy()")
1070 p_cmd = ("/bin/dd "
1071 "if=%s "
1072 "of=%s "
1073 "bs=1M "
1074 "iflag=direct "
1075 "oflag=direct "
1076 "conv=nocreat,notrunc,sparse") % (src, dst)
1077 p_cmd = p_cmd.split(" ")
1078 dd_p = subprocess.Popen(p_cmd,
1079 stdout = subprocess.PIPE,
1080 stderr = subprocess.PIPE)
1081 (p_out, p_err) = dd_p.communicate()
1082 if dd_p.returncode != 0:
1083 raise IOError("Unable to copy %s to %s : %s" % (src, dst, p_err))
1084
1085 IPlugin.logger.debug("EXIT : copy() - Success")
1086
1087 @classmethod
1089 """
1090 Return the plugin type.
1091
1092 @return: C{plugin_type} for this specific plugin
1093 @rtype: C{str}
1094 """
1095 return klass.plugin_type
1096
1097 @classmethod
1098 - def getTemporaryFile(klass,
1099 mode = 'w+b',
1100 bufsize = -1,
1101 suffix = '',
1102 prefix = 'tmpfil',
1103 directory = None):
1104 """
1105 This method is identical to the standard tempfile.TemporaryFile()
1106 method. Please see the tempfile.TemporaryFile() documentation on how to
1107 use it.
1108 """
1109 if directory == None:
1110 directory = klass.__plugin_temp_dir__
1111 if not os.path.exists(directory):
1112 os.makedirs(directory)
1113
1114 if "tempfile" not in sys.modules:
1115 import tempfile
1116
1117 new_tmp_file = tempfile.TemporaryFile(mode,
1118 bufsize,
1119 suffix,
1120 prefix,
1121 directory)
1122 if getattr(klass, "__temp_files__", None):
1123 klass.__temp_files__.append(new_tmp_file)
1124
1125 else:
1126 klass.__temp_files__ = [new_tmp_file]
1127
1128 return new_tmp_file
1129
1130 @classmethod
1131 - def getNamedTemporaryFile(klass,
1132 mode = 'w+b',
1133 bufsize = -1,
1134 suffix = '',
1135 prefix = 'tmpfil',
1136 directory = None,
1137 delete = True):
1138 """
1139 This method is identical to the standard tempfile.NamedTemporaryFile()
1140 method. Please see the tempfile.NamedTemporaryFile() documentation on
1141 how to use it.
1142 """
1143 if directory == None:
1144 directory = klass.__plugin_temp_dir__
1145 if not os.path.exists(directory):
1146 os.makedirs(directory)
1147 if "tempfile" not in sys.modules:
1148 import tempfile
1149 new_tmp_file = tempfile.NamedTemporaryFile(mode,
1150 bufsize,
1151 suffix,
1152 prefix,
1153 directory,
1154 delete)
1155 if getattr(klass, "__temp_files__", None):
1156 klass.__temp_files__.append(new_tmp_file)
1157 else:
1158 klass.__temp_files__ = [new_tmp_file]
1159 return new_tmp_file
1160
1162 """
1163 Plugin interface for Storage Array management.
1164 """
1165
1166 name = "IStorageArrayPlugin"
1167 """
1168 @cvar: Class name.
1169 @type: C{str}
1170 """
1171
1172 sa_api_version = ["1", "2", "7"]
1173 """
1174 @cvar: Storage Array Plugin API version.
1175 @type: C{list} of C{str}
1176 """
1177
1178 storage_types = []
1179 """
1180 @ivar: Storage types this plugin can handle, see L{SANStorage} and
1181 L{iSCSIStorage}
1182 @type: C{list}
1183 """
1184
1185 plugin_type = "isa"
1186 """
1187 @cvar: Oracle Storage Connect plugin type.
1188 @type: C{str}
1189 """
1190
1191 __required_methods__ = {"validate": True,
1192 "getCapabilities": True,
1193 "getStorageNames": True,
1194 "getInfo": True,
1195 "getAccessGroups": True,
1196 "createAccessGroups": True,
1197 "removeAccessGroups": True,
1198 "addToAccessGroup": True,
1199 "renameAccessGroup": True,
1200 "removeFromAccessGroup": True,
1201 "discover": False,
1202 "start": False,
1203 "stop": False,
1204 "refresh": False,
1205 "list": True,
1206 "updateSERecords": False,
1207 "getStatus": True,
1208 "online": True,
1209 "offline": True,
1210 "create": True,
1211 "startPresent": True,
1212 "stopPresent": True,
1213 "resize": True,
1214 "remove": True,
1215 "getCloneLimits": True,
1216 "isCloneable": True,
1217 "clone": True,
1218 "isSplittable": True,
1219 "splitClone": True,
1220 "cloneFromSnap": True,
1221 "getCurrentClones": True,
1222 "getSnapLimits": True,
1223 "isSnapable": True,
1224 "createSnap": True,
1225 "createMultiSnap": True,
1226 "isRestorable": True,
1227 "snapRestore": True,
1228 "snapRemove": True,
1229 "getCurrentSnaps": True,
1230 "getQoSList": True,
1231 "setQoS": True,
1232 "getAsyncProgress": False,
1233 "deviceTeardown": False,
1234 }
1235 """
1236 @cvar: List of required methods for this L{Version<plugin_api_version>} of
1237 the API
1238 @type: C{dict}
1239 """
1240
1241 @classmethod
1243 """
1244 Return all the required information to identify this plugin.
1245
1246 @return: C{{"plugin_type",
1247 "plugin_name",
1248 "vendor_name",
1249 "plugin_version",
1250 "plugin_desc",
1251 "storage_types",
1252 "ss_extra_info_help",
1253 "se_extra_info_help",
1254 "required_api_vers",
1255 "sa_api_version",
1256 "plugin_ability",
1257 "generic_plugin"}}
1258 @rtype: C{dict}
1259 """
1260 return {"plugin_type": klass.plugin_type,
1261 "plugin_name": klass.plugin_name,
1262 "vendor_name": klass.vendor_name,
1263 "plugin_version": klass.plugin_version,
1264 "plugin_desc": klass.plugin_desc,
1265 "storage_types": klass.storage_types,
1266 "ss_extra_info_help": klass.ss_extra_info_help,
1267 "se_extra_info_help": klass.se_extra_info_help,
1268 "required_api_vers": klass.required_api_vers,
1269 "sa_api_version": klass.sa_api_version,
1270 "plugin_ability": klass.plugin_ability,
1271 "generic_plugin": klass.__generic_plugin__,
1272 }
1273
1274 @staticmethod
1276 """
1277 Validate the Storage Server record.
1278
1279 @param ss_record: L{Storage Server record<__SSRecord__>}.
1280 @type ss_record: C{dict}.
1281
1282 @raise IPluginException: on failure.
1283 """
1284 raise NotImplementedError()
1285
1286 @staticmethod
1288 """
1289 Obtain the capabilities from the Storage Array.
1290
1291 @param ss_record: L{Storage Server record<__SSRecord__>}
1292 @type ss_record: C{dict}
1293
1294 @return: L{Storage Server Capabilities<plugin_ability>}
1295 @rtype: C{dict}
1296
1297 @raise IPluginException: on failure
1298 """
1299 raise NotImplementedError()
1300
1301
1302 @staticmethod
1304 """
1305 Obtain a list of available storage names from which the user would
1306 choose the specific Storage Array to associate with this specific
1307 Storage Server record.
1308
1309 @param ss_record: L{Storage Server record<__SSRecord__>}
1310 @type ss_record: C{dict}
1311
1312 @return: list of available storage names OR if not required or supported
1313 an empty list.
1314 @rtype: C{list}
1315
1316 @raise IPluginException: on failure
1317 """
1318 raise NotImplementedError()
1319
1320 @staticmethod
1321 - def getInfo(ss_record, se_record = None):
1322 """
1323 Obtain information on either the Storage Array or the Storage Element.
1324
1325 @param ss_record: L{Storage Server record<__SSRecord__>}
1326 @type ss_record: C{dict}
1327
1328 @param se_record: Optional L{Storage Element record<__SERecord__>}
1329 @type se_record: C{dict}
1330
1331 @return: updated L{Storage Server record<__SSRecord__>} OR
1332 updated L{Storage Element record<__SERecord__>}
1333 @rtype: C{dict}
1334
1335 @raise IPluginException: on failure
1336 """
1337 raise NotImplementedError()
1338
1339 @staticmethod
1341 """
1342 Get the access groups and access group entries for either the Storage
1343 Array or if specified the Storage Element.
1344
1345 @param ss_record: L{Storage Server record<__SSRecord__>}
1346 @type ss_record: C{dict}
1347
1348 @param se_record: An existing presented L{Storage Element record<__SERecord__>}
1349 @type se_record: C{dict}
1350
1351 @return: list of L{Access groups<__access_grp__>}
1352 @rtype: C{list}
1353
1354 @raise IPluginException: on failure
1355 """
1356 raise NotImplementedError()
1357
1358 @staticmethod
1360 """
1361 Create the access groups on the Storage Array.
1362
1363 @param ss_record: L{Storage Server record<__SSRecord__>}
1364 @type ss_record: C{dict}
1365
1366 @param access_grps: List of L{Access Groups<__access_grp__>} to create
1367 on the Storage Array.
1368 @type access_grps: C{list}
1369
1370 @return: list of L{Access groups<__access_grp__>}
1371 @rtype: C{list}
1372
1373 @raise IPluginException: on failure
1374 """
1375 raise NotImplementedError()
1376
1377 @staticmethod
1379 """
1380 Rename an access group on the Storage Array.
1381
1382 @param ss_record: L{Storage Server record<__SSRecord__>}
1383 @type ss_record: C{dict}
1384
1385 @param access_grp_name: Name of the L{Access Group<__access_grp__>} to rename.
1386 @type access_grp_name: C{str}
1387
1388 @param new_access_grp_name: New name for the L{Access Group<__access_grp__>}.
1389 @type new_access_grp_name: C{str}
1390
1391 @return: list of L{Access groups<__access_grp__>}
1392 @rtype: C{list}
1393
1394 @raise IPluginException: on failure
1395 """
1396 raise NotImplementedError()
1397
1398 @staticmethod
1400 """
1401 Remove the access groups from the Storage Array.
1402
1403 @param ss_record: L{Storage Server record<__SSRecord__>}
1404 @type ss_record: C{dict}
1405
1406 @param access_grps: List of L{Access Groups<__access_grp__>} to remove
1407 from the Storage Array.
1408 @type access_grps: C{list}
1409
1410 @param forced_remove: Flag if the access group should force fully be
1411 removed from the Storage Array.
1412 @type forced_remove: C{bool}
1413
1414 @return: list of L{Access groups<__access_grp__>}
1415 @rtype: C{list}
1416
1417 @raise IPluginException: on failure
1418 """
1419 raise NotImplementedError()
1420
1421 @staticmethod
1423 """
1424 Get the access groups and access group entries for either the Storage
1425 Array or if specified the Storage Element.
1426
1427 @param ss_record: L{Storage Server record<__SSRecord__>}
1428 @type ss_record: C{dict}
1429
1430 @param access_grp_name: Access group that the access control entries
1431 should be added to.
1432 @type access_grp_name: C{str}
1433
1434 @param grp_entries: List of access control entries to add to the access
1435 group.
1436 @type grp_entries: C{list}
1437
1438 @return: L{Access group<__access_grp__>}
1439 @rtype: C{dict}
1440
1441 @raise IPluginException: on failure
1442 """
1443 raise NotImplementedError()
1444
1445 @staticmethod
1447 """
1448 Get the access groups and access group entries for either the Storage
1449 Array or if specified the Storage Element.
1450
1451 @param ss_record: L{Storage Server record<__SSRecord__>}
1452 @type ss_record: C{dict}
1453
1454 @param access_grp_name: Access group that the access control entries
1455 should be removed from.
1456 @type access_grp_name: C{str}
1457
1458 @param grp_entries: List of access control entries to add to the access
1459 group.
1460 @type grp_entries: C{list}
1461
1462 @return: L{Access group<__access_grp__>}
1463 @rtype: C{dict}
1464
1465 @raise IPluginException: on failure
1466 """
1467 raise NotImplementedError()
1468
1469 @staticmethod
1471 """
1472 Discover the targets that the Storage Array makes available.
1473
1474 @note: The is is only applicable to an iSCSI Storage Array
1475
1476 @param ss_record: L{Storage Server record<__SSRecord__>}
1477 @type ss_record: C{dict}
1478
1479 @return: updated L{Storage Server record<__SSRecord__>} with the
1480 storage_id field filled in.
1481 @rtype: C{dict}
1482
1483 @raise IPluginException: on failure
1484 """
1485 IPlugin.logger.debug("ENTER: discover()")
1486 if ss_record["storage_type"] == IStorageArrayPlugin.iSCSIStorage:
1487 if not ss_record.get("access_port", None):
1488 ss_record["access_port"] = "3260"
1489
1490 if ss_record.get("username", None) or \
1491 ss_record.get("passwd", None) or \
1492 ss_record.get("chap", None):
1493 OSCPluginUtils.iSCSIDiscoveryAuth(ss_record)
1494
1495 if ss_record.get("netdev", None):
1496
1497
1498 pass
1499
1500 if not ss_record.get("storage_id", None):
1501 ss_record["storage_id"] = []
1502
1503 portal = "%s:%s" % (socket.gethostbyname(ss_record["access_host"]),
1504 ss_record["access_port"])
1505
1506 iscsi_p = subprocess.Popen([IPlugin.iscsiadm,
1507 "--mode", "discovery",
1508 "--type=sendtargets",
1509 "--portal=%s" % portal],
1510 stdout = subprocess.PIPE,
1511 stderr = subprocess.PIPE)
1512 (p_out, p_err) = iscsi_p.communicate()
1513 if iscsi_p.returncode != 0:
1514 IPlugin.logger.error("Failure to get the targets: %s" % p_err)
1515 raise TargetDiscoveryEx(_("Failure to get the targets: %s" %
1516 p_err))
1517
1518 if os.path.exists("/etc/iscsi/iscsid.conf.bak"):
1519 os.remove("/etc/iscsi/iscsid.conf")
1520 os.rename("/etc/iscsi/iscsid.conf.bak",
1521 "/etc/iscsi/iscsid.conf")
1522
1523
1524 for targets in p_out.splitlines():
1525 target = targets.split(" ")
1526 if target > 1:
1527 if target[1] in ss_record["storage_id"]:
1528 continue
1529
1530 if ss_record.get("username", None):
1531 iscsi_p = subprocess.Popen([IPlugin.iscsiadm,
1532 "--mode", "node",
1533 "--targetname=%s" % target[1],
1534 "--op", "update",
1535 "--name=node.session.auth.username",
1536 "--value=%s" % ss_record["username"]],
1537 stdout = subprocess.PIPE,
1538 stderr = subprocess.PIPE)
1539 (p_out, p_err) = iscsi_p.communicate()
1540 if iscsi_p.returncode != 0:
1541 IPlugin.logger.error("Unable to update username "
1542 "for %s: %s" % (target[1], p_err))
1543 raise LoginFailedEx(_("Unable to update username "
1544 "for %s: %s" % (target[1], p_err)))
1545
1546 if ss_record.get("passwd", None):
1547 iscsi_p = subprocess.Popen([IPlugin.iscsiadm,
1548 "--mode", "node",
1549 "--targetname=%s" % target[1],
1550 "--op", "update",
1551 "--name=node.session.auth.password",
1552 "--value=%s" % ss_record["passwd"]],
1553 stdout = subprocess.PIPE,
1554 stderr = subprocess.PIPE)
1555 (p_out, p_err) = iscsi_p.communicate()
1556 if iscsi_p.returncode != 0:
1557 IPlugin.logger.error("Unable to update password "
1558 "for %s: %s" % (target[1], p_err))
1559 raise LoginFailedEx(_("Unable to update password "
1560 "for %s: %s" % (target[1], p_err)))
1561
1562 if ss_record.get("chap", None):
1563 iscsi_p = subprocess.Popen([IPlugin.iscsiadm,
1564 "--mode", "node",
1565 "--targetname=%s" % target[1],
1566 "--op", "update",
1567 "--name=node.session.auth.authmethod",
1568 "--value=CHAP"],
1569 stdout = subprocess.PIPE,
1570 stderr = subprocess.PIPE)
1571 (p_out, p_err) = iscsi_p.communicate()
1572 if iscsi_p.returncode != 0:
1573 IPlugin.logger.error("Unable to set CHAP "
1574 "authentication for "
1575 "%s: %s" % (target[1], p_err))
1576 raise LoginFailedEx(_("Unable to set CHAP "
1577 "authentication for "
1578 "%s: %s" % (target[1], p_err)))
1579
1580 ss_record["storage_id"].append(target[1])
1581
1582 else:
1583 IPlugin.logger.error("Unable to determine target name")
1584 raise TargetDiscoveryEx(_("Unable to determine target name"))
1585
1586 return ss_record
1587 IPlugin.logger.debug("EXIT : discover() - Success")
1588
1589 @staticmethod
1591 """
1592 Start access to this Storage Array.
1593
1594 @note: The is is only applicable to an iSCSI Storage Array
1595
1596 @param ss_record: L{Storage Server record<__SSRecord__>}
1597 @type ss_record: C{dict}
1598
1599 @raise IPluginException: on failure.
1600 """
1601 IPlugin.logger.debug("ENTER: start()")
1602 if ss_record["storage_type"] == IStorageArrayPlugin.iSCSIStorage:
1603 if not ss_record.get("storage_id", None):
1604 raise TargetDiscoveryEx(_("Target discovery no done!"))
1605
1606 portal = "%s:%s" % (socket.gethostbyname(ss_record["access_host"]),
1607 ss_record["access_port"])
1608 for target in ss_record["storage_id"]:
1609 iscsi_p = subprocess.Popen([IPlugin.iscsiadm,
1610 "--mode", "node",
1611 "--targetname=%s" % target,
1612 "--portal=%s" % portal,
1613 "--login"],
1614 stdout = subprocess.PIPE,
1615 stderr = subprocess.PIPE)
1616
1617 (p_out, p_err) = iscsi_p.communicate()
1618 if iscsi_p.returncode != 0:
1619 if not "15 - already exists" in p_err:
1620 raise LoginFailedEx(_("Target login failed: %s" %
1621 p_err))
1622
1623 IPlugin.logger.debug("EXIT : start() - Success")
1624
1625 @staticmethod
1626 - def stop(ss_record):
1627 """
1628 Stop access to this Storage Array.
1629
1630 @note: The is is only applicable to an iSCSI Storage Array
1631
1632 @param ss_record: L{Storage Server record<__SSRecord__>}
1633 @type ss_record: C{dict}
1634
1635 @raise IPluginException: on failure.
1636 """
1637 IPlugin.logger.debug("ENTER: stop()")
1638 if ss_record["storage_type"] == IStorageArrayPlugin.iSCSIStorage:
1639 if not ss_record.get("storage_id", None):
1640 IPlugin.logger.error("Target discovery not done!")
1641 raise TargetDiscoveryEx(_("Target discovery not done!"))
1642
1643 for target in ss_record["storage_id"]:
1644 iscsi_p = subprocess.Popen([IPlugin.iscsiadm,
1645 "--mode", "node",
1646 "--targetname=%s" % target,
1647 "--logout"],
1648 stdout = subprocess.PIPE,
1649 stderr = subprocess.PIPE)
1650 (p_out, p_err) = iscsi_p.communicate()
1651 if iscsi_p.returncode != 0:
1652 IPlugin.logger.error("Target logout failed: %s" % p_err)
1653 raise LogoutFailedEx(_("Target logout failed: %s" % p_err))
1654
1655 IPlugin.logger.debug("EXIT : stop() - Success")
1656
1657 @staticmethod
1659 """
1660 Initiate a rescan for newly added or removed LUNs.
1661
1662 @note: This does not return a list of the new or or removed LUNs, it
1663 just initiate a rescan.
1664
1665 @param ss_record: L{Storage Server record<__SSRecord__>}
1666 @type ss_record: C{dict}
1667
1668 @raise IPluginException: on failure.
1669 """
1670 IPlugin.logger.debug("ENTER: refresh()")
1671 if ss_record["storage_type"] == IStorageArrayPlugin.iSCSIStorage:
1672 if not ss_record.get("storage_id", None):
1673 IPlugin.logger.error("Target discovery not done!")
1674 raise TargetDiscoveryEx(_("Target discovery not done!"))
1675
1676 for target in ss_record["storage_id"]:
1677 iscsi_p = subprocess.Popen([IPlugin.iscsiadm,
1678 "--mode", "node",
1679 "--targetname=%s" % target,
1680 "--rescan"],
1681 stdout = subprocess.PIPE,
1682 stderr = subprocess.PIPE)
1683 (p_out, p_err) = iscsi_p.communicate()
1684 if iscsi_p.returncode != 0:
1685 IPlugin.logger.error("Target refresh failed: %s" % p_err)
1686 raise RefreshFailedEx(_("Target refresh failed: %s" % p_err))
1687
1688 time.sleep(1.2)
1689
1690 elif ss_record["storage_type"] == IStorageArrayPlugin.SANStorage:
1691 if os.path.exists("/sys/class/fc_host"):
1692 for fc_host in os.listdir("/sys/class/fc_host"):
1693 try:
1694 lip_f = open("/sys/class/fc_host/%s/issue_lip" % fc_host,
1695 "w", 0)
1696 lip_f.write("1")
1697 lip_f.close()
1698
1699 except IOError, ioe:
1700 IPlugin.logger.error("IO Error: %s" % ioe.strerror)
1701 raise RefreshFailedEx(_("IO Error: %s" % ioe.strerror))
1702
1703 for fc_host in os.listdir("/sys/class/scsi_host"):
1704 try:
1705 scan_f = open("/sys/class/scsi_host/%s/scan" % fc_host,
1706 "w", 0)
1707 scan_f.write("- - -")
1708 scan_f.close()
1709
1710 except IOError, ioe:
1711 IPlugin.logger.error("IO Error: %s" % ioe.strerror)
1712 raise RefreshFailedEx(_("IO Error: %s" % ioe.strerror))
1713
1714 mpt_p = subprocess.Popen(["multipath", "-r"],
1715 stdout = subprocess.PIPE,
1716 stderr = subprocess.PIPE)
1717 (p_out, p_err) = mpt_p.communicate()
1718 if mpt_p.returncode != 0:
1719 IPlugin.logger.error("Multipath reload failed: %s" % p_err)
1720
1721 IPlugin.logger.debug("EXIT : refresh() - Success")
1722
1723
1724 @staticmethod
1726 """
1727 Tear down multipath device and associated slaves.
1728
1729 @param ss_record: L{Storage Server record<__SSRecord__>}
1730 @type ss_record: C{dict}
1731
1732 @param se_record: Optional L{Storage Element record<__SERecord__>}
1733 @type se_record: C{dict}
1734
1735 @raise IPluginException: on failure.
1736 """
1737 IPlugin.logger.debug("ENTER: deviceTearDown()")
1738
1739 dev_name = "%s/%s" % (IPlugin.dev_path_prefix, se_record["page83_id"])
1740
1741 if not exists(dev_name):
1742 IPlugin.logger.error("Device %s does not exist" % dev_name)
1743 raise InvalidValueEx(_("Device %s does not exist" % dev_name))
1744
1745 OSCPluginUtils.destroyMPDev(dev_name)
1746
1747 IPlugin.logger.debug("EXIT : deviceTearDown() - Success")
1748
1749
1750 @staticmethod
1753 """
1754 Return the list of Storage Entities associated with the Storage
1755 Array.
1756
1757 @param ss_record: L{Storage Server record<__SSRecord__>}
1758 @type ss_record: C{dict}
1759
1760 @param se_type: List of Storage Element types to be returned.
1761 @type se_type: C{list}
1762
1763 @return: list of L{Storage Element records<__SERecord__>}
1764 @rtype: C{list}
1765
1766 @raise IPluginException: on failure
1767 """
1768 raise NotImplementedError()
1769
1770 @staticmethod
1772 """
1773 Update the list of Storage Element records. The method should
1774 complete the each of the Storage Element records, including the
1775 device path if the Storage Element is visible on the server where
1776 the method is executing. NOTE: The plug-in should use the
1777 L{dev_path_prefix} value to determine the device path (if any) for
1778 each of the Storage Elements.
1779
1780 @param ss_record: L{Storage Server record<__SSRecord__>}
1781 @type ss_record: C{dict}
1782
1783 @param se_records: List of Storage Element records to examine and
1784 update with all the required information, this
1785 includes the local device path, if it is
1786 available on the server.
1787 @type se_records: C{list}
1788
1789 @param append_allowed: By default the method is not allowed to add
1790 new Storage Element records to the list
1791 passed in, if this flag is set the method is
1792 allowed to add Storage Element records to the
1793 list for newly discovered Storage Elements.
1794 @type append_allowed: C{bool}
1795
1796 @return: list of updated L{Storage Element records<__SERecord__>}
1797 @rtype: C{list}
1798
1799 @raise IPluginException: on failure
1800 """
1801
1802 IPlugin.logger.debug("ENTER: updateSERecord()")
1803
1804 if len(se_records) < 1 :
1805 IPlugin.logger.debug("EXIT : updateSERecord() - Nothing to do!")
1806 return se_records
1807
1808 for se_record in se_records:
1809 if not se_record.has_key('page83_id'):
1810 IPlugin.logger.error("SERecord does not contain a page83_id")
1811 continue
1812
1813 dev_name = "%s/%s" % (IPlugin.dev_path_prefix, se_record["page83_id"])
1814
1815 if os.path.exists(dev_name):
1816 se_record["path"].append(dev_name)
1817
1818 else:
1819 IPlugin.logger.error("Device %s does not exist", dev_name)
1820
1821 IPlugin.logger.debug("EXIT : updateSERecord() - Success")
1822 return se_records
1823
1824
1825 @staticmethod
1826 - def getStatus(ss_record, se_record = None):
1827 """
1828 Return the status of the Storage Array or the Storage Element.
1829
1830 @param ss_record: L{Storage Server record<__SSRecord__>}
1831 @type ss_record: C{dict}
1832
1833 @param se_record: Optional L{Storage Element record<__SERecord__>}
1834 @type se_record: C{dict}
1835
1836 @return: Status of the Storage Array or the Storage Element
1837 @rtype: C{str}
1838
1839 @raise IPluginException: on failure
1840 """
1841 raise NotImplementedError()
1842
1843 @staticmethod
1844 - def online(ss_record, se_record):
1845 """
1846 Online the Storage Element on the Storage Array (if offline).
1847
1848 @param ss_record: L{Storage Server record<__SSRecord__>}
1849 @type ss_record: C{dict}
1850
1851 @param se_record: L{Storage Element record<__SERecord__>}
1852 @type se_record: C{dict}
1853
1854 @raise IPluginException: on failure
1855 """
1856 raise NotImplementedError()
1857
1858 @staticmethod
1859 - def offline(ss_record, se_record):
1860 """
1861 Offline the Storage Element on the Storage Array (if offline).
1862
1863 @param ss_record: L{Storage Server record<__SSRecord__>}
1864 @type ss_record: C{dict}
1865
1866 @param se_record: L{Storage Element record<__SERecord__>}
1867 @type se_record: C{dict}
1868
1869 @raise IPluginException: on failure
1870 """
1871 raise NotImplementedError()
1872
1873 @staticmethod
1874 - def create(ss_record, se_record, thin_provision = True, qos = None):
1875 """
1876 Provision a new Storage Element on the Storage Array.
1877
1878 @param ss_record: L{Storage Server record<__SSRecord__>}
1879 @type ss_record: C{dict}
1880
1881 @param se_record: L{Storage Element record<__SERecord__>}
1882 @type se_record: C{dict}
1883
1884 @param thin_provision: Indicate if the Storage Element should be thin
1885 provisioned (if the Storage Array support thin
1886 provisioning) or fully provisioned.
1887 @type thin_provision: C{bool}
1888
1889 @param qos: Desired Quality-of-Service for the new Storage Element
1890 @type qos: C{str}
1891
1892 @return: updated L{Storage Element record<__SERecord__>}
1893 @rtype: C{dict}
1894
1895 @raise IPluginException: on failure
1896 """
1897 raise NotImplementedError()
1898
1899 @staticmethod
1901 """
1902 Present a Storage Element on Storage Array to the list of ports.
1903
1904 @param ss_record: L{Storage Server record<__SSRecord__>}
1905 @type ss_record: C{dict}
1906
1907 @param se_record: L{Storage Element record<__SERecord__>}
1908 @type se_record: C{dict}
1909
1910 @param access_grp_names: Names of the access groups the Storage Element
1911 should be presented to.
1912 @type access_grp_names: C{list}
1913
1914 @return: updated L{Storage Element record<__SERecord__>}
1915 @rtype: C{dict}
1916
1917 @raise IPluginException: on failure
1918 """
1919 raise NotImplementedError()
1920
1921 @staticmethod
1922 - def stopPresent(ss_record, se_record, access_grp_names):
1923 """
1924 Unpresent a Storage Element on Storage Array to the list of ports.
1925
1926 @param ss_record: L{Storage Server record<__SSRecord__>}
1927 @type ss_record: C{dict}
1928
1929 @param se_record: L{Storage Element record<__SERecord__>}
1930 @type se_record: C{dict}
1931
1932 @param access_grp_names: Names of the access groups the Storage Element
1933 should stop being be presented to.
1934 @type access_grp_names: C{list}
1935
1936 @return: updated L{Storage Element record<__SERecord__>}
1937 @rtype: C{dict}
1938
1939 @raise IPluginException: on failure
1940 """
1941 raise NotImplementedError()
1942
1943 @staticmethod
1944 - def resize(ss_record, se_record, new_size):
1945 """
1946 Resize the Storage Element on the Storage Array.
1947
1948 @param ss_record: L{Storage Server record<__SSRecord__>}
1949 @type ss_record: C{dict}
1950
1951 @param se_record: L{Storage Element record<__SERecord__>}
1952 @type se_record: C{dict}
1953
1954 @param new_size: New desired size for the Storage Element.
1955 @type new_size: C{int}
1956
1957 @return: updated L{Storage Element record<__SERecord__>}
1958 @rtype: C{dict}
1959
1960 @raise IPluginException: on failure
1961 """
1962 raise NotImplementedError()
1963
1964 @staticmethod
1965 - def remove(ss_record, se_record):
1966 """
1967 Remove a Storage Element from the Storage Array.
1968
1969 @param ss_record: L{Storage Server record<__SSRecord__>}
1970 @type ss_record: C{dict}
1971
1972 @param se_record: L{Storage Element record<__SERecord__>}
1973 @type se_record: C{dict}
1974
1975 @raise IPluginException: on failure
1976 """
1977 raise NotImplementedError()
1978
1979 @staticmethod
1981 """
1982 Return the maximum number of shallow (thin) clones allowed for a
1983 Storage Array or Storage Element.
1984
1985 @param ss_record: L{Storage Server record<__SSRecord__>}
1986 @type ss_record: C{dict}
1987
1988 @param se_record: Optional L{Storage Element record<__SERecord__>}
1989 @type se_record: C{dict}
1990
1991 @return: Maximum number (-1 for unlimited) of shallow clones allowed
1992 for the Storage Array or the specific type of Storage Element
1993 if supplied.
1994 @rtype: C{int}
1995
1996 @raise IPluginException: on failure
1997 """
1998 raise NotImplementedError()
1999
2000 @staticmethod
2002 """
2003 Check if shallow (thin) clone creations is allowed for the Storage
2004 Element.
2005
2006 @param ss_record: L{Storage Server record<__SSRecord__>}
2007 @type ss_record: C{dict}
2008
2009 @param se_record: L{Storage Element record<__SERecord__>}
2010 @type se_record: C{dict}
2011
2012 @return: True if a shallow clone can be created for the Storage Element.
2013 @rtype: C{bool}
2014
2015 @raise IPluginException: on failure
2016 """
2017 raise NotImplementedError()
2018
2019 @staticmethod
2020 - def clone(ss_record, se_record, dest_se_record = None, qos = None):
2021 """
2022 Create a shallow (thin) clone of the Storage Element.
2023
2024 @param ss_record: L{Storage Server record<__SSRecord__>}
2025 @type ss_record: C{dict}
2026
2027 @param se_record: L{Storage Element record<__SERecord__>}
2028 @type se_record: C{dict}
2029
2030 @param dest_se_record: Destination L{Storage Element record<__SERecord__>}
2031 @type dest_se_record: C{dict}
2032
2033 @param qos: Desired Quality-of_service for the new clone
2034 @type qos: C{str}
2035
2036 @return: Newly created L{Storage Element record<__SERecord__>} for the
2037 cloned Storage Element.
2038 @rtype: C{dict}
2039
2040 @raise IPluginException: on failure
2041 """
2042 raise NotImplementedError()
2043
2044 @staticmethod
2046 """
2047 Determine if a deep clone can be made from a shallow (thin) clone (split the clones).
2048
2049 @param ss_record: L{Storage Server record<__SSRecord__>}
2050 @type ss_record: C{dict}
2051
2052 @param se_record: L{Storage Element record<__SERecord__>}
2053 @type se_record: C{dict}
2054
2055 @return: True if the clones can be split.
2056 @rtype: C{bool}
2057
2058 @raise IPluginException: on failure
2059 """
2060 raise NotImplementedError()
2061
2062 @staticmethod
2064 """
2065 Create a deep clone from a shallow (thin) clone (split the clones).
2066
2067 @param ss_record: L{Storage Server record<__SSRecord__>}
2068 @type ss_record: C{dict}
2069
2070 @param se_record: L{Storage Element record<__SERecord__>}
2071 @type se_record: C{dict}
2072
2073 @raise IPluginException: on failure
2074 """
2075 raise NotImplementedError()
2076
2077 @staticmethod
2078 - def cloneFromSnap(ss_record, se_record, snap_se_record,
2079 dest_se_record = None, qos = None):
2080 """
2081 Create a shallow (thin) clone using a snapshot.
2082
2083 @param ss_record: L{Storage Server record<__SSRecord__>}
2084 @type ss_record: C{dict}
2085
2086 @param se_record: Original L{Storage Element record<__SERecord__>}
2087 @type se_record: C{dict}
2088
2089 @param snap_se_record: Snapshot L{Storage Element record<__SERecord__>}
2090 to be clone from
2091 @type snap_se_record: C{dict}
2092
2093 @param dest_se_record: Destination L{Storage Element record<__SERecord__>}
2094 @type dest_se_record: C{dict}
2095
2096 @param qos: Desired Quality-of_service for the new clone
2097 @type qos: C{str}
2098
2099 @return: created L{Storage Element record<__SERecord__>}
2100 @rtype: C{dict}
2101
2102 @raise IPluginException: on failure
2103 """
2104 raise NotImplementedError()
2105
2106 @staticmethod
2108 """
2109 Return a list of the current clones for a Storage Array or Storage
2110 Element.
2111
2112 @param ss_record: L{Storage Server record<__SSRecord__>}
2113 @type ss_record: C{dict}
2114
2115 @param se_record: Optional L{Storage Element record<__SERecord__>}
2116 @type se_record: C{dict}
2117
2118 @return: List of current known clones on the Storage Array or Storage
2119 Element if supplied.
2120 @rtype: C{list}
2121
2122 @raise IPluginException: on failure
2123 """
2124 raise NotImplementedError()
2125
2126 @staticmethod
2128 """
2129 Return the maximum number of snapshots allowed for a Storage Array or
2130 Storage Element.
2131
2132 @param ss_record: L{Storage Server record<__SSRecord__>}
2133 @type ss_record: C{dict}
2134
2135 @param se_record: Optional L{Storage Element record<__SERecord__>}
2136 @type se_record: C{dict}
2137
2138 @return: Maximum number (-1 for unlimited) of snapshots allowed for the
2139 Storage Array or the specific type of Storage Element if
2140 supplied.
2141 @rtype: C{int}
2142
2143 @raise IPluginException: on failure
2144 """
2145 raise NotImplementedError()
2146
2147 @staticmethod
2149 """
2150 Check if a snapshots can be created on the Storage Array or if
2151 specified for the specific Storage Element.
2152
2153 @param ss_record: L{Storage Server record<__SSRecord__>}
2154 @type ss_record: C{dict}
2155
2156 @param se_record: Optional L{Storage Element record<__SERecord__>}
2157 @type se_record: C{dict}
2158
2159 @return: True if a snapshots can be created on the Storage Array or if
2160 specified for the specific Storage Element.
2161 @rtype: C{bool}
2162
2163 @raise IPluginException: on failure
2164 """
2165 raise NotImplementedError()
2166
2167 @staticmethod
2168 - def createSnap(ss_record, se_record, snap_se_record = None):
2169 """
2170 Create a snapshot of the Storage Element.
2171
2172 @param ss_record: L{Storage Server record<__SSRecord__>}
2173 @type ss_record: C{dict}
2174
2175 @param se_record: L{Storage Element record<__SERecord__>}
2176 @type se_record: C{dict}
2177
2178 @param snap_se_record: Optional L{Storage Element record<__SERecord__>}
2179 to specify the snapshot name and destination
2180 @type snap_se_record: C{dict}
2181
2182 @return: created L{Storage Element record<__SERecord__>} for the snapshot
2183 @rtype: C{dict}
2184
2185 @raise IPluginException: on failure
2186 """
2187 raise NotImplementedError()
2188
2189 @staticmethod
2191 """
2192 Create a snapshot of all the listed Storage Entities together.
2193
2194 @param ss_record: L{Storage Server record<__SSRecord__>}
2195 @type ss_record: C{dict}
2196
2197 @param se_records: L{Storage Element record<__SERecord__>}
2198 @type se_records: C{dict}
2199
2200 @param snap_se_record: Optional L{Storage Element record<__SERecord__>}
2201 to specify the snapshot name and destination
2202 @type snap_se_record: C{dict}
2203
2204 @return: Created L{Storage Element record<__SERecord__>} for the
2205 snapshot.
2206 @rtype: C{dict}
2207
2208 @raise IPluginException: on failure
2209 """
2210 raise NotImplementedError()
2211
2212 @staticmethod
2213 - def isRestorable(ss_record, snap_se_record, se_record = None):
2214 """
2215 Check if the Storage Array or Storage Element can be rolled back to the
2216 named snapshot.
2217
2218 @param ss_record: L{Storage Server record<__SSRecord__>}
2219 @type ss_record: C{dict}
2220
2221 @param snap_se_record: L{Storage Element record<__SERecord__>} naming
2222 the snapshot to be rolled back to.
2223 @type snap_se_record: C{dict}
2224
2225 @param se_record: L{Storage Element record<__SERecord__>}
2226 @type se_record: C{dict}
2227
2228 @return: True if a snapshot can be rolled back to the snapshot,
2229 otherwise return False.
2230 @rtype: C{bool}
2231
2232 @raise IPluginException: on failure
2233 """
2234 raise NotImplementedError()
2235
2236 @staticmethod
2237 - def snapRestore(ss_record, snap_se_record, se_record = None):
2238 """
2239 Roll the Storage Array or Storage Element back to the named snapshot.
2240
2241 @param ss_record: L{Storage Server record<__SSRecord__>}
2242 @type ss_record: C{dict}
2243
2244 @param snap_se_record: L{Storage Element record<__SERecord__>} naming
2245 the snapshot to be rolled back to.
2246 @type snap_se_record: C{dict}
2247
2248 @param se_record: L{Storage Element record<__SERecord__>}
2249 @type se_record: C{dict}
2250
2251 @raise IPluginException: on failure
2252 """
2253 raise NotImplementedError()
2254
2255 @staticmethod
2257 """
2258 Destroy the named snapshot.
2259
2260 @param ss_record: L{Storage Server record<__SSRecord__>}
2261 @type ss_record: C{dict}
2262
2263 @param snap_se_record: L{Storage Element record<__SERecord__>}
2264 @type snap_se_record: C{dict}
2265
2266 @raise IPluginException: on failure
2267 """
2268 raise NotImplementedError()
2269
2270 @staticmethod
2272 """
2273 Return a list of the current snapshots for a Storage Array or Storage
2274 Element.
2275
2276 @param ss_record: L{Storage Server record<__SSRecord__>}
2277 @type ss_record: C{dict}
2278
2279 @param se_record: Optional L{Storage Element record<__SERecord__>}
2280 @type se_record: C{dict}
2281
2282 @return: List of L{Storage Element records<__SERecord__>} for all known
2283 snapshots on the Storage Array or Storage Element if supplied.
2284 @rtype: C{list}
2285
2286 @raise IPluginException: on failure
2287 """
2288 raise NotImplementedError()
2289
2290 @staticmethod
2292 """
2293 Return a list of possible QoS values for the Storage Array.
2294
2295 @param ss_record: L{Storage Server record<__SSRecord__>}
2296 @type ss_record: C{dict}
2297
2298 @return: List of L{qos_vals<__qos_vals__>} dicts for all the possible
2299 QoS values on the Storage Array.
2300 @rtype: C{list}
2301
2302 @raise IPluginException: on failure
2303 """
2304 raise NotImplementedError()
2305
2306 @staticmethod
2307 - def setQoS(ss_record, se_record, qos):
2308 """
2309 Set the QoS for the Storage Element to the QoS supplied.
2310
2311 @param ss_record: L{Storage Server record<__SSRecord__>}
2312 @type ss_record: C{dict}
2313
2314 @param se_record: L{Storage Server record<__SSRecord__>}
2315 @type se_record: C{dict}
2316
2317 @param qos: Desired Quality-of-Service for the new clone.
2318 @type qos: C{str}
2319
2320 @raise IPluginException: on failure
2321 """
2322 raise NotImplementedError()
2323
2324 @staticmethod
2326 """
2327 Obtain Async Progress. This should never be called as
2328 the plugin should overide this method if it is in
2329 asynch mode.
2330
2331 @param ss_record: L{Storage Server record<__SSRecord__>}
2332 @type ss_record: C{dict}
2333
2334 @param some_record: Record previously returned from the
2335 call that started the asynchronous
2336 operation with the async_progress and
2337 if required the async_handle fields
2338 added (and not set to None).
2339 @type some_record: C{dict}
2340
2341 @return: Fully completed record that would have been
2342 returned if the initial call completed
2343 synchronously except it have the async_progress field.
2344 @rtype: C{dict}
2345
2346 @raise IPluginException: on failure
2347 """
2348
2349 raise NotImplementedError()
2350
2352 """
2353 Plugin interface for file system management.
2354 """
2355
2356 name = "IFileSystemPlugin"
2357 """
2358 @cvar: Class name.
2359 @type: C{str}
2360 """
2361
2362 fs_api_version = ["1", "2", "7"]
2363 """
2364 @cvar: File system plugin API version.
2365 @type: C{list} of C{str}
2366 """
2367
2368 filesys_type = ""
2369 """
2370 @cvar: File system type this plugin can handle, either L{LocalFileSystem}
2371 or L{NetworkFileSystem}.
2372 @type: C{str}
2373 """
2374
2375 filesys_name = ""
2376 """
2377 @cvar: Name of the file system to show to the user when selecting which file
2378 system to use, for example "OCFS2" or "ZFS" etc.
2379 @type: C{str}
2380 """
2381
2382 plugin_type = "ifs"
2383 """
2384 @cvar: Oracle Storage Connect plugin type.
2385 @type: C{str}
2386 """
2387
2388 __required_methods__ = {"validate": True,
2389 "getCapabilities": True,
2390 "getStorageNames": True,
2391 "getStorageServerInfo": True,
2392 "getFileSystemInfo": True,
2393 "getFileInfo": True,
2394 "getAccessGroups": True,
2395 "createAccessGroups": True,
2396 "renameAccessGroup": True,
2397 "removeAccessGroups": True,
2398 "addToAccessGroup": True,
2399 "removeFromAccessGroup": True,
2400 "listFileSystems": True,
2401 "listMountPoints": True,
2402 "list": True,
2403 "getStatus": True,
2404 "mount": True,
2405 "unmount": True,
2406 "createFileSystem": True,
2407 "create": True,
2408 "startPresent": True,
2409 "stopPresent": True,
2410 "resizeFileSystem": True,
2411 "resize": True,
2412 "destroyFileSystem": True,
2413 "destroy": True,
2414 "getFileSystemCloneLimits": True,
2415 "getCloneLimits": True,
2416 "isCloneable": True,
2417 "clone": False,
2418 "isSplittable": True,
2419 "splitClone": True,
2420 "cloneFromSnap": True,
2421 "getCurrentClones": True,
2422 "getFileSystemSnapLimits": True,
2423 "getSnapLimits": True,
2424 "isSnapable": True,
2425 "createSnap": True,
2426 "createMultiSnap": True,
2427 "isRestorable": True,
2428 "snapRestore": True,
2429 "snapRemove": True,
2430 "getCurrentSnaps": True,
2431 "getQoSList": True,
2432 "setQoS": True,
2433 "getAsyncProgress": False,
2434 }
2435 """
2436 @cvar: List of required methods for this L{Version<plugin_api_version>} of
2437 the API
2438 @type: C{dict}
2439 """
2440
2441 @classmethod
2443 """
2444 Return all the required information to identify this plugin
2445
2446 @return: C{{"plugin_type",
2447 "plugin_name",
2448 "vendor_name",
2449 "plugin_version",
2450 "plugin_desc",
2451 "filesys_type",
2452 "filesys_name",
2453 "ss_extra_info_help",
2454 "fs_extra_info_help",
2455 "file_extra_info_help",
2456 "required_api_vers",
2457 "fs_api_version",
2458 "plugin_ability",
2459 "generic_plugin"}}
2460 @rtype: C{dict}
2461 """
2462 return {"plugin_type": klass.plugin_type,
2463 "plugin_name": klass.plugin_name,
2464 "vendor_name": klass.vendor_name,
2465 "plugin_version": klass.plugin_version,
2466 "plugin_desc": klass.plugin_desc,
2467 "filesys_type": klass.filesys_type,
2468 "filesys_name": klass.filesys_name,
2469 "ss_extra_info_help": klass.ss_extra_info_help,
2470 "fs_extra_info_help": klass.fs_extra_info_help,
2471 "file_extra_info_help": klass.file_extra_info_help,
2472 "required_api_vers": klass.required_api_vers,
2473 "fs_api_version": klass.fs_api_version,
2474 "plugin_ability": klass.plugin_ability,
2475 "generic_plugin": klass.__generic_plugin__,
2476 "cluster_required": klass.__cluster_required__,
2477 }
2478
2479 @staticmethod
2481 """
2482 Validate the Storage Server record.
2483
2484 @param ss_record: L{Storage Server record<__SSRecord__>}
2485 @type ss_record: C{dict}
2486
2487 @raise IPluginException: on failure
2488 """
2489 raise NotImplementedError()
2490
2491 @staticmethod
2493 """
2494 Obtain the capabilities from the Storage Server.
2495
2496 @param ss_record: L{Storage Server record<__SSRecord__>}
2497 @type ss_record: C{dict}
2498
2499 @return: L{Storage Server Capabilities<plugin_ability>}
2500 @rtype: C{dict}
2501
2502 @raise IPluginException: on failure
2503 """
2504 raise NotImplementedError()
2505
2506
2507 @staticmethod
2509 """
2510 Obtain a list of available storage names from which the user would
2511 choose the specific Storage Server to associate with this specific
2512 Storage Server record.
2513
2514 @param ss_record: L{Storage Server record<__SSRecord__>}
2515 @type ss_record: C{dict}
2516
2517 @return: list of available storage names OR if not required or supported
2518 an empty list.
2519 @rtype: C{list}
2520
2521 @raise IPluginException: on failure
2522 """
2523 raise NotImplementedError()
2524
2525 @staticmethod
2527 """
2528 Obtain information on the file File Server.
2529
2530 @param ss_record: L{Storage Server record<__SSRecord__>}
2531 @type ss_record: C{dict}
2532
2533 @return: updated L{Storage Server record<__SSRecord__>}
2534 @rtype: C{dict}
2535
2536 @raise IPluginException: on failure
2537 """
2538 raise NotImplementedError()
2539
2540 @staticmethod
2542 """
2543 Obtain information on either the File Server or the File System.
2544
2545 @param ss_record: L{Storage Server record<__SSRecord__>}
2546 @type ss_record: C{dict}
2547
2548 @param fs_record: L{File System record<__FSRecord__>}
2549 @type fs_record: C{dict}
2550
2551 @return: updated L{File System record<__FSRecord__>}
2552 @rtype: C{dict}
2553
2554 @raise IPluginException: on failure
2555 """
2556 raise NotImplementedError()
2557
2558 @staticmethod
2559 - def getFileInfo(ss_record, fs_record, file_record, file_comp_record = None):
2560 """
2561 Obtain information on the file or if two file records are given, info
2562 on both files including how much (if any) data blocks are shared
2563 by the files.
2564
2565 @param ss_record: L{Storage Server record<__SSRecord__>}
2566 @type ss_record: C{dict}
2567
2568 @param fs_record: L{File System record<__FSRecord__>}
2569 @type fs_record: C{dict}
2570
2571 @param file_record: L{File record<__FileRecord__>}
2572 @type file_record: C{dict}
2573
2574 @param file_comp_record: Optional L{File record<__FileRecord__>}
2575 @type file_comp_record: C{dict}
2576
2577 @return: updated L{File record<__FileRecord__>}
2578 @rtype: C{dict}
2579
2580 @raise IPluginException: on failure
2581 """
2582 raise NotImplementedError()
2583
2584 @staticmethod
2586 """
2587 Get the access groups and access group entries for either the Storage
2588 Server or if specified the File System.
2589
2590 @param ss_record: L{Storage Server record<__SSRecord__>}
2591 @type ss_record: C{dict}
2592
2593 @param fs_record: Optional L{File System record<__FSRecord__>}
2594 @type fs_record: C{dict}
2595
2596 @return: list of L{Access groups<__access_grp__>}
2597 @rtype: C{list}
2598
2599 @raise IPluginException: on failure
2600 """
2601 raise NotImplementedError()
2602
2603 @staticmethod
2605 """
2606 Create the access groups on the Storage Server.
2607
2608 @param ss_record: L{Storage Server record<__SSRecord__>}
2609 @type ss_record: C{dict}
2610
2611 @param access_grps: List of L{Access Groups<__access_grp__>} to create
2612 on the Storage Server.
2613 @type access_grps: C{list}
2614
2615 @return: list of L{Access groups<__access_grp__>}
2616 @rtype: C{list}
2617
2618 @raise IPluginException: on failure
2619 """
2620 raise NotImplementedError()
2621
2622 @staticmethod
2624 """
2625 Rename an access group on the Storage Server.
2626
2627 @param ss_record: L{Storage Server record<__SSRecord__>}
2628 @type ss_record: C{dict}
2629
2630 @param access_grp_name: Name of the L{Access Group<__access_grp__>} to rename.
2631 @type access_grp_name: C{str}
2632
2633 @param new_access_grp_name: New name for the L{Access Group<__access_grp__>}.
2634 @type new_access_grp_name: C{str}
2635
2636 @return: list of L{Access groups<__access_grp__>}
2637 @rtype: C{list}
2638
2639 @raise IPluginException: on failure
2640 """
2641 raise NotImplementedError()
2642
2643 @staticmethod
2645 """
2646 Remove the access groups from the Storage Server.
2647
2648 @param ss_record: L{Storage Server record<__SSRecord__>}
2649 @type ss_record: C{dict}
2650
2651 @param access_grps: List of L{Access Groups<__access_grp__>} to remove
2652 from the Storage Server.
2653 @type access_grps: C{list}
2654
2655 @return: list of L{Access groups<__access_grp__>}
2656 @rtype: C{list}
2657
2658 @raise IPluginException: on failure
2659 """
2660 raise NotImplementedError()
2661
2662 @staticmethod
2664 """
2665 Get the access groups and access group entries for either the Storage
2666 Server or if specified the File System.
2667
2668 @param ss_record: L{Storage Server record<__SSRecord__>}
2669 @type ss_record: C{dict}
2670
2671 @param access_grp_name: Access group that the access control entries
2672 should be added to.
2673 @type access_grp_name: C{str}
2674
2675 @param grp_entries: List of access control entries to add to the access
2676 group.
2677 @type grp_entries: C{list}
2678
2679 @return: L{Access group<__access_grp__>}
2680 @rtype: C{dict}
2681
2682 @raise IPluginException: on failure
2683 """
2684 raise NotImplementedError()
2685
2686 @staticmethod
2688 """
2689 Get the access groups and access group entries for either the Storage
2690 Server or if specified the File System.
2691
2692 @param ss_record: L{Storage Server record<__SSRecord__>}
2693 @type ss_record: C{dict}
2694
2695 @param access_grp_name: Access group that the access control entries
2696 should be removed from.
2697 @type access_grp_name: C{str}
2698
2699 @param grp_entries: List of access control entries to add to the access
2700 group.
2701 @type grp_entries: C{list}
2702
2703 @return: L{Access group<__access_grp__>}
2704 @rtype: C{dict}
2705
2706 @raise IPluginException: on failure
2707 """
2708 raise NotImplementedError()
2709
2710 @staticmethod
2712 """
2713 Return the list of available (or known) File Systems.
2714
2715 @param ss_record: L{Storage Server record<__SSRecord__>}
2716 @type ss_record: C{dict}
2717
2718 @param include_unpresented: True if ALL File Systems on the File Server
2719 should be returned not just the available ones.
2720 @type include_unpresented: C{bool}
2721
2722 @return: list of L{File System records<__FSRecord__>}
2723 @rtype: C{list}
2724
2725 @raise IPluginException: on failure
2726 """
2727 raise NotImplementedError()
2728
2729 @staticmethod
2731 """
2732 Return the list of mount points the plugin can manage or if the FS Record
2733 is supplied, all the mount points for the specific file system.
2734
2735 @param ss_record: L{Storage Server record<__SSRecord__>}
2736 @type ss_record: C{dict}
2737
2738 @param fs_record: Optional L{File System record<__FSRecord__>}
2739 @type fs_record: C{dict}
2740
2741 @return: list of L{Moint point records<__MountRecord__>}
2742 @rtype: C{list}
2743
2744 @raise IPluginException: on failure
2745 """
2746 raise NotImplementedError()
2747
2748 @staticmethod
2749 - def list(ss_record, fs_record, file_record, recursive = False):
2750 """
2751 Return the list of files.
2752
2753 @param ss_record: L{Storage Server record<__SSRecord__>}
2754 @type ss_record: C{dict}
2755
2756 @param fs_record: L{File System record<__FSRecord__>}
2757 @type fs_record: C{dict}
2758
2759 @param file_record: L{File record<__FileRecord__>}
2760 @type file_record: C{dict}
2761
2762 @param recursive: True if the list should traverse all directories
2763 below the directory specified in the
2764 L{file_record<__FileRecord__>}.
2765 @type recursive: C{bool}
2766
2767 @return: list of L{File records<__FileRecord__>}
2768 @rtype: C{list}
2769
2770 @raise IPluginException: on failure
2771 """
2772 raise NotImplementedError()
2773
2774 @staticmethod
2775 - def getStatus(ss_record, fs_record = None):
2776 """
2777 Return the status of the File System.
2778
2779 @param ss_record: L{Storage Server record<__SSRecord__>}
2780 @type ss_record: C{dict}
2781
2782 @param fs_record: Optional L{File System record<__FSRecord__>}
2783 @type fs_record: C{dict}
2784
2785 @return: Status of the File System or File Server
2786 @rtype: C{str}
2787
2788 @raise IPluginException: on failure
2789 """
2790 raise NotImplementedError()
2791
2792 @staticmethod
2793 - def mount(ss_record, fs_record, mount_point, share_path = None, create_mount_point = False, mount_options = None):
2794 """
2795 Mount the File System if not already mounted.
2796
2797 @param ss_record: L{Storage Server record<__SSRecord__>}
2798 @type ss_record: C{dict}
2799
2800 @param fs_record: L{File System record<__FSRecord__>}
2801 @type fs_record: C{dict}
2802
2803 @param mount_point: Directory where File System should be mounted.
2804 @type mount_point: C{str}
2805
2806 @param share_path: Subdirectory of File System could be mounted.
2807 @type share_path: C{str}
2808
2809 @param create_mount_point: Optional flag to indicate that the mount point should be created.
2810 @type create_mount_point: C{bool}
2811
2812 @param mount_options: Optional list of mount options
2813 @type mount_options: C{list}
2814
2815 @return: L{File System record<__FSRecord__>}
2816 @rtype: C{dict}
2817
2818 @raise IPluginException: on failure
2819 """
2820 raise NotImplementedError()
2821
2822 @staticmethod
2823 - def unmount(ss_record, fs_record, mount_point, destroy_mount_point = False):
2824 """
2825 Unmount the File System if mounted.
2826
2827 @param ss_record: L{Storage Server record<__SSRecord__>}
2828 @type ss_record: C{dict}
2829
2830 @param fs_record: L{File System record<__FSRecord__>}
2831 @type fs_record: C{dict}
2832
2833 @param mount_point: Directory of the File System that should be un-mounted.
2834 @type mount_point: C{str}
2835
2836 @param destroy_mount_point: Optional flag to indicate that the mount point should be removed.
2837 @type destroy_mount_point: C{bool}
2838
2839 @raise IPluginException: on failure
2840 """
2841 raise NotImplementedError()
2842
2843 @staticmethod
2844 - def createFileSystem(ss_record,
2845 name,
2846 backing_device,
2847 size = 0,
2848 access_grp_names = None,
2849 qos = None,
2850 force = False):
2851 """
2852 Create a new File System.
2853
2854 @param ss_record: L{Storage Server record<__SSRecord__>}
2855 @type ss_record: C{dict}
2856
2857 @param name: User friendly name for the new File System
2858 @type name: C{str}
2859
2860 @param backing_device: File System backing device, can
2861 be either a string with the backing
2862 device if only a single device is
2863 supported (as indicated in the
2864 plugin ability dict) or a list
2865 of backing devices.
2866 @type backing_device: C{str} or C{list}
2867
2868 @param size: Desired size for the new File System (0 implies as large
2869 as possible)
2870 @type size: C{int}
2871
2872 @param access_grp_names: Desired Quality-of-Service for the new File
2873 System
2874 @type access_grp_names: C{list}
2875
2876 @param qos: Desired Quality-of-Service for the new File System
2877 @type qos: C{str}
2878
2879 @param force: Flag to indicate any existing File System should be
2880 overwritten
2881 @type force: C{bool}
2882
2883 @return: new L{File System record<__FSRecord__>}
2884 @rtype: C{dict}
2885
2886 @note: ONLY overwrite an existing File System if the force option is
2887 specified.
2888
2889 @raise IPluginException: on failure
2890 """
2891 raise NotImplementedError()
2892
2893 @staticmethod
2894 - def create(ss_record, fs_record, file_name, file_type, size, sparse = True, force = False):
2895 """
2896 Create a new File.
2897
2898 @param ss_record: L{Storage Server record<__SSRecord__>}
2899 @type ss_record: C{dict}
2900
2901 @param fs_record: L{File System record<__FSRecord__>}
2902 @type fs_record: C{dict}
2903
2904 @param file_name: Name of the file to create.
2905 @type file_name: C{str}
2906
2907 @param file_type: Type of file to create. will be one of
2908 L{Known File Types<__FRTypes__>}
2909 @type file_type: C{str}
2910
2911 @param size: Size of the file to create.
2912 @type size: C{int}
2913
2914 @param sparse: Flag to indicate the File should be sparsely allocated (if possible).
2915 @type sparse: C{bool}
2916
2917 @param force: Flag to indicate any existing File should be overwritten.
2918 @type force: C{bool}
2919
2920 @return: updated L{File record<__FileRecord__>}
2921 @rtype: C{dict}
2922
2923 @note: ONLY overwrite an existing File if the force option is specified.
2924
2925 @raise IPluginException: on failure
2926 """
2927 raise NotImplementedError()
2928
2929 @staticmethod
2931 """
2932 Present a File system on the File Server to the list of nodes.
2933
2934 @param ss_record: L{Storage Server record<__SSRecord__>}
2935 @type ss_record: C{dict}
2936
2937 @param fs_record: L{File System record<__FSRecord__>}
2938 @type fs_record: C{dict}
2939
2940 @param access_grp_names: Names of the access groups the File System
2941 should be presented to.
2942 @type access_grp_names: C{list}
2943
2944 @return: updated L{File System record<__FSRecord__>}
2945 @rtype: C{dict}
2946
2947 @raise IPluginException: on failure
2948 """
2949 raise NotImplementedError()
2950
2951 @staticmethod
2952 - def stopPresent(ss_record, fs_record, access_grp_names):
2953 """
2954 Unpresent a File System on the File Server to the list of nodes.
2955
2956 @param ss_record: L{Storage Server record<__SSRecord__>}
2957 @type ss_record: C{dict}
2958
2959 @param fs_record: L{File System record<__FSRecord__>}
2960 @type fs_record: C{dict}
2961
2962 @param access_grp_names: Names of the access groups the File System
2963 should stop being be presented to.
2964 @type access_grp_names: C{list}
2965
2966 @return: updated L{File System record<__FSRecord__>}
2967 @rtype: C{dict}
2968
2969 @raise IPluginException: on failure
2970 """
2971 raise NotImplementedError()
2972
2973 @staticmethod
2975 """
2976 Resize the File System.
2977
2978 @param ss_record: L{Storage Server record<__SSRecord__>}
2979 @type ss_record: C{dict}
2980
2981 @param fs_record: L{File System record<__FSRecord__>}
2982 @type fs_record: C{dict}
2983
2984 @param new_size: New desired size for the File System.
2985 @type new_size: C{int}
2986
2987 @return: updated L{File System record<__FSRecord__>}
2988 @rtype: C{dict}
2989
2990 @note: It is the plugin responsibilty to verify that all conditions are
2991 met for the resize operation. For example if online resize is not
2992 supported, the plugin must make sure the file system is not
2993 mounted and raise an Exception if it is.
2994
2995 @raise IPluginException: on failure
2996 """
2997 raise NotImplementedError()
2998
2999 @staticmethod
3000 - def resize(ss_record, fs_record, file_record, new_size, sparse = True):
3001 """
3002 Resize the File.
3003
3004 @param ss_record: L{Storage Server record<__SSRecord__>}
3005 @type ss_record: C{dict}
3006
3007 @param fs_record: L{File System record<__FSRecord__>}
3008 @type fs_record: C{dict}
3009
3010 @param file_record: L{File record<__FileRecord__>}
3011 @type file_record: C{dict}
3012
3013 @param new_size: New desired size for the file.
3014 @type new_size: C{int}
3015
3016 @param sparse: Flag to indicate the File should be extended using sparse
3017 (if possible).
3018 @type sparse: C{bool}
3019
3020 @return: updated L{File record<__FileRecord__>}
3021 @rtype: C{dict}
3022
3023 @note: It is the plugin responsibilty to verify that all conditions are
3024 met for the resize operation. For example if online resize is not
3025 supported, the plugin must make sure the file is not currently
3026 open and/or locked and raise an Exception if it is.
3027
3028 @raise IPluginException: on failure
3029 """
3030 raise NotImplementedError()
3031
3032 @staticmethod
3034 """
3035 Remove a File System from the File Server.
3036
3037 @param ss_record: L{Storage Server record<__SSRecord__>}
3038 @type ss_record: C{dict}
3039
3040 @param fs_record: L{File System record<__FSRecord__>}
3041 @type fs_record: C{dict}
3042
3043 @raise IPluginException: on failure
3044 """
3045 raise NotImplementedError()
3046
3047 @staticmethod
3048 - def destroy(ss_record, fs_record, file_record):
3049 """
3050 Remove a file from the File System on the File Server.
3051
3052 @param ss_record: L{Storage Server record<__SSRecord__>}
3053 @type ss_record: C{dict}
3054
3055 @param fs_record: L{File System record<__FSRecord__>}
3056 @type fs_record: C{dict}
3057
3058 @param file_record: L{File record<__FileRecord__>}
3059 @type file_record: C{dict}
3060
3061 @raise IPluginException: on failure
3062 """
3063 raise NotImplementedError()
3064
3065 @staticmethod
3067 """
3068 Return the maximum number of clones allowed for a File Server or
3069 File System.
3070
3071 @param ss_record: L{Storage Server record<__SSRecord__>}
3072 @type ss_record: C{dict}
3073
3074 @param fs_record: Optional L{File System record<__FSRecord__>}
3075 @type fs_record: C{dict}
3076
3077 @return: Maximum number (-1 for unlimited) of clones allowed for the
3078 File Server or the specific file system if supplied.
3079 @rtype: C{int}
3080
3081 @raise IPluginException: on failure
3082 """
3083 raise NotImplementedError()
3084
3085 @staticmethod
3087 """
3088 Return the maximum number of snapshots allowed for a File Server or
3089 File System.
3090
3091 @param ss_record: L{Storage Server record<__SSRecord__>}
3092 @type ss_record: C{dict}
3093
3094 @param fs_record: L{File System record<__FSRecord__>}
3095 @type fs_record: C{dict}
3096
3097 @param file_record: L{File record<__FileRecord__>}
3098 @type file_record: C{dict}
3099
3100 @return: Maximum number (-1 for unlimited) of clones allowed for the
3101 File.
3102 @rtype: C{int}
3103
3104 @raise IPluginException: on failure
3105 """
3106 raise NotImplementedError()
3107
3108 @staticmethod
3110 """
3111 Check if shallow (thin) clone creations is allowed for the file on the
3112 File System.
3113
3114 @param ss_record: L{Storage Server record<__SSRecord__>}
3115 @type ss_record: C{dict}
3116
3117 @param fs_record: L{File System record<__FSRecord__>}
3118 @type fs_record: C{dict}
3119
3120 @param file_record: L{File record<__FileRecord__>}
3121 @type file_record: C{dict}
3122
3123 @return: True if a snapshot can be created for the File record.
3124 @rtype: C{bool}
3125
3126 @raise IPluginException: on failure
3127 """
3128 raise NotImplementedError()
3129
3130 @staticmethod
3131 - def clone(ss_record, fs_record, file_record, dest_file_name = None):
3132 """
3133 Create a shallow clone of the file on the file system.
3134
3135 @param ss_record: L{Storage Server record<__SSRecord__>}
3136 @type ss_record: C{dict}
3137
3138 @param fs_record: L{File System record<__FSRecord__>}
3139 @type fs_record: C{dict}
3140
3141 @param file_record: L{File record<__FileRecord__>}
3142 @type file_record: C{dict}
3143
3144 @param dest_file_name: Optional destination file name
3145 @type dest_file_name: C{str}
3146
3147 @return: newly created L{File record<__FileRecord__>} for the
3148 cloned storage element
3149 @rtype: C{dict}
3150
3151 @raise IPluginException: on failure
3152 """
3153 raise NotImplementedError()
3154
3155 @staticmethod
3157 """
3158 Determine if a deep clone can be made from a shallow (thin) clone (split the clones).
3159
3160 @param ss_record: L{Storage Server record<__SSRecord__>}
3161 @type ss_record: C{dict}
3162
3163 @param fs_record: L{File System record<__FSRecord__>}
3164 @type fs_record: C{dict}
3165
3166 @param file_record: L{File record<__FileRecord__>}
3167 @type file_record: C{dict}
3168
3169 @return: True if the clones can be split.
3170 @rtype: C{bool}
3171
3172 @raise IPluginException: on failure
3173 """
3174 raise NotImplementedError()
3175
3176 @staticmethod
3177 - def splitClone(ss_record, fs_record, file_record):
3178 """
3179 Create a deep clone from a shallow clone (Split the clones).
3180
3181 @param ss_record: L{Storage Server record<__SSRecord__>}
3182 @type ss_record: C{dict}
3183
3184 @param fs_record: L{File System record<__FSRecord__>}
3185 @type fs_record: C{dict}
3186
3187 @param file_record: L{File record<__FileRecord__>}
3188 @type file_record: C{dict}
3189
3190 @raise IPluginException: on failure
3191 """
3192 raise NotImplementedError()
3193
3194 @staticmethod
3195 - def cloneFromSnap(ss_record, fs_record, snap_file_record, dest_file_name = None):
3196 """
3197 Create a shallow clone from a named snapshot.
3198
3199 @param ss_record: L{Storage Server record<__SSRecord__>}
3200 @type ss_record: C{dict}
3201
3202 @param fs_record: L{File System record<__FSRecord__>}
3203 @type fs_record: C{dict}
3204
3205 @param snap_file_record: L{File record<__FileRecord__>}
3206 @type snap_file_record: C{dict}
3207
3208 @param dest_file_name: Optional destination file name
3209 @type dest_file_name: C{str}
3210
3211 @return: created L{File record<__FileRecord__>} for the new clone
3212 @rtype: C{dict}
3213
3214 @raise IPluginException: on failure
3215 """
3216 raise NotImplementedError()
3217
3218 @staticmethod
3220 """
3221 Return a list of the current clones for the File System or Storage
3222 Element.
3223
3224 @param ss_record: L{Storage Server record<__SSRecord__>}
3225 @type ss_record: C{dict}
3226
3227 @param fs_record: L{File System record<__FSRecord__>}
3228 @type fs_record: C{dict}
3229
3230 @param file_record: Optional L{File record<__FileRecord__>}
3231 @type file_record: C{dict}
3232
3233 @return: List of current known clones on the L{File record<__FileRecord__>}.
3234 @rtype: C{list}
3235
3236 @raise IPluginException: on failure
3237 """
3238 raise NotImplementedError()
3239
3240 @staticmethod
3242 """
3243 Return the maximum number of snapshots allowed for a Storage Array or
3244 File System.
3245
3246 @param ss_record: L{Storage Server record<__SSRecord__>}
3247 @type ss_record: C{dict}
3248
3249 @param fs_record: Optional L{File System record<__FSRecord__>}
3250 @type fs_record: C{dict}
3251
3252 @return: Maximum number (-1 for unlimited) of snapshots allowed for the
3253 Storage Array or the specific file system if supplied.
3254 @rtype: C{int}
3255
3256 @raise IPluginException: on failure
3257 """
3258 raise NotImplementedError()
3259
3260 @staticmethod
3262 """
3263 Return the maximum number of snapshots allowed for a specific file on
3264 the file system.
3265
3266 @param ss_record: L{Storage Server record<__SSRecord__>}
3267 @type ss_record: C{dict}
3268
3269 @param fs_record: L{File System record<__FSRecord__>}
3270 @type fs_record: C{dict}
3271
3272 @param file_record: L{File record<__FileRecord__>}
3273 @type file_record: C{dict}
3274
3275 @return: Maximum number (-1 for unlimited) of snapshots allowed for the
3276 specific file.
3277 @rtype: C{int}
3278
3279 @raise IPluginException: on failure
3280 """
3281 raise NotImplementedError()
3282
3283 @staticmethod
3284 - def isSnapable(ss_record, fs_record, file_record):
3285 """
3286 Check if a snapshot creation is allowed for the file on the file system
3287 file.
3288
3289 @param ss_record: L{Storage Server record<__SSRecord__>}
3290 @type ss_record: C{dict}
3291
3292 @param fs_record: L{File System record<__FSRecord__>}
3293 @type fs_record: C{dict}
3294
3295 @param file_record: L{File record<__FileRecord__>}
3296 @type file_record: C{dict}
3297
3298 @return: True if a snapshot can be created for the File record.
3299 @rtype: C{bool}
3300
3301 @raise IPluginException: on failure
3302 """
3303 raise NotImplementedError()
3304
3305 @staticmethod
3306 - def createSnap(ss_record, fs_record, file_record, snap_name = None):
3307 """
3308 Create a snapshot of the file for the file system.
3309
3310 @param ss_record: L{Storage Server record<__SSRecord__>}
3311 @type ss_record: C{dict}
3312
3313 @param fs_record: L{File System record<__FSRecord__>}
3314 @type fs_record: C{dict}
3315
3316 @param file_record: L{File record<__FileRecord__>}
3317 @type file_record: C{dict}
3318
3319 @param snap_name: Optional snapshot name
3320 @type snap_name: C{str}
3321
3322 @return: created L{File record<__FileRecord__>} for the snapshot
3323 @rtype: C{dict}
3324
3325 @raise IPluginException: on failure
3326 """
3327 raise NotImplementedError()
3328
3329 @staticmethod
3330 - def createMultiSnap(ss_record, fs_record, file_records, snap_name = None):
3331 """
3332 Create a snapshot of all the files listed for the file system.
3333
3334 @param ss_record: L{Storage Server record<__SSRecord__>}
3335 @type ss_record: C{dict}
3336
3337 @param fs_record: L{File System record<__FSRecord__>}
3338 @type fs_record: C{dict}
3339
3340 @param file_records: List of L{File record<__FileRecord__>}
3341 @type file_records: C{list}
3342
3343 @param snap_name: Optional snapshot name
3344 @type snap_name: C{str}
3345
3346 @return: Created L{File record<__FileRecord__>} for the snapshot
3347 @rtype: C{list}
3348
3349 @raise IPluginException: on failure
3350 """
3351 raise NotImplementedError()
3352
3353 @staticmethod
3354 - def isRestorable(ss_record, fs_record, file_record, snap_file_record):
3355 """
3356 Check if the Storage Array or Storage Element can be rolled back to the
3357 named snapshot.
3358
3359 @param ss_record: L{Storage Server record<__SSRecord__>}
3360 @type ss_record: C{dict}
3361
3362 @param fs_record: L{File System record<__FSRecord__>}
3363 @type fs_record: C{dict}
3364
3365 @param file_record: L{Storage Element record<__SERecord__>} naming
3366 the file tjat should be rolled back.
3367 @type file_record: C{dict}
3368
3369 @param snap_file_record: L{Storage Element record<__SERecord__>} naming
3370 the snapshot to be rolled back to.
3371 @type snap_file_record: C{dict}
3372
3373 @return: True if a snapshot can be rolled .
3374 @rtype: C{bool}
3375
3376 @raise IPluginException: on failure
3377 """
3378 raise NotImplementedError()
3379
3380 @staticmethod
3381 - def snapRestore(ss_record, fs_record, file_record, snap_file_record):
3382 """
3383 Roll the file back to the named snapshot.
3384
3385 @param ss_record: L{Storage Server record<__SSRecord__>}
3386 @type ss_record: C{dict}
3387
3388 @param fs_record: L{File System record<__FSRecord__>}
3389 @type fs_record: C{dict}
3390
3391 @param file_record: L{File record<__FileRecord__>} of the file to roll
3392 back.
3393 @type file_record: C{dict}
3394
3395 @param snap_file_record: L{File record<__FileRecord__>} naming the
3396 snapshot to roll back to.
3397 @type snap_file_record: C{dict}
3398
3399 @raise IPluginException: on failure
3400 """
3401 raise NotImplementedError()
3402
3403 @staticmethod
3404 - def snapRemove(ss_record, fs_record, snap_file_record):
3405 """
3406 Destroy the named snapshot.
3407
3408 @param ss_record: L{Storage Server record<__SSRecord__>}
3409 @type ss_record: C{dict}
3410
3411 @param fs_record: L{File System record<__FSRecord__>}
3412 @type fs_record: C{dict}
3413
3414 @param snap_file_record: L{File record<__FileRecord__>}
3415 @type snap_file_record: C{dict}
3416
3417 @raise IPluginException: on failure
3418 """
3419 raise NotImplementedError()
3420
3421 @staticmethod
3423 """
3424 Return a list of the current snapshots for a File System or File Record.
3425
3426 @param ss_record: L{Storage Server record<__SSRecord__>}
3427 @type ss_record: C{dict}
3428
3429 @param fs_record: L{File System record<__FSRecord__>}
3430 @type fs_record: C{dict}
3431
3432 @param file_record: Optional L{File record<__FileRecord__>}
3433 @type file_record: C{dict}
3434
3435 @return: List of current known snapshots for the File System or File
3436 record if supplied.
3437 @rtype: C{list}
3438
3439 @raise IPluginException: on failure
3440 """
3441 raise NotImplementedError()
3442
3443 @staticmethod
3445 """
3446 Return a list of possible QoS values for the File System.
3447
3448 @param ss_record: L{Storage Server record<__SSRecord__>}
3449 @type ss_record: C{dict}
3450
3451 @param fs_record: Optional L{File System record<__FSRecord__>}
3452 @type fs_record: C{dict}
3453
3454 @return: List of L{qos_vals<__qos_vals__>} dicts for all the possible
3455 QoS values for either the Storage Server or the File System.
3456 @rtype: C{list}
3457
3458 @raise IPluginException: on failure
3459 """
3460 raise NotImplementedError()
3461
3462 @staticmethod
3463 - def setQoS(ss_record, fs_record, qos):
3464 """
3465 Set the QoS for the Storage Element to the QoS supplied.
3466
3467 @param ss_record: L{Storage Server record<__SSRecord__>}
3468 @type ss_record: C{dict}
3469
3470 @param fs_record: L{File System record<__FSRecord__>}
3471 @type fs_record: C{dict}
3472
3473 @param qos: Desired Quality-of-Service for the new clone.
3474 @type qos: C{str}
3475
3476 @raise IPluginException: on failure
3477 """
3478 raise NotImplementedError()
3479
3480 @staticmethod
3482 """
3483 Get the list of valid backing devices that can be used to create
3484 a file system on.
3485
3486 @param ss_record: L{Storage Server record<__SSRecord__>}
3487 @type ss_record: C{dict}
3488
3489 @param fs_record: L{File System record<__FSRecord__>}
3490 @type fs_record: C{dict}
3491
3492 @return: List of L{backing_device<__BackingDeviceRecord__>} dicts
3493 for all the possible backing devices that can be used to
3494 create a new file system on.
3495 @rtype: C{list}
3496
3497 @raise IPluginException: on failure
3498 """
3499 raise NotImplementedError()
3500
3501 @staticmethod
3503 """
3504 Obtain Async Progress. This should never be called as
3505 the plugin should overide this method if it is in
3506 asynch mode.
3507
3508 @param ss_record: L{Storage Server record<__SSRecord__>}
3509 @type ss_record: C{dict}
3510
3511 @param some_record: Record previously returned from the
3512 call that started the asynchronous
3513 operation with the async_progress and
3514 if required the async_handle fields
3515 added (and not set to None).
3516 @type some_record: C{dict}
3517
3518 @return: Fully completed record that would have been
3519 returned if the initial call completed
3520 synchronously except it have the async_progress field.
3521 @rtype: C{dict}
3522
3523 @raise IPluginException: on failure
3524 """
3525
3526 raise NotImplementedError()
3527
3529 """
3530 All IPlugin exceptions inherits from IPluginException to allow for blanket
3531 exception catching.
3532 """
3534 Exception.__init__(self, msg)
3535 self.msg = msg
3536
3538 return repr(self.msg)
3539
3541 """
3542 Exception that gets raised if the call is not valid for the plugin.
3543 """
3546
3548 """
3549 Exception that gets raised if the operation failed.
3550 """
3553
3555 """
3556 Exception that gets raised if a required key is not in the record.
3557 """
3561
3570
3572 """
3573 Exception that gets raised if the Storage Array feature is not licensed.
3574 """
3577
3579 """
3580 Exception that gets raised if discovery failed.
3581 """
3584
3586 """
3587 Exception that gets raised if the login failed.
3588 """
3591
3593 """
3594 Exception that gets raised if the logout failed.
3595 """
3598
3600 """
3601 Exception that gets raised if the storage array refresh failed.
3602 """
3605
3607 """
3608 Exception that gets raised if the storage element list failed.
3609 """
3612
3614 """
3615 Exception that gets raised if a snapshot creation has failed.
3616 """
3619
3621 """
3622 Exception that gets raised if listing snapshots failed.
3623 """
3626
3628 """
3629 Exception that gets raised if snapshot cannot safely be rolled back.
3630 """
3633
3635 """
3636 Exception that gets raised if a clone opertaion failed.
3637 """
3640
3642 """
3643 Exception that gets raised if the ss_record is invalid.
3644 """
3647
3649 """
3650 Exception that gets raised on an invalid value in one of the records.
3651 """
3654
3656 """
3657 Exception that gets raised if permission is denied for the operation.
3658 """
3661
3663 """
3664 Exception that gets raised when the operation is not allowed while the
3665 Storage Element is still in use.
3666 """
3669
3671 """
3672 Exception that gets raised if a operation's prerequisite have not been met.
3673 """
3677
3679 """
3680 Exception that gets raised by the validate() method if the plug-in require
3681 a storage name to be set in the ss_record.
3682 """
3686
3688 """
3689 Exception that gets raised if the FS record file system type is invalid.
3690 """
3693
3695 """
3696 Exception that gets raised if the FS is busy.
3697 """
3700
3702 """
3703 Exception that gets raised if the comand is not available.
3704 """
3707
3710 """
3711 Exception that gets raised if the FS is already mounted.
3712 """
3715