diff --git a/include/LVM2_PV_Info.h b/include/LVM2_PV_Info.h index 5e228ac9..5de6989c 100644 --- a/include/LVM2_PV_Info.h +++ b/include/LVM2_PV_Info.h @@ -51,11 +51,14 @@ private: void load_lvm2_pv_info_cache() ; Glib::ustring get_pv_attr_by_path( const Glib::ustring & path, unsigned int entry ) const ; Glib::ustring get_pv_attr_by_row( unsigned int row, unsigned int entry ) const ; + Glib::ustring get_vg_attr_by_name( const Glib::ustring & vgname, unsigned int entry ) const ; + Glib::ustring get_vg_attr_by_row( unsigned int row, unsigned int entry ) const ; static Byte_Value lvm2_pv_attr_to_num( const Glib::ustring str ) ; static bool bit_set( const Glib::ustring & attr, unsigned int bit ) ; static bool lvm2_pv_info_cache_initialized ; static bool lvm_found ; static std::vector lvm2_pv_cache ; + static std::vector lvm2_vg_cache ; static std::vector error_messages ; }; diff --git a/src/LVM2_PV_Info.cc b/src/LVM2_PV_Info.cc index ce5d273a..521ef33f 100644 --- a/src/LVM2_PV_Info.cc +++ b/src/LVM2_PV_Info.cc @@ -25,10 +25,15 @@ enum PV_ATTRIBUTE PVATTR_PV_NAME = 0, PVATTR_PV_SIZE = 1, PVATTR_PV_FREE = 2, - PVATTR_VG_NAME = 3, - PVATTR_VG_BITS = 4, - PVATTR_LV_NAME = 5, - PVATTR_LV_BITS = 6 + PVATTR_VG_NAME = 3 +} ; + +enum VG_ATTRIBUTE +{ + VGATTR_VG_NAME = 0, + VGATTR_VG_BITS = 1, + VGATTR_LV_NAME = 2, + VGATTR_LV_BITS = 3 } ; enum VG_BIT @@ -45,32 +50,39 @@ enum LV_BIT //Data model: // lvm2_pv_info_cache_initialized -// - Has the cache been loaded let? +// - Has the cache been loaded yet? // lvm_found - Is the "lvm" command available? -// lvm2_pv_cache - String vector storing attributes of a PV. -// Attributes are: pv_name,pv_size,pv_free, -// vg_name,vg_attr,lv_name,lv_attr. Pv_size and -// pv_free are the size of the PV and number of -// free bytes. See vgs(8) and lvs(8) for details -// of vg_attr and lv_attr respectively. +// lvm2_pv_cache - String vector storing PV attributes: pv_name, pv_size, pv_free, vg_name. +// One string per PV. // E.g. -// ["/dev/sda10,2147483648,2147483648,,r-----,,", -// "/dev/sda11,2143289344,2143289344,GParted-VG1,wz--n-,,", -// "/dev/sda12,2143289344,1619001344,GParted-VG2,wz--n-,lvol0,-wi---", -// "/dev/sda12,2143289344,1619001344,GParted-VG2,wz--n-,,", -// "/dev/sda13,2143289344,830472192,GParted_VG3,wz--n-,lvol0,-wi-a-", -// "/dev/sda13,2143289344,830472192,GParted_VG3,wz--n-,lvol1,-wi-a-", -// "/dev/sda13,2143289344,830472192,GParted_VG3,wz--n-,,", -// "/dev/sda14,2143289344,1828716544,GParted-VG4,wzx-n-,lvol0,-wi---", -// "/dev/sda14,2143289344,1828716544,GParted-VG4,wzx-n-,,"] -// error_messages - String vector storing whole cache error -// messsages. +// ["/dev/sda10,1073741824,1073741824,", +// "/dev/sda11,1069547520,1069547520,Test-VG1", +// "/dev/sda12,1069547520,335544320,Test_VG2", +// "/dev/sda13,1069547520,0,Test_VG3", +// "/dev/sda14,1069547520,566231040,Test_VG3", +// "/dev/sda15,1069547520,545259520,Test-VG4" +// ] +// lvm2_vg_cache - String vector storing VG attributes: vg_name, vg_attr, lv_name, lv_attr. +// See vgs(8) and lvs(8) for details of vg_attr and lv_attr respectively. +// [",r-----,,", +// "Test-VG1,wz--n-,,", +// "Test_VG2,wz--n-,lvol0,-wi---", +// "Test_VG2,wz--n-,lvol1,-wi---", +// "Test_VG2,wz--n-,,", +// "Test_VG3,wz--n-,lvol0,-wi-a-", +// "Test_VG3,wz--n-,lvol0,-wi-a-", +// "Test_VG3,wz--n-,,", +// "Test-VG4,wzx-n-,lvol0,-wi---", +// "Test-VG4,wzx-n-,," +// ] +// error_messages - String vector storing whole cache error messages. //Initialize static data elements bool LVM2_PV_Info::lvm2_pv_info_cache_initialized = false ; bool LVM2_PV_Info::lvm_found = false ; std::vector LVM2_PV_Info::lvm2_pv_cache ; +std::vector LVM2_PV_Info::lvm2_vg_cache ; std::vector LVM2_PV_Info::error_messages ; LVM2_PV_Info::LVM2_PV_Info() @@ -129,11 +141,11 @@ bool LVM2_PV_Info::has_active_lvs( const Glib::ustring & path ) //PV not yet included in any VG return false ; - for ( unsigned int i = 0 ; i < lvm2_pv_cache .size() ; i ++ ) + for ( unsigned int i = 0 ; i < lvm2_vg_cache .size() ; i ++ ) { - if ( vgname == get_pv_attr_by_row( i, PVATTR_VG_NAME ) ) + if ( vgname == get_vg_attr_by_row( i, VGATTR_VG_NAME ) ) { - if ( bit_set( get_pv_attr_by_row( i, PVATTR_LV_BITS ), LVBIT_STATE ) ) + if ( bit_set( get_vg_attr_by_row( i, VGATTR_LV_BITS ), LVBIT_STATE ) ) //LV in VG is active return true ; } @@ -146,16 +158,7 @@ bool LVM2_PV_Info::is_vg_exported( const Glib::ustring & vgname ) { initialize_if_required() ; - for ( unsigned int i = 0 ; i < lvm2_pv_cache .size() ; i ++ ) - { - if ( vgname == get_pv_attr_by_row( i, PVATTR_VG_NAME ) ) - { - if ( bit_set( get_pv_attr_by_row( i, PVATTR_VG_BITS), VGBIT_EXPORTED ) ) - //VG is exported - return true ; - } - } - return false ; + return bit_set( get_vg_attr_by_name( vgname, VGATTR_VG_BITS ), VGBIT_EXPORTED ) ; } //Return vector of PVs which are members of the VG. Passing "" returns all empty PVs. @@ -164,25 +167,11 @@ std::vector LVM2_PV_Info::get_vg_members( const Glib::ustring & v initialize_if_required() ; std::vector members ; - //Generate array of unique PV member names of a VG for ( unsigned int i = 0 ; i < lvm2_pv_cache .size() ; i ++ ) { if ( vgname == get_pv_attr_by_row( i, PVATTR_VG_NAME ) ) { - bool already_added = false ; - Glib::ustring pvname = get_pv_attr_by_row( i, PVATTR_PV_NAME ) ; - for ( unsigned int j = 0 ; j < members .size() ; j ++ ) - { - if ( pvname == members[ j ] ) - { - already_added = true ; - break ; - } - } - if ( ! already_added ) - { - members .push_back( get_pv_attr_by_row( i, PVATTR_PV_NAME ) ) ; - } + members .push_back( get_pv_attr_by_row( i, PVATTR_PV_NAME ) ) ; } } @@ -197,11 +186,11 @@ std::vector LVM2_PV_Info::get_error_messages( const Glib::ustring return error_messages ; std::vector partition_specific_messages ; - partition_specific_messages .clear() ; Glib::ustring temp ; //Check for partition specific message: partial VG - if ( bit_set( get_pv_attr_by_path( path, PVATTR_VG_BITS ), VGBIT_PARTIAL ) ) + Glib::ustring vgname = get_pv_attr_by_path( path, PVATTR_VG_NAME ) ; + if ( bit_set( get_vg_attr_by_name( vgname, VGATTR_VG_BITS ), VGBIT_PARTIAL ) ) { temp = _("One or more Physical Volumes belonging to the Volume Group is missing.") ; temp += "\n" ; @@ -232,8 +221,10 @@ void LVM2_PV_Info::set_command_found() void LVM2_PV_Info::load_lvm2_pv_info_cache() { Glib::ustring output, error ; + unsigned int i ; lvm2_pv_cache .clear() ; + lvm2_vg_cache .clear() ; error_messages .clear() ; if ( lvm_found ) { @@ -242,15 +233,15 @@ void LVM2_PV_Info::load_lvm2_pv_info_cache() // is changed not using lvm commands. Utils::execute_command( "lvm vgscan", output, error, true ) ; - //Load LVM2 PV attribute cache. Output PV attributes in - // PV_ATTRIBUTE order - Glib::ustring cmd = "lvm pvs --config \"log{command_names=0}\" --nosuffix --noheadings --separator , --units b -o pv_name,pv_size,pv_free,vg_name,vg_attr,lv_name,lv_attr" ; + //Load LVM2 PV attribute cache. Output PV attributes in PV_ATTRIBUTE order + Glib::ustring cmd = "lvm pvs --config \"log{command_names=0}\" --nosuffix " + "--noheadings --separator , --units b -o pv_name,pv_size,pv_free,vg_name" ; if ( ! Utils::execute_command( cmd, output, error, true ) ) { if ( output != "" ) { Utils::tokenize( output, lvm2_pv_cache, "\n" ) ; - for ( unsigned int i = 0 ; i < lvm2_pv_cache .size() ; i ++ ) + for ( i = 0 ; i < lvm2_pv_cache .size() ; i ++ ) lvm2_pv_cache [i] = Utils::trim( lvm2_pv_cache [i] ) ; } } @@ -261,6 +252,31 @@ void LVM2_PV_Info::load_lvm2_pv_info_cache() error_messages .push_back ( output ) ; if ( ! error .empty() ) error_messages .push_back ( error ) ; + } + + //Load LVM2 VG attribute cache. Output VG and LV attributes in VG_ATTRIBUTE order + cmd = "lvm pvs --config \"log{command_names=0}\" --nosuffix " + "--noheadings --separator , --units b -o vg_name,vg_attr,lv_name,lv_attr" ; + if ( ! Utils::execute_command( cmd, output, error, true ) ) + { + if ( output != "" ) + { + Utils::tokenize( output, lvm2_vg_cache, "\n" ) ; + for ( i = 0 ; i < lvm2_vg_cache .size() ; i ++ ) + lvm2_vg_cache [i] = Utils::trim( lvm2_vg_cache [i] ) ; + } + } + else + { + error_messages .push_back( cmd ) ; + if ( ! output .empty() ) + error_messages .push_back ( output ) ; + if ( ! error .empty() ) + error_messages .push_back ( error ) ; + } + + if ( ! error_messages .empty() ) + { Glib::ustring temp ; temp = _("An error occurred reading LVM2 configuration!") ; temp += "\n" ; @@ -308,6 +324,41 @@ Glib::ustring LVM2_PV_Info::get_pv_attr_by_row( unsigned int row, unsigned int e return "" ; } +//Return VG's nth attribute. Performs linear search of the cache and +// uses the first matching VG entry. Attributes are numbered 0 upward +// using VG_ATTRIBUTE enumeration. +Glib::ustring LVM2_PV_Info::get_vg_attr_by_name( const Glib::ustring & vgname, unsigned int entry ) const +{ + for ( unsigned int i = 0 ; i < lvm2_vg_cache .size() ; i ++ ) + { + std::vector vg_attrs ; + Utils::split( lvm2_vg_cache [i], vg_attrs, "," ) ; + if ( VGATTR_VG_NAME < vg_attrs .size() && vgname == vg_attrs [VGATTR_VG_NAME] ) + { + if ( entry < vg_attrs .size() ) + return vg_attrs [entry] ; + else + break ; + } + } + + return "" ; +} + +//Return VG's nth attribute from specified cache row. Row is numbered +// 0 upwards and attributes are numbers numbered 0 upwards using +// VG_ATTRIBUTE enumeration. +Glib::ustring LVM2_PV_Info::get_vg_attr_by_row( unsigned int row, unsigned int entry ) const +{ + if ( row >= lvm2_vg_cache .size() ) + return "" ; + std::vector vg_attrs ; + Utils::split( lvm2_vg_cache [row], vg_attrs, "," ) ; + if ( entry < vg_attrs .size() ) + return vg_attrs [entry] ; + return "" ; +} + //Return string converted to a number, or -1 for error. //Used to convert PVs size or free bytes. Byte_Value LVM2_PV_Info::lvm2_pv_attr_to_num( const Glib::ustring str )