From mboxrd@z Thu Jan 1 00:00:00 1970 From: kupcevic@sourceware.org Date: 28 Jun 2006 20:09:11 -0000 Subject: [Cluster-devel] conga/ricci modules/storage/LV.cpp modules/sto ... Message-ID: <20060628200911.4457.qmail@sourceware.org> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit CVSROOT: /cvs/cluster Module name: conga Changes by: kupcevic at sourceware.org 2006-06-28 20:09:08 Modified files: ricci/modules/storage: LV.cpp LVM.cpp LVM.h PV.cpp VG.cpp ricci/docs : storage_api.html Added files: ricci/modules/storage: ClvmdError.h Log message: storage module: clvm support Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/storage/ClvmdError.h.diff?cvsroot=cluster&r1=NONE&r2=1.1 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/storage/LV.cpp.diff?cvsroot=cluster&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/storage/LVM.cpp.diff?cvsroot=cluster&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/storage/LVM.h.diff?cvsroot=cluster&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/storage/PV.cpp.diff?cvsroot=cluster&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/storage/VG.cpp.diff?cvsroot=cluster&r1=1.3&r2=1.4 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/docs/storage_api.html.diff?cvsroot=cluster&r1=1.2&r2=1.3 /cvs/cluster/conga/ricci/modules/storage/ClvmdError.h,v --> standard output revision 1.1 --- conga/ricci/modules/storage/ClvmdError.h +++ - 2006-06-28 20:09:09.165044000 +0000 @@ -0,0 +1,41 @@ +/* + Copyright Red Hat, Inc. 2006 + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + MA 02139, USA. +*/ +/* + * Author: Stanko Kupcevic + */ + + +#ifndef ClvmdError_h +#define ClvmdError_h + +#include "Except.h" + + +class ClvmdError : public Except +{ + public: + ClvmdError() + : Except(4, std::string("clvmd required, but unable to start. Start cluster infrastructure.")) {} + virtual ~ClvmdError() + {} + +}; + + +#endif // ClvmdError_h --- conga/ricci/modules/storage/LV.cpp 2006/03/10 17:50:11 1.2 +++ conga/ricci/modules/storage/LV.cpp 2006/06/28 20:09:08 1.3 @@ -29,6 +29,7 @@ #include "utils.h" #include "ContentFactory.h" #include "ContentNone.h" +#include "ClvmdError.h" using namespace std; @@ -42,6 +43,13 @@ string vgname = bd_temp.props.get("vgname").get_string(); + + // if VG is marked as clustered, but cluster locking is not available, throw + if (!LVM::clustered_available() && + bd_temp.props.get("clustered").get_bool()) + throw ClvmdError(); + + string lvname = bd_temp.props.get("lvname").get_string(); long long size = bd_temp.props.get("size").get_int(); @@ -158,6 +166,11 @@ counting_auto_ptr LV::apply(const BDParsed& bd_parsed) { + // if VG is marked as clustered, but cluster locking is not available, throw + if (_props.get("clustered").get_bool() && + !LVM::clustered_available()) + throw ClvmdError(); + // snapshots neither resize nor replace content, see LV() if (_props.get("snapshot").get_bool()) { @@ -217,6 +230,11 @@ void LV::remove() { + // if VG is marked as clustered, but cluster locking is not available, throw + if (_props.get("clustered").get_bool() && + !LVM::clustered_available()) + throw ClvmdError(); + content->remove(); LVM::lvremove(path()); } --- conga/ricci/modules/storage/LVM.cpp 2006/03/10 17:50:11 1.2 +++ conga/ricci/modules/storage/LVM.cpp 2006/06/28 20:09:08 1.3 @@ -27,6 +27,7 @@ #include "BDFactory.h" #include "LV.h" #include "defines.h" +#include "ClvmdError.h" #include @@ -41,6 +42,12 @@ using namespace std; +static string +get_locking_type(); + +static vector +vg_props(const string& vgname); + @@ -55,8 +62,8 @@ static unsigned int PVS_EXTENT_SIZE_IDX = 7; static unsigned int PVS_OPTIONS_LENGTH = 8; // last - -static string LVS_OPTIONS_STRING = "lv_name,vg_name,stripes,stripesize,lv_attr,lv_uuid,devices,origin,snap_percent,seg_start,seg_size,vg_extent_size,lv_size,vg_free_count"; + +static string LVS_OPTIONS_STRING = "lv_name,vg_name,stripes,stripesize,lv_attr,lv_uuid,devices,origin,snap_percent,seg_start,seg_size,vg_extent_size,lv_size,vg_free_count,vg_attr"; static unsigned int LVS_NAME_IDX = 0; static unsigned int LVS_VG_NAME_IDX = 1; //static unsigned int LVS_STRIPES_NUM_IDX = 2; @@ -71,11 +78,12 @@ static unsigned int LVS_EXTENT_SIZE_IDX = 11; static unsigned int LVS_SIZE_IDX = 12; static unsigned int LVS_VG_FREE_COUNT = 13; +static unsigned int LVS_VG_ATTR_IDX = 14; // if LVS_HAS_MIRROR_OPTIONS: // LVS_OPTION_STRING += ",mirror_log"; //static unsigned int LVS_MIRROR_LOG_IDX = 13; -static unsigned int LVS_OPTIONS_LENGTH = 14; // last - +static unsigned int LVS_OPTIONS_LENGTH = 15; // last + static string VGS_OPTIONS_STRING = "vg_name,vg_attr,vg_size,vg_extent_size,vg_free_count,max_lv,max_pv,vg_uuid"; @@ -95,6 +103,8 @@ std::string LVM::vgname_from_lvpath(const std::string& lvpath) { + check_locking(); + vector args; args.push_back("lvdisplay"); args.push_back("-c"); @@ -121,6 +131,8 @@ std::string LVM::vgname_from_pvpath(const std::string& path) { + check_locking(); + vector args; args.push_back("pvs"); args.push_back("--nosuffix"); @@ -161,6 +173,8 @@ void LVM::probe_lv(const std::string& lvpath, Props& props) { + check_locking(); + vector args; args.push_back("lvs"); args.push_back("--nosuffix"); @@ -212,6 +226,10 @@ props.set(Variable("mirrored", attrs[0] == 'm')); + // clustered + string vg_attrs = words[LVS_VG_ATTR_IDX]; + props.set(Variable("clustered", vg_attrs[5] == 'c')); + // snapshots string origin = words[LVS_SNAP_ORIGIN_IDX]; props.set(Variable("snapshot", origin != "")); @@ -253,6 +271,8 @@ void LVM::probe_pv(const std::string& path, Props& props) { + check_locking(); + vector args; args.push_back("pvs"); args.push_back("--nosuffix"); @@ -314,6 +334,8 @@ list >& sources, list >& targets) { + check_locking(); + // pv to vg mappings map pv_to_vg; vector args; @@ -344,44 +366,13 @@ // probe vg if (!vgname.empty()) { - args.clear(); - args.push_back("vgs"); - args.push_back("--nosuffix"); - args.push_back("--noheadings"); - args.push_back("--units"); - args.push_back("b"); - args.push_back("--separator"); - args.push_back(";"); - args.push_back("-o"); - args.push_back(VGS_OPTIONS_STRING); - // args.push_back(vgname); - out = err = ""; - if (utils::execute(LVM_BIN_PATH, args, out, err, status)) - throw string("execute failed"); - if (status != 0) - throw string("vgs failed"); - - - vector lines = utils::split(out, "\n"); - vector words; - for (vector::iterator iter = lines.begin(); - iter != lines.end(); - iter++) { - string line = utils::strip(*iter); - vector t_words = utils::split(line, ";"); - if (t_words.size() < VGS_OPTIONS_LENGTH) - continue; - if (t_words[VGS_NAME_IDX] == vgname) { - words = t_words; - break; - } - } - if (words.size() < VGS_OPTIONS_LENGTH) - throw string("no such vg"); + vector words = vg_props(vgname); props.set(Variable("vgname", words[VGS_NAME_IDX])); - props.set(Variable("attrs", words[VGS_ATTR_IDX])); + + string vg_attrs(words[VGS_ATTR_IDX]); + props.set(Variable("attrs", vg_attrs)); long long size = utils::to_long(words[VGS_SIZE_IDX]); long long extent_size = utils::to_long(words[VGS_EXTENT_SIZE_IDX]); @@ -404,26 +395,8 @@ props.set(Variable("uuid", words[VGS_UUID_IDX])); // clustered - bool clustered = false; - args.clear(); - args.push_back("vgdisplay"); - args.push_back(vgname); - out = err = ""; - if (utils::execute(LVM_BIN_PATH, args, out, err, status)) - throw string("execute failed"); - if (status != 0) - throw string("vgdisplay failed"); - lines = utils::split(out, "\n"); - for (vector::iterator iter = lines.begin(); - iter != lines.end(); - iter++) { - string line = utils::strip(*iter); - vector words = utils::split(line, " "); - if (words.size() == 2) - if (words[0] == "Clustered" && words[1] == "yes") - clustered = true; - } - props.set(Variable("clustered", clustered)); + bool clustered = (vg_attrs[5] == 'c'); + props.set(Variable("clustered", clustered, true)); } // PVS @@ -497,14 +470,21 @@ void -LVM::vgcreate(const std::string& vgname, - long long extent_size, +LVM::vgcreate(const std::string& vgname, + long long extent_size, + bool clustered, const list& pv_paths) { + if (clustered && + !clustered_available()) + throw ClvmdError(); + vector args; args.push_back("vgcreate"); args.push_back("--physicalextentsize"); args.push_back(utils::to_string(extent_size/1024) + "k"); + args.push_back("-c"); + args.push_back(clustered ? "y" : "n"); args.push_back(vgname); for (list::const_iterator iter = pv_paths.begin(); iter != pv_paths.end(); @@ -574,6 +554,28 @@ utils::clear_cache(); } +void +LVM::vgchange(const std::string& vgname, + bool clustered) +{ + if (clustered && + !clustered_available()) + throw ClvmdError(); + + vector args; + args.push_back("vgchange"); + args.push_back("-c"); + args.push_back(clustered ? "y" : "n"); + args.push_back(vgname); + string out, err; + int status; + if (utils::execute(LVM_BIN_PATH, args, out, err, status, false)) + throw string("execute failed"); + if (status != 0) + throw string("vgchange failed"); + utils::clear_cache(); +} + void LVM::lvcreate(const std::string& vgname, @@ -676,3 +678,96 @@ throw string("lvextend failed"); utils::clear_cache(); } + + +bool +LVM::clustered_available() +{ + return get_locking_type() == "2"; +} + +void +LVM::check_locking() +{ + if (get_locking_type() == "2") { + // try to start clvmd, if not running + string out, err; + int status; + vector args; + args.push_back("clvmd"); + args.push_back("start"); + if (utils::execute("/sbin/service", args, out, err, status)) + throw string("execute failed"); + if (status) + throw ClvmdError(); + } +} + +string +get_locking_type() +{ + string out, err; + int status; + vector args; + args.push_back("locking_type"); + args.push_back("/etc/lvm/lvm.conf"); + if (utils::execute("/bin/grep", args, out, err, status)) + throw string("execute failed"); + vector lines(utils::split(utils::strip(out), "\n")); + for (vector::const_iterator line = lines.begin(); + line != lines.end(); + line++) { + vector words(utils::split(utils::strip(*line))); + if (words.size() < 3) + continue; + if (words[0] == "locking_type" && + words[1] == "=") { + return words[2]; + } + } + throw string("locking_type not found in lvm.conf!!!"); +} + +vector +vg_props(const string& vgname) +{ + string out, err; + int status; + vector args; + args.push_back("vgs"); + args.push_back("--nosuffix"); + args.push_back("--noheadings"); + args.push_back("--units"); + args.push_back("b"); + args.push_back("--separator"); + args.push_back(";"); + args.push_back("-o"); + args.push_back(VGS_OPTIONS_STRING); + // args.push_back(vgname); + if (utils::execute(LVM_BIN_PATH, args, out, err, status)) + throw string("execute failed"); + if (status) + throw string("vgs failed"); + + vector lines = utils::split(out, "\n"); + for (vector::iterator iter = lines.begin(); + iter != lines.end(); + iter++) { + string line = utils::strip(*iter); + vector words = utils::split(line, ";"); + if (words.size() < VGS_OPTIONS_LENGTH) + continue; + if (words[VGS_NAME_IDX] == vgname) { + return words; + } + } + throw string("no such vg"); +} + +bool +LVM::vg_clustered(const string& vgname) +{ + if (vgname.empty()) + return false; + return vg_props(vgname)[VGS_ATTR_IDX][5] == 'c'; +} --- conga/ricci/modules/storage/LVM.h 2006/03/10 17:50:11 1.2 +++ conga/ricci/modules/storage/LVM.h 2006/06/28 20:09:08 1.3 @@ -50,14 +50,17 @@ static void pvcreate(const std::string& path); static void pvremove(const std::string& path); - static void vgcreate(const std::string& vgname, - long long extent_size, + static void vgcreate(const std::string& vgname, + long long extent_size, + bool clustered, const std::list& pv_paths); static void vgremove(const std::string& vgname); static void vgextend(const std::string& vgname, const std::list& pv_paths); static void vgreduce(const std::string& vgname, const std::string& pv_path); + static void vgchange(const std::string& vgname, + bool clustered); static void lvcreate(const std::string& vgname, const std::string& lvname, @@ -70,6 +73,10 @@ static void lvreduce(const std::string& path, long long new_size); static void lvextend(const std::string& path, long long new_size); + static void check_locking(); + static bool clustered_available(); + static bool vg_clustered(const std::string& vgname); + }; --- conga/ricci/modules/storage/PV.cpp 2006/03/10 17:50:11 1.2 +++ conga/ricci/modules/storage/PV.cpp 2006/06/28 20:09:08 1.3 @@ -25,6 +25,7 @@ #include "LVM.h" #include "MapperFactory.h" #include "utils.h" +#include "ClvmdError.h" using namespace std; @@ -91,6 +92,13 @@ string vgname = _props.get("vgname").get_string(); + + // if VG is marked as clustered, but cluster locking is not available, throw + if (!LVM::clustered_available() && + LVM::vg_clustered(vgname)) + throw ClvmdError(); + + if (vg->sources.size() == 1) { if (vgname.size()) LVM::vgremove(vgname); @@ -111,6 +119,14 @@ string vgname_old(_props.get("vgname").get_string()); string vgname_new(new_props.get("vgname").get_string()); + + // if VG is marked as clustered, but cluster locking is not available, throw + if (!LVM::clustered_available() && + (LVM::vg_clustered(vgname_old) || + LVM::vg_clustered(vgname_new))) + throw ClvmdError(); + + counting_auto_ptr vg_old = MapperFactory::get_mapper(_mapper_type, _mapper_id); @@ -135,6 +151,13 @@ { string vgname(templ->_props.get("vgname").get_string()); + + // if VG is marked as clustered, but cluster locking is not available, throw + if (!LVM::clustered_available() && + LVM::vg_clustered(vgname)) + throw ClvmdError(); + + LVM::pvcreate(path); try { if (vgname.size()) --- conga/ricci/modules/storage/VG.cpp 2006/05/16 20:10:39 1.3 +++ conga/ricci/modules/storage/VG.cpp 2006/06/28 20:09:08 1.4 @@ -28,6 +28,7 @@ #include "defines.h" #include "utils.h" #include "MidAir.h" +#include "ClvmdError.h" #include "Time.h" @@ -41,6 +42,8 @@ list get_VG_ids() { + LVM::check_locking(); + list vgids; vector args; @@ -148,6 +151,7 @@ new_lv->props.set(Variable("vgname", _vgname)); new_lv->props.set(Variable("snapshot", false)); + new_lv->props.set(Variable("clustered", _props.get("clustered").get_bool())); new_targets.push_back(new_lv); // snapshots @@ -183,14 +187,25 @@ void -VG::apply(const MapperParsed&) +VG::apply(const MapperParsed& mp) { - // nothing to do, for now + string vgname(mp.props.get("vgname").get_string()); + + // clustered + bool clustered_old = _props.get("clustered").get_bool(); + bool clustered_new = mp.props.get("clustered").get_bool(); + if (clustered_old != clustered_new) + LVM::vgchange(vgname, clustered_new); } void VG::__add_sources(const list >& bds) { + // if VG is marked as clustered, but cluster locking is not available, throw + if (_props.get("clustered").get_bool() && + !LVM::clustered_available()) + throw ClvmdError(); + string vgname; try { vgname = _props.get("vgname").get_string(); @@ -231,6 +246,11 @@ void VG::__remove() { + // if VG is marked as clustered, but cluster locking is not available, throw + if (_props.get("clustered").get_bool() && + !LVM::clustered_available()) + throw ClvmdError(); + string vgname = _props.get("vgname").get_string(); LVM::vgremove(vgname); for (list >::const_iterator iter = sources.begin(); @@ -251,6 +271,11 @@ string vgname = temp.props.get("vgname").get_string(); long long extent_size = temp.props.get("extent_size").get_int(); + bool clustered = temp.props.get("clustered").get_bool(); + + if (clustered && + !LVM::clustered_available()) + throw ClvmdError(); try { utils::clear_cache(); @@ -267,7 +292,7 @@ } // create VG - LVM::vgcreate(vgname, extent_size, pv_paths); + LVM::vgcreate(vgname, extent_size, clustered, pv_paths); } catch ( ... ) { for (list >::const_iterator iter = temp.sources.begin(); iter != temp.sources.end(); @@ -319,6 +344,9 @@ 4 * 1024 * 1024 /* 4 MB */, ext_sizes)); + // clustered + props.set(Variable("clustered", false, true)); + // new sources VG unused(VG_PREFIX); for (list >::iterator iter = unused.sources.begin(); --- conga/ricci/docs/storage_api.html 2006/04/13 18:06:14 1.2 +++ conga/ricci/docs/storage_api.html 2006/06/28 20:09:08 1.3 @@ -5,7 +5,7 @@ Storage Module - +

Storage module manages all aspects of storage. Supports partition @@ -66,6 +66,13 @@

  • 3 ??? umount error
    It will happen in the case of umount failure.

    +
  • 4 ??? clvmd not running
    Clustered Volume Groups need clvmd + daemon running, and yet clvmd is not running.
    Storage module + will try to start it. On failure, this error will be raised.
    User + should either start clvmd, or mark VG non-clustered.
    In order to + start clvmd:
    1. lvm2-cluster needs to be installed
    2. cluster + infrastructure needs to be started
    3. clvmd should be started + (service clvmd start)