Skip to content

Commit

Permalink
#252: Created and packaged a C++ based utility as an atlernative to t…
Browse files Browse the repository at this point in the history
…he python based helper.
  • Loading branch information
ericcano committed Sep 10, 2019
1 parent bc65a35 commit cfd621e
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ ELSE(DEFINED PackageOnly)
add_subdirectory(tapeserver)
add_subdirectory(XRootdSSiRmcd)

add_subdirectory(continuousintegration/orchestration/tests)

#Generate version information
configure_file(${PROJECT_SOURCE_DIR}/version.hpp.in
${CMAKE_BINARY_DIR}/version.h)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ if [ ! -e /etc/buildtreeRunner ]; then
yum-config-manager --enable ceph

# Install missing RPMs
yum -y install cta-cli cta-debuginfo xrootd-client eos-client jq python36
yum -y install cta-cli cta-systemtest-helpers cta-debuginfo xrootd-client eos-client jq python36

## Keep this temporary fix that may be needed if going to protobuf3-3.5.1 for CTA
# Install eos-protobuf3 separately as eos is OK with protobuf3 but cannot use it..
Expand Down
26 changes: 26 additions & 0 deletions continuousintegration/orchestration/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# The CERN Tape Archive(CTA) project
# Copyright(C) 2015 CERN
#
# 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 3 of the License, 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. If not, see <http://www.gnu.org/licenses/>.

cmake_minimum_required (VERSION 2.6)

find_package (xrootd REQUIRED)
find_package (xrootdclient REQUIRED)

include_directories (${XROOTD_INCLUDE_DIR} ${CMAKE_SOURCE_DIR})

add_executable(cta-client-ar-abortPrepare client-ar-abortPrepare.cpp)
target_link_libraries(cta-client-ar-abortPrepare XrdCl ctacommon)
install(TARGETS cta-client-ar-abortPrepare DESTINATION usr/bin)
161 changes: 161 additions & 0 deletions continuousintegration/orchestration/tests/client-ar-abortPrepare.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
* The CERN Tape Archive (CTA) project
* Copyright (C) 2015 CERN
*
* 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 3 of the License, 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. If not, see <http://www.gnu.org/licenses/>.
*/

#include <getopt.h>
#include <string>
#include <iostream>
#include <memory>
#include <XrdCl/XrdClFileSystem.hh>
#include "common/utils/Regex.hpp"
#include "common/exception/XrootCl.hpp"


// No short options.
const char short_options[] = "";
// We require a handful of long options.

enum class OptionIds: int {
eos_instance = 1,
eos_poweruser = 2,
eos_dir = 3,
subdir = 4,
file = 5,
error_dir = 6
};

const struct ::option long_options[] = {
{ "eos-instance", required_argument, nullptr, (int)OptionIds::eos_instance },
{ "eos-poweruser", required_argument, nullptr, (int)OptionIds::eos_poweruser },
{ "eos-dir", required_argument, nullptr, (int)OptionIds::eos_dir },
{ "subdir", required_argument, nullptr, (int)OptionIds::subdir },
{ "file", required_argument, nullptr, (int)OptionIds::file },
{ "error-dir", required_argument, nullptr, (int)OptionIds::error_dir },
{ nullptr, 0, nullptr, 0 }
};

void help() {
std::cerr << "Expected parameters are: ";
const struct ::option * pOpt = long_options;
while (pOpt->name) {
std::cerr << "--" << pOpt->name << " ";
++pOpt;
}
std::cerr << std::endl;
}

// We make these variables global as they will be part of the process's environment.
char envXRD_LOGLEVEL[] = "XRD_LOGLEVEL=Dump";
std::unique_ptr<char[]> envKRB5CCNAME;
char envXrdSecPROTOCOL[] = "XrdSecPROTOCOL=krb5";


int main(int argc, char **argv) {

struct {
std::string eos_instance;
std::string eos_poweruser;
std::string eos_dir;
std::string subdir;
std::string file;
std::string error_dir;
} options;

int opt_ret;
while (-1 != (opt_ret = getopt_long(argc, argv, short_options, long_options, nullptr))) {
switch (opt_ret) {
case (int)OptionIds::eos_instance:
options.eos_instance = optarg;
break;
case (int)OptionIds::eos_poweruser:
options.eos_poweruser = optarg;
break;
case (int)OptionIds::eos_dir:
options.eos_dir = optarg;
break;
case (int)OptionIds::subdir:
options.subdir = optarg;
break;
case (int)OptionIds::file:
options.file = optarg;
break;
case (int)OptionIds::error_dir:
options.error_dir = optarg;
break;
case '?':
default:
std::cerr << "Unexpected option or missing argument." << std::endl;
exit(EXIT_FAILURE);
break;
}
}

if (options.eos_instance.empty() || options.eos_poweruser.empty() || options.error_dir.empty() || options.subdir.empty() ||
options.file.empty() || options.error_dir.empty()) {
std::cerr << "At least one option missing." << std::endl;
help();
exit (EXIT_FAILURE);
}

std::cout << "To run again: " << argv[0]
<< " --eos-instance=" << options.eos_instance
<< " --eos-poweruser=" << options.eos_poweruser
<< " --eos-dir=" << options.eos_dir
<< " --subdir=" << options.subdir
<< " --file=" << options.file
<< " --error_dir=" << options.error_dir << std::endl;

// Get the extended attribute for the retrieve request id
try {
// Prepare environment.
putenv(envXRD_LOGLEVEL);
std::string envKRB5CCNAMEvalue = std::string("KRB5CCNAME=/tmp/") + options.eos_poweruser + "/krb5cc_0";
// We need to copy to an array because of putenv's lack of const correctness.
envKRB5CCNAME.reset(new char[envKRB5CCNAMEvalue.size() + 1]);
strncpy(envKRB5CCNAME.get(), envKRB5CCNAMEvalue.c_str(), envKRB5CCNAMEvalue.size() + 1);
putenv(envKRB5CCNAME.get());
putenv(envXrdSecPROTOCOL);

XrdCl::FileSystem xrdfs(options.eos_instance);
std::string fileName = options.eos_dir + "/" + options.subdir + "/" + options.file;
std::string query = fileName + "?mgm.pcmd=xattr&mgm.subcmd=get&mgm.xattrname=sys.retrieve.req_id";
auto qcOpaque = XrdCl::QueryCode::OpaqueFile;
XrdCl::Buffer xrdArg;
xrdArg.FromString(query);
XrdCl::Buffer *respPtr = nullptr;
auto status = xrdfs.Query(qcOpaque, xrdArg, respPtr, (uint16_t)0 /*timeout=default*/);
// Ensure proper memory management for the response buffer (it is our responsilibity to free it, we delegate to the unique_ptr).
std::unique_ptr<XrdCl::Buffer> respUP(respPtr);
respPtr = nullptr;
cta::exception::XrootCl::throwOnError(status, "Error during XrdCl::Query");
cta::utils::Regex re("value=(.*)");
std::string respStr(respUP->GetBuffer(), respUP->GetSize());
auto reResult = re.exec(respStr);
if (reResult.size() != 2) {
// We did not receive the expected structure
throw cta::exception::Exception(std::string("Unexpected result from xattr query: ") + respStr);
}
std::string retrieveRequestId = reResult[1];
std::vector<std::string> files = { retrieveRequestId, fileName };
XrdCl::PrepareFlags::Flags flags = XrdCl::PrepareFlags::Cancel;
auto abortStatus = xrdfs.Prepare(files, flags, 0, respPtr, 0 /* timeout */);
cta::exception::XrootCl::throwOnError(abortStatus, "Error during XrdCl::Prepare");
} catch (cta::exception::Exception & ex) {
std::cerr << "Received exception: " << ex.what() << std::endl;
}
return 0;
}
10 changes: 6 additions & 4 deletions continuousintegration/orchestration/tests/client_ar.sh
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,8 @@ for ((subdir=0; subdir < ${NB_DIRS}; subdir++)); do
done

# Put all tape drives down
echo "Sleeping 3 seconds to let previous sessions finish."
sleep 3
admin_kdestroy &>/dev/null
admin_kinit &>/dev/null
INITIAL_DRIVES_STATE=`admin_cta --json dr ls`
Expand Down Expand Up @@ -403,7 +405,7 @@ fi
for ((subdir=0; subdir < ${NB_DIRS}; subdir++)); do
echo -n "Cancelling prepare for files in ${EOS_DIR}/${subdir} using ${NB_PROCS} processes (prepare_abort)..."
cat ${STATUS_FILE} | grep ^${subdir}/ | cut -d/ -f2 \
| xargs --max-procs=${NB_PROCS} -iTEST_FILE_NAME /root/client_ar_abortPrepare.py --eos-instance ${EOSINSTANCE} \
| xargs --max-procs=${NB_PROCS} -iTEST_FILE_NAME cta-client-ar-abortPrepare --eos-instance ${EOSINSTANCE} \
--eos-poweruser ${EOSPOWER_USER} --eos-dir ${EOS_DIR} --subdir ${subdir} --file TEST_FILE_NAME --error-dir ${ERROR_DIR} \
| tee ${LOGDIR}/prepare_abort_sys.retrieve.req_id_${subdir}.log # | grep ^ERROR
echo Done.
Expand Down Expand Up @@ -440,11 +442,12 @@ while test ${REMAINING_REQUESTS} -gt 0; do
done

# Check that the files were not retrieved
echo "Checking restaged files."
echo -n "Checking restaged files. Found: "
RESTAGEDFILES=0
for ((subdir=0; subdir < ${NB_DIRS}; subdir++)); do
RESTAGEDFILES=$(( ${RESTAGEDFILES} + $(eos root://${EOSINSTANCE} ls -y ${EOS_DIR}/${subdir} | egrep '^d[1-9][0-9]*::t1' | wc -l) ))
(( RESTAGEDFILES += $(eos root://${EOSINSTANCE} ls -y ${EOS_DIR}/${subdir} | egrep '^d[1-9][0-9]*::t1' | wc -l) ))
done
echo ${RESTAGEDFILES}

if [ "0" != "$(ls ${ERROR_DIR} 2> /dev/null | wc -l)" ]; then
# there were some prepare errors
Expand All @@ -453,7 +456,6 @@ if [ "0" != "$(ls ${ERROR_DIR} 2> /dev/null | wc -l)" ]; then
mv ${ERROR_DIR}/* ${LOGDIR}/xrd_errors/
fi


# We can now delete the files
DELETED=0
if [[ $REMOVE == 1 ]]; then
Expand Down
10 changes: 10 additions & 0 deletions cta.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -410,3 +410,13 @@ collects EOS disk copies that have been safely stored to tape.
%postun -n cta-fst-gcd
%systemd_postun cta-fst-gcd.service
%systemdDaemonReload

%package -n cta-systemtest-helpers
Summary: Collection of utilities deployed in system test client containers.
Group: Application/CTA
Requires: cta-lib = %{version}-%{release}
%description -n cta-systemtest-helpers
Collection of utilities deployed in system test client containers.
Currently contains a helper for the client-ar script, which should be installed alongside it.
%files -n cta-systemtest-helpers
%attr(0755,root,root) /usr/bin/cta-client-ar-abortPrepare

0 comments on commit cfd621e

Please sign in to comment.