usr/bin/lsmcli000075500000001661147207345650007357 0ustar00#!/usr/bin/env python2 # Copyright (C) 2012 Red Hat, Inc. # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; If not, see . # # Author: tasleson from lsm.lsmcli import cmd_line_wrapper # Command line interface for libStorageMgmt. # This is contained in a separate class which can be shared across all the py # plug-ins. if __name__ == '__main__': cmd_line_wrapper() data_display.pyc000064400000073525147576777270007770 0ustar00 /P`c@s*ddlZddlmZddlmZmZmZmZmZmZm Z m Z m Z m Z m Z mZmZmZyddlmZWn!ek rddlmZnXdZdZdZdZd Zid ej6d ej6d ej6d ej6dej6dej6Z dZ!idej"6dej#6Z$dZ%i d ej6d ej6dej6d ej6d ej6dej&6dej'6dej(6dej)6dej*6Z+dZ,idej-6dej.6dej/6dej06dej16dej26d ej36Z4id!ej56d"ej66Z7d#Z8d$Z9id%e j:6d&e j;6d'e j<6d(e j=6Z>d)Z?id*e j@6d+e jA6ZBd,ZCid-e jD6d.e jE6d/e jF6d0e jG6d(e jH6ZId1ZJi d(e jK6de jL6d2e jM6d3e jN6d4e jO6d5e jP6d6e jQ6d7e jR6d8e jS6d9e jT6d:e jU6d;e jV6d<e jW6ZXd=ZYid e j6d e j6de j6de j6d e j6d>e jZ6d?e j[6d@e j\6de j&6de j)6dAe j]6dBe j^6dCe j_6dDe j`6ZadEZbid e jc6de jd6dFe je6dGe jf6dHe jg6ZhdIZidJZjidejL6d5ejP6dKejk6dGejl6ZmdLZndMZodNZpdOZqid ejK6dejL6dPejr6dQejs6ZtdRZuid ej6dej6d ej6dSejv6dTejw6dUejx6d ej6d ej6ZydVZzid e j{6dWe j|6dXe j}6dYe j~6dZe j6d[e j6d\e j6Zd]Zd^Zd_efd`YZdaefdbYZdcefddYZdeefdfYZdgefdhYZdiefdjYZdkefdlYZdS(miN(tdatetime(tsize_bytes_2_size_humantLsmErrort ErrorNumbertBatterytSystemtPooltDisktVolumet AccessGroupt FileSystemt FsSnapshott NfsExportt TargetPortt LocalDisk(t OrderedDictt,cCs\y7tjjt|tjjdtjjWntk rWtjdnXdS(Ns i(tsyststdouttwritetstrtflushtIOErrortexit(tmsg((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytout's  cCsg}t|}x8t|jD]$}||@r%|j||q%q%W|dkryt|dkrydt|Stj|S(Nis Unknown(%s)(tinttlisttkeystappendtlenthextBIT_MAP_STRING_SPLITTERtjoin(tbit_mapt conv_dicttrctcur_enum((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyt_bit_map_to_str0s  cCs4t|}|t|jkr,||Sd|S(Ns Unknown(%d)(RRR(tint_typeR#((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyt_enum_type_to_str<s cCswgt|jD]*\}}|j|jkr|^q}t|dkr]|dSttjd|dS(Nis Failed to convert %s to lsm type(RtitemstlowerRRRtINVALID_ARGUMENT(ttype_strR#tktvR((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyt _str_to_enumDs $ tUnknowntOKtErrortDegradedsPredictive failuretOthercCs t|tS(N(R&t_SYSTEM_STATUS_CONV(t system_status((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytsystem_status_to_strWssHW RAIDtHBAcCstj|dS(Nt(t_SYSTEM_MODE_CONVtget(t system_mode((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytsystem_mode_to_strastStoppedtReconstructingt Verifyingt InitializingtGrowingcCs t|tS(N(R&t_POOL_STATUS_CONV(t pool_status((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytpool_status_to_strsstPOOLtVOLUMEt VOLUME_THINt VOLUME_FULLtFStSYSTEM_RESERVEDtDELTAs Volume Grows Volume ShrinkcCs t|tS(N(R&t_POOL_ELEMENT_TYPE_CONV(t element_type((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytpool_element_type_to_strscCs t|tS(N(R&t_POOL_UNSUPPORTED_ACTION_CONV(tunsupported_actions((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytpool_unsupported_actions_to_strstDEFAULTtFULLtTHINtUNKNOWNcCs t|tS(N(R/t_VOL_PROVISION_CONV(tvol_provision_str((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytvol_provision_str_to_typestYestNocCs t|tS(N(R(t_VOL_ADMIN_STATE_CONV(tvol_admin_state((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytvol_admin_state_to_strstCLONEtCOPYt MIRROR_SYNCt MIRROR_ASYNCcCs t|tS(N(R/t_VOL_REP_TYPE_CONV(tvol_rep_type_str((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytvol_rep_type_str_to_typestATAtSATAtSAStFCsSCSI Over PCI-E(SSD)tSCSItNL_SAStHDDtSSDtHybrids Remote LUNcCs t|tS(N(R(t_DISK_TYPE_CONV(t disk_type((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytdisk_type_to_strstRemovedtStartingtStoppingt MaintenancetSparet ReconstructtFreecCs t|tS(N(R&t_DISK_STATUS_CONV(t disk_status((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytdisk_status_to_strstWWPNtiSCSIsiSCSI/WWPN MixedcCs t|tS(N(R(t_AG_INIT_TYPE_CONV(t init_type((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytag_init_type_to_strscCs t|tS(N(R/R~(t init_type_str((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytag_init_type_str_to_lsmstFCoEcCs t|tS(N(R(t_TGT_PORT_TYPE_CONV(t port_type((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyttgt_port_type_to_strscCsf|dkrdS|tjkr#dS|tjkr6dS|tjkrIdS|tjkr\dSt|S(NR9s No SupportR0sNon-Rotating MediumsRotating Medium Unknown Speed(RtRPM_NO_SUPPORTt RPM_UNKNOWNtRPM_NON_ROTATING_MEDIUMtRPM_ROTATING_UNKNOWN_SPEEDR(trpm((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytdisk_rpm_to_strs cCs |dkrdSt|tjS(NR9s No Support(R(t LocalDiskInfot_LINK_TYPE_MAP(t link_type((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytdisk_link_type_to_strs cCs`|dkrdS|tjkr#dS|tjkr6dS|tjkrIdS|tjkr\dSdS(NR9s No SupportR0tFailuretWarningtGood(RtHEALTH_STATUS_UNKNOWNtHEALTH_STATUS_FAILtHEALTH_STATUS_WARNtHEALTH_STATUS_GOOD(t health_status((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytdisk_health_status_to_strs tChemicalt CapacitorcCs t|tS(N(R(t_BATTERY_TYPE_CONV(t battery_type((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytbattery_type_to_str#st DischargingtChargingtLearningcCs t|tS(N(R&t_BATTERY_STATUS_CONV(tbattery_status((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytbattery_status_to_str3stIDENT_ONt IDENT_OFFt IDENT_UNKNOWNtFAULT_ONt FAULT_OFFt FAULT_UNKNOWNcCs t|tS(N(R&t_DISK_LED_STATUS_CONV(t led_status((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytdisk_led_status_to_strBscCs%|tjkrdSdt|dS(NR0s %.1f Gbpsg@@(RtLINK_SPEED_UNKNOWNtfloat(t link_speed((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytdisk_link_speed_to_strFstPlugDatacBseZdZRS(cCs||_||_dS(N(tdesctversion(tselft descriptiontplugin_version((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyt__init__Ms (t__name__t __module__R(((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyRLstVolumeRAIDInfocBseZidej6dej6dej6dej6dej6dej6dej 6dej 6dej 6d ej 6d ej 6d ej6d ej6d ej6dej6dej6dej6Zdddddd d gZdZedZedZRS(tRAID0tRAID1tRAID3tRAID4tRAID5tRAID6tRAID10tRAID15tRAID16tRAID50tRAID60tRAID51tRAID61tJBODtMIXEDtOTHERRVcCs:||_||_||_||_||_||_dS(N(tvol_idt raid_typet strip_sizet disk_countt min_io_sizet opt_io_size(RRRRRRR((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyRjs      cCst|tjS(N(R(Rt_RAID_TYPE_MAP(R((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytraid_type_to_strsscCst|tjS(N(R/RR(t raid_type_str((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytraid_type_str_to_lsmws(RRRtRAID_TYPE_RAID0tRAID_TYPE_RAID1tRAID_TYPE_RAID3tRAID_TYPE_RAID4tRAID_TYPE_RAID5tRAID_TYPE_RAID6tRAID_TYPE_RAID10tRAID_TYPE_RAID15tRAID_TYPE_RAID16tRAID_TYPE_RAID50tRAID_TYPE_RAID60tRAID_TYPE_RAID51tRAID_TYPE_RAID61tRAID_TYPE_JBODtRAID_TYPE_MIXEDtRAID_TYPE_OTHERtRAID_TYPE_UNKNOWNRtVOL_CREATE_RAID_TYPES_STRRt staticmethodRR(((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyRRs,                  t PoolRAIDInfocBsNeZidej6dej6dej6dej6ZdZe dZ RS(R0RRcCs(||_||_||_||_dS(N(tpool_idRt member_typet member_ids(RRRRR((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyRs   cCst|tjS(N(R(Rt_MEMBER_TYPE_MAP(R((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytmember_type_to_strs( RRRtMEMBER_TYPE_UNKNOWNtMEMBER_TYPE_OTHERtMEMBER_TYPE_POOLtMEMBER_TYPE_DISKRRRR(((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyR|s     tVcrCapcBseZdZRS(cCs||_||_||_dS(N(t system_idt raid_typest strip_sizes(RRRR((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyRs  (RRR(((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyRsRcBseZi dej6dej6dej6dej6dej6dej6dej 6dej 6dej 6d ej 6d ej 6d ej6d ej6Zd ZRS(s No SupportR0RitSSAtSBPtSRPR}RhtADTs PATA/SATAtUSBsSCSI over PCIEsPCI-Ec CsL||_||_||_||_||_||_||_||_dS(N(tsd_pathtvpd83RRt serial_numRRR( RRRRRRRRR((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyRs       (RRRtLINK_TYPE_NO_SUPPORTtLINK_TYPE_UNKNOWNt LINK_TYPE_FCt LINK_TYPE_SSAt LINK_TYPE_SBPt LINK_TYPE_SRPtLINK_TYPE_ISCSIt LINK_TYPE_SASt LINK_TYPE_ADTt LINK_TYPE_ATAt LINK_TYPE_USBt LINK_TYPE_SOPtLINK_TYPE_PCIERR(((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyRs             tVolumeRAMCacheInfocBs$eZidej6dej6dej6dej6Zidej6dej 6dej 6dej 6Z idej 6dej6dej6Zidej6dej6dej6Zidej6dej6dej6ZdZedZed Zed Zed Zed ZRS( sUse Disk SettingtEnabledtDisabledR0s Write BacktAutos Write ThroughcCs:||_||_||_||_||_||_dS(N(Rtwrite_cache_policytwrite_cache_statustread_cache_policytread_cache_statustphy_disk_cache(RRRRRRR((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyRs      cCst|tjS(N(R(R t_PHY_DISK_CACHE_STATUS_MAP(R((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytphy_disk_cache_status_to_strscCst|tjS(N(R(R t_W_CACHE_POLICY_MAP(t w_cache_p((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytw_cache_policy_to_strscCst|tjS(N(R(R t_W_CACHE_STATUS_MAP(tw_cache_status((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytw_cache_status_to_strscCst|tjS(N(R(R t_R_CACHE_POLICY_MAP(t r_cache_p((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytr_cache_policy_to_strscCst|tjS(N(R(R t_R_CACHE_STATUS_MAP(tr_cache_status((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytr_cache_status_to_strs( RRRt$PHYSICAL_DISK_CACHE_USE_DISK_SETTINGtPHYSICAL_DISK_CACHE_ENABLEDtPHYSICAL_DISK_CACHE_DISABLEDtPHYSICAL_DISK_CACHE_UNKNOWNRtWRITE_CACHE_POLICY_UNKNOWNtWRITE_CACHE_POLICY_WRITE_BACKtWRITE_CACHE_POLICY_AUTOt WRITE_CACHE_POLICY_WRITE_THROUGHRtWRITE_CACHE_STATUS_UNKNOWNtWRITE_CACHE_STATUS_WRITE_BACKt WRITE_CACHE_STATUS_WRITE_THROUGHRtREAD_CACHE_POLICY_UNKNOWNtREAD_CACHE_POLICY_ENABLEDtREAD_CACHE_POLICY_DISABLEDRtREAD_CACHE_STATUS_UNKNOWNtREAD_CACHE_STATUS_ENABLEDtREAD_CACHE_STATUS_DISABLEDR RRRRRRR"(((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyR s8                  t DisplayDatac Bs eZdZdZdZeZdZiZeZ de d6Z;gZ<ie7d6e8d6e;d6e<d6ee=de>dd@dBdDdFdHdJdLdNdPd6e?d6e@d6eAd6eeB8stPathRs Serial NumberRs LED StatusRs Link SpeedRs Health StatusRttypeR9sWrite Cache PolicyRs Write CacheRsRead Cache PolicyRs Read CacheRsPhysical Disk CacheRcCsyt||}Wn4tk rI}|jtjkr@d}qJ|nX|s~|t|jkr~|||}q~n|r||krt|tkrtd|D}qt|}qn|S(NR9css|]}t|VqdS(N(R(t.0ts((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pys s( tgetattrRtcodeRt NO_SUPPORTRRRgR(tobjtkeyRCRDt flag_humant flag_enumtvaluetlsm_err((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyt_get_man_pro_values   cCs]d}xPtdt|D]9}||}t|||krt||}qqW|S(Nii(trangeR(t two_d_listt column_indext max_widtht row_indextrow_data((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyt_find_max_widths  cCsBt}tjt|}|d}|d} |d} |rLtj}ng} |tjkrxat|jD]&} | |dkrt| j| qtqtWn$|tjkrt|j} n|rx-|D]"} | | kr| j| qqWnx@| D]8}||}tj ||| | ||}|||s$ ^                                                                                                                    *E__init__.py000064400000001416147576777270006714 0ustar00# Copyright (C) 2011-2016 Red Hat, Inc. # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; If not, see . try: from .cmdline import cmd_line_wrapper except ImportError: from cmdline import cmd_line_wrapper __init__.pyc000064400000000421147576777270007052 0ustar00 /P`c@s<yddlmZWn!ek r7ddlmZnXdS(i(tcmd_line_wrapperiN(tcmdlineRt ImportError(((s7/usr/lib/python2.7/site-packages/lsm/lsmcli/__init__.pyts data_display.pyo000064400000073525147576777270010004 0ustar00 /P`c@s*ddlZddlmZddlmZmZmZmZmZmZm Z m Z m Z m Z m Z mZmZmZyddlmZWn!ek rddlmZnXdZdZdZdZd Zid ej6d ej6d ej6d ej6dej6dej6Z dZ!idej"6dej#6Z$dZ%i d ej6d ej6dej6d ej6d ej6dej&6dej'6dej(6dej)6dej*6Z+dZ,idej-6dej.6dej/6dej06dej16dej26d ej36Z4id!ej56d"ej66Z7d#Z8d$Z9id%e j:6d&e j;6d'e j<6d(e j=6Z>d)Z?id*e j@6d+e jA6ZBd,ZCid-e jD6d.e jE6d/e jF6d0e jG6d(e jH6ZId1ZJi d(e jK6de jL6d2e jM6d3e jN6d4e jO6d5e jP6d6e jQ6d7e jR6d8e jS6d9e jT6d:e jU6d;e jV6d<e jW6ZXd=ZYid e j6d e j6de j6de j6d e j6d>e jZ6d?e j[6d@e j\6de j&6de j)6dAe j]6dBe j^6dCe j_6dDe j`6ZadEZbid e jc6de jd6dFe je6dGe jf6dHe jg6ZhdIZidJZjidejL6d5ejP6dKejk6dGejl6ZmdLZndMZodNZpdOZqid ejK6dejL6dPejr6dQejs6ZtdRZuid ej6dej6d ej6dSejv6dTejw6dUejx6d ej6d ej6ZydVZzid e j{6dWe j|6dXe j}6dYe j~6dZe j6d[e j6d\e j6Zd]Zd^Zd_efd`YZdaefdbYZdcefddYZdeefdfYZdgefdhYZdiefdjYZdkefdlYZdS(miN(tdatetime(tsize_bytes_2_size_humantLsmErrort ErrorNumbertBatterytSystemtPooltDisktVolumet AccessGroupt FileSystemt FsSnapshott NfsExportt TargetPortt LocalDisk(t OrderedDictt,cCs\y7tjjt|tjjdtjjWntk rWtjdnXdS(Ns i(tsyststdouttwritetstrtflushtIOErrortexit(tmsg((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytout's  cCsg}t|}x8t|jD]$}||@r%|j||q%q%W|dkryt|dkrydt|Stj|S(Nis Unknown(%s)(tinttlisttkeystappendtlenthextBIT_MAP_STRING_SPLITTERtjoin(tbit_mapt conv_dicttrctcur_enum((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyt_bit_map_to_str0s  cCs4t|}|t|jkr,||Sd|S(Ns Unknown(%d)(RRR(tint_typeR#((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyt_enum_type_to_str<s cCswgt|jD]*\}}|j|jkr|^q}t|dkr]|dSttjd|dS(Nis Failed to convert %s to lsm type(RtitemstlowerRRRtINVALID_ARGUMENT(ttype_strR#tktvR((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyt _str_to_enumDs $ tUnknowntOKtErrortDegradedsPredictive failuretOthercCs t|tS(N(R&t_SYSTEM_STATUS_CONV(t system_status((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytsystem_status_to_strWssHW RAIDtHBAcCstj|dS(Nt(t_SYSTEM_MODE_CONVtget(t system_mode((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytsystem_mode_to_strastStoppedtReconstructingt Verifyingt InitializingtGrowingcCs t|tS(N(R&t_POOL_STATUS_CONV(t pool_status((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytpool_status_to_strsstPOOLtVOLUMEt VOLUME_THINt VOLUME_FULLtFStSYSTEM_RESERVEDtDELTAs Volume Grows Volume ShrinkcCs t|tS(N(R&t_POOL_ELEMENT_TYPE_CONV(t element_type((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytpool_element_type_to_strscCs t|tS(N(R&t_POOL_UNSUPPORTED_ACTION_CONV(tunsupported_actions((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytpool_unsupported_actions_to_strstDEFAULTtFULLtTHINtUNKNOWNcCs t|tS(N(R/t_VOL_PROVISION_CONV(tvol_provision_str((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytvol_provision_str_to_typestYestNocCs t|tS(N(R(t_VOL_ADMIN_STATE_CONV(tvol_admin_state((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytvol_admin_state_to_strstCLONEtCOPYt MIRROR_SYNCt MIRROR_ASYNCcCs t|tS(N(R/t_VOL_REP_TYPE_CONV(tvol_rep_type_str((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytvol_rep_type_str_to_typestATAtSATAtSAStFCsSCSI Over PCI-E(SSD)tSCSItNL_SAStHDDtSSDtHybrids Remote LUNcCs t|tS(N(R(t_DISK_TYPE_CONV(t disk_type((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytdisk_type_to_strstRemovedtStartingtStoppingt MaintenancetSparet ReconstructtFreecCs t|tS(N(R&t_DISK_STATUS_CONV(t disk_status((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytdisk_status_to_strstWWPNtiSCSIsiSCSI/WWPN MixedcCs t|tS(N(R(t_AG_INIT_TYPE_CONV(t init_type((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytag_init_type_to_strscCs t|tS(N(R/R~(t init_type_str((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytag_init_type_str_to_lsmstFCoEcCs t|tS(N(R(t_TGT_PORT_TYPE_CONV(t port_type((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyttgt_port_type_to_strscCsf|dkrdS|tjkr#dS|tjkr6dS|tjkrIdS|tjkr\dSt|S(NR9s No SupportR0sNon-Rotating MediumsRotating Medium Unknown Speed(RtRPM_NO_SUPPORTt RPM_UNKNOWNtRPM_NON_ROTATING_MEDIUMtRPM_ROTATING_UNKNOWN_SPEEDR(trpm((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytdisk_rpm_to_strs cCs |dkrdSt|tjS(NR9s No Support(R(t LocalDiskInfot_LINK_TYPE_MAP(t link_type((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytdisk_link_type_to_strs cCs`|dkrdS|tjkr#dS|tjkr6dS|tjkrIdS|tjkr\dSdS(NR9s No SupportR0tFailuretWarningtGood(RtHEALTH_STATUS_UNKNOWNtHEALTH_STATUS_FAILtHEALTH_STATUS_WARNtHEALTH_STATUS_GOOD(t health_status((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytdisk_health_status_to_strs tChemicalt CapacitorcCs t|tS(N(R(t_BATTERY_TYPE_CONV(t battery_type((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytbattery_type_to_str#st DischargingtChargingtLearningcCs t|tS(N(R&t_BATTERY_STATUS_CONV(tbattery_status((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytbattery_status_to_str3stIDENT_ONt IDENT_OFFt IDENT_UNKNOWNtFAULT_ONt FAULT_OFFt FAULT_UNKNOWNcCs t|tS(N(R&t_DISK_LED_STATUS_CONV(t led_status((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytdisk_led_status_to_strBscCs%|tjkrdSdt|dS(NR0s %.1f Gbpsg@@(RtLINK_SPEED_UNKNOWNtfloat(t link_speed((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytdisk_link_speed_to_strFstPlugDatacBseZdZRS(cCs||_||_dS(N(tdesctversion(tselft descriptiontplugin_version((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyt__init__Ms (t__name__t __module__R(((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyRLstVolumeRAIDInfocBseZidej6dej6dej6dej6dej6dej6dej 6dej 6dej 6d ej 6d ej 6d ej6d ej6d ej6dej6dej6dej6Zdddddd d gZdZedZedZRS(tRAID0tRAID1tRAID3tRAID4tRAID5tRAID6tRAID10tRAID15tRAID16tRAID50tRAID60tRAID51tRAID61tJBODtMIXEDtOTHERRVcCs:||_||_||_||_||_||_dS(N(tvol_idt raid_typet strip_sizet disk_countt min_io_sizet opt_io_size(RRRRRRR((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyRjs      cCst|tjS(N(R(Rt_RAID_TYPE_MAP(R((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytraid_type_to_strsscCst|tjS(N(R/RR(t raid_type_str((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytraid_type_str_to_lsmws(RRRtRAID_TYPE_RAID0tRAID_TYPE_RAID1tRAID_TYPE_RAID3tRAID_TYPE_RAID4tRAID_TYPE_RAID5tRAID_TYPE_RAID6tRAID_TYPE_RAID10tRAID_TYPE_RAID15tRAID_TYPE_RAID16tRAID_TYPE_RAID50tRAID_TYPE_RAID60tRAID_TYPE_RAID51tRAID_TYPE_RAID61tRAID_TYPE_JBODtRAID_TYPE_MIXEDtRAID_TYPE_OTHERtRAID_TYPE_UNKNOWNRtVOL_CREATE_RAID_TYPES_STRRt staticmethodRR(((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyRRs,                  t PoolRAIDInfocBsNeZidej6dej6dej6dej6ZdZe dZ RS(R0RRcCs(||_||_||_||_dS(N(tpool_idRt member_typet member_ids(RRRRR((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyRs   cCst|tjS(N(R(Rt_MEMBER_TYPE_MAP(R((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytmember_type_to_strs( RRRtMEMBER_TYPE_UNKNOWNtMEMBER_TYPE_OTHERtMEMBER_TYPE_POOLtMEMBER_TYPE_DISKRRRR(((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyR|s     tVcrCapcBseZdZRS(cCs||_||_||_dS(N(t system_idt raid_typest strip_sizes(RRRR((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyRs  (RRR(((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyRsRcBseZi dej6dej6dej6dej6dej6dej6dej 6dej 6dej 6d ej 6d ej 6d ej6d ej6Zd ZRS(s No SupportR0RitSSAtSBPtSRPR}RhtADTs PATA/SATAtUSBsSCSI over PCIEsPCI-Ec CsL||_||_||_||_||_||_||_||_dS(N(tsd_pathtvpd83RRt serial_numRRR( RRRRRRRRR((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyRs       (RRRtLINK_TYPE_NO_SUPPORTtLINK_TYPE_UNKNOWNt LINK_TYPE_FCt LINK_TYPE_SSAt LINK_TYPE_SBPt LINK_TYPE_SRPtLINK_TYPE_ISCSIt LINK_TYPE_SASt LINK_TYPE_ADTt LINK_TYPE_ATAt LINK_TYPE_USBt LINK_TYPE_SOPtLINK_TYPE_PCIERR(((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyRs             tVolumeRAMCacheInfocBs$eZidej6dej6dej6dej6Zidej6dej 6dej 6dej 6Z idej 6dej6dej6Zidej6dej6dej6Zidej6dej6dej6ZdZedZed Zed Zed Zed ZRS( sUse Disk SettingtEnabledtDisabledR0s Write BacktAutos Write ThroughcCs:||_||_||_||_||_||_dS(N(Rtwrite_cache_policytwrite_cache_statustread_cache_policytread_cache_statustphy_disk_cache(RRRRRRR((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyRs      cCst|tjS(N(R(R t_PHY_DISK_CACHE_STATUS_MAP(R((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytphy_disk_cache_status_to_strscCst|tjS(N(R(R t_W_CACHE_POLICY_MAP(t w_cache_p((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytw_cache_policy_to_strscCst|tjS(N(R(R t_W_CACHE_STATUS_MAP(tw_cache_status((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytw_cache_status_to_strscCst|tjS(N(R(R t_R_CACHE_POLICY_MAP(t r_cache_p((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytr_cache_policy_to_strscCst|tjS(N(R(R t_R_CACHE_STATUS_MAP(tr_cache_status((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pytr_cache_status_to_strs( RRRt$PHYSICAL_DISK_CACHE_USE_DISK_SETTINGtPHYSICAL_DISK_CACHE_ENABLEDtPHYSICAL_DISK_CACHE_DISABLEDtPHYSICAL_DISK_CACHE_UNKNOWNRtWRITE_CACHE_POLICY_UNKNOWNtWRITE_CACHE_POLICY_WRITE_BACKtWRITE_CACHE_POLICY_AUTOt WRITE_CACHE_POLICY_WRITE_THROUGHRtWRITE_CACHE_STATUS_UNKNOWNtWRITE_CACHE_STATUS_WRITE_BACKt WRITE_CACHE_STATUS_WRITE_THROUGHRtREAD_CACHE_POLICY_UNKNOWNtREAD_CACHE_POLICY_ENABLEDtREAD_CACHE_POLICY_DISABLEDRtREAD_CACHE_STATUS_UNKNOWNtREAD_CACHE_STATUS_ENABLEDtREAD_CACHE_STATUS_DISABLEDR RRRRRRR"(((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyR s8                  t DisplayDatac Bs eZdZdZdZeZdZiZeZ de d6Z;gZ<ie7d6e8d6e;d6e<d6ee=de>dd@dBdDdFdHdJdLdNdPd6e?d6e@d6eAd6eeB8stPathRs Serial NumberRs LED StatusRs Link SpeedRs Health StatusRttypeR9sWrite Cache PolicyRs Write CacheRsRead Cache PolicyRs Read CacheRsPhysical Disk CacheRcCsyt||}Wn4tk rI}|jtjkr@d}qJ|nX|s~|t|jkr~|||}q~n|r||krt|tkrtd|D}qt|}qn|S(NR9css|]}t|VqdS(N(R(t.0ts((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pys s( tgetattrRtcodeRt NO_SUPPORTRRRgR(tobjtkeyRCRDt flag_humant flag_enumtvaluetlsm_err((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyt_get_man_pro_values   cCs]d}xPtdt|D]9}||}t|||krt||}qqW|S(Nii(trangeR(t two_d_listt column_indext max_widtht row_indextrow_data((s;/usr/lib/python2.7/site-packages/lsm/lsmcli/data_display.pyt_find_max_widths  cCsBt}tjt|}|d}|d} |d} |rLtj}ng} |tjkrxat|jD]&} | |dkrt| j| qtqtWn$|tjkrt|j} n|rx-|D]"} | | kr| j| qqWnx@| D]8}||}tj ||| | ||}|||s$ ^                                                                                                                    *Edata_display.py000064400000110003147576777270007604 0ustar00# Copyright (C) 2014 Red Hat, Inc. # (C) Copyright 2017 Hewlett Packard Enterprise Development LP # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; If not, see . # # Author: Gris Ge import sys from datetime import datetime from lsm import (size_bytes_2_size_human, LsmError, ErrorNumber, Battery, System, Pool, Disk, Volume, AccessGroup, FileSystem, FsSnapshot, NfsExport, TargetPort, LocalDisk) try: from collections import OrderedDict except ImportError: # python 2.6 or earlier, use backport from ordereddict import OrderedDict BIT_MAP_STRING_SPLITTER = ',' # Users are reporting errors with broken pipe when piping output # to another program. This appears to be related to this issue: # http://bugs.python.org/issue11380 # Unable to reproduce, but hopefully this will address it. # @param msg The message to be written to stdout def out(msg): try: sys.stdout.write(str(msg)) sys.stdout.write("\n") sys.stdout.flush() except IOError: sys.exit(1) def _bit_map_to_str(bit_map, conv_dict): rc = [] bit_map = int(bit_map) for cur_enum in list(conv_dict.keys()): if cur_enum & bit_map: rc.append(conv_dict[cur_enum]) # If there are no bits set we really don't need a string if bit_map != 0 and len(rc) == 0: return 'Unknown(%s)' % hex(bit_map) return BIT_MAP_STRING_SPLITTER.join(rc) def _enum_type_to_str(int_type, conv_dict): int_type = int(int_type) if int_type in list(conv_dict.keys()): return conv_dict[int_type] return 'Unknown(%d)' % int_type def _str_to_enum(type_str, conv_dict): keys = [k for k, v in list(conv_dict.items()) if v.lower() == type_str.lower()] if len(keys) > 0: return keys[0] raise LsmError(ErrorNumber.INVALID_ARGUMENT, "Failed to convert %s to lsm type" % type_str) _SYSTEM_STATUS_CONV = { System.STATUS_UNKNOWN: 'Unknown', System.STATUS_OK: 'OK', System.STATUS_ERROR: 'Error', System.STATUS_DEGRADED: 'Degraded', System.STATUS_PREDICTIVE_FAILURE: 'Predictive failure', System.STATUS_OTHER: 'Other', } def system_status_to_str(system_status): return _bit_map_to_str(system_status, _SYSTEM_STATUS_CONV) _SYSTEM_MODE_CONV = { System.MODE_HARDWARE_RAID: "HW RAID", System.MODE_HBA: "HBA", } def system_mode_to_str(system_mode): return _SYSTEM_MODE_CONV.get(system_mode, "") _POOL_STATUS_CONV = { Pool.STATUS_UNKNOWN: 'Unknown', Pool.STATUS_OK: 'OK', Pool.STATUS_OTHER: 'Other', Pool.STATUS_DEGRADED: 'Degraded', Pool.STATUS_ERROR: 'Error', Pool.STATUS_STOPPED: 'Stopped', Pool.STATUS_RECONSTRUCTING: 'Reconstructing', Pool.STATUS_VERIFYING: 'Verifying', Pool.STATUS_INITIALIZING: 'Initializing', Pool.STATUS_GROWING: 'Growing', } def pool_status_to_str(pool_status): return _bit_map_to_str(pool_status, _POOL_STATUS_CONV) _POOL_ELEMENT_TYPE_CONV = { Pool.ELEMENT_TYPE_POOL: 'POOL', Pool.ELEMENT_TYPE_VOLUME: 'VOLUME', Pool.ELEMENT_TYPE_VOLUME_THIN: 'VOLUME_THIN', Pool.ELEMENT_TYPE_VOLUME_FULL: 'VOLUME_FULL', Pool.ELEMENT_TYPE_FS: 'FS', Pool.ELEMENT_TYPE_SYS_RESERVED: 'SYSTEM_RESERVED', Pool.ELEMENT_TYPE_DELTA: "DELTA", } _POOL_UNSUPPORTED_ACTION_CONV = { Pool.UNSUPPORTED_VOLUME_GROW: "Volume Grow", Pool.UNSUPPORTED_VOLUME_SHRINK: "Volume Shrink" } def pool_element_type_to_str(element_type): return _bit_map_to_str(element_type, _POOL_ELEMENT_TYPE_CONV) def pool_unsupported_actions_to_str(unsupported_actions): return _bit_map_to_str(unsupported_actions, _POOL_UNSUPPORTED_ACTION_CONV) _VOL_PROVISION_CONV = { Volume.PROVISION_DEFAULT: 'DEFAULT', Volume.PROVISION_FULL: 'FULL', Volume.PROVISION_THIN: 'THIN', Volume.PROVISION_UNKNOWN: 'UNKNOWN', } def vol_provision_str_to_type(vol_provision_str): return _str_to_enum(vol_provision_str, _VOL_PROVISION_CONV) _VOL_ADMIN_STATE_CONV = { Volume.ADMIN_STATE_DISABLED: 'Yes', Volume.ADMIN_STATE_ENABLED: 'No', } def vol_admin_state_to_str(vol_admin_state): return _enum_type_to_str(vol_admin_state, _VOL_ADMIN_STATE_CONV) _VOL_REP_TYPE_CONV = { Volume.REPLICATE_CLONE: 'CLONE', Volume.REPLICATE_COPY: 'COPY', Volume.REPLICATE_MIRROR_SYNC: 'MIRROR_SYNC', Volume.REPLICATE_MIRROR_ASYNC: 'MIRROR_ASYNC', Volume.REPLICATE_UNKNOWN: 'UNKNOWN', } def vol_rep_type_str_to_type(vol_rep_type_str): return _str_to_enum(vol_rep_type_str, _VOL_REP_TYPE_CONV) _DISK_TYPE_CONV = { Disk.TYPE_UNKNOWN: 'UNKNOWN', Disk.TYPE_OTHER: 'Other', Disk.TYPE_ATA: 'ATA', Disk.TYPE_SATA: 'SATA', Disk.TYPE_SAS: 'SAS', Disk.TYPE_FC: 'FC', Disk.TYPE_SOP: 'SCSI Over PCI-E(SSD)', Disk.TYPE_SCSI: 'SCSI', Disk.TYPE_NL_SAS: 'NL_SAS', Disk.TYPE_HDD: 'HDD', Disk.TYPE_SSD: 'SSD', Disk.TYPE_HYBRID: 'Hybrid', Disk.TYPE_LUN: 'Remote LUN', } def disk_type_to_str(disk_type): return _enum_type_to_str(disk_type, _DISK_TYPE_CONV) _DISK_STATUS_CONV = { Disk.STATUS_UNKNOWN: 'Unknown', Disk.STATUS_OK: 'OK', Disk.STATUS_OTHER: 'Other', Disk.STATUS_PREDICTIVE_FAILURE: 'Predictive failure', Disk.STATUS_ERROR: 'Error', Disk.STATUS_REMOVED: 'Removed', Disk.STATUS_STARTING: 'Starting', Disk.STATUS_STOPPING: 'Stopping', Disk.STATUS_STOPPED: 'Stopped', Disk.STATUS_INITIALIZING: 'Initializing', Disk.STATUS_MAINTENANCE_MODE: 'Maintenance', Disk.STATUS_SPARE_DISK: 'Spare', Disk.STATUS_RECONSTRUCT: 'Reconstruct', Disk.STATUS_FREE: 'Free', } def disk_status_to_str(disk_status): return _bit_map_to_str(disk_status, _DISK_STATUS_CONV) _AG_INIT_TYPE_CONV = { AccessGroup.INIT_TYPE_UNKNOWN: 'Unknown', AccessGroup.INIT_TYPE_OTHER: 'Other', AccessGroup.INIT_TYPE_WWPN: 'WWPN', AccessGroup.INIT_TYPE_ISCSI_IQN: 'iSCSI', AccessGroup.INIT_TYPE_ISCSI_WWPN_MIXED: 'iSCSI/WWPN Mixed', } def ag_init_type_to_str(init_type): return _enum_type_to_str(init_type, _AG_INIT_TYPE_CONV) def ag_init_type_str_to_lsm(init_type_str): return _str_to_enum(init_type_str, _AG_INIT_TYPE_CONV) _TGT_PORT_TYPE_CONV = { TargetPort.TYPE_OTHER: 'Other', TargetPort.TYPE_FC: 'FC', TargetPort.TYPE_FCOE: 'FCoE', TargetPort.TYPE_ISCSI: 'iSCSI', } def tgt_port_type_to_str(port_type): return _enum_type_to_str(port_type, _TGT_PORT_TYPE_CONV) def disk_rpm_to_str(rpm): if rpm == '': return "No Support" if rpm == Disk.RPM_NO_SUPPORT: return "No Support" if rpm == Disk.RPM_UNKNOWN: return "Unknown" if rpm == Disk.RPM_NON_ROTATING_MEDIUM: return "Non-Rotating Medium" if rpm == Disk.RPM_ROTATING_UNKNOWN_SPEED: return "Rotating Medium Unknown Speed" return str(rpm) def disk_link_type_to_str(link_type): if link_type == '': return "No Support" return _enum_type_to_str(link_type, LocalDiskInfo._LINK_TYPE_MAP) def disk_health_status_to_str(health_status): if health_status == '': return "No Support" if health_status == Disk.HEALTH_STATUS_UNKNOWN: return "Unknown" if health_status == Disk.HEALTH_STATUS_FAIL: return "Failure" if health_status == Disk.HEALTH_STATUS_WARN: return "Warning" if health_status == Disk.HEALTH_STATUS_GOOD: return "Good" _BATTERY_TYPE_CONV = { Battery.TYPE_UNKNOWN: "Unknown", Battery.TYPE_OTHER: "Other", Battery.TYPE_CHEMICAL: "Chemical", Battery.TYPE_CAPACITOR: "Capacitor", } def battery_type_to_str(battery_type): return _enum_type_to_str(battery_type, _BATTERY_TYPE_CONV) _BATTERY_STATUS_CONV = { Battery.STATUS_UNKNOWN: "Unknown", Battery.STATUS_OTHER: "Other", Battery.STATUS_OK: "OK", Battery.STATUS_DISCHARGING: "Discharging", Battery.STATUS_CHARGING: "Charging", Battery.STATUS_LEARNING: "Learning", Battery.STATUS_DEGRADED: "Degraded", Battery.STATUS_ERROR: "Error", } def battery_status_to_str(battery_status): return _bit_map_to_str(battery_status, _BATTERY_STATUS_CONV) _DISK_LED_STATUS_CONV = { Disk.LED_STATUS_UNKNOWN: 'Unknown', Disk.LED_STATUS_IDENT_ON: 'IDENT_ON', Disk.LED_STATUS_IDENT_OFF: 'IDENT_OFF', Disk.LED_STATUS_IDENT_UNKNOWN: 'IDENT_UNKNOWN', Disk.LED_STATUS_FAULT_ON: 'FAULT_ON', Disk.LED_STATUS_FAULT_OFF: 'FAULT_OFF', Disk.LED_STATUS_FAULT_UNKNOWN: 'FAULT_UNKNOWN', } def disk_led_status_to_str(led_status): return _bit_map_to_str(led_status, _DISK_LED_STATUS_CONV) def disk_link_speed_to_str(link_speed): if link_speed == Disk.LINK_SPEED_UNKNOWN: return "Unknown" return "%.1f Gbps" % float(link_speed / 1000.0) class PlugData(object): def __init__(self, description, plugin_version): self.desc = description self.version = plugin_version class VolumeRAIDInfo(object): _RAID_TYPE_MAP = { Volume.RAID_TYPE_RAID0: 'RAID0', Volume.RAID_TYPE_RAID1: 'RAID1', Volume.RAID_TYPE_RAID3: 'RAID3', Volume.RAID_TYPE_RAID4: 'RAID4', Volume.RAID_TYPE_RAID5: 'RAID5', Volume.RAID_TYPE_RAID6: 'RAID6', Volume.RAID_TYPE_RAID10: 'RAID10', Volume.RAID_TYPE_RAID15: 'RAID15', Volume.RAID_TYPE_RAID16: 'RAID16', Volume.RAID_TYPE_RAID50: 'RAID50', Volume.RAID_TYPE_RAID60: 'RAID60', Volume.RAID_TYPE_RAID51: 'RAID51', Volume.RAID_TYPE_RAID61: 'RAID61', Volume.RAID_TYPE_JBOD: 'JBOD', Volume.RAID_TYPE_MIXED: 'MIXED', Volume.RAID_TYPE_OTHER: 'OTHER', Volume.RAID_TYPE_UNKNOWN: 'UNKNOWN', } VOL_CREATE_RAID_TYPES_STR = [ 'RAID0', 'RAID1', 'RAID5', 'RAID6', 'RAID10', 'RAID50', 'RAID60'] def __init__(self, vol_id, raid_type, strip_size, disk_count, min_io_size, opt_io_size): self.vol_id = vol_id self.raid_type = raid_type self.strip_size = strip_size self.disk_count = disk_count self.min_io_size = min_io_size self.opt_io_size = opt_io_size @staticmethod def raid_type_to_str(raid_type): return _enum_type_to_str(raid_type, VolumeRAIDInfo._RAID_TYPE_MAP) @staticmethod def raid_type_str_to_lsm(raid_type_str): return _str_to_enum(raid_type_str, VolumeRAIDInfo._RAID_TYPE_MAP) class PoolRAIDInfo(object): _MEMBER_TYPE_MAP = { Pool.MEMBER_TYPE_UNKNOWN: 'Unknown', Pool.MEMBER_TYPE_OTHER: 'Unknown', Pool.MEMBER_TYPE_POOL: 'Pool', Pool.MEMBER_TYPE_DISK: 'Disk', } def __init__(self, pool_id, raid_type, member_type, member_ids): self.pool_id = pool_id self.raid_type = raid_type self.member_type = member_type self.member_ids = member_ids @staticmethod def member_type_to_str(member_type): return _enum_type_to_str( member_type, PoolRAIDInfo._MEMBER_TYPE_MAP) class VcrCap(object): def __init__(self, system_id, raid_types, strip_sizes): self.system_id = system_id self.raid_types = raid_types self.strip_sizes = strip_sizes class LocalDiskInfo(object): _LINK_TYPE_MAP = { Disk.LINK_TYPE_NO_SUPPORT: "No Support", Disk.LINK_TYPE_UNKNOWN: "Unknown", Disk.LINK_TYPE_FC: "FC", Disk.LINK_TYPE_SSA: "SSA", Disk.LINK_TYPE_SBP: "SBP", Disk.LINK_TYPE_SRP: "SRP", Disk.LINK_TYPE_ISCSI: "iSCSI", Disk.LINK_TYPE_SAS: "SAS", Disk.LINK_TYPE_ADT: "ADT", Disk.LINK_TYPE_ATA: "PATA/SATA", Disk.LINK_TYPE_USB: "USB", Disk.LINK_TYPE_SOP: "SCSI over PCIE", Disk.LINK_TYPE_PCIE: "PCI-E", } def __init__(self, sd_path, vpd83, rpm, link_type, serial_num, led_status, link_speed, health_status): self.sd_path = sd_path self.vpd83 = vpd83 self.rpm = rpm self.link_type = link_type self.serial_num = serial_num self.led_status = led_status self.link_speed = link_speed self.health_status = health_status class VolumeRAMCacheInfo(object): _PHY_DISK_CACHE_STATUS_MAP = { Volume.PHYSICAL_DISK_CACHE_USE_DISK_SETTING: "Use Disk Setting", Volume.PHYSICAL_DISK_CACHE_ENABLED: "Enabled", Volume.PHYSICAL_DISK_CACHE_DISABLED: "Disabled", Volume.PHYSICAL_DISK_CACHE_UNKNOWN: "Unknown", } _W_CACHE_POLICY_MAP = { Volume.WRITE_CACHE_POLICY_UNKNOWN: "Unknown", Volume.WRITE_CACHE_POLICY_WRITE_BACK: "Write Back", Volume.WRITE_CACHE_POLICY_AUTO: "Auto", Volume.WRITE_CACHE_POLICY_WRITE_THROUGH: "Write Through", } _W_CACHE_STATUS_MAP = { Volume.WRITE_CACHE_STATUS_UNKNOWN: "Unknown", Volume.WRITE_CACHE_STATUS_WRITE_BACK: "Write Back", Volume.WRITE_CACHE_STATUS_WRITE_THROUGH: "Write Through", } _R_CACHE_POLICY_MAP = { Volume.READ_CACHE_POLICY_UNKNOWN: "Unknown", Volume.READ_CACHE_POLICY_ENABLED: "Enabled", Volume.READ_CACHE_POLICY_DISABLED: "Disabled", } _R_CACHE_STATUS_MAP = { Volume.READ_CACHE_STATUS_UNKNOWN: "Unknown", Volume.READ_CACHE_STATUS_ENABLED: "Enabled", Volume.READ_CACHE_STATUS_DISABLED: "Disabled", } def __init__(self, vol_id, write_cache_policy, write_cache_status, read_cache_policy, read_cache_status, phy_disk_cache): self.vol_id = vol_id self.write_cache_policy = write_cache_policy self.write_cache_status = write_cache_status self.read_cache_policy = read_cache_policy self.read_cache_status = read_cache_status self.phy_disk_cache = phy_disk_cache @staticmethod def phy_disk_cache_status_to_str(phy_disk_cache): return _enum_type_to_str( phy_disk_cache, VolumeRAMCacheInfo._PHY_DISK_CACHE_STATUS_MAP) @staticmethod def w_cache_policy_to_str(w_cache_p): return _enum_type_to_str( w_cache_p, VolumeRAMCacheInfo._W_CACHE_POLICY_MAP) @staticmethod def w_cache_status_to_str(w_cache_status): return _enum_type_to_str( w_cache_status, VolumeRAMCacheInfo._W_CACHE_STATUS_MAP) @staticmethod def r_cache_policy_to_str(r_cache_p): return _enum_type_to_str( r_cache_p, VolumeRAMCacheInfo._R_CACHE_POLICY_MAP) @staticmethod def r_cache_status_to_str(r_cache_status): return _enum_type_to_str( r_cache_status, VolumeRAMCacheInfo._R_CACHE_STATUS_MAP) class DisplayData(object): def __init__(self): pass DISPLAY_WAY_COLUMN = 0 DISPLAY_WAY_SCRIPT = 1 DISPLAY_WAY_DEFAULT = DISPLAY_WAY_COLUMN DEFAULT_SPLITTER = ' | ' VALUE_CONVERT = {} # lsm.System SYSTEM_HEADER = OrderedDict() SYSTEM_HEADER['id'] = 'ID' SYSTEM_HEADER['name'] = 'Name' SYSTEM_HEADER['status'] = 'Status' SYSTEM_HEADER['status_info'] = 'Info' SYSTEM_HEADER['fw_version'] = "FW Ver" SYSTEM_HEADER['mode'] = "Mode" SYSTEM_HEADER['read_cache_pct'] = "Read Cache Percentage" SYSTEM_COLUMN_SKIP_KEYS = [] # XXX_COLUMN_SKIP_KEYS contain a list of property should be skipped when # displaying in column way. SYSTEM_VALUE_CONV_ENUM = { 'status': system_status_to_str, 'mode': system_mode_to_str, } SYSTEM_VALUE_CONV_HUMAN = [] VALUE_CONVERT[System] = { 'headers': SYSTEM_HEADER, 'column_skip_keys': SYSTEM_COLUMN_SKIP_KEYS, 'value_conv_enum': SYSTEM_VALUE_CONV_ENUM, 'value_conv_human': SYSTEM_VALUE_CONV_HUMAN, } PLUG_DATA_HEADER = OrderedDict() PLUG_DATA_HEADER['desc'] = 'Description' PLUG_DATA_HEADER['version'] = 'Version' PLUG_DATA_COLUMN_SKIP_KEYS = [] PLUG_DATA_VALUE_CONV_ENUM = {} PLUG_DATA_VALUE_CONV_HUMAN = [] VALUE_CONVERT[PlugData] = { 'headers': PLUG_DATA_HEADER, 'column_skip_keys': PLUG_DATA_COLUMN_SKIP_KEYS, 'value_conv_enum': PLUG_DATA_VALUE_CONV_ENUM, 'value_conv_human': PLUG_DATA_VALUE_CONV_HUMAN, } # lsm.Pool POOL_HEADER = OrderedDict() POOL_HEADER['id'] = 'ID' POOL_HEADER['name'] = 'Name' POOL_HEADER['element_type'] = 'Element Type' POOL_HEADER['unsupported_actions'] = 'Does not support' POOL_HEADER['total_space'] = 'Total Space' POOL_HEADER['free_space'] = 'Free Space' POOL_HEADER['status'] = 'Status' POOL_HEADER['status_info'] = 'Info' POOL_HEADER['system_id'] = 'System ID' POOL_COLUMN_SKIP_KEYS = ['unsupported_actions'] POOL_VALUE_CONV_ENUM = { 'status': pool_status_to_str, 'element_type': pool_element_type_to_str, 'unsupported_actions': pool_unsupported_actions_to_str } POOL_VALUE_CONV_HUMAN = ['total_space', 'free_space'] VALUE_CONVERT[Pool] = { 'headers': POOL_HEADER, 'column_skip_keys': POOL_COLUMN_SKIP_KEYS, 'value_conv_enum': POOL_VALUE_CONV_ENUM, 'value_conv_human': POOL_VALUE_CONV_HUMAN, } # lsm.Volume VOL_HEADER = OrderedDict() VOL_HEADER['id'] = 'ID' VOL_HEADER['name'] = 'Name' VOL_HEADER['vpd83'] = 'SCSI VPD 0x83' VOL_HEADER['block_size'] = 'Block Size' VOL_HEADER['num_of_blocks'] = 'Block Count' VOL_HEADER['size_bytes'] = 'Size' VOL_HEADER['admin_state'] = 'Disabled' VOL_HEADER['pool_id'] = 'Pool ID' VOL_HEADER['system_id'] = 'System ID' VOL_HEADER['sd_paths'] = 'Disk Paths' # This is appended by cmdline.py VOL_COLUMN_SKIP_KEYS = ['block_size', 'num_of_blocks'] VOL_VALUE_CONV_ENUM = { 'admin_state': vol_admin_state_to_str } VOL_VALUE_CONV_HUMAN = ['size_bytes', 'block_size'] VALUE_CONVERT[Volume] = { 'headers': VOL_HEADER, 'column_skip_keys': VOL_COLUMN_SKIP_KEYS, 'value_conv_enum': VOL_VALUE_CONV_ENUM, 'value_conv_human': VOL_VALUE_CONV_HUMAN, } # lsm.Disk DISK_HEADER = OrderedDict() DISK_HEADER['id'] = 'ID' DISK_HEADER['name'] = 'Name' DISK_HEADER['disk_type'] = 'Type' DISK_HEADER['block_size'] = 'Block Size' DISK_HEADER['num_of_blocks'] = 'Block Count' DISK_HEADER['size_bytes'] = 'Size' DISK_HEADER['status'] = 'Status' DISK_HEADER['system_id'] = 'System ID' DISK_HEADER['vpd83'] = 'SCSI VPD 0x83' DISK_HEADER['sd_paths'] = 'Disk Paths' # This is appended by cmdline.py DISK_HEADER['rpm'] = 'Revolutions Per Minute' DISK_HEADER['link_type'] = 'Link Type' DISK_HEADER['location'] = 'Location' DISK_COLUMN_SKIP_KEYS = ['block_size', 'num_of_blocks', 'location'] DISK_VALUE_CONV_ENUM = { 'status': disk_status_to_str, 'disk_type': disk_type_to_str, 'rpm': disk_rpm_to_str, 'link_type': disk_link_type_to_str, } DISK_VALUE_CONV_HUMAN = ['size_bytes', 'block_size'] VALUE_CONVERT[Disk] = { 'headers': DISK_HEADER, 'column_skip_keys': DISK_COLUMN_SKIP_KEYS, 'value_conv_enum': DISK_VALUE_CONV_ENUM, 'value_conv_human': DISK_VALUE_CONV_HUMAN, } # lsm.AccessGroup AG_HEADER = OrderedDict() AG_HEADER['id'] = 'ID' AG_HEADER['name'] = 'Name' AG_HEADER['init_ids'] = 'Initiator IDs' AG_HEADER['init_type'] = 'Type' AG_HEADER['system_id'] = 'System ID' AG_COLUMN_SKIP_KEYS = ['init_type'] AG_VALUE_CONV_ENUM = { 'init_type': ag_init_type_to_str, } AG_VALUE_CONV_HUMAN = [] VALUE_CONVERT[AccessGroup] = { 'headers': AG_HEADER, 'column_skip_keys': AG_COLUMN_SKIP_KEYS, 'value_conv_enum': AG_VALUE_CONV_ENUM, 'value_conv_human': AG_VALUE_CONV_HUMAN, } # lsm.FileSystem FS_HEADER = OrderedDict() FS_HEADER['id'] = 'ID' FS_HEADER['name'] = 'Name' FS_HEADER['total_space'] = 'Total Space' FS_HEADER['free_space'] = 'Free Space' FS_HEADER['pool_id'] = 'Pool ID' FS_HEADER['system_id'] = 'System ID' FS_COLUMN_SKIP_KEYS = [] FS_VALUE_CONV_ENUM = { } FS_VALUE_CONV_HUMAN = ['total_space', 'free_space'] VALUE_CONVERT[FileSystem] = { 'headers': FS_HEADER, 'column_skip_keys': FS_COLUMN_SKIP_KEYS, 'value_conv_enum': FS_VALUE_CONV_ENUM, 'value_conv_human': FS_VALUE_CONV_HUMAN, } # lsm.FsSnapshot FS_SNAP_HEADER = OrderedDict() FS_SNAP_HEADER['id'] = 'ID' FS_SNAP_HEADER['name'] = 'Name' FS_SNAP_HEADER['ts'] = 'Time Stamp' FS_SNAP_COLUMN_SKIP_KEYS = [] FS_SNAP_VALUE_CONV_ENUM = { 'ts': datetime.fromtimestamp } FS_SNAP_VALUE_CONV_HUMAN = [] VALUE_CONVERT[FsSnapshot] = { 'headers': FS_SNAP_HEADER, 'column_skip_keys': FS_SNAP_COLUMN_SKIP_KEYS, 'value_conv_enum': FS_SNAP_VALUE_CONV_ENUM, 'value_conv_human': FS_SNAP_VALUE_CONV_HUMAN, } # lsm.NfsExport NFS_EXPORT_HEADER = OrderedDict() NFS_EXPORT_HEADER['id'] = 'ID' NFS_EXPORT_HEADER['fs_id'] = 'FileSystem ID' NFS_EXPORT_HEADER['export_path'] = 'Export Path' NFS_EXPORT_HEADER['auth'] = 'Auth Type' NFS_EXPORT_HEADER['root'] = 'Root Hosts' NFS_EXPORT_HEADER['rw'] = 'RW Hosts' NFS_EXPORT_HEADER['ro'] = 'RO Hosts' NFS_EXPORT_HEADER['anonuid'] = 'Anonymous UID' NFS_EXPORT_HEADER['anongid'] = 'Anonymous GID' NFS_EXPORT_HEADER['options'] = 'Options' NFS_EXPORT_COLUMN_SKIP_KEYS = ['anonuid', 'anongid', 'auth'] NFS_EXPORT_VALUE_CONV_ENUM = {} NFS_EXPORT_VALUE_CONV_HUMAN = [] VALUE_CONVERT[NfsExport] = { 'headers': NFS_EXPORT_HEADER, 'column_skip_keys': NFS_EXPORT_COLUMN_SKIP_KEYS, 'value_conv_enum': NFS_EXPORT_VALUE_CONV_ENUM, 'value_conv_human': NFS_EXPORT_VALUE_CONV_HUMAN, } # lsm.TargetPort TGT_PORT_HEADER = OrderedDict() TGT_PORT_HEADER['id'] = 'ID' TGT_PORT_HEADER['port_type'] = 'Type' TGT_PORT_HEADER['physical_name'] = 'Physical Name' TGT_PORT_HEADER['service_address'] = 'Address' TGT_PORT_HEADER['network_address'] = 'Network Address' TGT_PORT_HEADER['physical_address'] = 'Physical Address' TGT_PORT_HEADER['system_id'] = 'System ID' TGT_PORT_COLUMN_SKIP_KEYS = ['physical_address', 'physical_name'] TGT_PORT_VALUE_CONV_ENUM = { 'port_type': tgt_port_type_to_str, } TGT_PORT_VALUE_CONV_HUMAN = [] VALUE_CONVERT[TargetPort] = { 'headers': TGT_PORT_HEADER, 'column_skip_keys': TGT_PORT_COLUMN_SKIP_KEYS, 'value_conv_enum': TGT_PORT_VALUE_CONV_ENUM, 'value_conv_human': TGT_PORT_VALUE_CONV_HUMAN, } VOL_RAID_INFO_HEADER = OrderedDict() VOL_RAID_INFO_HEADER['vol_id'] = 'Volume ID' VOL_RAID_INFO_HEADER['raid_type'] = 'RAID Type' VOL_RAID_INFO_HEADER['strip_size'] = 'Strip Size' VOL_RAID_INFO_HEADER['disk_count'] = 'Disk Count' VOL_RAID_INFO_HEADER['min_io_size'] = 'Minimum I/O Size' VOL_RAID_INFO_HEADER['opt_io_size'] = 'Optimal I/O Size' VOL_RAID_INFO_COLUMN_SKIP_KEYS = [] VOL_RAID_INFO_VALUE_CONV_ENUM = { 'raid_type': VolumeRAIDInfo.raid_type_to_str, } VOL_RAID_INFO_VALUE_CONV_HUMAN = [ 'strip_size', 'min_io_size', 'opt_io_size'] VALUE_CONVERT[VolumeRAIDInfo] = { 'headers': VOL_RAID_INFO_HEADER, 'column_skip_keys': VOL_RAID_INFO_COLUMN_SKIP_KEYS, 'value_conv_enum': VOL_RAID_INFO_VALUE_CONV_ENUM, 'value_conv_human': VOL_RAID_INFO_VALUE_CONV_HUMAN, } POOL_RAID_INFO_HEADER = OrderedDict() POOL_RAID_INFO_HEADER['pool_id'] = 'Pool ID' POOL_RAID_INFO_HEADER['raid_type'] = 'RAID Type' POOL_RAID_INFO_HEADER['member_type'] = 'Member Type' POOL_RAID_INFO_HEADER['member_ids'] = 'Member IDs' POOL_RAID_INFO_COLUMN_SKIP_KEYS = [] POOL_RAID_INFO_VALUE_CONV_ENUM = { 'raid_type': VolumeRAIDInfo.raid_type_to_str, 'member_type': PoolRAIDInfo.member_type_to_str, } POOL_RAID_INFO_VALUE_CONV_HUMAN = [] VALUE_CONVERT[PoolRAIDInfo] = { 'headers': POOL_RAID_INFO_HEADER, 'column_skip_keys': POOL_RAID_INFO_COLUMN_SKIP_KEYS, 'value_conv_enum': POOL_RAID_INFO_VALUE_CONV_ENUM, 'value_conv_human': POOL_RAID_INFO_VALUE_CONV_HUMAN, } VCR_CAP_HEADER = OrderedDict() VCR_CAP_HEADER['system_id'] = 'System ID' VCR_CAP_HEADER['raid_types'] = 'Supported RAID Types' VCR_CAP_HEADER['strip_sizes'] = 'Supported Strip Sizes' VCR_CAP_COLUMN_SKIP_KEYS = [] VCR_CAP_VALUE_CONV_ENUM = { 'raid_types': lambda i: [VolumeRAIDInfo.raid_type_to_str(x) for x in i] } VCR_CAP_VALUE_CONV_HUMAN = ['strip_sizes'] VALUE_CONVERT[VcrCap] = { 'headers': VCR_CAP_HEADER, 'column_skip_keys': VCR_CAP_COLUMN_SKIP_KEYS, 'value_conv_enum': VCR_CAP_VALUE_CONV_ENUM, 'value_conv_human': VCR_CAP_VALUE_CONV_HUMAN, } LOCAL_DISK_HEADER = OrderedDict() LOCAL_DISK_HEADER['sd_path'] = 'Path' LOCAL_DISK_HEADER['vpd83'] = 'SCSI VPD 0x83' LOCAL_DISK_HEADER['rpm'] = 'Revolutions Per Minute' LOCAL_DISK_HEADER['link_type'] = 'Link Type' LOCAL_DISK_HEADER['serial_num'] = 'Serial Number' LOCAL_DISK_HEADER['led_status'] = 'LED Status' LOCAL_DISK_HEADER['link_speed'] = 'Link Speed' LOCAL_DISK_HEADER['health_status'] = 'Health Status' LOCAL_DISK_COLUMN_SKIP_KEYS = ['rpm', 'led_status', 'link_speed'] LOCAL_DISK_VALUE_CONV_ENUM = { 'rpm': disk_rpm_to_str, 'link_type': disk_link_type_to_str, 'led_status': disk_led_status_to_str, 'link_speed': disk_link_speed_to_str, 'health_status': disk_health_status_to_str, } LOCAL_DISK_VALUE_CONV_HUMAN = [] VALUE_CONVERT[LocalDiskInfo] = { 'headers': LOCAL_DISK_HEADER, 'column_skip_keys': LOCAL_DISK_COLUMN_SKIP_KEYS, 'value_conv_enum': LOCAL_DISK_VALUE_CONV_ENUM, 'value_conv_human': LOCAL_DISK_VALUE_CONV_HUMAN, } BATTERY_HEADER = OrderedDict() BATTERY_HEADER['id'] = 'ID' BATTERY_HEADER['name'] = 'Name' BATTERY_HEADER['type'] = 'Type' BATTERY_HEADER['status'] = 'Status' BATTERY_HEADER['system_id'] = 'System ID' BATTERY_COLUMN_SKIP_KEYS = [] BATTERY_VALUE_CONV_ENUM = { 'type': battery_type_to_str, 'status': battery_status_to_str, } BATTERY_VALUE_CONV_HUMAN = [''] VALUE_CONVERT[Battery] = { 'headers': BATTERY_HEADER, 'column_skip_keys': BATTERY_COLUMN_SKIP_KEYS, 'value_conv_enum': BATTERY_VALUE_CONV_ENUM, 'value_conv_human': BATTERY_VALUE_CONV_HUMAN, } VOL_CACHE_INFO_HEADER = OrderedDict() VOL_CACHE_INFO_HEADER['vol_id'] = 'Volume ID' VOL_CACHE_INFO_HEADER['write_cache_policy'] = 'Write Cache Policy' VOL_CACHE_INFO_HEADER['write_cache_status'] = 'Write Cache' VOL_CACHE_INFO_HEADER['read_cache_policy'] = 'Read Cache Policy' VOL_CACHE_INFO_HEADER['read_cache_status'] = 'Read Cache' VOL_CACHE_INFO_HEADER['phy_disk_cache'] = 'Physical Disk Cache' VOL_CACHE_INFO_COLUMN_SKIP_KEYS = [] VOL_CACHE_INFO_VALUE_CONV_ENUM = { 'write_cache_policy': VolumeRAMCacheInfo.w_cache_policy_to_str, 'write_cache_status': VolumeRAMCacheInfo.w_cache_status_to_str, 'read_cache_policy': VolumeRAMCacheInfo.r_cache_policy_to_str, 'read_cache_status': VolumeRAMCacheInfo.r_cache_status_to_str, 'phy_disk_cache': VolumeRAMCacheInfo.phy_disk_cache_status_to_str, } VOL_CACHE_INFO_VALUE_CONV_HUMAN = [] VALUE_CONVERT[VolumeRAMCacheInfo] = { 'headers': VOL_CACHE_INFO_HEADER, 'column_skip_keys': VOL_CACHE_INFO_COLUMN_SKIP_KEYS, 'value_conv_enum': VOL_CACHE_INFO_VALUE_CONV_ENUM, 'value_conv_human': VOL_CACHE_INFO_VALUE_CONV_HUMAN, } @staticmethod def _get_man_pro_value(obj, key, value_conv_enum, value_conv_human, flag_human, flag_enum): try: value = getattr(obj, key) except LsmError as lsm_err: if lsm_err.code == ErrorNumber.NO_SUPPORT: value = '' else: raise lsm_err if not flag_enum: if key in list(value_conv_enum.keys()): value = value_conv_enum[key](value) if flag_human: if key in value_conv_human: if type(value) is list: value = list(size_bytes_2_size_human(s) for s in value) else: value = size_bytes_2_size_human(value) return value @staticmethod def _find_max_width(two_d_list, column_index): max_width = 1 for row_index in range(0, len(two_d_list)): row_data = two_d_list[row_index] if len(row_data[column_index]) > max_width: max_width = len(row_data[column_index]) return max_width @staticmethod def _data_dict_gen(obj, flag_human, flag_enum, display_way, extra_properties=None, flag_dsp_all_data=False): data_dict = OrderedDict() value_convert = DisplayData.VALUE_CONVERT[type(obj)] headers = value_convert['headers'] value_conv_enum = value_convert['value_conv_enum'] value_conv_human = value_convert['value_conv_human'] if flag_dsp_all_data: display_way = DisplayData.DISPLAY_WAY_SCRIPT display_keys = [] if display_way == DisplayData.DISPLAY_WAY_COLUMN: for key_name in list(headers.keys()): if key_name not in value_convert['column_skip_keys']: display_keys.append(key_name) elif display_way == DisplayData.DISPLAY_WAY_SCRIPT: display_keys = list(headers.keys()) if extra_properties: for extra_key_name in extra_properties: if extra_key_name not in display_keys: display_keys.append(extra_key_name) for key in display_keys: key_str = headers[key] value = DisplayData._get_man_pro_value( obj, key, value_conv_enum, value_conv_human, flag_human, flag_enum) data_dict[key_str] = value return data_dict @staticmethod def display_data(objs, display_way=None, flag_human=True, flag_enum=False, extra_properties=None, splitter=None, flag_with_header=True, flag_dsp_all_data=False): if len(objs) == 0: return None if display_way is None: display_way = DisplayData.DISPLAY_WAY_DEFAULT if splitter is None: splitter = DisplayData.DEFAULT_SPLITTER data_dict_list = [] if type(objs[0]) in list(DisplayData.VALUE_CONVERT.keys()): for obj in objs: data_dict = DisplayData._data_dict_gen( obj, flag_human, flag_enum, display_way, extra_properties, flag_dsp_all_data) data_dict_list.extend([data_dict]) else: return None if display_way == DisplayData.DISPLAY_WAY_SCRIPT: DisplayData.display_data_script_way(data_dict_list, splitter) elif display_way == DisplayData.DISPLAY_WAY_COLUMN: DisplayData._display_data_column_way( data_dict_list, splitter, flag_with_header) return True @staticmethod def display_data_script_way(data_dict_list, splitter): key_column_width = 1 value_column_width = 1 for data_dict in data_dict_list: for key_name in list(data_dict.keys()): # find the max column width of key cur_key_width = len(key_name) if cur_key_width > key_column_width: key_column_width = cur_key_width # find the max column width of value cur_value = data_dict[key_name] if isinstance(cur_value, list): if len(cur_value) == 0: continue cur_value_width = len(str(cur_value[0])) else: cur_value_width = len(str(cur_value)) if cur_value_width > value_column_width: value_column_width = cur_value_width row_format = '%%-%ds%s%%-%ds' % (key_column_width, splitter, value_column_width) sub_row_format = '%s%s%%-%ds' % (' ' * key_column_width, splitter, value_column_width) obj_splitter = '%s%s%s' % ('-' * key_column_width, '-' * len(splitter), '-' * value_column_width) for data_dict in data_dict_list: out(obj_splitter) for key_name in data_dict: value = data_dict[key_name] if isinstance(value, list): flag_first_data = True for sub_value in value: if flag_first_data: out(row_format % (key_name, str(sub_value))) flag_first_data = False else: out(sub_row_format % str(sub_value)) else: out(row_format % (key_name, str(value))) out(obj_splitter) @staticmethod def _display_data_column_way(data_dict_list, splitter, flag_with_header): if len(data_dict_list) == 0: return two_d_list = [] item_count = len(list(data_dict_list[0].keys())) # determine how many lines we will print row_width = 0 for data_dict in data_dict_list: cur_max_wd = 0 for key_name in list(data_dict.keys()): if isinstance(data_dict[key_name], list): cur_row_width = len(data_dict[key_name]) if cur_row_width > cur_max_wd: cur_max_wd = cur_row_width else: pass if cur_max_wd == 0: cur_max_wd = 1 row_width += cur_max_wd if flag_with_header: # first line for header row_width += 1 # init 2D list for raw in range(0, row_width): new = [] for column in range(0, item_count): new.append('') two_d_list.append(new) # header current_row_num = -1 if flag_with_header: two_d_list[0] = list(data_dict_list[0].keys()) current_row_num = 0 # Fill the 2D list with data_dict_list for data_dict in data_dict_list: current_row_num += 1 save_row_num = current_row_num values = list(data_dict.values()) for index in range(0, len(values)): value = values[index] if isinstance(value, list): for sub_index in range(0, len(value)): tmp_row_num = save_row_num + sub_index two_d_list[tmp_row_num][index] = str(value[sub_index]) if save_row_num + len(value) > current_row_num: current_row_num = save_row_num + len(value) - 1 else: two_d_list[save_row_num][index] = str(value) # display two_list row_formats = [] header_splitter = '' for column_index in range(0, len(two_d_list[0])): max_width = DisplayData._find_max_width(two_d_list, column_index) row_formats.extend(['%%-%ds' % max_width]) header_splitter += '-' * max_width if column_index != (len(two_d_list[0]) - 1): header_splitter += '-' * len(splitter) row_format = splitter.join(row_formats) for row_index in range(0, len(two_d_list)): out(row_format % tuple(two_d_list[row_index])) if row_index == 0 and flag_with_header: out(header_splitter) cmdline.py000064400000216125147576777270006575 0ustar00# Copyright (C) 2012-2016 Red Hat, Inc. # (C) Copyright 2017 Hewlett Packard Enterprise Development LP # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; If not, see . # # Author: tasleson # Gris Ge import os import sys import getpass import re import time import tty import termios from argparse import ArgumentParser, ArgumentTypeError from argparse import RawTextHelpFormatter import six from lsm import (Client, Pool, VERSION, LsmError, Disk, Volume, JobStatus, ErrorNumber, BlockRange, uri_parse, Proxy, size_human_2_size_bytes, AccessGroup, FileSystem, NfsExport, TargetPort, LocalDisk, Battery) from lsm.lsmcli.data_display import ( DisplayData, PlugData, out, vol_provision_str_to_type, vol_rep_type_str_to_type, VolumeRAIDInfo, PoolRAIDInfo, VcrCap, LocalDiskInfo, VolumeRAMCacheInfo) _CONNECTION_FREE_COMMANDS = ['local-disk-list', 'local-disk-ident-led-on', 'local-disk-ident-led-off', 'local-disk-fault-led-on', 'local-disk-fault-led-off'] if six.PY3: long = int try: from collections import OrderedDict except ImportError: # python 2.6 or earlier, use backport # noinspection PyUnresolvedReferences from ordereddict import OrderedDict # Wraps the invocation to the command line # @param c Object to invoke calls on (optional) def cmd_line_wrapper(c=None): """ Common command line code, called. """ err_exit = 0 cli = None try: cli = CmdLine() cli.process(c) except ArgError as ae: sys.stderr.write(str(ae)) sys.stderr.flush() err_exit = 2 except LsmError as le: sys.stderr.write(str(le) + "\n") sys.stderr.flush() if le.code == ErrorNumber.PERMISSION_DENIED: err_exit = 13 # common error code for EACCES else: err_exit = 4 except KeyboardInterrupt: err_exit = 1 except SystemExit as se: # argparse raises a SystemExit err_exit = se.code except: import traceback traceback.print_exc(file=sys.stdout) # We get *any* other exception don't return a successful error code err_exit = 2 finally: # Regardless of what happens, we will try to close the connection if # possible to allow the plugin to clean up gracefully. if cli: try: # This will exit if are successful cli.shutdown(err_exit) except Exception: pass sys.exit(err_exit) # Get a character from stdin without needing a return key pressed. # Returns the character pressed def getch(): fd = sys.stdin.fileno() prev = termios.tcgetattr(fd) try: tty.setraw(sys.stdin.fileno()) ch = sys.stdin.read(1) finally: termios.tcsetattr(fd, termios.TCSADRAIN, prev) return ch def parse_convert_init(init_id): """ If init_id is a WWPN, convert it into LSM standard version: (?:[0-9a-f]{2}:){7}[0-9a-f]{2} Return (converted_init_id, lsm_init_type) """ valid, converted_init_type, converted_init_id = \ AccessGroup.initiator_id_verify(init_id) if valid: return converted_init_id, converted_init_type raise ArgError("--init \"%s\" is not a valid WWPN or iSCSI IQN" % init_id) def _check_init(init_id): """ Call back from validating an initiator :param init_id: Initiator to validate :return: Value of initiator or raises an exception """ valid, _, converted_init_id = \ AccessGroup.initiator_id_verify(init_id) if valid: return converted_init_id raise ArgumentTypeError("\"%s\" is invalid WWPN or iSCSI IQN" % init_id) def _check_positive_integer(num): """ Call back for validating a positive integer :param num: Number string to check :return: Numeric value, else exception """ try: rc = long(num, 10) if rc < 0: raise ArgumentTypeError( "invalid: require positive integer value '%d'" % rc) return rc except ValueError: raise ArgumentTypeError( "invalid: not a positive integer value '%s'" % num) _CHILD_OPTION_DST_PREFIX = 'child_' def _upper(s): return s.upper() def _valid_ip4_address(address): """ Check if a string represents a valid ip4 address :param address: String representing address :return: True if valid address, else false """ if not address: return False parts = address.split('.') if len(parts) != 4: return False if '/' in address: return False for i in parts: if not 0 < len(i) <= 3: return False if len(i) > 1 and i[0] == '0': return False try: if int(i, 10) > 255: return False except ValueError: return False return True def _valid_ip6_address(address): """ Check if a string represents a valid ipv6 address :param address: String representing address :return: True if valid address, else false """ allowed = 'ABCDEFabcdef0123456789:' has_zeros = False if not address: return False if '/' in address: return False if len(address.split("::")) > 2: return False parts = address.split(':') if len(parts) < 3 or len(parts) > 9: return False # Check for ipv4 suffix, validate and remove while adding padding for # addl. checks. if '.' in parts[-1]: if not _valid_ip4_address(parts.pop()): print("Not valid ipv suffix") return False parts.extend(['0', '0']) if '::' in address: parts = [p for p in parts if p != ''] # Add one segment of zero to catch full address with extra ':' parts.append('0') has_zeros = True if (has_zeros and len(parts) <= 8) or len(parts) == 8: return all(len(x) <= 4 for x in parts) and \ all(x in allowed for x in "".join(parts)) return False def _is_valid_network_name(ip_hn): """ Checks to see if the supplied string is a valid ip4/6 or hostname :param ip_hn: String representing address user inputted :return: True if valid IP address or hostname """ allowed = re.compile("(?!-)[A-Z0-9-]{1,63}(? 255: return False # A hostname cannot exist with only digits per spec. as that is confusing # for distinguishing IP from hostname if digits_only.match(ip_hn): return False if ip_hn[-1] == ".": ip_hn = ip_hn[:-1] # Yes, absolute hostnames have a trailing dot! return all(allowed.match(x) for x in ip_hn.split(".")) def _add_common_options(arg_parser, is_child=False): """ As https://bugs.python.org/issue23058 indicate, argument parser should not have subparser sharing the same argument and destination. For subparser, we add common options as 'child_xxx' destination. For default value, False is the only allowed default value in root. """ prefix = '' if is_child: prefix = _CHILD_OPTION_DST_PREFIX arg_parser.add_argument( '-v', '--version', action='version', version="%s %s" % (sys.argv[0], VERSION)) arg_parser.add_argument( '-u', '--uri', action="store", type=str, metavar='', dest="%suri" % prefix, help='Uniform resource identifier (env LSMCLI_URI)') arg_parser.add_argument( '-P', '--prompt', action="store_true", dest="%sprompt" % prefix, help='Prompt for password (env LSMCLI_PASSWORD)') arg_parser.add_argument( '-H', '--human', action="store_true", dest="%shuman" % prefix, help='Print sizes in human readable format\n' '(e.g., MiB, GiB, TiB)') arg_parser.add_argument( '-t', '--terse', action="store", dest="%ssep" % prefix, metavar='', help='Print output in terse form with "SEP" ' 'as a record separator') arg_parser.add_argument( '-e', '--enum', action="store_true", dest="%senum" % prefix, default=False, help='Display enumerated types as numbers instead of text') arg_parser.add_argument( '-f', '--force', action="store_true", dest="%sforce" % prefix, default=False, help='Bypass confirmation prompt for data loss operations') arg_parser.add_argument( '-w', '--wait', action="store", dest="%swait" % prefix, help="Command timeout value in ms (default = 30s)", type=_check_positive_integer) arg_parser.add_argument( '--header', action="store_true", dest="%sheader" % prefix, help='Include the header with terse') arg_parser.add_argument( '-b', action="store_true", dest="%s_async" % prefix, default=False, help='Run the command async. Instead of waiting for completion.\n ' 'Command will exit(7) and job id written to stdout.') arg_parser.add_argument( '-s', '--script', action="store_true", dest="%sscript" % prefix, default=False, help='Displaying data in script friendly way with ' 'additional information(if exists)') if is_child: default_dict = dict() default_dict['%swait' % prefix] = 30000 arg_parser.set_defaults(**default_dict) def _add_sd_paths(lsm_obj): lsm_obj.sd_paths = [] try: if len(lsm_obj.vpd83) > 0: lsm_obj.sd_paths = LocalDisk.vpd83_search(lsm_obj.vpd83) except LsmError as lsm_err: if lsm_err.code != ErrorNumber.NO_SUPPORT: raise return lsm_obj # This class represents a command line argument error class ArgError(Exception): def __init__(self, message, *args, **kwargs): """ Class represents an error. """ Exception.__init__(self, *args, **kwargs) self.msg = message def __str__(self): return "%s: error: %s\n" % (os.path.basename(sys.argv[0]), self.msg) # Finds an item based on the id. Each list item requires a member "id" # @param l list to search # @param the_id the id to match # @param friendly_name - name to put in the exception saying what we # couldn't find def _get_item(l, the_id, friendly_name='item', raise_error=True): for item in l: if item.id == the_id: return item if raise_error: raise ArgError('%s with ID %s not found!' % (friendly_name, the_id)) else: return None def _check_network_host(addr): """ Custom value checker for hostname/IP address :param addr: :return: """ valid = _is_valid_network_name(addr) if valid: return addr raise ArgumentTypeError("%s is invalid IP or hostname" % addr) list_choices = ['VOLUMES', 'POOLS', 'FS', 'SNAPSHOTS', 'EXPORTS', "NFS_CLIENT_AUTH", 'ACCESS_GROUPS', 'SYSTEMS', 'DISKS', 'PLUGINS', 'TARGET_PORTS', 'BATTERIES'] provision_types = ('DEFAULT', 'THIN', 'FULL') provision_help = "provisioning type: " + ", ".join(provision_types) replicate_types = ('CLONE', 'COPY', 'MIRROR_ASYNC', 'MIRROR_SYNC') replicate_help = "replication type: " + ", ".join(replicate_types) policy_types = ['ENABLE', 'DISABLE'] policy_help = 'Policy: ' + ', '.join(policy_types) policy_opt = dict(name="--policy", metavar='', help=policy_help, choices=policy_types, type=_upper) write_cache_policy_types = ['WB', 'AUTO', 'WT'] write_cache_policy_help = 'Write cache polices: ' + \ ', '.join(write_cache_policy_types) + \ ' which stand for "write back", "auto", ' + \ '"write through"' write_cache_policy_opt = dict(name="--policy", metavar='', help=write_cache_policy_help, choices=write_cache_policy_types, type=_upper) size_help = 'Can use B, KiB, MiB, GiB, TiB, PiB postfix (IEC sizing)' sys_id_opt = dict(name='--sys', metavar='', help='System ID') sys_id_filter_opt = sys_id_opt.copy() sys_id_filter_opt['help'] = \ 'Search by System ID. Only supported for: \n' \ '(VOLUMES, POOLS, FS, DISKS, ACCESS_GROUPS,\n' \ 'TARGET_PORTS, BATTERIES)' pool_id_opt = dict(name='--pool', metavar='', help='Pool ID') pool_id_filter_opt = pool_id_opt.copy() pool_id_filter_opt['help'] = \ 'Search by Pool ID. Only supported for:\n' \ '(VOLUMES, POOLS, FS)' vol_id_opt = dict(name='--vol', metavar='', help='Volume ID') vol_id_filter_opt = vol_id_opt.copy() vol_id_filter_opt['help'] = \ 'Search by Volume ID. Only supported for:\n' \ '(VOLUMES, ACCESS_GROUPS)' fs_id_opt = dict(name='--fs', metavar='', help='File System ID') fs_id_filter_opt = fs_id_opt.copy() fs_id_filter_opt['help'] = \ 'Search by FS ID. Only supported for:\n' \ '(FS, SNAPSHOTS, EXPORTS)' ag_id_opt = dict(name='--ag', metavar='', help='Access Group ID') ag_id_filter_opt = ag_id_opt.copy() ag_id_filter_opt['help'] = \ 'Search by Access Group ID. Only supported for:\n' \ '(ACCESS_GROUPS, VOLUMES)' init_id_opt = dict(name='--init', metavar='', help='Initiator ID', type=_check_init) snap_id_opt = dict(name='--snap', metavar='', help='Snapshot ID') export_id_opt = dict(name='--export', metavar='', help='Export ID') nfs_export_id_filter_opt = dict( name='--nfs-export', metavar='', help= 'Search by NFS Export ID. Only supported for:\n' '(EXPORTS)') disk_id_filter_opt = dict(name='--disk', metavar='', help='Search by Disk ID. Only supported for:\n' '(DISKS)') size_opt = dict(name='--size', metavar='', help=size_help) tgt_id_filter_opt = dict(name="--tgt", metavar='', help="Search by target port ID. Only supported for:\n" "(TARGET_PORTS)") local_disk_path_opt = dict(name='--path', help="Local disk path", metavar='') cmds = ( dict( name='list', help="List records of different types", args=[ dict(name='--type', help="List records of type:\n " + "\n ".join(list_choices) + "\n\nWhen listing SNAPSHOTS, it requires --fs .", metavar='', choices=list_choices, type=_upper), ], optional=[ dict(sys_id_filter_opt), dict(pool_id_filter_opt), dict(vol_id_filter_opt), dict(disk_id_filter_opt), dict(ag_id_filter_opt), dict(fs_id_filter_opt), dict(nfs_export_id_filter_opt), dict(tgt_id_filter_opt), ], ), dict( name='job-status', help='Retrieve information about a job', args=[ dict(name="--job", metavar="", help='job status id'), ], ), dict( name='capabilities', help='Retrieves array capabilities', args=[ dict(sys_id_opt), ], ), dict( name='plugin-info', help='Retrieves plugin description and version', ), dict( name='volume-create', help='Creates a volume (logical unit)', args=[ dict(name="--name", help='volume name', metavar=''), dict(size_opt), dict(pool_id_opt), ], optional=[ dict(name="--provisioning", help=provision_help, default='DEFAULT', choices=provision_types, type=_upper), ], ), dict( name='volume-raid-create', help='Creates a RAIDed volume on hardware RAID', args=[ dict(name="--name", help='volume name', metavar=''), dict(name="--disk", metavar='', help='Free disks for new RAIDed volume.\n' 'This is repeatable argument.', action='append'), dict(name="--raid-type", help="RAID type for the new RAID group. " "Should be one of these:\n %s" % "\n ". join(VolumeRAIDInfo.VOL_CREATE_RAID_TYPES_STR), choices=VolumeRAIDInfo.VOL_CREATE_RAID_TYPES_STR, type=_upper), ], optional=[ dict(name="--strip-size", help="Strip size. " + size_help), ], ), dict( name='volume-raid-create-cap', help='Query capability of creating a RAIDed volume on hardware RAID', args=[ dict(sys_id_opt), ], ), dict( name='volume-delete', help='Deletes a volume given its id', args=[ dict(vol_id_opt), ], ), dict( name='volume-resize', help='Re-sizes a volume', args=[ dict(vol_id_opt), dict(name='--size', metavar='', help="New size. %s" % size_help), ], ), dict( name='volume-replicate', help='Creates a new volume and replicates provided volume to it.', args=[ dict(vol_id_opt), dict(name="--name", metavar='', help='The name for New replicated volume'), dict(name="--rep-type", metavar='', help=replicate_help, choices=replicate_types), ], optional=[ dict(name="--pool", help='Pool ID to contain the new volume.\nBy default, ' 'new volume will be created in the same pool.'), ], ), dict( name='volume-replicate-range', help='Replicates a portion of a volume to existing volume', args=[ dict(name="--src-vol", metavar='', help='Source volume id'), dict(name="--dst-vol", metavar='', help='Destination volume id'), dict(name="--rep-type", metavar='', help="Replication type: CLONE, COPY", choices=["CLONE", "COPY"]), dict(name="--src-start", metavar='', help='Source volume start block number.\n' 'This is repeatable argument.', action='append', type=_check_positive_integer), dict(name="--dst-start", metavar='', help='Destination volume start block number.\n' 'This is repeatable argument.', action='append', type=_check_positive_integer), dict(name="--count", metavar='', help='Number of blocks to replicate.\n' 'This is repeatable argument.', action='append', type=_check_positive_integer), ], ), dict( name='volume-replicate-range-block-size', help='Size of each replicated block on a system in bytes', args=[ dict(sys_id_opt), ], ), dict( name='volume-dependants', help='Returns True if volume has a dependant child, like replication', args=[ dict(vol_id_opt), ], ), dict( name='volume-dependants-rm', help='Removes volume dependencies', args=[ dict(vol_id_opt), ], ), dict( name='volume-access-group', help='Lists the access group(s) that have access to volume', args=[ dict(vol_id_opt), ], ), dict( name='volume-mask', help='Grants access to an access group to a volume, ' 'like LUN Masking', args=[ dict(vol_id_opt), dict(ag_id_opt), ], ), dict( name='volume-unmask', help='Revoke the access of specified access group to a volume', args=[ dict(ag_id_opt), dict(vol_id_opt), ], ), dict( name='volume-enable', help='Enable block access of a volume', args=[ dict(vol_id_opt), ], ), dict( name='volume-disable', help='Disable block access of a volume', args=[ dict(vol_id_opt), ], ), dict( name='volume-raid-info', help='Query volume RAID information', args=[ dict(vol_id_opt), ], ), dict( name='volume-ident-led-on', help='Enable the IDENT LED for a volume', args=[ dict(name="--vol", metavar='', help='Targeted volume.\n'), ], ), dict( name='volume-ident-led-off', help='Disable the IDENT LED for a volume', args=[ dict(name="--vol", metavar='', help='Targeted volume.\n'), ], ), dict( name='system-read-cache-pct-update', help='Change the read cache percentage of a system', args=[ dict(name="--sys", metavar='', help='Targeted system.\n'), dict(name="--read-pct", help="Read cache percentage.\n", type=_check_positive_integer), ], ), dict( name='pool-member-info', help='Query Pool membership information', args=[ dict(pool_id_opt), ], ), dict( name='access-group-create', help='Create an access group', args=[ dict(name='--name', metavar='', help="Human readable name for access group"), # TODO: _client.py access_group_create should support multiple # initiators when creating. dict(init_id_opt), dict(sys_id_opt), ], ), dict( name='access-group-add', help='Add an initiator into existing access group', args=[ dict(ag_id_opt), dict(init_id_opt), ], ), dict( name='access-group-remove', help='Remove an initiator from existing access group', args=[ dict(ag_id_opt), dict(init_id_opt), ], ), dict( name='access-group-delete', help='Deletes an access group', args=[ dict(ag_id_opt), ], ), dict( name='access-group-volumes', help='Lists the volumes that the access group has' ' been granted access to', args=[ dict(ag_id_opt), ], ), dict( name='iscsi-chap', help='Configures iSCSI inbound/outbound CHAP authentication', args=[ dict(init_id_opt), ], optional=[ dict(name="--in-user", metavar='', help='Inbound chap user name'), dict(name="--in-pass", metavar='', help='Inbound chap password'), dict(name="--out-user", metavar='', help='Outbound chap user name'), dict(name="--out-pass", metavar='', help='Outbound chap password'), ], ), dict( name='fs-create', help='Creates a file system', args=[ dict(name="--name", metavar='', help='name of the file system'), dict(size_opt), dict(pool_id_opt), ], ), dict( name='fs-delete', help='Delete a filesystem', args=[ dict(fs_id_opt) ], ), dict( name='fs-resize', help='Re-sizes a filesystem', args=[ dict(fs_id_opt), dict(name="--size", metavar="", help="New size. %s" % size_help), ], ), dict( name='fs-export', help='Export a filesystem via NFS.', args=[ dict(fs_id_opt), ], optional=[ dict(name="--exportpath", metavar='', help="NFS server export path. e.g. '/foo/bar'."), dict(name="--anonuid", metavar='', help='UID(User ID) to map to anonymous user', default=NfsExport.ANON_UID_GID_NA, type=_check_positive_integer), dict(name="--anongid", metavar='', help='GID(Group ID) to map to anonymous user', default=NfsExport.ANON_UID_GID_NA, type=_check_positive_integer), dict(name="--auth-type", metavar='', help='NFS client authentication type'), dict(name="--root-host", metavar='', help="The host/IP has root access.\n" "This is repeatable argument.", action='append', default=[], type=_check_network_host), dict(name="--ro-host", metavar='', help="The host/IP has readonly access.\n" "This is repeatable argument.\n" "At least one '--ro-host' or '--rw-host' is required.", action='append', default=[], type=_check_network_host), dict(name="--rw-host", metavar='', help="The host/IP has readwrite access.\n" "This is repeatable argument.\n" "At least one '--ro-host' or '--rw-host' is required.", action='append', default=[], type=_check_network_host), ], ), dict( name='fs-unexport', help='Remove an NFS export', args=[ dict(export_id_opt), ], ), dict( name='fs-clone', help='Creates a file system clone', args=[ dict(name="--src-fs", metavar='', help='The ID of existing source file system.'), dict(name="--dst-name", metavar='', help='The name for newly created destination file system.'), ], optional=[ dict(name="--backing-snapshot", metavar='', help='backing snapshot id'), ], ), dict( name='fs-snap-create', help='Creates a snapshot', args=[ dict(name="--name", metavar="", help='The human friendly name of new snapshot'), dict(fs_id_opt), ], ), dict( name='fs-snap-delete', help='Deletes a snapshot', args=[ dict(snap_id_opt), dict(fs_id_opt), # TODO: why we need filesystem ID? ], ), dict( name='fs-snap-restore', help='Restores a FS or specified files to ' 'previous snapshot state', args=[ dict(snap_id_opt), dict(fs_id_opt), ], optional=[ dict(name="--file", metavar="", help="Only restore provided file\n" "Without this argument, all files will be restored\n" "This is a repeatable argument.", action='append', default=[]), dict(name="--fileas", metavar="", help="store restore file name to another name.\n" "This is a repeatable argument.", action='append', default=[]), ], ), dict( name='fs-dependants', help='Returns True if filesystem has a child ' 'dependency(clone/snapshot) exists', args=[ dict(fs_id_opt), ], optional=[ dict(name="--file", metavar="", action="append", default=[], help="For file check\nThis is a repeatable argument."), ], ), dict( name='fs-dependants-rm', help='Removes file system dependencies', args=[ dict(fs_id_opt), ], optional=[ dict(name="--file", action='append', default=[], help='File or files to remove dependencies for.\n' "This is a repeatable argument.",), ], ), dict( name='file-clone', help='Creates a clone of a file (thin provisioned)', args=[ dict(fs_id_opt), dict(name="--src", metavar="", help='source file to clone (relative path)\n' "This is a repeatable argument.",), dict(name="--dst", metavar="", help='Destination file (relative path)' ", this is a repeatable argument."), ], optional=[ dict(name="--backing-snapshot", help='backing snapshot id'), ], ), dict( name='local-disk-list', help='Query local disk information', args=[ ], optional=[ ], ), dict( name='volume-cache-info', help='Query volume RAM cache information', args=[ dict(vol_id_opt), ], ), dict( name='volume-phy-disk-cache-update', help='Update volume physical disk cache setting', args=[ dict(vol_id_opt), dict(policy_opt), ], ), dict( name='volume-read-cache-policy-update', help='Update volume read cache policy', args=[ dict(vol_id_opt), dict(policy_opt), ], ), dict( name='volume-write-cache-policy-update', help='Update volume write cache policy', args=[ dict(vol_id_opt), dict(write_cache_policy_opt), ], ), dict( name='local-disk-ident-led-on', help='Turn on the identification LED for a local disk', args=[ dict(local_disk_path_opt), ], ), dict( name='local-disk-ident-led-off', help='Turn off the identification LED for a local disk', args=[ dict(local_disk_path_opt), ], ), dict( name='local-disk-fault-led-on', help='Turn on the fault LED for a local disk', args=[ dict(local_disk_path_opt), ], ), dict( name='local-disk-fault-led-off', help='Turn off the fault LED for a local disk', args=[ dict(local_disk_path_opt), ], ), ) aliases = dict( ls='list --type systems', lp='list --type pools', lv='list --type volumes', ld='list --type disks', la='list --type access_groups', lf='list --type fs', lt='list --type target_ports', c='capabilities', p='plugin-info', vc='volume-create', vrc='volume-raid-create', vrcc='volume-raid-create-cap', vd='volume-delete', vr='volume-resize', vm='volume-mask', vu='volume-unmask', ve='volume-enable', vi='volume-disable', ac='access-group-create', aa='access-group-add', ar='access-group-remove', ad='access-group-delete', vri='volume-raid-info', vilon='volume-ident-led-on', viloff='volume-ident-led-off', srcpu='system-read-cache-pct-update', pmi='pool-member-info', ldl='local-disk-list', lb='list --type batteries', vci='volume-cache-info', vpdcu='volume-phy-disk-cache-update', vrcpu='volume-read-cache-policy-update', vwcpu='volume-write-cache-policy-update', ldilon='local-disk-ident-led-on', ldiloff='local-disk-ident-led-off', ldflon='local-disk-fault-led-on', ldfloff='local-disk-fault-led-off', ) # Class that encapsulates the command line arguments for lsmcli # Note: This class is used by lsmcli and any python plug-ins. class CmdLine(object): """ Command line interface class. """ ## # Warn of imminent data loss # @param deleting Indicate data will be lost vs. may be lost # (re-size) # @return True if operation confirmed, else False def confirm_prompt(self, deleting): """ Give the user a chance to bail. """ if not self.args.force: msg = "will" if deleting else "may" out("Warning: You are about to do an operation that %s cause data " "to be lost!\nPress [Y|y] to continue, any other key to abort" % msg) pressed = getch() if pressed.upper() == 'Y': return True else: out('Operation aborted!') return False else: return True ## # Tries to make the output better when it varies considerably from # plug-in to plug-in. # @param objects Data, first row is header all other data. def display_data(self, objects): display_all = False if len(objects) == 0: return display_way = DisplayData.DISPLAY_WAY_DEFAULT flag_with_header = True if self.args.sep: flag_with_header = False if self.args.header: flag_with_header = True if self.args.script: display_way = DisplayData.DISPLAY_WAY_SCRIPT DisplayData.display_data( objects, display_way=display_way, flag_human=self.args.human, flag_enum=self.args.enum, splitter=self.args.sep, flag_with_header=flag_with_header, flag_dsp_all_data=display_all) def display_available_plugins(self): d = [] sep = '<}{>' plugins = Client.available_plugins(sep) for p in plugins: desc, version = p.split(sep) d.append(PlugData(desc, version)) self.display_data(d) @staticmethod def handle_alias(): """ Walk the command line argument list and build up a new command line with the appropriate substitutions which is then passed to argparse, so that we can avoid adding more sub parsers and do all argument parsing before the need to talk to the library :return copy of command line args with alias expansion: """ rc = [] for i in sys.argv[1:]: if i in aliases: rc.extend(aliases[i].split(" ")) else: rc.append(i) return rc @staticmethod def alias_help_text(): rc = "command aliases:\n" for k, v in sorted(aliases.items()): rc += " {0:<18} Alias of '{1}'\n".format(k, v) return rc # All the command line arguments and options are created in this method def cli(self): """ Command line interface parameters """ parent_parser = ArgumentParser(add_help=False) _add_common_options(parent_parser, is_child=True) parser = ArgumentParser( description='The libStorageMgmt command line interface.' ' Run %(prog)s -h for more on each command.', epilog=CmdLine.alias_help_text() + '\n\nCopyright 2012-2018 Red Hat, Inc.\n' 'Please report bugs to ' '\n', formatter_class=RawTextHelpFormatter) _add_common_options(parser, is_child=False) subparsers = parser.add_subparsers(metavar="command") # Walk the command list and add all of them to the parser for cmd in cmds: sub_parser = subparsers.add_parser( cmd['name'], help=cmd['help'], parents=[parent_parser], formatter_class=RawTextHelpFormatter) group = sub_parser.add_argument_group("cmd required arguments") for arg in cmd.get('args', []): name = arg['name'] del arg['name'] group.add_argument(name, required=True, **arg) group = sub_parser.add_argument_group("cmd optional arguments") for arg in cmd.get('optional', []): flags = arg['name'] del arg['name'] if not isinstance(flags, tuple): flags = (flags,) group.add_argument(*flags, **arg) sub_parser.set_defaults( func=getattr(self, cmd['name'].replace("-", "_"))) if len(sys.argv) == 1: parser.print_usage() exit(1) self.parser = parser known_args = parser.parse_args(args=CmdLine.handle_alias()) # Copy child value to root. for k, v in vars(known_args).items(): if k.startswith(_CHILD_OPTION_DST_PREFIX): root_k = k[len(_CHILD_OPTION_DST_PREFIX):] if getattr(known_args, root_k) is None or \ getattr(known_args, root_k) is False: setattr(known_args, root_k, v) return known_args # Display the types of nfs client authentication that are supported. # @return None def display_nfs_client_authentication(self): """ Dump the supported nfs client authentication types """ if self.args.sep: out(self.args.sep.join(self.c.export_auth())) else: out(", ".join(self.c.export_auth())) # Determine what the search key and search value are for listing # @param args Argparse argument object # @return (key, value) tuple @staticmethod def _get_search_key_value(args): search_key = None search_value = None search_args = ((args.sys, 'system_id'), (args.pool, 'pool_id'), (args.vol, 'volume_id'), (args.disk, 'disk_id'), (args.ag, 'access_group_id'), (args.fs, 'fs_id'), (args.nfs_export, 'nfs_export_id'), (args.tgt, 'tgt_port_id')) for sa in search_args: if sa[0]: if search_key: raise ArgError( "Search key specified more than once (%s, %s)" % (search_key, sa[1])) else: (search_value, search_key) = sa return search_key, search_value # Method that calls the appropriate method based on what the list type is # @param args Argparse argument object def list(self, args): (search_key, search_value) = CmdLine._get_search_key_value(args) if args.type == 'VOLUMES': lsm_vols = [] if search_key == 'volume_id': search_key = 'id' if search_key == 'access_group_id': lsm_ag = _get_item(self.c.access_groups(), args.ag, "Access Group", raise_error=False) if lsm_ag: lsm_vols = self.c.volumes_accessible_by_access_group( lsm_ag) elif search_key and search_key not in Volume.SUPPORTED_SEARCH_KEYS: raise ArgError("Search key '%s' is not supported by " "volume listing." % search_key) else: lsm_vols = self.c.volumes(search_key, search_value) self.display_data(list(_add_sd_paths(v) for v in lsm_vols)) elif args.type == 'POOLS': if search_key == 'pool_id': search_key = 'id' if search_key and search_key not in Pool.SUPPORTED_SEARCH_KEYS: raise ArgError("Search key '%s' is not supported by " "pool listing." % search_key) self.display_data( self.c.pools(search_key, search_value)) elif args.type == 'FS': if search_key == 'fs_id': search_key = 'id' if search_key and \ search_key not in FileSystem.SUPPORTED_SEARCH_KEYS: raise ArgError("Search key '%s' is not supported by " "volume listing." % search_key) self.display_data(self.c.fs(search_key, search_value)) elif args.type == 'SNAPSHOTS': if args.fs is None: raise ArgError("--fs required") if search_key and search_key != "fs_id": raise ArgError("Search key '%s' is not supported by " "snapshot listing." % search_key) fs = _get_item(self.c.fs(), args.fs, 'File System') self.display_data(self.c.fs_snapshots(fs)) elif args.type == 'EXPORTS': if search_key == 'nfs_export_id': search_key = 'id' if search_key and \ search_key not in NfsExport.SUPPORTED_SEARCH_KEYS: raise ArgError("Search key '%s' is not supported by " "NFS Export listing" % search_key) self.display_data(self.c.exports(search_key, search_value)) elif args.type == 'NFS_CLIENT_AUTH': if search_key: raise ArgError("NFS client authentication type listing with " "search is not supported") self.display_nfs_client_authentication() elif args.type == 'ACCESS_GROUPS': if search_key == 'access_group_id': search_key = 'id' if search_key == 'volume_id': lsm_vol = _get_item(self.c.volumes(), args.vol, "Volume", raise_error=False) if lsm_vol: return self.display_data( self.c.access_groups_granted_to_volume(lsm_vol)) else: return self.display_data([]) elif (search_key and search_key not in AccessGroup.SUPPORTED_SEARCH_KEYS): raise ArgError("Search key '%s' is not supported by " "Access Group listing" % search_key) self.display_data( self.c.access_groups(search_key, search_value)) elif args.type == 'SYSTEMS': if search_key: raise ArgError("System listing with search is not supported") self.display_data(self.c.systems()) elif args.type == 'DISKS': if search_key == 'disk_id': search_key = 'id' if search_key and search_key not in Disk.SUPPORTED_SEARCH_KEYS: raise ArgError("Search key '%s' is not supported by " "disk listing" % search_key) self.display_data( list(_add_sd_paths(d) for d in self.c.disks(search_key, search_value))) elif args.type == 'TARGET_PORTS': if search_key == 'tgt_port_id': search_key = 'id' if search_key and \ search_key not in TargetPort.SUPPORTED_SEARCH_KEYS: raise ArgError("Search key '%s' is not supported by " "target port listing" % search_key) self.display_data( self.c.target_ports(search_key, search_value)) elif args.type == 'PLUGINS': if search_key: raise ArgError("Plugins listing with search is not supported") self.display_available_plugins() elif args.type == 'BATTERIES': if search_key and \ search_key not in Battery.SUPPORTED_SEARCH_KEYS: raise ArgError("Search key '%s' is not supported by " "battery listing" % search_key) self.display_data( self.c.batteries(search_key, search_value)) else: raise ArgError("unsupported listing type=%s" % args.type) # Creates an access group. def access_group_create(self, args): system = _get_item(self.c.systems(), args.sys, "System") (init_id, init_type) = parse_convert_init(args.init) access_group = self.c.access_group_create(args.name, init_id, init_type, system) self.display_data([access_group]) def _add_rm_access_grp_init(self, args, op): lsm_ag = _get_item(self.c.access_groups(), args.ag, "Access Group") (init_id, init_type) = parse_convert_init(args.init) if op: return self.c.access_group_initiator_add(lsm_ag, init_id, init_type) else: return self.c.access_group_initiator_delete(lsm_ag, init_id, init_type) # Adds an initiator from an access group def access_group_add(self, args): self.display_data([self._add_rm_access_grp_init(args, True)]) # Removes an initiator from an access group def access_group_remove(self, args): self.display_data([self._add_rm_access_grp_init(args, False)]) def access_group_volumes(self, args): agl = self.c.access_groups() group = _get_item(agl, args.ag, "Access Group") vols = self.c.volumes_accessible_by_access_group(group) self.display_data(list(_add_sd_paths(v) for v in vols)) def iscsi_chap(self, args): (init_id, init_type) = parse_convert_init(args.init) if init_type != AccessGroup.INIT_TYPE_ISCSI_IQN: raise ArgError("--init \"%s\" is not a valid iSCSI IQN" % args.init) if self.args.in_user and not self.args.in_pass: raise ArgError("--in-user requires --in-pass") if self.args.in_pass and not self.args.in_user: raise ArgError("--in-pass requires --in-user") if self.args.out_user and not self.args.out_pass: raise ArgError("--out-user requires --out-pass") if self.args.out_pass and not self.args.out_user: raise ArgError("--out-pass requires --out-user") # Enforce consistency across all if self.args.out_user and self.args.out_pass and not \ (self.args.in_user and self.args.in_pass): raise ArgError("out-user and out-password only supported if " "inbound is supplied") self.c.iscsi_chap_auth(init_id, args.in_user, self.args.in_pass, self.args.out_user, self.args.out_pass) def volume_access_group(self, args): vol = _get_item(self.c.volumes(), args.vol, "Volume") groups = self.c.access_groups_granted_to_volume(vol) self.display_data(groups) # Used to delete access group def access_group_delete(self, args): agl = self.c.access_groups() group = _get_item(agl, args.ag, "Access Group") return self.c.access_group_delete(group) # Used to delete a file system def fs_delete(self, args): fs = _get_item(self.c.fs(), args.fs, "File System") if self.confirm_prompt(True): self._wait_for_it("fs-delete", self.c.fs_delete(fs), None) # Used to create a file system def fs_create(self, args): p = _get_item(self.c.pools(), args.pool, "Pool") fs = self._wait_for_it("fs-create", *self.c.fs_create(p, args.name, self._size(args.size))) self.display_data([fs]) # Used to resize a file system def fs_resize(self, args): fs = _get_item(self.c.fs(), args.fs, "File System") size = self._size(args.size) if size == fs.total_space: raise LsmError( ErrorNumber.NO_STATE_CHANGE, "Specified size same as current") if self.confirm_prompt(False): fs = self._wait_for_it("fs-resize", *self.c.fs_resize(fs, size)) self.display_data([fs]) # Used to clone a file system def fs_clone(self, args): src_fs = _get_item( self.c.fs(), args.src_fs, "Source File System") ss = None if args.backing_snapshot: # go get the snapshot ss = _get_item(self.c.fs_snapshots(src_fs), args.backing_snapshot, "Snapshot") fs = self._wait_for_it( "fs_clone", *self.c.fs_clone(src_fs, args.dst_name, ss)) self.display_data([fs]) # Used to clone a file(s) def file_clone(self, args): fs = _get_item(self.c.fs(), args.fs, "File System") if self.args.backing_snapshot: # go get the snapshot ss = _get_item(self.c.fs_snapshots(fs), args.backing_snapshot, "Snapshot") else: ss = None self._wait_for_it( "fs_file_clone", self.c.fs_file_clone(fs, args.src, args.dst, ss), None) # Converts a size parameter into the appropriate number of bytes # @param s Size to convert to bytes handles B, K, M, G, T, P postfix # @return Size in bytes @staticmethod def _size(s): size_bytes = size_human_2_size_bytes(s) if size_bytes <= 0: raise ArgError("Incorrect size argument format: '%s'" % s) return size_bytes def _cp(self, cap, val): if self.args.sep is not None: s = self.args.sep else: s = ':' if val: v = "SUPPORTED" else: v = "UNSUPPORTED" out("%s%s%s" % (cap, s, v)) def capabilities(self, args): s = _get_item(self.c.systems(), args.sys, "System") cap = self.c.capabilities(s) sup_caps = sorted(cap.get_supported().values()) all_caps = sorted(cap.get_supported(True).values()) sep = DisplayData.DEFAULT_SPLITTER if self.args.sep is not None: sep = self.args.sep cap_data = OrderedDict() # Show support capabilities first for v in sup_caps: cap_data[v] = 'SUPPORTED' for v in all_caps: if v not in sup_caps: cap_data[v] = 'UNSUPPORTED' DisplayData.display_data_script_way([cap_data], sep) def plugin_info(self, args): desc, version = self.c.plugin_info() if args.sep: out("%s%s%s" % (desc, args.sep, version)) else: out("Description: %s Version: %s" % (desc, version)) # Creates a volume def volume_create(self, args): # Get pool p = _get_item(self.c.pools(), args.pool, "Pool") vol = self._wait_for_it( "volume-create", *self.c.volume_create( p, args.name, self._size(args.size), vol_provision_str_to_type(args.provisioning))) self.display_data([_add_sd_paths(vol)]) # Creates a snapshot def fs_snap_create(self, args): # Get fs fs = _get_item(self.c.fs(), args.fs, "File System") ss = self._wait_for_it("snapshot-create", *self.c.fs_snapshot_create( fs, args.name)) self.display_data([ss]) # Restores a snap shot def fs_snap_restore(self, args): # Get snapshot fs = _get_item(self.c.fs(), args.fs, "File System") ss = _get_item(self.c.fs_snapshots(fs), args.snap, "Snapshot") files = self.args.file if len(files) == 0: files = None flag_all_files = True if self.args.file: flag_all_files = False if self.args.fileas: if len(self.args.file) != len(self.args.fileas): raise ArgError( "number of --file not equal to --fileas") if self.confirm_prompt(True): self._wait_for_it( 'fs-snap-restore', self.c.fs_snapshot_restore( fs, ss, files, self.args.fileas, flag_all_files), None) # Deletes a volume def volume_delete(self, args): v = _get_item(self.c.volumes(), args.vol, "Volume") if self.confirm_prompt(True): self._wait_for_it("volume-delete", self.c.volume_delete(v), None) # Deletes a snap shot def fs_snap_delete(self, args): fs = _get_item(self.c.fs(), args.fs, "File System") ss = _get_item(self.c.fs_snapshots(fs), args.snap, "Snapshot") if self.confirm_prompt(True): self._wait_for_it("fs_snap_delete", self.c.fs_snapshot_delete(fs, ss), None) # Waits for an operation to complete by polling for the status of the # operations. # @param msg Message to display if this job fails # @param job The job id to wait on # @param item The item that could be available now if there is no job def _wait_for_it(self, msg, job, item): if not job: return item else: # If a user doesn't want to wait, return the job id to stdout # and exit with job in progress if self.args._async: out(job) self.shutdown(ErrorNumber.JOB_STARTED) while True: (s, percent, item) = self.c.job_status(job) if s == JobStatus.INPROGRESS: # Add an option to spit out progress? # print "%s - Percent %s complete" % (job, percent) time.sleep(0.25) elif s == JobStatus.COMPLETE: self.c.job_free(job) return item else: # Something better to do here? raise ArgError(msg + " job error code= " + str(s)) # Retrieves the status of the specified job def job_status(self, args): (s, percent, item) = self.c.job_status(args.job) if s == JobStatus.COMPLETE: if item: self.display_data([_add_sd_paths(item)]) self.c.job_free(args.job) else: out(str(percent)) self.shutdown(ErrorNumber.JOB_STARTED) # Replicates a volume def volume_replicate(self, args): p = None if args.pool: p = _get_item(self.c.pools(), args.pool, "Pool") v = _get_item(self.c.volumes(), args.vol, "Volume") rep_type = vol_rep_type_str_to_type(args.rep_type) if rep_type == Volume.REPLICATE_UNKNOWN: raise ArgError("invalid replication type= %s" % rep_type) vol = self._wait_for_it( "replicate volume", *self.c.volume_replicate(p, rep_type, v, args.name)) self.display_data([_add_sd_paths(vol)]) # Check to see if block ranges are overlapping @staticmethod def _check_overlap(ranges): def _overlap(r, member): for i in range(1, len(r)): ps = getattr(r[i - 1], member) # Previous start pc = r[i - 1].block_count # Previous count cs = getattr(r[i], member) # Current start cc = r[i].block_count # Current count if ps + pc > cs: raise ArgError("Overlapping %s replication " "range %d..%d overlaps with %d..%d" % (member, ps, ps + pc - 1, cs, cs + cc - 1)) # Sort the src ranges ranges.sort(key=lambda x: x.src_block) _overlap(ranges, "src_block") ranges.sort(key=lambda x: x.dest_block) _overlap(ranges, "dest_block") # Replicates a range of a volume def volume_replicate_range(self, args): src = _get_item(self.c.volumes(), args.src_vol, "Source Volume") dst = _get_item(self.c.volumes(), args.dst_vol, "Destination Volume") rep_type = vol_rep_type_str_to_type(args.rep_type) if rep_type == Volume.REPLICATE_UNKNOWN: raise ArgError("invalid replication type= %s" % rep_type) src_starts = args.src_start dst_starts = args.dst_start counts = args.count if not len(src_starts) \ or not (len(src_starts) == len(dst_starts) == len(counts)): raise ArgError("Differing numbers of src_start, dest_start, " "and count parameters") ranges = [] for b in range(len(src_starts)): # Validate some assumptions for source & count count = long(counts[b]) src_start = long(src_starts[b]) dst_start = long(dst_starts[b]) if count < 0: raise ArgError("--count: value < 0") if src_start < 0: raise ArgError("--src-start: value < 0") if dst_start < 0: raise ArgError("--dst_start: value < 0") if src_start + count > src.num_of_blocks: raise ArgError("--src-start + --count > source size") if dst_start + count > dst.num_of_blocks: raise ArgError("--dst-start + --count > destination size") ranges.append(BlockRange(src_start, dst_start, count)) CmdLine._check_overlap(ranges) if self.confirm_prompt(False): self.c.volume_replicate_range(rep_type, src, dst, ranges) # # Returns the block size in bytes for each block represented in # volume_replicate_range def volume_replicate_range_block_size(self, args): s = _get_item(self.c.systems(), args.sys, "System") out(self.c.volume_replicate_range_block_size(s)) def volume_mask(self, args): vol = _get_item(self.c.volumes(), args.vol, 'Volume') ag = _get_item(self.c.access_groups(), args.ag, 'Access Group') self.c.volume_mask(ag, vol) def volume_unmask(self, args): ag = _get_item(self.c.access_groups(), args.ag, "Access Group") vol = _get_item(self.c.volumes(), args.vol, "Volume") return self.c.volume_unmask(ag, vol) # Re-sizes a volume def volume_resize(self, args): v = _get_item(self.c.volumes(), args.vol, "Volume") size = self._size(args.size) if size == v.block_size * v.num_of_blocks: raise LsmError( ErrorNumber.NO_STATE_CHANGE, "Specified size same as current") if self.confirm_prompt(False): vol = self._wait_for_it("resize", *self.c.volume_resize(v, size)) self.display_data([_add_sd_paths(vol)]) # Enable a volume def volume_enable(self, args): v = _get_item(self.c.volumes(), args.vol, "Volume") self.c.volume_enable(v) # Disable a volume def volume_disable(self, args): v = _get_item(self.c.volumes(), args.vol, "Volume") self.c.volume_disable(v) # Removes a nfs export def fs_unexport(self, args): export = _get_item(self.c.exports(), args.export, "NFS Export") self.c.export_remove(export) # Exports a file system as a NFS export def fs_export(self, args): fs = _get_item(self.c.fs(), args.fs, "File System") # Check to see if we have some type of access specified if len(args.rw_host) == 0 \ and len(args.ro_host) == 0: raise ArgError(" please specify --ro-host or --rw-host") export = self.c.export_fs( fs.id, args.exportpath, args.root_host, args.rw_host, args.ro_host, args.anonuid, args.anongid, args.auth_type, None) self.display_data([export]) # Displays volume dependants. def volume_dependants(self, args): v = _get_item(self.c.volumes(), args.vol, "Volume") rc = self.c.volume_child_dependency(v) out(rc) # Removes volume dependants. def volume_dependants_rm(self, args): v = _get_item(self.c.volumes(), args.vol, "Volume") self._wait_for_it("volume-dependant-rm", self.c.volume_child_dependency_rm(v), None) def volume_raid_info(self, args): lsm_vol = _get_item(self.c.volumes(), args.vol, "Volume") self.display_data( [ VolumeRAIDInfo( lsm_vol.id, *self.c.volume_raid_info(lsm_vol))]) def pool_member_info(self, args): lsm_pool = _get_item(self.c.pools(), args.pool, "Pool") self.display_data( [ PoolRAIDInfo( lsm_pool.id, *self.c.pool_member_info(lsm_pool))]) def volume_raid_create(self, args): raid_type = VolumeRAIDInfo.raid_type_str_to_lsm(args.raid_type) all_lsm_disks = self.c.disks() lsm_disks = [d for d in all_lsm_disks if d.id in args.disk] if len(lsm_disks) != len(args.disk): raise LsmError( ErrorNumber.NOT_FOUND_DISK, "Disk ID %s not found" % ', '.join(set(args.disk) - set(d.id for d in all_lsm_disks))) busy_disks = [d.id for d in lsm_disks if not d.status & Disk.STATUS_FREE] if len(busy_disks) >= 1: raise LsmError( ErrorNumber.DISK_NOT_FREE, "Disk %s is not free" % ", ".join(busy_disks)) if args.strip_size: strip_size = size_human_2_size_bytes(args.strip_size) else: strip_size = Volume.VCR_STRIP_SIZE_DEFAULT self.display_data([ _add_sd_paths( self.c.volume_raid_create( args.name, raid_type, lsm_disks, strip_size))]) def volume_raid_create_cap(self, args): lsm_sys = _get_item(self.c.systems(), args.sys, "System") self.display_data([ VcrCap(lsm_sys.id, *self.c.volume_raid_create_cap_get(lsm_sys))]) def volume_ident_led_on(self, args): lsm_volume = _get_item(self.c.volumes(), args.vol, "Volume") self.c.volume_ident_led_on(lsm_volume) def volume_ident_led_off(self, args): lsm_volume = _get_item(self.c.volumes(), args.vol, "Volume") self.c.volume_ident_led_off(lsm_volume) def system_read_cache_pct_update(self, args): lsm_system = _get_item(self.c.systems(), args.sys, "System") try: read_pct = int(args.read_pct) except ValueError as ve: raise LsmError(ErrorNumber.INVALID_ARGUMENT, str(ve)) self.c.system_read_cache_pct_update(lsm_system, read_pct) lsm_system = _get_item(self.c.systems(), args.sys, "System") self.display_data([lsm_system]) # Displays file system dependants def fs_dependants(self, args): fs = _get_item(self.c.fs(), args.fs, "File System") rc = self.c.fs_child_dependency(fs, args.file) out(rc) # Removes file system dependants def fs_dependants_rm(self, args): fs = _get_item(self.c.fs(), args.fs, "File System") self._wait_for_it("fs-dependants-rm", self.c.fs_child_dependency_rm(fs, args.file), None) def _read_configfile(self): """ Set uri from config file. Will be overridden by cmdline option or env var if present. """ allowed_config_options = ("uri",) config_path = os.path.expanduser("~") + "/.lsmcli" if not os.path.exists(config_path): return with open(config_path) as f: for line in f: if line.lstrip().startswith("#"): continue try: name, val = [x.strip() for x in line.split("=", 1)] if name in allowed_config_options: setattr(self, name, val) except ValueError: pass def is_connection_free_cmd(self): """ Return True if current command is one of _CONNECTION_FREE_COMMANDS. """ if self.args.func.__name__.replace("_", "-") in \ _CONNECTION_FREE_COMMANDS: return True return False # Class constructor. def __init__(self): self.uri = None self.c = None self.parser = None self.unknown_args = None self.args = self.cli() self.cleanup = None self.tmo = int(self.args.wait) if not self.tmo or self.tmo < 0: raise ArgError("[-w|--wait] requires a non-zero positive integer") if self.is_connection_free_cmd(): return self._read_configfile() if os.getenv('LSMCLI_URI') is not None: self.uri = os.getenv('LSMCLI_URI') self.password = os.getenv('LSMCLI_PASSWORD') if self.args.uri is not None: self.uri = self.args.uri if self.uri is None: # We need a valid plug-in to instantiate even if all we are trying # to do is list the plug-ins at the moment to keep that code # the same in all cases, even though it isn't technically # required for the client library (static method) # TODO: Make this not necessary. if 'type' in self.args and self.args.type == "PLUGINS": self.uri = "sim://" self.password = None else: raise ArgError("--uri missing or export LSMCLI_URI") # Lastly get the password if requested. if self.args.prompt: self.password = getpass.getpass() if self.password is not None: # Check for username u = uri_parse(self.uri) if u['username'] is None: raise ArgError("password specified with no user name in uri") # Does appropriate clean-up # @param ec The exit code def shutdown(self, ec=None): if self.cleanup: self.cleanup() if ec: sys.exit(ec) # Process the specified command # @param cli The object instance to invoke methods on. def process(self, cli=None): """ Process the parsed command. """ if self.is_connection_free_cmd(): self.args.func(self.args) else: if cli: # Directly invoking code though a wrapper to catch unsupported # operations. self.c = Proxy(cli()) self.c.plugin_register(self.uri, self.password, self.tmo) self.cleanup = self.c.plugin_unregister else: # Going across the ipc pipe self.c = Proxy(Client(self.uri, self.password, self.tmo)) if os.getenv('LSM_DEBUG_PLUGIN'): input("Attach debugger to plug-in, " "press when ready...") self.cleanup = self.c.close self.args.func(self.args) self.shutdown() def local_disk_list(self, args): local_disks = [] func_dict = { "vpd83": LocalDisk.vpd83_get, "rpm": LocalDisk.rpm_get, "link_type": LocalDisk.link_type_get, "serial_num": LocalDisk.serial_num_get, "led_status": LocalDisk.led_status_get, "link_speed": LocalDisk.link_speed_get, "health_status": LocalDisk.health_status_get, } for disk_path in LocalDisk.list(): info_dict = { "vpd83": "", "rpm": Disk.RPM_NO_SUPPORT, "link_type": Disk.LINK_TYPE_NO_SUPPORT, "serial_num": "", "led_status": Disk.LED_STATUS_UNKNOWN, "link_speed": Disk.LINK_SPEED_UNKNOWN, "health_status": Disk.HEALTH_STATUS_UNKNOWN, } for key in info_dict.keys(): try: info_dict[key] = func_dict[key](disk_path) except LsmError as lsm_err: if lsm_err.code != ErrorNumber.NO_SUPPORT: sys.stderr.write("WARN: %s('%s'): %d %s\n" % (func_dict[key].__name__, disk_path, lsm_err.code, lsm_err.msg)) local_disks.append( LocalDiskInfo(disk_path, info_dict["vpd83"], info_dict["rpm"], info_dict["link_type"], info_dict["serial_num"], info_dict["led_status"], info_dict["link_speed"], info_dict["health_status"])) self.display_data(local_disks) def volume_cache_info(self, args): lsm_vol = _get_item(self.c.volumes(), args.vol, "Volume") self.display_data( [ VolumeRAMCacheInfo( lsm_vol.id, *self.c.volume_cache_info(lsm_vol))]) def volume_phy_disk_cache_update(self, args): lsm_vol = _get_item(self.c.volumes(), args.vol, "Volume") if args.policy == "ENABLE": policy = Volume.READ_CACHE_POLICY_ENABLED else: policy = Volume.READ_CACHE_POLICY_DISABLED self.c.volume_physical_disk_cache_update(lsm_vol, policy) self.display_data( [ VolumeRAMCacheInfo( lsm_vol.id, *self.c.volume_cache_info(lsm_vol))]) def volume_read_cache_policy_update(self, args): lsm_vol = _get_item(self.c.volumes(), args.vol, "Volume") if args.policy == "ENABLE": policy = Volume.PHYSICAL_DISK_CACHE_ENABLED else: policy = Volume.PHYSICAL_DISK_CACHE_DISABLED self.c.volume_read_cache_policy_update(lsm_vol, policy) self.display_data( [ VolumeRAMCacheInfo( lsm_vol.id, *self.c.volume_cache_info(lsm_vol))]) def volume_write_cache_policy_update(self, args): lsm_vol = _get_item(self.c.volumes(), args.vol, "Volume") if args.policy == 'WB': policy = Volume.WRITE_CACHE_POLICY_WRITE_BACK elif args.policy == 'AUTO': policy = Volume.WRITE_CACHE_POLICY_AUTO else: policy = Volume.WRITE_CACHE_POLICY_WRITE_THROUGH self.c.volume_write_cache_policy_update(lsm_vol, policy) self.display_data( [ VolumeRAMCacheInfo( lsm_vol.id, *self.c.volume_cache_info(lsm_vol))]) def local_disk_ident_led_on(self, args): LocalDisk.ident_led_on(args.path) def local_disk_ident_led_off(self, args): LocalDisk.ident_led_off(args.path) def local_disk_fault_led_on(self, args): LocalDisk.fault_led_on(args.path) def local_disk_fault_led_off(self, args): LocalDisk.fault_led_off(args.path) __init__.pyo000064400000000421147576777270007066 0ustar00 /P`c@s<yddlmZWn!ek r7ddlmZnXdS(i(tcmd_line_wrapperiN(tcmdlineRt ImportError(((s7/usr/lib/python2.7/site-packages/lsm/lsmcli/__init__.pyts cmdline.pyc000064400000170163147576777270006741 0ustar00 /P`cK@sddlZddlZddlZddlZddlZddlZddlZddlmZm Z ddlm Z ddl Z ddl m Z mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZddlm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)dddd d gZ*e j+rie,Z-nydd l.m/Z/Wn!e0k rdd l1m/Z/nXdd Z3d Z4dZ5dZ6dZ7dZ8dZ9dZ:dZ;dZ<e=dZ>dZ?de@fdYZAdeBdZCdZDdddd d!d"d#d$d%d&d'd(g ZEdpZFd,d-jGeFZHdqZId2d-jGeIZJd3d4gZKd5d-jGeKZLeMd6d7d8d9d:eLd;eKd<e9ZNd=d>d?gZOd@d-jGeOdAdBZPeMd6d7d8d9d:ePd;eOd<e9ZQdCZReMd6dDd8dEd:dFZSeSjTZUdGeUd:dqeMeegeMd6d d:d?dqeMeegeMd6d d:d@dqeMeegf3ZheMdAdBdCdDdEdFdGdHdIdJdKdLdMdNdOd}dPddQddRddSddTddUddVddWddXddYddZdd[dd\dd]dd^dd_dd`ddaddbddcddddedfd5dgd7dhd9did;djddkddld dmd %ZidnejfdoYZkdS(riN(tArgumentParsertArgumentTypeError(tRawTextHelpFormatter(tClienttPooltVERSIONtLsmErrortDisktVolumet JobStatust ErrorNumbert BlockRanget uri_parsetProxytsize_human_2_size_bytest AccessGroupt FileSystemt NfsExportt TargetPortt LocalDisktBattery( t DisplayDatatPlugDatatouttvol_provision_str_to_typetvol_rep_type_str_to_typetVolumeRAIDInfot PoolRAIDInfotVcrCapt LocalDiskInfotVolumeRAMCacheInfoslocal-disk-listslocal-disk-ident-led-onslocal-disk-ident-led-offslocal-disk-fault-led-onslocal-disk-fault-led-off(t OrderedDictcCsbd}d}zyt}|j|Wntk rg}tjjt|tjjd}nt k r}tjjt|dtjj|j t j krd}qd}n]t k rd}nGtk r}|j }n,ddl}|jd tjd}nXWd|rPy|j|WqPtk rLqPXntj|XdS( s+ Common command line code, called. iis i iiiNtfile(tNonetCmdLinetprocesstArgErrortsyststderrtwritetstrtflushRtcodeR tPERMISSION_DENIEDtKeyboardInterruptt SystemExitt tracebackt print_exctstdouttshutdownt Exceptiontexit(tcterr_exittclitaetletseR.((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytcmd_line_wrapper;s<           cCshtjj}tj|}z,tjtjjtjjd}Wdtj|tj |X|S(Ni( R%tstdintfilenottermiost tcgetattrtttytsetrawtreadt tcsetattrt TCSADRAIN(tfdtprevtch((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytgetchhscCs<tj|\}}}|r(||fStd|dS(s If init_id is a WWPN, convert it into LSM standard version: (?:[0-9a-f]{2}:){7}[0-9a-f]{2} Return (converted_init_id, lsm_init_type) s,--init "%s" is not a valid WWPN or iSCSI IQNN(Rtinitiator_id_verifyR$(tinit_idtvalidtconverted_init_typetconverted_init_id((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytparse_convert_initss cCs6tj|\}}}|r"|Std|dS(s Call back from validating an initiator :param init_id: Initiator to validate :return: Value of initiator or raises an exception s!"%s" is invalid WWPN or iSCSI IQNN(RRHR(RIRJt_RL((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt _check_initscCs^y6t|d}|dkr1td|n|SWn!tk rYtd|nXdS(s Call back for validating a positive integer :param num: Number string to check :return: Numeric value, else exception i is,invalid: require positive integer value '%d's*invalid: not a positive integer value '%s'N(tlongRt ValueError(tnumtrc((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_check_positive_integers  tchild_cCs |jS(N(tupper(ts((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_upperscCs|s tS|jd}t|dkr/tSd|kr?tSx|D]}dt|koidknsrtSt|dkr|ddkrtSyt|dd krtSWqFtk rtSXqFWtS( s Check if a string represents a valid ip4 address :param address: String representing address :return: True if valid address, else false t.it/iiit0i i(tFalsetsplittlentintRQtTrue(taddresstpartsti((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_valid_ip4_addresss$  ""  cskdt}|stSd|kr&tSt|jddkrEtS|jd}t|dksxt|dkr|tSd|d krt|jsd GHtS|jd d gnd|krg|D]}|d kr|^q}|jd t}n|rt|d ks.t|d krgtd|Doftfdd j |DStS(s Check if a string represents a valid ipv6 address :param address: String representing address :return: True if valid address, else false sABCDEFabcdef0123456789:RZs::it:ii RYisNot valid ipv suffixR[ticss!|]}t|dkVqdS(iN(R^(t.0tx((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pys sc3s|]}|kVqdS(N((RgRh(tallowed(s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pys s( R\R^R]RdtpoptextendtappendR`talltjoin(Rat has_zerosRbtp((Ris6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_valid_ip6_addresss0 $ %  *#cstjdtjtjd}t|r4tSt|rDtSt|dkrZtS|j|rmtS|ddkr|d }nt fd|j dDS(s Checks to see if the supplied string is a valid ip4/6 or hostname :param ip_hn: String representing address user inputted :return: True if valid IP address or hostname s(?!-)[A-Z0-9-]{1,63}(?s( tretcompilet IGNORECASERdR`RqR^R\RrRmR](tip_hnt digits_only((Ris6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_is_valid_network_names   c Csd}|rt}n|jddddddtjdtf|jdd dd d td d dd|dd|jdddddd|dd|jdddddd|dd|jdddd dd|d ddd|jd d!dddd"|d#tdd$|jd%d&dddd'|d#tdd(|jd)d*dd dd+|dd,d t|jd-dddd.|dd/|jd0dddd1|d#tdd2|jd3d4dddd5|d#tdd6|rt}d7|d+|<|j |nd8S(9s As https://bugs.python.org/issue23058 indicate, argument parser should not have subparser sharing the same argument and destination. For subparser, we add common options as 'child_xxx' destination. For default value, False is the only allowed default value in root. Rfs-vs --versiontactiontversions%s %sis-us--uritstorettypetmetavarstdests%surithelps,Uniform resource identifier (env LSMCLI_URI)s-Ps--promptt store_trues%sprompts)Prompt for password (env LSMCLI_PASSWORD)s-Hs--humans%shumans:Print sizes in human readable format (e.g., MiB, GiB, TiB)s-ts--terses%ssepss;Print output in terse form with "SEP" as a record separators-es--enums%senumtdefaults3Display enumerated types as numbers instead of texts-fs--forces%sforces3Bypass confirmation prompt for data loss operationss-ws--waits%swaits+Command timeout value in ms (default = 30s)s--headers%sheadersInclude the header with terses-bs%s_asyncsmRun the command async. Instead of waiting for completion. Command will exit(7) and job id written to stdout.s-ss--scripts%sscriptsMDisplaying data in script friendly way with additional information(if exists)i0uN( t_CHILD_OPTION_DST_PREFIXt add_argumentR%targvRR(R\RTtdictt set_defaults(t arg_parsertis_childtprefixt default_dict((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_add_common_optionss\   cCslg|_y1t|jdkr9tj|j|_nWn+tk rg}|jtjkrhqhnX|S(Ni( tsd_pathsR^tvpd83Rt vpd83_searchRR*R t NO_SUPPORT(tlsm_objtlsm_err((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt _add_sd_pathsXs  R$cBseZdZdZRS(cOs tj|||||_dS(s, Class represents an error. N(R2t__init__tmsg(tselftmessagetargstkwargs((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRescCs$dtjjtjd|jfS(Ns%s: error: %s i(tostpathtbasenameR%RR(R((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt__str__ls(t__name__t __module__RR(((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyR$ds titemcCsKx!|D]}|j|kr|SqW|rCtd||fndSdS(Ns%s with ID %s not found!(tidR$R!(tltthe_idt friendly_namet raise_errorR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt _get_itemus  cCs*t|}|r|Std|dS(sT Custom value checker for hostname/IP address :param addr: :return: s%s is invalid IP or hostnameN(RxR(taddrRJ((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_check_network_hosts tVOLUMEStPOOLStFSt SNAPSHOTStEXPORTStNFS_CLIENT_AUTHt ACCESS_GROUPStSYSTEMStDISKStPLUGINSt TARGET_PORTSt BATTERIEStDEFAULTtTHINtFULLsprovisioning type: s, tCLONEtCOPYt MIRROR_ASYNCt MIRROR_SYNCsreplication type: tENABLEtDISABLEsPolicy: tnames--policyR}sRtchoicesR|tWBtAUTOtWTsWrite cache polices: s' which stand for "write back", "auto", s"write through"s7Can use B, KiB, MiB, GiB, TiB, PiB postfix (IEC sizing)s--sysss System IDsmSearch by System ID. Only supported for: (VOLUMES, POOLS, FS, DISKS, ACCESS_GROUPS, TARGET_PORTS, BATTERIES)s--pools sPool IDs;Search by Pool ID. Only supported for: (VOLUMES, POOLS, FS)s--volss Volume IDsASearch by Volume ID. Only supported for: (VOLUMES, ACCESS_GROUPS)s--fsssFile System IDs=Search by FS ID. Only supported for: (FS, SNAPSHOTS, EXPORTS)s--agssAccess Group IDsGSearch by Access Group ID. Only supported for: (ACCESS_GROUPS, VOLUMES)s--inits s Initiator IDs--snaps s Snapshot IDs--exports s Export IDs --nfs-exportss6Search by NFS Export ID. Only supported for: (EXPORTS)s--disks s.Search by Disk ID. Only supported for: (DISKS)s--sizess--tgtss=Search by target port ID. Only supported for: (TARGET_PORTS)s--pathsLocal disk paths tlistsList records of different typesRs--typesList records of type: s s3 When listing SNAPSHOTS, it requires --fs .stoptionals job-statuss Retrieve information about a jobs--jobss job status idt capabilitiessRetrieves array capabilitiess plugin-infos(Retrieves plugin description and versions volume-createsCreates a volume (logical unit)s--names volume namess--provisioningRsvolume-raid-creates(Creates a RAIDed volume on hardware RAIDss>Free disks for new RAIDed volume. This is repeatable argument.RyRls --raid-types@RAID type for the new RAID group. Should be one of these: %ss --strip-sizes Strip size. svolume-raid-create-caps=Query capability of creating a RAIDed volume on hardware RAIDs volume-deletesDeletes a volume given its ids volume-resizesRe-sizes a volumes s New size. %ssvolume-replicates:Creates a new volume and replicates provided volume to it.ss"The name for New replicated volumes --rep-types s[Pool ID to contain the new volume. By default, new volume will be created in the same pool.svolume-replicate-ranges3Replicates a portion of a volume to existing volumes --src-vols sSource volume ids --dst-vols sDestination volume ids sReplication type: CLONE, COPYs --src-startss>Source volume start block number. This is repeatable argument.s --dst-startssCDestination volume start block number. This is repeatable argument.s--counts s;Number of blocks to replicate. This is repeatable argument.s!volume-replicate-range-block-sizes2Size of each replicated block on a system in bytessvolume-dependantss>Returns True if volume has a dependant child, like replicationsvolume-dependants-rmsRemoves volume dependenciessvolume-access-groups4Lists the access group(s) that have access to volumes volume-masks>Grants access to an access group to a volume, like LUN Maskings volume-unmasks7Revoke the access of specified access group to a volumes volume-enablesEnable block access of a volumesvolume-disables Disable block access of a volumesvolume-raid-infosQuery volume RAID informationsvolume-ident-led-ons!Enable the IDENT LED for a volumesTargeted volume. svolume-ident-led-offs"Disable the IDENT LED for a volumessystem-read-cache-pct-updates,Change the read cache percentage of a systemsTargeted system. s --read-pctsRead cache percentage. spool-member-infos!Query Pool membership informationsaccess-group-createsCreate an access groups s$Human readable name for access groupsaccess-group-adds+Add an initiator into existing access groupsaccess-group-removes.Remove an initiator from existing access groupsaccess-group-deletesDeletes an access groupsaccess-group-volumessBLists the volumes that the access group has been granted access tos iscsi-chaps5Configures iSCSI inbound/outbound CHAP authentications --in-users sInbound chap user names --in-passs sInbound chap passwords --out-users sOutbound chap user names --out-passs sOutbound chap passwords fs-createsCreates a file systems sname of the file systems fs-deletesDelete a filesystems fs-resizesRe-sizes a filesystems fs-exportsExport a filesystem via NFS.s --exportpaths s(NFS server export path. e.g. '/foo/bar'.s --anonuids s%UID(User ID) to map to anonymous users --anongids s&GID(Group ID) to map to anonymous users --auth-types sNFS client authentication types --root-hosts s9The host/IP has root access. This is repeatable argument.s --ro-hosts srThe host/IP has readonly access. This is repeatable argument. At least one '--ro-host' or '--rw-host' is required.s --rw-hosts ssThe host/IP has readwrite access. This is repeatable argument. At least one '--ro-host' or '--rw-host' is required.s fs-unexportsRemove an NFS exportsfs-clonesCreates a file system clones--src-fss s&The ID of existing source file system.s --dst-names s3The name for newly created destination file system.s--backing-snapshots sbacking snapshot idsfs-snap-createsCreates a snapshots s'The human friendly name of new snapshotsfs-snap-deletesDeletes a snapshotsfs-snap-restores;Restores a FS or specified files to previous snapshot states--files skOnly restore provided file Without this argument, all files will be restored This is a repeatable argument.s--fileasssGstore restore file name to another name. This is a repeatable argument.s fs-dependantssHReturns True if filesystem has a child dependency(clone/snapshot) existss-For file check This is a repeatable argument.sfs-dependants-rms Removes file system dependenciessHFile or files to remove dependencies for. This is a repeatable argument.s file-clones,Creates a clone of a file (thin provisioned)s--srcssCsource file to clone (relative path) This is a repeatable argument.s--dstss@Destination file (relative path), this is a repeatable argument.sQuery local disk informationsvolume-cache-infos"Query volume RAM cache informationsvolume-phy-disk-cache-updates)Update volume physical disk cache settingsvolume-read-cache-policy-updatesUpdate volume read cache policys volume-write-cache-policy-updates Update volume write cache policys/Turn on the identification LED for a local disks0Turn off the identification LED for a local disks&Turn on the fault LED for a local disks'Turn off the fault LED for a local disktlsslist --type systemstlpslist --type poolstlvslist --type volumestldslist --type diskstlaslist --type access_groupstlfslist --type fstltslist --type target_portsR4Rptvctvrctvrcctvdtvrtvmtvutvetvitactaatartadtvritvilontvilofftsrcputpmitldltlbslist --type batteriestvcitvpdcutvrcputvwcputldilontldilofftldflontldfloffR"cBseZdZdZdZdZedZedZdZ dZ edZ d Z d Z d Zd Zd ZdZdZdZdZdZdZdZdZdZedZdZdZdZdZdZdZ dZ!dZ"d Z#d!Z$d"Z%ed#Z&d$Z'd%Z(d&Z)d'Z*d(Z+d)Z,d*Z-d+Z.d,Z/d-Z0d.Z1d/Z2d0Z3d1Z4d2Z5d3Z6d4Z7d5Z8d6Z9d7Z:d8Z;d9Z<d:Z=dFd;Z?dFd<Z@d=ZAd>ZBd?ZCd@ZDdAZEdBZFdCZGdDZHdEZIRS(Gs' Command line interface class. cCsd|jjs\|rdnd}td|t}|jdkrKtStdtSntSdS(s1 Give the user a chance to bail. twilltmaysxWarning: You are about to do an operation that %s cause data to be lost! Press [Y|y] to continue, any other key to aborttYsOperation aborted!N(RtforceRRGRVR`R\(RtdeletingRtpressed((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytconfirm_promptTs   cCst}t|dkrdStj}t}|jjr@t}n|jjrUt}n|jjrmtj }ntj |d|d|jj d|jj d|jjd|d|dS(Nit display_wayt flag_humant flag_enumtsplittertflag_with_headertflag_dsp_all_data( R\R^RtDISPLAY_WAY_DEFAULTR`RtseptheadertscripttDISPLAY_WAY_SCRIPTt display_datathumantenum(Rtobjectst display_allRR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRks         cCshg}d}tj|}x9|D]1}|j|\}}|jt||q"W|j|dS(Ns<}{>(Rtavailable_pluginsR]RlRR(RtdRtpluginsRptdescRz((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytdisplay_available_pluginss cCsXg}xKtjdD]<}|tkrC|jt|jdq|j|qW|S(sb Walk the command line argument list and build up a new command line with the appropriate substitutions which is then passed to argparse, so that we can avoid adding more sub parsers and do all argument parsing before the need to talk to the library :return copy of command line args with alias expansion: it (R%RtaliasesRkR]Rl(RSRc((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt handle_aliass  cCsCd}x6ttjD]"\}}|dj||7}qW|S(Nscommand aliases: s {0:<18} Alias of '{1}' (tsortedRtitemstformat(RStktv((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytalias_help_textsc CsZtdt}t|dttdddtjddt}t|dt|jdd }xtD]}|j |d d |d d |gdt}|j d }xA|j dgD]-}|d }|d =|j |dt|qW|j d}xV|j dgD]B}|d } |d =t | tsF| f} n|j | |qW|jdt||d jddqmWttjdkr|jtdn||_|jdtj} xt| jD]k\} } | jtr| tt} t| | dks<t| | tkrRt| | | qRqqW| S(s3 Command line interface parameters tadd_helpRt descriptions^The libStorageMgmt command line interface. Run %(prog)s -h for more on each command.tepilogsh Copyright 2012-2018 Red Hat, Inc. Please report bugs to tformatter_classR}tcommandRRtparentsscmd required argumentsRtrequiredscmd optional argumentsRtfunct-RNiN( RR\RR`R"R Rtadd_subparserstcmdst add_parsertadd_argument_grouptgetRt isinstancettupleRtgetattrtreplaceR^R%Rt print_usageR3tparsert parse_argsRtvarsRt startswithRR!tsetattr(Rt parent_parserR t subparserstcmdt sub_parsertgrouptargRtflagst known_argsR R troot_k((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyR6sN        $   cCsQ|jjr1t|jjj|jjntdj|jjdS(sD Dump the supported nfs client authentication types s, N(RRRRnR4t export_auth(R((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt!display_nfs_client_authentications %c Csd}d}|jdf|jdf|jdf|jdf|jdf|jdf|jdf|jdff}xJ|D]B}|d ry|rt d ||d fq|\}}qyqyW||fS( Nt system_idtpool_idt volume_idtdisk_idtaccess_group_idtfs_idt nfs_export_idt tgt_port_idis,Search key specified more than once (%s, %s)i( R!R%tpooltvoltdisktagtfst nfs_exportttgtR$(Rt search_keyt search_valuet search_argstsa((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_get_search_key_values$         cCsstj|\}}|jdkrg}|dkr?d}n|dkrt|jj|jddt}|r|jj|}qn=|r|t j krt d|n|jj ||}|j td|Dn|jd krU|d krd}n|r6|tj kr6t d |n|j |jj||n|jd kr|d kryd}n|r|tj krt d|n|j |jj||n|jdkrL|jdkrt dn|r|d krt d|nt|jj|jd}|j |jj|n#|jdkr|dkrpd}n|r|tj krt d|n|j |jj||n|jdkr|rt dn|jn|jdkr|dkr d}n|dkrkt|jj |jddt}|r[|j |jj|S|j gSn(|r|tj krt d|n|j |jj||n|jdkr|rt dn|j |jjn|jdkrj|dkrd}n|r;|tj kr;t d|n|j td|jj||Dn|jd kr|d!krd}n|r|tj krt d"|n|j |jj||n|jd#kr|rt d$n|j ni|jd%kr\|r=|t!j kr=t d&|n|j |jj"||nt d'|jdS((NRR2RR4s Access GroupRs3Search key '%s' is not supported by volume listing.css|]}t|VqdS(N(R(RgR ((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pys sRR1s1Search key '%s' is not supported by pool listing.RR5Rs--fs requireds5Search key '%s' is not supported by snapshot listing.s File SystemRR6s6Search key '%s' is not supported by NFS Export listingRsCNFS client authentication type listing with search is not supportedRRs8Search key '%s' is not supported by Access Group listingRs+System listing with search is not supportedRR3s0Search key '%s' is not supported by disk listingcss|]}t|VqdS(N(R(RgR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pys bsRR7s7Search key '%s' is not supported by target port listingRs,Plugins listing with search is not supportedRs3Search key '%s' is not supported by battery listingsunsupported listing type=%s(#R"RCR|RR4t access_groupsR;R\t"volumes_accessible_by_access_groupRtSUPPORTED_SEARCH_KEYSR$tvolumesRRRtpoolsRR<R!t fs_snapshotsRtexportsR/R9taccess_groups_granted_to_volumeRtsystemsRtdisksRt target_portsRRt batteries(RRR?R@tlsm_volstlsm_agR<tlsm_vol((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyR s                               cCset|jj|jd}t|j\}}|jj|j|||}|j|gdS(NtSystem( RR4RLR%RMtinittaccess_group_createRR(RRtsystemRIt init_typet access_group((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRU|s  cCsit|jj|jd}t|j\}}|rO|jj|||S|jj|||SdS(Ns Access Group(RR4RDR;RMRTtaccess_group_initiator_addtaccess_group_initiator_delete(RRtopRQRIRW((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_add_rm_access_grp_initscCs |j|j|tgdS(N(RR\R`(RR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytaccess_group_addscCs |j|j|tgdS(N(RR\R\(RR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytaccess_group_removescCsW|jj}t||jd}|jj|}|jtd|DdS(Ns Access Groupcss|]}t|VqdS(N(R(RgR ((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pys s(R4RDRR;RERR(RRtaglR)tvols((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytaccess_group_volumessc CsOt|j\}}|tjkr:td|jn|jjrb|jj rbtdn|jjr|jj rtdn|jjr|jj rtdn|jj r|jj rtdn|jjr|jj r|jjo|jj rtdn|j j ||j|jj|jj|jj dS(Ns$--init "%s" is not a valid iSCSI IQNs--in-user requires --in-passs--in-pass requires --in-users--out-user requires --out-passs--out-pass requires --out-users?out-user and out-password only supported if inbound is supplied( RMRTRtINIT_TYPE_ISCSI_IQNR$Rtin_usertin_passtout_usertout_passR4tiscsi_chap_auth(RRRIRW((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt iscsi_chaps$  cCsAt|jj|jd}|jj|}|j|dS(NR(RR4RGR9RKR(RRR9tgroups((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytvolume_access_groupscCs4|jj}t||jd}|jj|S(Ns Access Group(R4RDRR;taccess_group_delete(RRR_R)((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRkscCsSt|jj|jd}|jtrO|jd|jj|dndS(Ns File Systems fs-delete(RR4R<RR`t _wait_for_itt fs_deleteR!(RRR<((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRmscCset|jj|jd}|jd|jj||j|j|j}|j |gdS(NRs fs-create( RR4RHR8Rlt fs_createRt_sizetsizeR(RRRpR<((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRns  cCst|jj|jd}|j|j}||jkrTttjdn|j t r|j d|jj ||}|j |gndS(Ns File SystemsSpecified size same as currents fs-resize(RR4R<RoRpt total_spaceRR tNO_STATE_CHANGERR\Rlt fs_resizeR(RRR<Rp((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRss cCst|jj|jd}d}|jrQt|jj||jd}n|jd|jj||j |}|j |gdS(NsSource File SystemtSnapshottfs_clone( RR4R<tsrc_fsR!tbacking_snapshotRIRlRutdst_nameR(RRRvtssR<((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRus !cCst|jj|jd}|jjrNt|jj||jd}nd}|jd|jj||j |j |ddS(Ns File SystemRtt fs_file_clone( RR4R<RRwRIR!RlRztsrctdst(RRR<Ry((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt file_clones !cCs/t|}|dkr+td|n|S(Nis$Incorrect size argument format: '%s'(RR$(RWt size_bytes((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRos  cCsW|jjdk r!|jj}nd}|r6d}nd}td|||fdS(NRet SUPPORTEDt UNSUPPORTEDs%s%s%s(RRR!R(RtcaptvalRWR ((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_cps c Cst|jj|jd}|jj|}t|jj}t|jtj}t j }|j j dk r|j j }nt}x|D]}d||sRcSs|jS(N(t dest_block(Rh((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRsR(tsort(trangesR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_check_overlaps   c Cst|jj|jd}t|jj|jd}t|j}|tjkrmt d|n|j }|j }|j }t | st |t |kot |kn rt dng}xtt |D]} t|| } t|| } t|| } | dkr=t dn| dkrXt dn| dkrst dn| | |jkrt d n| | |jkrt d n|jt| | | qWtj||jtr |jj||||ndS( Ns Source VolumesDestination Volumesinvalid replication type= %ss@Differing numbers of src_start, dest_start, and count parametersis--count: value < 0s--src-start: value < 0s--dst_start: value < 0s#--src-start + --count > source sizes(--dst-start + --count > destination size(RR4RGtsrc_voltdst_volRRRRR$t src_startt dst_starttcountR^RRPt num_of_blocksRlR R"RRR\tvolume_replicate_range( RRR{R|Rt src_startst dst_startstcountsRtbRRR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRs>     /    cCs8t|jj|jd}t|jj|dS(NRS(RR4RLR%Rt!volume_replicate_range_block_size(RRRW((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRscCsSt|jj|jd}t|jj|jd}|jj||dS(NRs Access Group(RR4RGR9RDR;t volume_mask(RRR9R;((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRscCsOt|jj|jd}t|jj|jd}|jj||S(Ns Access GroupR(RR4RDR;RGR9t volume_unmask(RRR;R9((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRscCst|jj|jd}|j|j}||j|jkr[tt j dn|j t r|j d|jj||}|jt|gndS(NRsSpecified size same as currenttresize(RR4RGR9RoRpt block_sizeRRR RrRR\Rlt volume_resizeRR(RRR RpR9((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRs cCs2t|jj|jd}|jj|dS(NR(RR4RGR9t volume_enable(RRR ((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRscCs2t|jj|jd}|jj|dS(NR(RR4RGR9tvolume_disable(RRR ((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRscCs2t|jj|jd}|jj|dS(Ns NFS Export(RR4RJtexportt export_remove(RRR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt fs_unexportsc Cst|jj|jd}t|jdkrWt|jdkrWtdn|jj|j|j |j |j|j|j |j |j d }|j|gdS(Ns File Systemis& please specify --ro-host or --rw-host(RR4R<R^trw_hosttro_hostR$t export_fsRt exportpatht root_hosttanonuidtanongidt auth_typeR!R(RRR<R((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt fs_export!s  cCs>t|jj|jd}|jj|}t|dS(NR(RR4RGR9tvolume_child_dependencyR(RRR RS((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytvolume_dependants6scCsAt|jj|jd}|jd|jj|ddS(NRsvolume-dependant-rm(RR4RGR9Rltvolume_child_dependency_rmR!(RRR ((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytvolume_dependants_rm<s cCsJt|jj|jd}|jt|j|jj|gdS(NR(RR4RGR9RRRtvolume_raid_info(RRRR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRAscCsJt|jj|jd}|jt|j|jj|gdS(NR(RR4RHR8RRRtpool_member_info(RRtlsm_pool((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRHscCs\tj|j}|jj}g|D]}|j|jkr(|^q(}t|t|jkrtt j ddj t |jt d|Dng|D]}|j tj@s|j^q}t|dkrtt jddj |n|jr!t|j}n tj}|jt|jj|j|||gdS(NsDisk ID %s not founds, css|]}|jVqdS(N(R(RgR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pys XsisDisk %s is not free(Rtraid_type_str_to_lsmt raid_typeR4RMRR:R^RR tNOT_FOUND_DISKRntsettstatusRt STATUS_FREEt DISK_NOT_FREEt strip_sizeRRtVCR_STRIP_SIZE_DEFAULTRRtvolume_raid_createR(RRRt all_lsm_disksRt lsm_diskst busy_disksR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyROs*+3    cCsJt|jj|jd}|jt|j|jj|gdS(NRS(RR4RLR%RRRtvolume_raid_create_cap_get(RRtlsm_sys((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytvolume_raid_create_caplscCs2t|jj|jd}|jj|dS(NR(RR4RGR9tvolume_ident_led_on(RRt lsm_volume((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRqscCs2t|jj|jd}|jj|dS(NR(RR4RGR9tvolume_ident_led_off(RRR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRvscCst|jj|jd}yt|j}Wn+tk r^}ttj t |nX|jj ||t|jj|jd}|j |gdS(NRS( RR4RLR%R_tread_pctRQRR tINVALID_ARGUMENTR(tsystem_read_cache_pct_updateR(RRt lsm_systemRR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyR{scCsDt|jj|jd}|jj||j}t|dS(Ns File System(RR4R<tfs_child_dependencyR R(RRR<RS((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt fs_dependantsscCsGt|jj|jd}|jd|jj||jddS(Ns File Systemsfs-dependants-rm(RR4R<Rltfs_child_dependency_rmR R!(RRR<((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytfs_dependants_rms    c Csd}tjjdd}tjj|s2dSt|}x|D]}|jjdriqHnyTg|jddD]}|j^q\}}||krt |||nWqHt k rqHXqHWWdQXdS( so Set uri from config file. Will be overridden by cmdline option or env var if present. turit~s/.lsmcliNt#t=i(suri( RRt expandusertexiststopentlstripR#R]tstripR$RQ(Rtallowed_config_optionst config_pathtftlineRhRR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_read_configfiles 1  cCs)|jjjjddtkr%tStS(sU Return True if current command is one of _CONNECTION_FREE_COMMANDS. RNR(RRRRt_CONNECTION_FREE_COMMANDSR`R\(R((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytis_connection_free_cmds cCsd|_d|_d|_d|_|j|_d|_t|jj |_ |j sj|j dkryt dn|j rdS|j tjddk rtjd|_ntjd|_|jjdk r|jj|_n|jdkrGd|jkr8|jjdkr8d|_d|_qGt dn|jjretj|_n|jdk rt|j}|d dkrt d qndS( Nis0[-w|--wait] requires a non-zero positive integert LSMCLI_URItLSMCLI_PASSWORDR|Rssim://s"--uri missing or export LSMCLI_URItusernames+password specified with no user name in uri(R!RR4R t unknown_argsR6RtcleanupR_twaitttmoR$RRRtgetenvtpasswordR|tprompttgetpassR (Rtu((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRs8       !   cCs0|jr|jn|r,tj|ndS(N(R R%R3(Rtec((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyR1s  cCs|jr"|jj|jn|rkt||_|jj|j|j|j|jj |_ nOtt |j|j|j|_t j drtdn|jj|_ |jj|j|jdS(s- Process the parsed command. tLSM_DEBUG_PLUGINs8Attach debugger to plug-in, press when ready...N(RRRR R4tplugin_registerRRR tplugin_unregisterR RRRtinputtcloseR1(RR6((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyR#s $ c Csg}itjd6tjd6tjd6tjd6tjd6tjd6tjd6}x%tjD]}idd6t j d6t j d6dd6t j d6t j d6t jd6}x|jD]v}y|||||  p                  2                    /  *     (RRR(RRRR(lRR%RRsRR?R=targparseRRRtsixtlsmRRRRRRR R R R R RRRRRRRtlsm.lsmcli.data_displayRRRRRRRRRRRtPY3R_RPt collectionsRt ImportErrort ordereddictR!R:RGRMRORTRRXRdRqRxR\RRR2R$R`RRt list_choicestprovision_typesRntprovision_helptreplicate_typestreplicate_helpt policy_typest policy_helpRt policy_opttwrite_cache_policy_typestwrite_cache_policy_helptwrite_cache_policy_optt size_helpt sys_id_opttcopytsys_id_filter_optt pool_id_opttpool_id_filter_optt vol_id_opttvol_id_filter_optt fs_id_opttfs_id_filter_optt ag_id_opttag_id_filter_optt init_id_optt snap_id_optt export_id_opttnfs_export_id_filter_opttdisk_id_filter_opttsize_optttgt_id_filter_opttlocal_disk_path_opttVOL_CREATE_RAID_TYPES_STRtANON_UID_GID_NARRtobjectR"(((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyts        vF     -     *  G                                                                            cmdline.pyo000064400000170163147576777270006755 0ustar00 /P`cK@sddlZddlZddlZddlZddlZddlZddlZddlmZm Z ddlm Z ddl Z ddl m Z mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZddlm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)dddd d gZ*e j+rie,Z-nydd l.m/Z/Wn!e0k rdd l1m/Z/nXdd Z3d Z4dZ5dZ6dZ7dZ8dZ9dZ:dZ;dZ<e=dZ>dZ?de@fdYZAdeBdZCdZDdddd d!d"d#d$d%d&d'd(g ZEdpZFd,d-jGeFZHdqZId2d-jGeIZJd3d4gZKd5d-jGeKZLeMd6d7d8d9d:eLd;eKd<e9ZNd=d>d?gZOd@d-jGeOdAdBZPeMd6d7d8d9d:ePd;eOd<e9ZQdCZReMd6dDd8dEd:dFZSeSjTZUdGeUd:dqeMeegeMd6d d:d?dqeMeegeMd6d d:d@dqeMeegf3ZheMdAdBdCdDdEdFdGdHdIdJdKdLdMdNdOd}dPddQddRddSddTddUddVddWddXddYddZdd[dd\dd]dd^dd_dd`ddaddbddcddddedfd5dgd7dhd9did;djddkddld dmd %ZidnejfdoYZkdS(riN(tArgumentParsertArgumentTypeError(tRawTextHelpFormatter(tClienttPooltVERSIONtLsmErrortDisktVolumet JobStatust ErrorNumbert BlockRanget uri_parsetProxytsize_human_2_size_bytest AccessGroupt FileSystemt NfsExportt TargetPortt LocalDisktBattery( t DisplayDatatPlugDatatouttvol_provision_str_to_typetvol_rep_type_str_to_typetVolumeRAIDInfot PoolRAIDInfotVcrCapt LocalDiskInfotVolumeRAMCacheInfoslocal-disk-listslocal-disk-ident-led-onslocal-disk-ident-led-offslocal-disk-fault-led-onslocal-disk-fault-led-off(t OrderedDictcCsbd}d}zyt}|j|Wntk rg}tjjt|tjjd}nt k r}tjjt|dtjj|j t j krd}qd}n]t k rd}nGtk r}|j }n,ddl}|jd tjd}nXWd|rPy|j|WqPtk rLqPXntj|XdS( s+ Common command line code, called. iis i iiiNtfile(tNonetCmdLinetprocesstArgErrortsyststderrtwritetstrtflushRtcodeR tPERMISSION_DENIEDtKeyboardInterruptt SystemExitt tracebackt print_exctstdouttshutdownt Exceptiontexit(tcterr_exittclitaetletseR.((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytcmd_line_wrapper;s<           cCshtjj}tj|}z,tjtjjtjjd}Wdtj|tj |X|S(Ni( R%tstdintfilenottermiost tcgetattrtttytsetrawtreadt tcsetattrt TCSADRAIN(tfdtprevtch((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytgetchhscCs<tj|\}}}|r(||fStd|dS(s If init_id is a WWPN, convert it into LSM standard version: (?:[0-9a-f]{2}:){7}[0-9a-f]{2} Return (converted_init_id, lsm_init_type) s,--init "%s" is not a valid WWPN or iSCSI IQNN(Rtinitiator_id_verifyR$(tinit_idtvalidtconverted_init_typetconverted_init_id((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytparse_convert_initss cCs6tj|\}}}|r"|Std|dS(s Call back from validating an initiator :param init_id: Initiator to validate :return: Value of initiator or raises an exception s!"%s" is invalid WWPN or iSCSI IQNN(RRHR(RIRJt_RL((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt _check_initscCs^y6t|d}|dkr1td|n|SWn!tk rYtd|nXdS(s Call back for validating a positive integer :param num: Number string to check :return: Numeric value, else exception i is,invalid: require positive integer value '%d's*invalid: not a positive integer value '%s'N(tlongRt ValueError(tnumtrc((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_check_positive_integers  tchild_cCs |jS(N(tupper(ts((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_upperscCs|s tS|jd}t|dkr/tSd|kr?tSx|D]}dt|koidknsrtSt|dkr|ddkrtSyt|dd krtSWqFtk rtSXqFWtS( s Check if a string represents a valid ip4 address :param address: String representing address :return: True if valid address, else false t.it/iiit0i i(tFalsetsplittlentintRQtTrue(taddresstpartsti((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_valid_ip4_addresss$  ""  cskdt}|stSd|kr&tSt|jddkrEtS|jd}t|dksxt|dkr|tSd|d krt|jsd GHtS|jd d gnd|krg|D]}|d kr|^q}|jd t}n|rt|d ks.t|d krgtd|Doftfdd j |DStS(s Check if a string represents a valid ipv6 address :param address: String representing address :return: True if valid address, else false sABCDEFabcdef0123456789:RZs::it:ii RYisNot valid ipv suffixR[ticss!|]}t|dkVqdS(iN(R^(t.0tx((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pys sc3s|]}|kVqdS(N((RgRh(tallowed(s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pys s( R\R^R]RdtpoptextendtappendR`talltjoin(Rat has_zerosRbtp((Ris6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_valid_ip6_addresss0 $ %  *#cstjdtjtjd}t|r4tSt|rDtSt|dkrZtS|j|rmtS|ddkr|d }nt fd|j dDS(s Checks to see if the supplied string is a valid ip4/6 or hostname :param ip_hn: String representing address user inputted :return: True if valid IP address or hostname s(?!-)[A-Z0-9-]{1,63}(?s( tretcompilet IGNORECASERdR`RqR^R\RrRmR](tip_hnt digits_only((Ris6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_is_valid_network_names   c Csd}|rt}n|jddddddtjdtf|jdd dd d td d dd|dd|jdddddd|dd|jdddddd|dd|jdddd dd|d ddd|jd d!dddd"|d#tdd$|jd%d&dddd'|d#tdd(|jd)d*dd dd+|dd,d t|jd-dddd.|dd/|jd0dddd1|d#tdd2|jd3d4dddd5|d#tdd6|rt}d7|d+|<|j |nd8S(9s As https://bugs.python.org/issue23058 indicate, argument parser should not have subparser sharing the same argument and destination. For subparser, we add common options as 'child_xxx' destination. For default value, False is the only allowed default value in root. Rfs-vs --versiontactiontversions%s %sis-us--uritstorettypetmetavarstdests%surithelps,Uniform resource identifier (env LSMCLI_URI)s-Ps--promptt store_trues%sprompts)Prompt for password (env LSMCLI_PASSWORD)s-Hs--humans%shumans:Print sizes in human readable format (e.g., MiB, GiB, TiB)s-ts--terses%ssepss;Print output in terse form with "SEP" as a record separators-es--enums%senumtdefaults3Display enumerated types as numbers instead of texts-fs--forces%sforces3Bypass confirmation prompt for data loss operationss-ws--waits%swaits+Command timeout value in ms (default = 30s)s--headers%sheadersInclude the header with terses-bs%s_asyncsmRun the command async. Instead of waiting for completion. Command will exit(7) and job id written to stdout.s-ss--scripts%sscriptsMDisplaying data in script friendly way with additional information(if exists)i0uN( t_CHILD_OPTION_DST_PREFIXt add_argumentR%targvRR(R\RTtdictt set_defaults(t arg_parsertis_childtprefixt default_dict((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_add_common_optionss\   cCslg|_y1t|jdkr9tj|j|_nWn+tk rg}|jtjkrhqhnX|S(Ni( tsd_pathsR^tvpd83Rt vpd83_searchRR*R t NO_SUPPORT(tlsm_objtlsm_err((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt _add_sd_pathsXs  R$cBseZdZdZRS(cOs tj|||||_dS(s, Class represents an error. N(R2t__init__tmsg(tselftmessagetargstkwargs((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRescCs$dtjjtjd|jfS(Ns%s: error: %s i(tostpathtbasenameR%RR(R((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt__str__ls(t__name__t __module__RR(((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyR$ds titemcCsKx!|D]}|j|kr|SqW|rCtd||fndSdS(Ns%s with ID %s not found!(tidR$R!(tltthe_idt friendly_namet raise_errorR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt _get_itemus  cCs*t|}|r|Std|dS(sT Custom value checker for hostname/IP address :param addr: :return: s%s is invalid IP or hostnameN(RxR(taddrRJ((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_check_network_hosts tVOLUMEStPOOLStFSt SNAPSHOTStEXPORTStNFS_CLIENT_AUTHt ACCESS_GROUPStSYSTEMStDISKStPLUGINSt TARGET_PORTSt BATTERIEStDEFAULTtTHINtFULLsprovisioning type: s, tCLONEtCOPYt MIRROR_ASYNCt MIRROR_SYNCsreplication type: tENABLEtDISABLEsPolicy: tnames--policyR}sRtchoicesR|tWBtAUTOtWTsWrite cache polices: s' which stand for "write back", "auto", s"write through"s7Can use B, KiB, MiB, GiB, TiB, PiB postfix (IEC sizing)s--sysss System IDsmSearch by System ID. Only supported for: (VOLUMES, POOLS, FS, DISKS, ACCESS_GROUPS, TARGET_PORTS, BATTERIES)s--pools sPool IDs;Search by Pool ID. Only supported for: (VOLUMES, POOLS, FS)s--volss Volume IDsASearch by Volume ID. Only supported for: (VOLUMES, ACCESS_GROUPS)s--fsssFile System IDs=Search by FS ID. Only supported for: (FS, SNAPSHOTS, EXPORTS)s--agssAccess Group IDsGSearch by Access Group ID. Only supported for: (ACCESS_GROUPS, VOLUMES)s--inits s Initiator IDs--snaps s Snapshot IDs--exports s Export IDs --nfs-exportss6Search by NFS Export ID. Only supported for: (EXPORTS)s--disks s.Search by Disk ID. Only supported for: (DISKS)s--sizess--tgtss=Search by target port ID. Only supported for: (TARGET_PORTS)s--pathsLocal disk paths tlistsList records of different typesRs--typesList records of type: s s3 When listing SNAPSHOTS, it requires --fs .stoptionals job-statuss Retrieve information about a jobs--jobss job status idt capabilitiessRetrieves array capabilitiess plugin-infos(Retrieves plugin description and versions volume-createsCreates a volume (logical unit)s--names volume namess--provisioningRsvolume-raid-creates(Creates a RAIDed volume on hardware RAIDss>Free disks for new RAIDed volume. This is repeatable argument.RyRls --raid-types@RAID type for the new RAID group. Should be one of these: %ss --strip-sizes Strip size. svolume-raid-create-caps=Query capability of creating a RAIDed volume on hardware RAIDs volume-deletesDeletes a volume given its ids volume-resizesRe-sizes a volumes s New size. %ssvolume-replicates:Creates a new volume and replicates provided volume to it.ss"The name for New replicated volumes --rep-types s[Pool ID to contain the new volume. By default, new volume will be created in the same pool.svolume-replicate-ranges3Replicates a portion of a volume to existing volumes --src-vols sSource volume ids --dst-vols sDestination volume ids sReplication type: CLONE, COPYs --src-startss>Source volume start block number. This is repeatable argument.s --dst-startssCDestination volume start block number. This is repeatable argument.s--counts s;Number of blocks to replicate. This is repeatable argument.s!volume-replicate-range-block-sizes2Size of each replicated block on a system in bytessvolume-dependantss>Returns True if volume has a dependant child, like replicationsvolume-dependants-rmsRemoves volume dependenciessvolume-access-groups4Lists the access group(s) that have access to volumes volume-masks>Grants access to an access group to a volume, like LUN Maskings volume-unmasks7Revoke the access of specified access group to a volumes volume-enablesEnable block access of a volumesvolume-disables Disable block access of a volumesvolume-raid-infosQuery volume RAID informationsvolume-ident-led-ons!Enable the IDENT LED for a volumesTargeted volume. svolume-ident-led-offs"Disable the IDENT LED for a volumessystem-read-cache-pct-updates,Change the read cache percentage of a systemsTargeted system. s --read-pctsRead cache percentage. spool-member-infos!Query Pool membership informationsaccess-group-createsCreate an access groups s$Human readable name for access groupsaccess-group-adds+Add an initiator into existing access groupsaccess-group-removes.Remove an initiator from existing access groupsaccess-group-deletesDeletes an access groupsaccess-group-volumessBLists the volumes that the access group has been granted access tos iscsi-chaps5Configures iSCSI inbound/outbound CHAP authentications --in-users sInbound chap user names --in-passs sInbound chap passwords --out-users sOutbound chap user names --out-passs sOutbound chap passwords fs-createsCreates a file systems sname of the file systems fs-deletesDelete a filesystems fs-resizesRe-sizes a filesystems fs-exportsExport a filesystem via NFS.s --exportpaths s(NFS server export path. e.g. '/foo/bar'.s --anonuids s%UID(User ID) to map to anonymous users --anongids s&GID(Group ID) to map to anonymous users --auth-types sNFS client authentication types --root-hosts s9The host/IP has root access. This is repeatable argument.s --ro-hosts srThe host/IP has readonly access. This is repeatable argument. At least one '--ro-host' or '--rw-host' is required.s --rw-hosts ssThe host/IP has readwrite access. This is repeatable argument. At least one '--ro-host' or '--rw-host' is required.s fs-unexportsRemove an NFS exportsfs-clonesCreates a file system clones--src-fss s&The ID of existing source file system.s --dst-names s3The name for newly created destination file system.s--backing-snapshots sbacking snapshot idsfs-snap-createsCreates a snapshots s'The human friendly name of new snapshotsfs-snap-deletesDeletes a snapshotsfs-snap-restores;Restores a FS or specified files to previous snapshot states--files skOnly restore provided file Without this argument, all files will be restored This is a repeatable argument.s--fileasssGstore restore file name to another name. This is a repeatable argument.s fs-dependantssHReturns True if filesystem has a child dependency(clone/snapshot) existss-For file check This is a repeatable argument.sfs-dependants-rms Removes file system dependenciessHFile or files to remove dependencies for. This is a repeatable argument.s file-clones,Creates a clone of a file (thin provisioned)s--srcssCsource file to clone (relative path) This is a repeatable argument.s--dstss@Destination file (relative path), this is a repeatable argument.sQuery local disk informationsvolume-cache-infos"Query volume RAM cache informationsvolume-phy-disk-cache-updates)Update volume physical disk cache settingsvolume-read-cache-policy-updatesUpdate volume read cache policys volume-write-cache-policy-updates Update volume write cache policys/Turn on the identification LED for a local disks0Turn off the identification LED for a local disks&Turn on the fault LED for a local disks'Turn off the fault LED for a local disktlsslist --type systemstlpslist --type poolstlvslist --type volumestldslist --type diskstlaslist --type access_groupstlfslist --type fstltslist --type target_portsR4Rptvctvrctvrcctvdtvrtvmtvutvetvitactaatartadtvritvilontvilofftsrcputpmitldltlbslist --type batteriestvcitvpdcutvrcputvwcputldilontldilofftldflontldfloffR"cBseZdZdZdZdZedZedZdZ dZ edZ d Z d Z d Zd Zd ZdZdZdZdZdZdZdZdZdZedZdZdZdZdZdZdZ dZ!dZ"d Z#d!Z$d"Z%ed#Z&d$Z'd%Z(d&Z)d'Z*d(Z+d)Z,d*Z-d+Z.d,Z/d-Z0d.Z1d/Z2d0Z3d1Z4d2Z5d3Z6d4Z7d5Z8d6Z9d7Z:d8Z;d9Z<d:Z=dFd;Z?dFd<Z@d=ZAd>ZBd?ZCd@ZDdAZEdBZFdCZGdDZHdEZIRS(Gs' Command line interface class. cCsd|jjs\|rdnd}td|t}|jdkrKtStdtSntSdS(s1 Give the user a chance to bail. twilltmaysxWarning: You are about to do an operation that %s cause data to be lost! Press [Y|y] to continue, any other key to aborttYsOperation aborted!N(RtforceRRGRVR`R\(RtdeletingRtpressed((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytconfirm_promptTs   cCst}t|dkrdStj}t}|jjr@t}n|jjrUt}n|jjrmtj }ntj |d|d|jj d|jj d|jjd|d|dS(Nit display_wayt flag_humant flag_enumtsplittertflag_with_headertflag_dsp_all_data( R\R^RtDISPLAY_WAY_DEFAULTR`RtseptheadertscripttDISPLAY_WAY_SCRIPTt display_datathumantenum(Rtobjectst display_allRR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRks         cCshg}d}tj|}x9|D]1}|j|\}}|jt||q"W|j|dS(Ns<}{>(Rtavailable_pluginsR]RlRR(RtdRtpluginsRptdescRz((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytdisplay_available_pluginss cCsXg}xKtjdD]<}|tkrC|jt|jdq|j|qW|S(sb Walk the command line argument list and build up a new command line with the appropriate substitutions which is then passed to argparse, so that we can avoid adding more sub parsers and do all argument parsing before the need to talk to the library :return copy of command line args with alias expansion: it (R%RtaliasesRkR]Rl(RSRc((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt handle_aliass  cCsCd}x6ttjD]"\}}|dj||7}qW|S(Nscommand aliases: s {0:<18} Alias of '{1}' (tsortedRtitemstformat(RStktv((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytalias_help_textsc CsZtdt}t|dttdddtjddt}t|dt|jdd }xtD]}|j |d d |d d |gdt}|j d }xA|j dgD]-}|d }|d =|j |dt|qW|j d}xV|j dgD]B}|d } |d =t | tsF| f} n|j | |qW|jdt||d jddqmWttjdkr|jtdn||_|jdtj} xt| jD]k\} } | jtr| tt} t| | dks<t| | tkrRt| | | qRqqW| S(s3 Command line interface parameters tadd_helpRt descriptions^The libStorageMgmt command line interface. Run %(prog)s -h for more on each command.tepilogsh Copyright 2012-2018 Red Hat, Inc. Please report bugs to tformatter_classR}tcommandRRtparentsscmd required argumentsRtrequiredscmd optional argumentsRtfunct-RNiN( RR\RR`R"R Rtadd_subparserstcmdst add_parsertadd_argument_grouptgetRt isinstancettupleRtgetattrtreplaceR^R%Rt print_usageR3tparsert parse_argsRtvarsRt startswithRR!tsetattr(Rt parent_parserR t subparserstcmdt sub_parsertgrouptargRtflagst known_argsR R troot_k((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyR6sN        $   cCsQ|jjr1t|jjj|jjntdj|jjdS(sD Dump the supported nfs client authentication types s, N(RRRRnR4t export_auth(R((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt!display_nfs_client_authentications %c Csd}d}|jdf|jdf|jdf|jdf|jdf|jdf|jdf|jdff}xJ|D]B}|d ry|rt d ||d fq|\}}qyqyW||fS( Nt system_idtpool_idt volume_idtdisk_idtaccess_group_idtfs_idt nfs_export_idt tgt_port_idis,Search key specified more than once (%s, %s)i( R!R%tpooltvoltdisktagtfst nfs_exportttgtR$(Rt search_keyt search_valuet search_argstsa((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_get_search_key_values$         cCsstj|\}}|jdkrg}|dkr?d}n|dkrt|jj|jddt}|r|jj|}qn=|r|t j krt d|n|jj ||}|j td|Dn|jd krU|d krd}n|r6|tj kr6t d |n|j |jj||n|jd kr|d kryd}n|r|tj krt d|n|j |jj||n|jdkrL|jdkrt dn|r|d krt d|nt|jj|jd}|j |jj|n#|jdkr|dkrpd}n|r|tj krt d|n|j |jj||n|jdkr|rt dn|jn|jdkr|dkr d}n|dkrkt|jj |jddt}|r[|j |jj|S|j gSn(|r|tj krt d|n|j |jj||n|jdkr|rt dn|j |jjn|jdkrj|dkrd}n|r;|tj kr;t d|n|j td|jj||Dn|jd kr|d!krd}n|r|tj krt d"|n|j |jj||n|jd#kr|rt d$n|j ni|jd%kr\|r=|t!j kr=t d&|n|j |jj"||nt d'|jdS((NRR2RR4s Access GroupRs3Search key '%s' is not supported by volume listing.css|]}t|VqdS(N(R(RgR ((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pys sRR1s1Search key '%s' is not supported by pool listing.RR5Rs--fs requireds5Search key '%s' is not supported by snapshot listing.s File SystemRR6s6Search key '%s' is not supported by NFS Export listingRsCNFS client authentication type listing with search is not supportedRRs8Search key '%s' is not supported by Access Group listingRs+System listing with search is not supportedRR3s0Search key '%s' is not supported by disk listingcss|]}t|VqdS(N(R(RgR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pys bsRR7s7Search key '%s' is not supported by target port listingRs,Plugins listing with search is not supportedRs3Search key '%s' is not supported by battery listingsunsupported listing type=%s(#R"RCR|RR4t access_groupsR;R\t"volumes_accessible_by_access_groupRtSUPPORTED_SEARCH_KEYSR$tvolumesRRRtpoolsRR<R!t fs_snapshotsRtexportsR/R9taccess_groups_granted_to_volumeRtsystemsRtdisksRt target_portsRRt batteries(RRR?R@tlsm_volstlsm_agR<tlsm_vol((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyR s                               cCset|jj|jd}t|j\}}|jj|j|||}|j|gdS(NtSystem( RR4RLR%RMtinittaccess_group_createRR(RRtsystemRIt init_typet access_group((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRU|s  cCsit|jj|jd}t|j\}}|rO|jj|||S|jj|||SdS(Ns Access Group(RR4RDR;RMRTtaccess_group_initiator_addtaccess_group_initiator_delete(RRtopRQRIRW((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_add_rm_access_grp_initscCs |j|j|tgdS(N(RR\R`(RR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytaccess_group_addscCs |j|j|tgdS(N(RR\R\(RR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytaccess_group_removescCsW|jj}t||jd}|jj|}|jtd|DdS(Ns Access Groupcss|]}t|VqdS(N(R(RgR ((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pys s(R4RDRR;RERR(RRtaglR)tvols((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytaccess_group_volumessc CsOt|j\}}|tjkr:td|jn|jjrb|jj rbtdn|jjr|jj rtdn|jjr|jj rtdn|jj r|jj rtdn|jjr|jj r|jjo|jj rtdn|j j ||j|jj|jj|jj dS(Ns$--init "%s" is not a valid iSCSI IQNs--in-user requires --in-passs--in-pass requires --in-users--out-user requires --out-passs--out-pass requires --out-users?out-user and out-password only supported if inbound is supplied( RMRTRtINIT_TYPE_ISCSI_IQNR$Rtin_usertin_passtout_usertout_passR4tiscsi_chap_auth(RRRIRW((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt iscsi_chaps$  cCsAt|jj|jd}|jj|}|j|dS(NR(RR4RGR9RKR(RRR9tgroups((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytvolume_access_groupscCs4|jj}t||jd}|jj|S(Ns Access Group(R4RDRR;taccess_group_delete(RRR_R)((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRkscCsSt|jj|jd}|jtrO|jd|jj|dndS(Ns File Systems fs-delete(RR4R<RR`t _wait_for_itt fs_deleteR!(RRR<((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRmscCset|jj|jd}|jd|jj||j|j|j}|j |gdS(NRs fs-create( RR4RHR8Rlt fs_createRt_sizetsizeR(RRRpR<((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRns  cCst|jj|jd}|j|j}||jkrTttjdn|j t r|j d|jj ||}|j |gndS(Ns File SystemsSpecified size same as currents fs-resize(RR4R<RoRpt total_spaceRR tNO_STATE_CHANGERR\Rlt fs_resizeR(RRR<Rp((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRss cCst|jj|jd}d}|jrQt|jj||jd}n|jd|jj||j |}|j |gdS(NsSource File SystemtSnapshottfs_clone( RR4R<tsrc_fsR!tbacking_snapshotRIRlRutdst_nameR(RRRvtssR<((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRus !cCst|jj|jd}|jjrNt|jj||jd}nd}|jd|jj||j |j |ddS(Ns File SystemRtt fs_file_clone( RR4R<RRwRIR!RlRztsrctdst(RRR<Ry((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt file_clones !cCs/t|}|dkr+td|n|S(Nis$Incorrect size argument format: '%s'(RR$(RWt size_bytes((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRos  cCsW|jjdk r!|jj}nd}|r6d}nd}td|||fdS(NRet SUPPORTEDt UNSUPPORTEDs%s%s%s(RRR!R(RtcaptvalRWR ((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_cps c Cst|jj|jd}|jj|}t|jj}t|jtj}t j }|j j dk r|j j }nt}x|D]}d||sRcSs|jS(N(t dest_block(Rh((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRsR(tsort(trangesR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_check_overlaps   c Cst|jj|jd}t|jj|jd}t|j}|tjkrmt d|n|j }|j }|j }t | st |t |kot |kn rt dng}xtt |D]} t|| } t|| } t|| } | dkr=t dn| dkrXt dn| dkrst dn| | |jkrt d n| | |jkrt d n|jt| | | qWtj||jtr |jj||||ndS( Ns Source VolumesDestination Volumesinvalid replication type= %ss@Differing numbers of src_start, dest_start, and count parametersis--count: value < 0s--src-start: value < 0s--dst_start: value < 0s#--src-start + --count > source sizes(--dst-start + --count > destination size(RR4RGtsrc_voltdst_volRRRRR$t src_startt dst_starttcountR^RRPt num_of_blocksRlR R"RRR\tvolume_replicate_range( RRR{R|Rt src_startst dst_startstcountsRtbRRR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRs>     /    cCs8t|jj|jd}t|jj|dS(NRS(RR4RLR%Rt!volume_replicate_range_block_size(RRRW((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRscCsSt|jj|jd}t|jj|jd}|jj||dS(NRs Access Group(RR4RGR9RDR;t volume_mask(RRR9R;((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRscCsOt|jj|jd}t|jj|jd}|jj||S(Ns Access GroupR(RR4RDR;RGR9t volume_unmask(RRR;R9((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRscCst|jj|jd}|j|j}||j|jkr[tt j dn|j t r|j d|jj||}|jt|gndS(NRsSpecified size same as currenttresize(RR4RGR9RoRpt block_sizeRRR RrRR\Rlt volume_resizeRR(RRR RpR9((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRs cCs2t|jj|jd}|jj|dS(NR(RR4RGR9t volume_enable(RRR ((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRscCs2t|jj|jd}|jj|dS(NR(RR4RGR9tvolume_disable(RRR ((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRscCs2t|jj|jd}|jj|dS(Ns NFS Export(RR4RJtexportt export_remove(RRR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt fs_unexportsc Cst|jj|jd}t|jdkrWt|jdkrWtdn|jj|j|j |j |j|j|j |j |j d }|j|gdS(Ns File Systemis& please specify --ro-host or --rw-host(RR4R<R^trw_hosttro_hostR$t export_fsRt exportpatht root_hosttanonuidtanongidt auth_typeR!R(RRR<R((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt fs_export!s  cCs>t|jj|jd}|jj|}t|dS(NR(RR4RGR9tvolume_child_dependencyR(RRR RS((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytvolume_dependants6scCsAt|jj|jd}|jd|jj|ddS(NRsvolume-dependant-rm(RR4RGR9Rltvolume_child_dependency_rmR!(RRR ((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytvolume_dependants_rm<s cCsJt|jj|jd}|jt|j|jj|gdS(NR(RR4RGR9RRRtvolume_raid_info(RRRR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRAscCsJt|jj|jd}|jt|j|jj|gdS(NR(RR4RHR8RRRtpool_member_info(RRtlsm_pool((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRHscCs\tj|j}|jj}g|D]}|j|jkr(|^q(}t|t|jkrtt j ddj t |jt d|Dng|D]}|j tj@s|j^q}t|dkrtt jddj |n|jr!t|j}n tj}|jt|jj|j|||gdS(NsDisk ID %s not founds, css|]}|jVqdS(N(R(RgR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pys XsisDisk %s is not free(Rtraid_type_str_to_lsmt raid_typeR4RMRR:R^RR tNOT_FOUND_DISKRntsettstatusRt STATUS_FREEt DISK_NOT_FREEt strip_sizeRRtVCR_STRIP_SIZE_DEFAULTRRtvolume_raid_createR(RRRt all_lsm_disksRt lsm_diskst busy_disksR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyROs*+3    cCsJt|jj|jd}|jt|j|jj|gdS(NRS(RR4RLR%RRRtvolume_raid_create_cap_get(RRtlsm_sys((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytvolume_raid_create_caplscCs2t|jj|jd}|jj|dS(NR(RR4RGR9tvolume_ident_led_on(RRt lsm_volume((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRqscCs2t|jj|jd}|jj|dS(NR(RR4RGR9tvolume_ident_led_off(RRR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRvscCst|jj|jd}yt|j}Wn+tk r^}ttj t |nX|jj ||t|jj|jd}|j |gdS(NRS( RR4RLR%R_tread_pctRQRR tINVALID_ARGUMENTR(tsystem_read_cache_pct_updateR(RRt lsm_systemRR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyR{scCsDt|jj|jd}|jj||j}t|dS(Ns File System(RR4R<tfs_child_dependencyR R(RRR<RS((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt fs_dependantsscCsGt|jj|jd}|jd|jj||jddS(Ns File Systemsfs-dependants-rm(RR4R<Rltfs_child_dependency_rmR R!(RRR<((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytfs_dependants_rms    c Csd}tjjdd}tjj|s2dSt|}x|D]}|jjdriqHnyTg|jddD]}|j^q\}}||krt |||nWqHt k rqHXqHWWdQXdS( so Set uri from config file. Will be overridden by cmdline option or env var if present. turit~s/.lsmcliNt#t=i(suri( RRt expandusertexiststopentlstripR#R]tstripR$RQ(Rtallowed_config_optionst config_pathtftlineRhRR((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyt_read_configfiles 1  cCs)|jjjjddtkr%tStS(sU Return True if current command is one of _CONNECTION_FREE_COMMANDS. RNR(RRRRt_CONNECTION_FREE_COMMANDSR`R\(R((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pytis_connection_free_cmds cCsd|_d|_d|_d|_|j|_d|_t|jj |_ |j sj|j dkryt dn|j rdS|j tjddk rtjd|_ntjd|_|jjdk r|jj|_n|jdkrGd|jkr8|jjdkr8d|_d|_qGt dn|jjretj|_n|jdk rt|j}|d dkrt d qndS( Nis0[-w|--wait] requires a non-zero positive integert LSMCLI_URItLSMCLI_PASSWORDR|Rssim://s"--uri missing or export LSMCLI_URItusernames+password specified with no user name in uri(R!RR4R t unknown_argsR6RtcleanupR_twaitttmoR$RRRtgetenvtpasswordR|tprompttgetpassR (Rtu((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyRs8       !   cCs0|jr|jn|r,tj|ndS(N(R R%R3(Rtec((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyR1s  cCs|jr"|jj|jn|rkt||_|jj|j|j|j|jj |_ nOtt |j|j|j|_t j drtdn|jj|_ |jj|j|jdS(s- Process the parsed command. tLSM_DEBUG_PLUGINs8Attach debugger to plug-in, press when ready...N(RRRR R4tplugin_registerRRR tplugin_unregisterR RRRtinputtcloseR1(RR6((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyR#s $ c Csg}itjd6tjd6tjd6tjd6tjd6tjd6tjd6}x%tjD]}idd6t j d6t j d6dd6t j d6t j d6t jd6}x|jD]v}y|||||  p                  2                    /  *     (RRR(RRRR(lRR%RRsRR?R=targparseRRRtsixtlsmRRRRRRR R R R R RRRRRRRtlsm.lsmcli.data_displayRRRRRRRRRRRtPY3R_RPt collectionsRt ImportErrort ordereddictR!R:RGRMRORTRRXRdRqRxR\RRR2R$R`RRt list_choicestprovision_typesRntprovision_helptreplicate_typestreplicate_helpt policy_typest policy_helpRt policy_opttwrite_cache_policy_typestwrite_cache_policy_helptwrite_cache_policy_optt size_helpt sys_id_opttcopytsys_id_filter_optt pool_id_opttpool_id_filter_optt vol_id_opttvol_id_filter_optt fs_id_opttfs_id_filter_optt ag_id_opttag_id_filter_optt init_id_optt snap_id_optt export_id_opttnfs_export_id_filter_opttdisk_id_filter_opttsize_optttgt_id_filter_opttlocal_disk_path_opttVOL_CREATE_RAID_TYPES_STRtANON_UID_GID_NARRtobjectR"(((s6/usr/lib/python2.7/site-packages/lsm/lsmcli/cmdline.pyts        vF     -     *  G