diff --git a/CMakeLists.txt b/CMakeLists.txt index 1dcdfbae824f63a2540b4e96557ad9de760c7073..5df2dd1add5b8ee55976e3086a72cd0737f0ec28 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,7 @@ cmake_minimum_required (VERSION 2.6) project(cta) + set(CMAKE_C_FLAGS "-fPIC -Wall -Wextra -Werror -Wno-unused-parameter") # Please note that the -fms-extensions option should be dropped when this @@ -112,6 +113,7 @@ ELSE(DEFINED PackageOnly) # OCCI support is on by default set (OCCI_SUPPORT ON) + find_package(stk REQUIRED) # Switch OCCI support off if using gcc 5.1 or higher #if (CMAKE_COMPILER_IS_GNUCC) # if (GCC_VERSION VERSION_GREATER 5.0) diff --git a/cmake/Findstk.cmake b/cmake/Findstk.cmake new file mode 100644 index 0000000000000000000000000000000000000000..f954e63bb23370884f5dd9148448cf126e319ff3 --- /dev/null +++ b/cmake/Findstk.cmake @@ -0,0 +1,38 @@ + +# 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/>. +# This module will set the following variables: +# STK_FOUND +# STK_LIBRARIES +# STK_INCLUDE_DIR + +find_library (STK_LIBRARIES + stk-ssi + PATHS /usr/lib64/CDK /usr/lib/CDK + NO_DEFAULT_PATH) + +find_path (STK_INCLUDE_DIRS + acssys.h + PATHS /usr/include/CDK + NO_DEFAULT_PATH) + +message (STATUS "STK_LIBRARIES=${STK_LIBRARIES}") +message (STATUS "STK_INCLUDE_DIRS=${STK_INCLUDE_DIRS}") + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(stk DEFAULT_MSG + STK_LIBRARIES + STK_INCLUDE_DIRS) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 51a936c8b179c896498f9bfd988bdcfed6d2efdf..73f7306c0342996a58fb068fb23baa8d74beaa46 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -73,23 +73,29 @@ set (COMMON_LIB_SRC_FILES admin/AdminUser.cpp archiveRoutes/ArchiveRoute.cpp checksum/Checksum.cpp - exception/Backtrace.cpp - exception/Errnum.cpp - exception/Exception.cpp - exception/NonRetryableError.cpp - exception/RetryableError.cpp - exception/UserError.cpp exception/AcceptConnectionInterrupted.cpp + exception/AcsQueryVolumeCmd.cpp + exception/Backtrace.cpp exception/BadAlloc.cpp exception/CommandLineNotParsed.cpp + exception/DismountFailed.cpp + exception/Errnum.cpp + exception/Exception.cpp exception/InvalidArgument.cpp exception/InvalidConfigEntry.cpp + exception/Mismatch.cpp exception/MissingOperand.cpp + exception/MountFailed.cpp exception/NoEntry.cpp + exception/NonRetryableError.cpp exception/NoPortInRange.cpp exception/NotAnOwner.cpp exception/OutOfMemory.cpp + exception/QueryVolumeFailed.cpp + exception/RequestFailed.cpp + exception/RetryableError.cpp exception/TimeOut.cpp + exception/UserError.cpp exception/XrootCl.cpp log/DummyLogger.cpp log/FileLogger.cpp diff --git a/common/exception/AcsQueryVolumeCmd.cpp b/common/exception/AcsQueryVolumeCmd.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1f087eb2591e24b47ab27092e98114371b11f631 --- /dev/null +++ b/common/exception/AcsQueryVolumeCmd.cpp @@ -0,0 +1,33 @@ + +/****************************************************************************** + * + * This file is part of the Castor project. + * See http://castor.web.cern.ch/castor + * + * Copyright (C) 2003 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * + * @author Castor Dev team, castor-dev@cern.ch + *****************************************************************************/ + +#include "AcsQueryVolumeCmd.hpp" + + +// ----------------------------------------------------------------------------- +// Constructor +// ----------------------------------------------------------------------------- +cta::exception::AcsQueryVolumeCmd::AcsQueryVolumeCmd(): + cta::exception::Exception() { +} diff --git a/common/exception/AcsQueryVolumeCmd.hpp b/common/exception/AcsQueryVolumeCmd.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b9e3734ff071acac5427da78983c7ceaebe719b5 --- /dev/null +++ b/common/exception/AcsQueryVolumeCmd.hpp @@ -0,0 +1,46 @@ + +/****************************************************************************** + * + * This file is part of the Castor project. + * See http://castor.web.cern.ch/castor + * + * Copyright (C) 2003 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * + * @author Castor Dev team, castor-dev@cern.ch + *****************************************************************************/ + +#pragma once + +#include "Exception.hpp" + +namespace cta { namespace exception { + + /** + * Failed to query volume. + */ + class AcsQueryVolumeCmd : public cta::exception::Exception { + + public: + + /** + * Constructor + */ + AcsQueryVolumeCmd(); + + }; // class AcsQueryVolumeCmd + +} } // namespace castor exception + diff --git a/common/exception/DismountFailed.cpp b/common/exception/DismountFailed.cpp new file mode 100644 index 0000000000000000000000000000000000000000..370d35792389040f2e4e01b8f279753541f75c2e --- /dev/null +++ b/common/exception/DismountFailed.cpp @@ -0,0 +1,32 @@ +/****************************************************************************** + * + * This file is part of the Castor project. + * See http://castor.web.cern.ch/castor + * + * Copyright (C) 2003 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * + * @author Castor Dev team, castor-dev@cern.ch + *****************************************************************************/ + +#include "common/exception/DismountFailed.hpp" + + +// ----------------------------------------------------------------------------- +// Constructor +// ----------------------------------------------------------------------------- +cta::exception::DismountFailed::DismountFailed(): + cta::exception::Exception() { +} diff --git a/common/exception/DismountFailed.hpp b/common/exception/DismountFailed.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a62288a2c285e705154432eabf17ec53ae9d9cc1 --- /dev/null +++ b/common/exception/DismountFailed.hpp @@ -0,0 +1,45 @@ +/****************************************************************************** + * + * This file is part of the Castor project. + * See http://castor.web.cern.ch/castor + * + * Copyright (C) 2003 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * + * @author Castor Dev team, castor-dev@cern.ch + *****************************************************************************/ + +#pragma once + +#include "common/exception/Exception.hpp" + +namespace cta { namespace exception { + + /** + * Failed to dismount volume. + */ + class DismountFailed : public cta::exception::Exception { + + public: + + /** + * Constructor + */ + DismountFailed(); + + }; // class DismountFailed + +} } // namespace cta exception + diff --git a/common/exception/Exception.cpp b/common/exception/Exception.cpp index f355a22e059cab1d36e9bb0a93af3436322e3450..e41f242c11b1f161df9f5c75876aa60f7bb7e6d6 100644 --- a/common/exception/Exception.cpp +++ b/common/exception/Exception.cpp @@ -16,7 +16,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "common/exception/Exception.hpp" +#include "Exception.hpp" //------------------------------------------------------------------------------ // constructor diff --git a/common/exception/Exception.hpp b/common/exception/Exception.hpp index b45aeccbd1061bc5d6962479b4aa6489c7a40e69..32760c778dd94ce6404a4e26313892828efd7c8b 100644 --- a/common/exception/Exception.hpp +++ b/common/exception/Exception.hpp @@ -18,7 +18,7 @@ #pragma once -#include "common/exception/Backtrace.hpp" +#include "Backtrace.hpp" #include <exception> #include <sstream> diff --git a/common/exception/Mismatch.cpp b/common/exception/Mismatch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..42b396b4a7b5ea149fe000076fb486002d922282 --- /dev/null +++ b/common/exception/Mismatch.cpp @@ -0,0 +1,33 @@ + +/****************************************************************************** + * + * This file is part of the Castor project. + * See http://castor.web.cern.ch/castor + * + * Copyright (C) 2003 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * + * @author Castor Dev team, castor-dev@cern.ch + *****************************************************************************/ + +#include "Mismatch.hpp" + + +// ----------------------------------------------------------------------------- +// Constructor +// ----------------------------------------------------------------------------- +cta::exception::Mismatch::Mismatch(): + cta::exception::Exception() { +} diff --git a/common/exception/Mismatch.hpp b/common/exception/Mismatch.hpp new file mode 100644 index 0000000000000000000000000000000000000000..dace59fd67ce878bf87bd0fe399bf8d8408e7d0c --- /dev/null +++ b/common/exception/Mismatch.hpp @@ -0,0 +1,45 @@ +/****************************************************************************** + * + * This file is part of the Castor project. + * See http://castor.web.cern.ch/castor + * + * Copyright (C) 2003 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * + * @author Castor Dev team, castor-dev@cern.ch + *****************************************************************************/ + +#pragma once + +#include "common/exception/Exception.hpp" + +namespace cta { namespace exception { + + /** + * Mismatch. + */ + class Mismatch : public cta::exception::Exception { + + public: + + /** + * Constructor + */ + Mismatch(); + + }; // class Mismatch + +} } // namespace cta exception + diff --git a/common/exception/MountFailed.cpp b/common/exception/MountFailed.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d5cb36dfd6c9ba07b01471520c07bf81d8fa8488 --- /dev/null +++ b/common/exception/MountFailed.cpp @@ -0,0 +1,32 @@ +/****************************************************************************** + * + * This file is part of the Castor project. + * See http://castor.web.cern.ch/castor + * + * Copyright (C) 2003 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * + * @author Castor Dev team, castor-dev@cern.ch + *****************************************************************************/ + +#include "MountFailed.hpp" + + +// ----------------------------------------------------------------------------- +// Constructor +// ----------------------------------------------------------------------------- +cta::exception::MountFailed::MountFailed(): + cta::exception::Exception() { +} diff --git a/common/exception/MountFailed.hpp b/common/exception/MountFailed.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5d5376f78f2404d9ca8f207da5eccb720ca1279c --- /dev/null +++ b/common/exception/MountFailed.hpp @@ -0,0 +1,45 @@ +/****************************************************************************** + * + * This file is part of the Castor project. + * See http://castor.web.cern.ch/castor + * + * Copyright (C) 2003 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * + * @author Castor Dev team, castor-dev@cern.ch + *****************************************************************************/ + +#pragma once + +#include "common/exception/Exception.hpp" + +namespace cta { namespace exception { + + /** + * Failed to mount volume. + */ + class MountFailed : public cta::exception::Exception { + + public: + + /** + * Constructor + */ + MountFailed(); + + }; // class MountFailed + +} } // namespace castor exception + diff --git a/common/exception/QueryVolumeFailed.cpp b/common/exception/QueryVolumeFailed.cpp new file mode 100644 index 0000000000000000000000000000000000000000..80b4eb5ed6b40c794d350271d994854879bf53dd --- /dev/null +++ b/common/exception/QueryVolumeFailed.cpp @@ -0,0 +1,32 @@ +/****************************************************************************** + * + * This file is part of the Castor project. + * See http://castor.web.cern.ch/castor + * + * Copyright (C) 2003 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * + * @author Castor Dev team, castor-dev@cern.ch + *****************************************************************************/ + +#include "QueryVolumeFailed.hpp" + + +// ----------------------------------------------------------------------------- +// Constructor +// ----------------------------------------------------------------------------- +cta::exception::QueryVolumeFailed::QueryVolumeFailed(): + cta::exception::Exception() { +} diff --git a/common/exception/QueryVolumeFailed.hpp b/common/exception/QueryVolumeFailed.hpp new file mode 100644 index 0000000000000000000000000000000000000000..09236633356079b1dfc309f5e340e37d8b6a8502 --- /dev/null +++ b/common/exception/QueryVolumeFailed.hpp @@ -0,0 +1,45 @@ +/****************************************************************************** + * + * This file is part of the Castor project. + * See http://castor.web.cern.ch/castor + * + * Copyright (C) 2003 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * + * @author Castor Dev team, castor-dev@cern.ch + *****************************************************************************/ + +#pragma once + +#include "Exception.hpp" + +namespace cta { namespace exception { + + /** + * Failed to query volume. + */ + class QueryVolumeFailed : public cta::exception::Exception { + + public: + + /** + * Constructor + */ + QueryVolumeFailed(); + + }; // class QueryVolumeFailed + +} } // namespace castor exception + diff --git a/common/exception/RequestFailed.cpp b/common/exception/RequestFailed.cpp new file mode 100644 index 0000000000000000000000000000000000000000..73546f017afc3c53568680bd6aead746d5de11ee --- /dev/null +++ b/common/exception/RequestFailed.cpp @@ -0,0 +1,32 @@ +/****************************************************************************** + * + * This file is part of the Castor project. + * See http://castor.web.cern.ch/castor + * + * Copyright (C) 2003 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * + * @author Castor Dev team, castor-dev@cern.ch + *****************************************************************************/ + +#include "RequestFailed.hpp" + + +// ----------------------------------------------------------------------------- +// Constructor +// ----------------------------------------------------------------------------- +cta::exception::RequestFailed::RequestFailed(): + cta::exception::Exception() { +} diff --git a/common/exception/RequestFailed.hpp b/common/exception/RequestFailed.hpp new file mode 100644 index 0000000000000000000000000000000000000000..77c9cd0bad29e4dba9025295de069681a538caae --- /dev/null +++ b/common/exception/RequestFailed.hpp @@ -0,0 +1,45 @@ +/****************************************************************************** + * + * This file is part of the Castor project. + * See http://castor.web.cern.ch/castor + * + * Copyright (C) 2003 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * + * @author Castor Dev team, castor-dev@cern.ch + *****************************************************************************/ + +#pragma once + +#include "Exception.hpp" + +namespace cta { namespace exception { + + /** + * request failed. + */ + class RequestFailed : public cta::exception::Exception { + + public: + + /** + * Constructor + */ + RequestFailed(); + + }; // class RequestFailed + +} } // namespace cta exception + diff --git a/cta.spec.in b/cta.spec.in index 9b367417379174dffb657dae397d0721ef3a6597..647cc3d133616bb6e775b142cb13c5020e2f88a6 100644 --- a/cta.spec.in +++ b/cta.spec.in @@ -317,5 +317,21 @@ Tools to faciliate working with rmcd and smc in cta %attr(0644,root,root) %config(noreplace) /etc/sysconfig/cta-rmcd %attr(0644,root,root) /etc/systemd/system/cta-rmcd.service +%package -n cta-tape-developer-acs-tools +Summary: Cern Advanced mass STORage +Group: Application/Castor +Requires: cta-lib = %{version}-%{release} +Requires: stk-ssi-lib +BuildRequires: stk-ssi-devel +%description -n cta-tape-developer-acs-tools +castor (Cern Advanced STORage system) + ASC tools for CASTOR tape developers +%files -n cta-tape-developer-acs-tools +%defattr(-,root,root) +%attr(0755,root,root) /usr/bin/cta-tape-acs-queryvolume +%attr(0755,root,root) /usr/bin/cta-tape-acs-dismount +%attr(0755,root,root) /usr/bin/cta-tape-acs-mount +%attr(0644,root,root) %doc /usr/share/man/man1/cta-tape-acs-queryvolume.1cta.gz +%attr(0644,root,root) %doc /usr/share/man/man1/cta-tape-acs-mount.1cta.gz +%attr(0644,root,root) %doc /usr/share/man/man1/cta-tape-acs-dismount.1cta.gz %endif - diff --git a/mediachanger/CMakeLists.txt b/mediachanger/CMakeLists.txt index 6d156042e27736a26b45662635afc7268d9fa4f4..91ad469581c4e7c245288ab2d39243bc0b43b15c 100644 --- a/mediachanger/CMakeLists.txt +++ b/mediachanger/CMakeLists.txt @@ -15,6 +15,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. cmake_minimum_required (VERSION 2.6) +add_subdirectory(acs) add_subdirectory(castorrmc) find_package(openssl REQUIRED) find_package(Protobuf3 REQUIRED) diff --git a/mediachanger/acs/Acs.cpp b/mediachanger/acs/Acs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d35112c3d43bcfd77324b3adc01521bb7ec2a451 --- /dev/null +++ b/mediachanger/acs/Acs.cpp @@ -0,0 +1,169 @@ +/* + * 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 "Acs.hpp" +#include "common/utils/utils.hpp" + +#include <iomanip> +#include <sstream> +#include <stdint.h> +#include <string.h> + +//------------------------------------------------------------------------------ +// destructor +//------------------------------------------------------------------------------ +cta::acs::Acs::~Acs() throw() { +} + +//------------------------------------------------------------------------------ +// str2DriveId +//------------------------------------------------------------------------------ +DRIVEID cta::acs::Acs::str2DriveId(const std::string &str) { + std::vector<std::string> components; + cta::utils::splitString(str, ':', components); + + // The drive ID should consist of 4 components: ACS, LSM, Panel and Transport + if(4 != components.size()) { + //cta::exception::InvalidArgument ex; + cta::exception::InvalidArgument ex; + ex.getMessage() << "Invalid number of components in drive ID" + ": expected=4, actual=" << components.size(); + throw ex; + } + + const std::string &acsStr = components[0]; + const std::string &lsmStr = components[1]; + const std::string &panStr = components[2]; + const std::string &drvStr = components[3]; + + // Each of the 4 components must be between 1 and than 3 characters long + if(1 > acsStr.length() || 3 < acsStr.length()) { + cta::exception::InvalidArgument ex; + ex.getMessage() << "Invalid ACS string length" + ": expected=1..3, actual=" << acsStr.length(); + throw ex; + } + if(1 > lsmStr.length() || 3 < lsmStr.length()) { + cta::exception::InvalidArgument ex; + ex.getMessage() << "Invalid LSM string length" + ": expected=1..3, actual=" << lsmStr.length(); + throw ex; + } + if(1 > panStr.length() || 3 < panStr.length()) { + cta::exception::InvalidArgument ex; + ex.getMessage() << "Invalid panel string length" + ": expected=1..3, actual=" << panStr.length(); + throw ex; + } + if(1 > drvStr.length() || 3 < drvStr.length()) { + cta::exception::InvalidArgument ex; + ex.getMessage() << "Invalid drive string length" + ": expected=1..3, actual=" << drvStr.length(); + throw ex; + } + + // Each of the 4 components must only contain numerals + if(!onlyContainsNumerals(acsStr)) { + cta::exception::InvalidArgument ex; + ex.getMessage() << "ACS must only contain numerals: value=" << acsStr; + throw ex; + } + if(!onlyContainsNumerals(lsmStr)) { + cta::exception::InvalidArgument ex; + ex.getMessage() << "LSM must only contain numerals: value=" << acsStr; + throw ex; + } + if(!onlyContainsNumerals(panStr)) { + cta::exception::InvalidArgument ex; + ex.getMessage() << "Panel must only contain numerals: value=" << acsStr; + throw ex; + } + if(!onlyContainsNumerals(drvStr)) { + cta::exception::InvalidArgument ex; + ex.getMessage() << "Drive/Transport must only contain numerals: value=" << + acsStr; + throw ex; + } + + DRIVEID driveId; + driveId.panel_id.lsm_id.acs = (ACS)atoi(acsStr.c_str()); + driveId.panel_id.lsm_id.lsm = (LSM)atoi(lsmStr.c_str()); + driveId.panel_id.panel = (PANEL)atoi(panStr.c_str()); + driveId.drive = (DRIVE)atoi(drvStr.c_str()); + + return driveId; +} + +//------------------------------------------------------------------------------ +// onlyContainsNumerals +//------------------------------------------------------------------------------ +bool cta::acs::Acs::onlyContainsNumerals(const std::string &str) throw() { + for(std::string::const_iterator itor = str.begin(); itor != str.end(); + itor++) { + if(*itor < '0' || *itor > '9') { + return false; + } + } + return true; +} + +//------------------------------------------------------------------------------ +// alpd2DriveId +//------------------------------------------------------------------------------ +DRIVEID cta::acs::Acs::alpd2DriveId(const uint32_t acs, + const uint32_t lsm, const uint32_t panel, const uint32_t drive) throw () { + + DRIVEID driveId; + driveId.panel_id.lsm_id.acs = (ACS)acs; + driveId.panel_id.lsm_id.lsm = (LSM)lsm; + driveId.panel_id.panel = (PANEL)panel; + driveId.drive = (DRIVE)drive; + + return driveId; +} + +//------------------------------------------------------------------------------ +// str2Volid +//------------------------------------------------------------------------------ +VOLID cta::acs::Acs::str2Volid(const std::string &str) { + if(EXTERNAL_LABEL_SIZE < str.length()) { + cta::exception::InvalidArgument ex; + ex.getMessage() << "Failed to convert string to volume identifier" + ": String is longer than the " << EXTERNAL_LABEL_SIZE << + " character maximum"; + throw ex; + } + + VOLID v; + strncpy(v.external_label, str.c_str(), sizeof(v.external_label)); + v.external_label[sizeof(v.external_label) - 1] = '\0'; + return v; +} + +//------------------------------------------------------------------------------ +// driveId2Str +//------------------------------------------------------------------------------ +std::string cta::acs::Acs::driveId2Str(const DRIVEID &driveId) throw() { + std::ostringstream oss; + oss << std::setfill('0') << + std::setw(3) << (int32_t)driveId.panel_id.lsm_id.acs << ":" << + std::setw(3) << (int32_t)driveId.panel_id.lsm_id.lsm << ":" << + std::setw(3) << (int32_t)driveId.panel_id.panel << ":" << + std::setw(3) << (int32_t)driveId.drive; + return oss.str(); +} diff --git a/mediachanger/acs/Acs.hpp b/mediachanger/acs/Acs.hpp new file mode 100644 index 0000000000000000000000000000000000000000..33952de09a2eb618f285371592be3e3a4a69cc2b --- /dev/null +++ b/mediachanger/acs/Acs.hpp @@ -0,0 +1,179 @@ +/* + * 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/>. + */ + +#pragma once + +#include "common/exception/InvalidArgument.hpp" +extern "C" { +#include "acssys.h" +#include "acsapi.h" +} + +#include <string> +#include <stdint.h> + +namespace cta { +namespace acs { + +/** + * Abstract class that defines the interface to an object that wraps the ACLS + * C-API. + */ +class Acs { +public: + /** + * Pure-virtual destructor to ensure this class is abstract. + */ + virtual ~Acs() throw() = 0; + + /** + * Parses the specified string and returns the corresponding drive ID object. + * + * This method throws a cta::exception::InvalidArgument if the syntax of + * the string is invalid. + * + * @param str The string to be parsed. + * @return The drive ID object. + */ + static DRIVEID str2DriveId(const std::string &str); + + /** + * Converts acs, lsm, panel, drive numbers to the corresponding + * drive ID object. + * + * @param acs The integer for acs. + * @param lsm The integer for lsm. + * @param panel The integer for panel. + * @param drive The integer for drive. + * @return The drive ID object. + */ + static DRIVEID alpd2DriveId(const uint32_t acs, const uint32_t lsm, + const uint32_t panel, const uint32_t drive) throw(); + + /** + * Returns the VOLID equibvalent of the specified string. + * + * This method throws a cta::exception::InvalidArgument if the string is + * longer than EXTERNAL_LABEL_SIZE. + * + * @param str The string representation of the volume identifier. + * @return The VOLID representation of the volume identifier. + */ + static VOLID str2Volid(const std::string &str); + + /** + * Returns the string reprsentation of the specified drive identifier. + * + * The string format is ACS:LSM:panel:drive + * + * @param driveId The drive identifier. + * @return The string representation. + */ + static std::string driveId2Str(const DRIVEID &driveId) throw(); + + /** + * C++ wrapper around the acs_mount() function of the ACSLS C-API. + * + * @param seqNumber Client supplied sequence number. + * @param lockId Lock identifier or 0 meaning no lock. + * @param volId The indentifier of volume to be mounted. + * @param driveId The ID of the drive into which the volume is to be mounted. + * @param readOnly Set to true to request the volume be mounted for read-only + * access. + * @param bypass Set to true to override the ACSLS verification of + * compatibility between the drive and the media type of the volume. + * @return status value returned by acs_mount(). + */ + virtual STATUS mount( + const SEQ_NO seqNumber, + const LOCKID lockId, + const VOLID &volId, + const DRIVEID &driveId, + const BOOLEAN readOnly, + const BOOLEAN bypass) + throw() = 0; + + /** + * C++ wrapper around the acs_dismount() function of the ACSLS C-API. + * + * @param seqNumber Client supplied sequence number. + * @param lockId Lock identifier or 0 meaning no lock. + * @param volId The identifier of the volume to be mounted. + * @param driveId The ID of the drive into which the volume is to be mounted. + * @param force Set to true if the dismount should be forced. Forcing a + * dismount means dismounting the volume from the specified drive without + * checking the identifier of the volume. + * @return status value returned by acs_dismount(). + */ + virtual STATUS dismount( + const SEQ_NO seqNumber, + const LOCKID lockId, + const VOLID &volId, + const DRIVEID &driveId, + const BOOLEAN force) + throw() = 0; + + /** + * C++ wrapper around the acs_response() function of the ACSLS C-API. + * + * @param timeout Time in seconds to wait for a response. A value of -1 + * means block indefinitely and an a value of 0 means poll for the existence + * of a response. + * @param seqNumber Output parameter. If a response exists then seqNumber + * is set. + * @param reqId Output parameter. For an acknowledge response reqId is set + * to the request identifier of the original request. For an intermediate or + * final response reqId will be set to 0. + * @param rType Output parameter. Set to the type of the response. + * @param rBuf Output parameter. Set to the response information. + * @return status value returned by acs_response(). + */ + virtual STATUS response( + const int timeout, + SEQ_NO &seqNumber, + REQ_ID &reqId, + ACS_RESPONSE_TYPE &rType, + ALIGNED_BYTES rBuf) throw() = 0; + + /** + * C++ wrapper around the acs_query_volume() function of the ACSLS C-API. + * + * @param seqNumber Client supplied sequence number. + * @param volIds Array of the volume identifiers to be queried. + * @param count The number of volume identifiers contained iwthin the volId + * parameter. + * @return status value returned by acs_response(). + */ + virtual STATUS queryVolume( + const SEQ_NO seqNumber, + VOLID (&volIds)[MAX_ID], + const unsigned short count) throw() = 0; + +protected: + + /** + * Returns true if the specified string only contains numerals else false. + * + * @return True if the specified string only contains numerals else false. + */ + static bool onlyContainsNumerals(const std::string &str) throw(); + +}; // class Acs + +} // namespace acs +} // namespace cta diff --git a/mediachanger/acs/AcsCmd.cpp b/mediachanger/acs/AcsCmd.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4841fa2560431714f34efb7fd6da7a8ffa903367 --- /dev/null +++ b/mediachanger/acs/AcsCmd.cpp @@ -0,0 +1,115 @@ +/* + * 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 "AcsCmd.hpp" +#include "common/exception/Exception.hpp" +#include <stdlib.h> + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +cta::acs::AcsCmd::AcsCmd(std::istream &inStream, + std::ostream &outStream, std::ostream &errStream, Acs &acs) throw(): + CmdLineTool(inStream, outStream, errStream), m_acs(acs) { +} + +//------------------------------------------------------------------------------ +// destructor +//------------------------------------------------------------------------------ +cta::acs::AcsCmd::~AcsCmd() throw() { +} + +//------------------------------------------------------------------------------ +// bool2Str +//------------------------------------------------------------------------------ +std::string cta::acs::AcsCmd::bool2Str(const BOOLEAN value) const + throw() { + return value ? "TRUE" : "FALSE"; +} + +//------------------------------------------------------------------------------ +// requestResponsesUntilFinal +//------------------------------------------------------------------------------ +void cta::acs::AcsCmd::requestResponsesUntilFinal( + const SEQ_NO requestSeqNumber, + ALIGNED_BYTES (&buf)[MAX_MESSAGE_SIZE / sizeof(ALIGNED_BYTES)], + const int queryInterval, const int timeout) { + ACS_RESPONSE_TYPE responseType = RT_NONE; + int elapsedTime = 0; + do { + const int remainingTime = timeout - elapsedTime; + const int responseTimeout = remainingTime > queryInterval ? + queryInterval : remainingTime; + + const time_t startTime = time(NULL); + responseType = requestResponse(responseTimeout, requestSeqNumber, buf); + elapsedTime += time(NULL) - startTime; + + if(RT_ACKNOWLEDGE == responseType) { + m_dbg << "Received RT_ACKNOWLEDGE" << std::endl; + } + + if(elapsedTime >= timeout) { + cta::exception::RequestFailed ex; + ex.getMessage() << "Timed out after " << timeout << " seconds"; + throw ex; + } + } while(RT_FINAL != responseType); + + m_dbg << "Received RT_FINAL" << std::endl; +} + +//------------------------------------------------------------------------------ +// requestResponse +//------------------------------------------------------------------------------ +ACS_RESPONSE_TYPE cta::acs::AcsCmd::requestResponse( + const int timeout, const SEQ_NO requestSeqNumber, + ALIGNED_BYTES (&buf)[MAX_MESSAGE_SIZE / sizeof(ALIGNED_BYTES)]) { + SEQ_NO responseSeqNumber = 0; + REQ_ID reqId = (REQ_ID)0; + ACS_RESPONSE_TYPE responseType = RT_NONE; + + m_dbg << "Calling Acs::response()" << std::endl; + const STATUS s = m_acs.response(timeout, responseSeqNumber, reqId, + responseType, buf); + m_dbg << "Acs::response() returned " << acs_status(s) << std::endl; + + switch(s) { + case STATUS_SUCCESS: + checkResponseSeqNumber(requestSeqNumber, responseSeqNumber); + return responseType; + case STATUS_PENDING: + return RT_NONE; + default: + cta::exception::RequestFailed ex; + ex.getMessage() << "Failed to request response: " << acs_status(s); + throw ex; + } +} + +//------------------------------------------------------------------------------ +// checkSeqNumber +//------------------------------------------------------------------------------ +void cta::acs::AcsCmd::checkResponseSeqNumber( const SEQ_NO requestSeqNumber, const SEQ_NO responseSeqNumber) { + if(requestSeqNumber != responseSeqNumber) { + cta::exception::Mismatch ex; + ex.getMessage() << ": Sequence number mismatch: requestSeqNumber=" + << requestSeqNumber << " responseSeqNumber=" << responseSeqNumber; + throw ex; + } +} diff --git a/mediachanger/acs/AcsCmd.hpp b/mediachanger/acs/AcsCmd.hpp new file mode 100644 index 0000000000000000000000000000000000000000..744a62bab35af862cd5eace4a7085b50b7d5fcbf --- /dev/null +++ b/mediachanger/acs/AcsCmd.hpp @@ -0,0 +1,121 @@ +/* + * 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/>. + */ + +#pragma once + +#include "common/exception/InvalidArgument.hpp" +#include "common/exception/Mismatch.hpp" +//#include "common/exception/RequestFailed.hpp" +#include "common/exception/RequestFailed.hpp" +#include "Acs.hpp" +#include "AcsCmd.hpp" +#include "CmdLineTool.hpp" + +#include <istream> +#include <ostream> +#include <string> + +extern "C" { +#include "acssys.h" +#include "acsapi.h" +} + +namespace cta { +namespace acs { + +/** + * Abstract class implementing common code and data structures for command-line + * tools that interact with ACLS compatible tape libraries. + */ +class AcsCmd: public CmdLineTool { +public: + /** + * Constructor. + * + * @param inStream Standard input stream. + * @param outStream Standard output stream. + * @param errStream Standard error stream. + * @param acs Wrapper around the ACSLS C-API. + */ + AcsCmd(std::istream &inStream, std::ostream &outStream, + std::ostream &errStream, Acs &acs) throw(); + + /** + * Pure-virtual destructor to guarantee this class is abstract. + */ + virtual ~AcsCmd() throw() = 0; + +protected: + + /** + * Wrapper around the ACSLS C-API. + */ + Acs &m_acs; + + /** + * Returns the string representation of the specfied boolean value. + * + * @param value The boolean value. + */ + std::string bool2Str(const BOOLEAN value) const throw(); + + /** + * Requests responses from ACSLS in a loop until the RT_FINAL response is + * received. + * + * @param requestSeqNumber The sequemce number that was sent in the initial + * request to the ACSLS. + * @param buf Output parameter. Message buffer into which the RT_FINAL + * response shall be written. + * @param queryInterval Time in seconds to wait between queries to ACS for + * responses. + * @param timeout The time in seconds to spend trying to get the RT_FINAL + * response. + */ + void requestResponsesUntilFinal(const SEQ_NO requestSeqNumber, + ALIGNED_BYTES (&buf)[MAX_MESSAGE_SIZE / sizeof(ALIGNED_BYTES)], + const int queryInterval, const int timeout); + + /** + * Sends a request for a response to the ACSLS. + * + * @param timeout The timeout. + * @param requestSeqNumber The sequemce number that was sent in the initial + * request to the ACSLS. + * @param buf Output parameter. The response message if there is one. + * @return The type of the response message if there is one or RT_NONE if + * there isn't one. + */ + ACS_RESPONSE_TYPE requestResponse(const int timeout, + const SEQ_NO requestSeqNumber, + ALIGNED_BYTES (&buf)[MAX_MESSAGE_SIZE / sizeof(ALIGNED_BYTES)]); + + /** + * Throws cta::exception::Mismatch if the specified request and + * response sequence-numbers do not match. + * + * @param requestSeqNumber Request sequence-number. + * @param responseSeqNumber Response sequence-number. + */ + void checkResponseSeqNumber(const SEQ_NO requestSeqNumber, + const SEQ_NO responseSeqNumber); + +}; // class AcsCmd + +} // namespace acs +} // namespace cta diff --git a/mediachanger/acs/AcsCmdLine.cpp b/mediachanger/acs/AcsCmdLine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1c4998166d7f12fe864760945b2c6e8f1ae3fb3b --- /dev/null +++ b/mediachanger/acs/AcsCmdLine.cpp @@ -0,0 +1,75 @@ +/* + * 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 "AcsCmdLine.hpp" +#include "common/exception/InvalidArgument.hpp" +#include "common/exception/MissingOperand.hpp" + +#include <stdlib.h> +#include <unistd.h> + +//------------------------------------------------------------------------------ +// parseQueryInterval +//------------------------------------------------------------------------------ +int cta::acs::AcsCmdLine::parseQueryInterval(const std::string &s) { + const int queryInterval = atoi(s.c_str()); + if(0 >= queryInterval) { + cta::exception::InvalidArgument ex; + ex.getMessage() << "Query value must be an integer greater than 0" + ": value=" << queryInterval; + throw ex; + } + + return queryInterval; +} + +//------------------------------------------------------------------------------ +// parseTimeout +//------------------------------------------------------------------------------ +int cta::acs::AcsCmdLine::parseTimeout(const std::string &s) { + const int timeout = atoi(s.c_str()); + if(0 >= timeout) { + cta::exception::InvalidArgument ex; + ex.getMessage() << "Timeout value must be an integer greater than 0" + ": value=" << timeout; + throw ex; + } + return timeout; +} + +//------------------------------------------------------------------------------ +// handleMissingParameter +//------------------------------------------------------------------------------ +void cta::acs::AcsCmdLine::handleMissingParameter(const int opt) { + cta::exception::MissingOperand ex; + ex.getMessage() << "The -" << (char)opt << " option requires a parameter"; + throw ex; +} + +//------------------------------------------------------------------------------ +// handleUnknownOption +//------------------------------------------------------------------------------ +void cta::acs::AcsCmdLine::handleUnknownOption(const int opt) { + cta::exception::InvalidArgument ex; + if(0 == optopt) { + ex.getMessage() << "Unknown command-line option"; + } else { + ex.getMessage() << "Unknown command-line option: -" << (char)opt; + } + throw ex; +} diff --git a/mediachanger/acs/AcsCmdLine.hpp b/mediachanger/acs/AcsCmdLine.hpp new file mode 100644 index 0000000000000000000000000000000000000000..26455c6c02eabc3088e1a5731d729f50f106dac0 --- /dev/null +++ b/mediachanger/acs/AcsCmdLine.hpp @@ -0,0 +1,64 @@ +/* + * 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/>. + */ + +#pragma once + +#include <string> + +namespace cta { +namespace acs { + +/** + * Class containing the code common to the parsed command-line of the ACS + * command-line tools provided by CASTOR. + */ +struct AcsCmdLine { +protected: + + /** + * Parses the specified query interval. + * + * @return The parse query interval. + */ + int parseQueryInterval(const std::string &s); + + /** + * Parses the specified timeout. + * + * @return The parse query interval. + */ + int parseTimeout(const std::string &s); + + /** + * Handles the specified parameter that is missing a parameter. + * + * @param opt The option. + */ + void handleMissingParameter(const int opt); + + /** + * Handles the specified unknown option. + * + * @param opt The option. + */ + void handleUnknownOption(const int opt); + +}; // class AcsCmdLine + +} // namespace acs +} // namespace cta diff --git a/mediachanger/acs/AcsDaemonConfig.cpp b/mediachanger/acs/AcsDaemonConfig.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fcfc67256660dfa0095105e565e8ed720d71402b --- /dev/null +++ b/mediachanger/acs/AcsDaemonConfig.cpp @@ -0,0 +1,57 @@ +/****************************************************************************** + * + * This file is part of the Castor project. + * See http://castor.web.cern.ch/castor + * + * Copyright (C) 2003 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * + * @author Castor Dev team, castor-dev@cern.ch + *****************************************************************************/ + +#include "AcsDaemonConfig.hpp" +//#include "castor/acs/Constants.hpp" +#include "common/log/Constants.hpp" +#include "castor/server/LoggedCastorConfiguration.hpp" + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +castor::acs::AcsDaemonConfig::AcsDaemonConfig() throw(): + port(0), + queryInterval(0), + cmdTimeout(0) { +} + +//------------------------------------------------------------------------------ +// createFromCastorConfig +//------------------------------------------------------------------------------ +castor::acs::AcsDaemonConfig castor::acs::AcsDaemonConfig:: + createFromCastorConf(log::Logger *const log) { + server::LoggedCastorConfiguration castorConf( + common::CastorConfiguration::getConfig()); + AcsDaemonConfig config; + + config.port = castorConf.getConfEntInt("AcsDaemon", "Port", + (unsigned short)ACS_PORT); + + config.queryInterval = castorConf.getConfEntInt("AcsDaemon", "QueryInterval", + (time_t)ACS_QUERY_INTERVAL); + + config.cmdTimeout = castorConf.getConfEntInt("AcsDaemon", "CmdTimeout", + (time_t)ACS_CMD_TIMEOUT); + + return config; +} diff --git a/mediachanger/acs/AcsDaemonConfig.hpp b/mediachanger/acs/AcsDaemonConfig.hpp new file mode 100644 index 0000000000000000000000000000000000000000..02716e3a188e03efce004fab32047626098a0f75 --- /dev/null +++ b/mediachanger/acs/AcsDaemonConfig.hpp @@ -0,0 +1,75 @@ +/****************************************************************************** + * + * This file is part of the Castor project. + * See http://castor.web.cern.ch/castor + * + * Copyright (C) 2003 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * @author Castor Dev team, castor-dev@cern.ch + *****************************************************************************/ + +#pragma once + +//#include "castor/log/Logger.hpp" +#include "common/log/Logger.hpp" + +#include <time.h> + +namespace castor { +namespace acs { + +/** + * Structure used to store the CASTOR configuration parameters used by the + * CASTOR ACS daemon. + */ +struct AcsDaemonConfig { + + /** + * The TCP/IP port on which the CASTOR ACS daemon listens for incoming Zmq + * connections from the tape server. + */ + unsigned short port; + + /** + * Time to wait in seconds between queries to the tape Library. + */ + time_t queryInterval; + + /** + * The maximum time to wait in seconds for a tape-library command to + * conclude. + */ + time_t cmdTimeout; + + /** + * Constructor that sets all integer member-variables to 0 and all string + * member-variables to the empty string. + */ + AcsDaemonConfig() throw(); + + /** + * Returns a configuration structure based on the contents of + * /etc/castor/castor.conf and compile-time constants. + * + * @param log pointer to NULL or an optional logger object. + * @return The configuration structure. + */ + static AcsDaemonConfig createFromCastorConf( + log::Logger *const log = NULL); + +}; // struct AcsDaemonConfig + +} // namespace acs +} // namespace castor + diff --git a/mediachanger/acs/AcsDismountCmd.cpp b/mediachanger/acs/AcsDismountCmd.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ede15c6d11c193cb4e2c643484953106a93732e5 --- /dev/null +++ b/mediachanger/acs/AcsDismountCmd.cpp @@ -0,0 +1,128 @@ +/* + * 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 "AcsDismountCmd.hpp" + +#include <getopt.h> + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +cta::acs::AcsDismountCmd::AcsDismountCmd( + std::istream &inStream, std::ostream &outStream, std::ostream &errStream, + Acs &acs) throw(): + AcsCmd(inStream, outStream, errStream, acs) { +} + +//------------------------------------------------------------------------------ +// destructor +//------------------------------------------------------------------------------ +cta::acs::AcsDismountCmd::~AcsDismountCmd() throw() { + // Do nothing +} + +//------------------------------------------------------------------------------ +// exceptionThrowingMain +//------------------------------------------------------------------------------ +int cta::acs::AcsDismountCmd::exceptionThrowingMain(const int argc, + char *const *const argv) { + try { + m_cmdLine = AcsDismountCmdLine(argc, argv); + } catch(cta::exception::Exception &ex) { + m_err << ex.getMessage().str() << std::endl; + m_err << std::endl; + m_err << m_cmdLine.getUsage() << std::endl; + return 1; + } + + // Display the usage message to standard out and exit with success if the + // user requested help + if(m_cmdLine.help) { + m_out << AcsDismountCmdLine::getUsage(); + return 0; + } + + // Setup debug mode to be on or off depending on the command-line arguments + m_debugBuf.setDebug(m_cmdLine.debug); + + m_dbg << "force = " << (m_cmdLine.force ? "TRUE" : "FALSE") << std::endl; + m_dbg << "query = " << m_cmdLine.queryInterval << std::endl; + m_dbg << "timeout = " << m_cmdLine.timeout << std::endl; + m_dbg << "VID = " << m_cmdLine.volId.external_label << std::endl; + m_dbg << "DRIVE_SLOT = " << m_acs.driveId2Str(m_cmdLine.libraryDriveSlot) + << std::endl; + + syncDismount(); + return 0; +} + +//------------------------------------------------------------------------------ +// syncDismount +//------------------------------------------------------------------------------ +void cta::acs::AcsDismountCmd::syncDismount() { + const SEQ_NO requestSeqNumber = 1; + ALIGNED_BYTES buf[MAX_MESSAGE_SIZE / sizeof(ALIGNED_BYTES)]; + + try { + sendDismountRequest(requestSeqNumber); + requestResponsesUntilFinal(requestSeqNumber, buf, m_cmdLine.queryInterval, + m_cmdLine.timeout); + processDismountResponse(buf); + } catch(cta::exception::Exception &ex) { + cta::exception::DismountFailed df; + df.getMessage() << "Failed to dismount volume " << + m_cmdLine.volId.external_label << ": " << ex.getMessage().str(); + throw df; + } +} + +//------------------------------------------------------------------------------ +// sendDismountRequest +//------------------------------------------------------------------------------ +void cta::acs::AcsDismountCmd::sendDismountRequest( + const SEQ_NO seqNumber) { + const LOCKID lockId = 0; // No lock + + m_dbg << "Calling Acs::dismount()" << std::endl; + const STATUS s = m_acs.dismount(seqNumber, lockId, m_cmdLine.volId, + m_cmdLine.libraryDriveSlot, m_cmdLine.force); + m_dbg << "Acs::dismount() returned " << acs_status(s) << std::endl; + if(STATUS_SUCCESS != s) { + cta::exception::DismountFailed ex; + ex.getMessage() << "Failed to send request to dismount volume " << + m_cmdLine.volId.external_label << " from drive " << + m_acs.driveId2Str(m_cmdLine.libraryDriveSlot) << ": force=" << + (m_cmdLine.force ? "TRUE" : "FALSE") << ": " << acs_status(s); + throw ex; + } +} + +//------------------------------------------------------------------------------ +// processDismountResponse +//------------------------------------------------------------------------------ +void cta::acs::AcsDismountCmd::processDismountResponse( + ALIGNED_BYTES (&buf)[MAX_MESSAGE_SIZE / sizeof(ALIGNED_BYTES)]) { + const ACS_DISMOUNT_RESPONSE *const msg = (ACS_DISMOUNT_RESPONSE *)buf; + + if(STATUS_SUCCESS != msg->dismount_status) { + cta::exception::DismountFailed ex; + ex.getMessage() << "Status of dismount response is not success: " << + acs_status(msg->dismount_status); + throw ex; + } +} diff --git a/mediachanger/acs/AcsDismountCmd.hpp b/mediachanger/acs/AcsDismountCmd.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3a9bb88f7e92fd0d4297383ea55b1c584c626831 --- /dev/null +++ b/mediachanger/acs/AcsDismountCmd.hpp @@ -0,0 +1,107 @@ +/* + * 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/>. + */ + +#pragma once + +#include "AcsCmd.hpp" +#include "AcsDismountCmdLine.hpp" +#include "common/exception/DismountFailed.hpp" +#include "common/exception/InvalidArgument.hpp" +#include "common/exception/MissingOperand.hpp" + +namespace cta { +namespace acs { + +/** + * The class implementing the mount command. + */ +class AcsDismountCmd: public AcsCmd { +public: + + /** + * Constructor. + * + * @param inStream Standard input stream. + * @param outStream Standard output stream. + * @param errStream Standard error stream. + * @param acs Wrapper around the ACSLS C-API. + */ + AcsDismountCmd(std::istream &inStream, std::ostream &outStream, + std::ostream &errStream, Acs &acs) throw(); + + /** + * Destructor. + */ + virtual ~AcsDismountCmd() throw(); + + /** + * The entry function of the command. + * + * This method sets the m_cmdLine member-variable. + * + * @param argc The number of command-line arguments. + * @param argv The command-line arguments. + * @return The exit value of the program. + */ + int exceptionThrowingMain(const int argc, char *const *const argv); + +protected: + + /** + * Dismounts the tape with the specified VID into the drive with the specified + * drive ID. + * + * This method does not return until the mount has either suceeded, failed or + * the specified timeout has been reached. + * + * @param dismountTimeout The maximum amount of time in seconds to wait for + * the dismount operation to conclude. + * @param queryInterval The amount of time in seconds to wait between + * querying ACS for responses. + */ + void syncDismount(); + + /** + * Sends the dismount request to ACSLS. + * + * @param seqNumber The sequence number to be used in the request. + */ + void sendDismountRequest(const SEQ_NO seqNumber); + + /** + * Throws cta::exception::DismountFailed if the mount was not + * successful. + * + * @param buf The mount-response message. + */ + void processDismountResponse( + ALIGNED_BYTES (&buf)[MAX_MESSAGE_SIZE / sizeof(ALIGNED_BYTES)]); + +private: + + /** + * The parsed command-line. + * + * This member-variable is set by the main() method of this class. + */ + AcsDismountCmdLine m_cmdLine; + +}; // class AcsDismountCmd + +} // namespace acs +} // namespace cta diff --git a/mediachanger/acs/AcsDismountCmdLine.cpp b/mediachanger/acs/AcsDismountCmdLine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..78668fd819bbf5d7373e391af9f4acdce33a2e98 --- /dev/null +++ b/mediachanger/acs/AcsDismountCmdLine.cpp @@ -0,0 +1,182 @@ +/* + * 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 "Acs.hpp" +#include "AcsCmdLine.hpp" +#include "AcsDismountCmdLine.hpp" +#include "Constants.hpp" +#include "common/exception/InvalidArgument.hpp" +#include "common/exception/MissingOperand.hpp" + +#include <getopt.h> +#include <stdlib.h> +#include <string.h> + +//----------------------------------------------------------------------------- +// constructor +//----------------------------------------------------------------------------- +cta::acs::AcsDismountCmdLine::AcsDismountCmdLine() throw(): + debug(false), + force(FALSE), + help(false), + queryInterval(0), + timeout(0) { + libraryDriveSlot.panel_id.lsm_id.acs = (ACS)0; + libraryDriveSlot.panel_id.lsm_id.lsm = (LSM)0; + libraryDriveSlot.panel_id.panel = (PANEL)0; + libraryDriveSlot.drive = (DRIVE)0; + memset(volId.external_label, '\0', sizeof(volId.external_label)); +} + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +cta::acs::AcsDismountCmdLine::AcsDismountCmdLine(const int argc, + char *const *const argv): + debug(false), + force(FALSE), + help(false), + queryInterval(ACS_QUERY_INTERVAL), + timeout(ACS_CMD_TIMEOUT) { + libraryDriveSlot.panel_id.lsm_id.acs = (ACS)0; + libraryDriveSlot.panel_id.lsm_id.lsm = (LSM)0; + libraryDriveSlot.panel_id.panel = (PANEL)0; + libraryDriveSlot.drive = (DRIVE)0; + memset(volId.external_label, '\0', sizeof(volId.external_label)); + + static struct option longopts[] = { + {"debug", 0, NULL, 'd'}, + {"force", 0, NULL, 'f'}, + {"help" , 0, NULL, 'h'}, + {"query" , required_argument, NULL, 'q'}, + {"timeout" , required_argument, NULL, 't'}, + {NULL , 0, NULL, 0 } + }; + + // Prevent getopt() from printing an error message if it does not recognize + // an option character + opterr = 0; + + int opt = 0; + while((opt = getopt_long(argc, argv, ":dfhq:t:", longopts, NULL)) != -1) { + processOption(opt); + } + + // There is no need to continue parsing when the help option is set + if(help) { + return; + } + + // Calculate the number of non-option ARGV-elements + const int nbArgs = argc-optind; + + // Check that both VID and DRIVE_SLOT have been specified + if(nbArgs < 2) { + cta::exception::MissingOperand ex; + + ex.getMessage() << + "Both VID and DRIVE_SLOT must be specified"; + + throw ex; + } + + // Parse VID + volId = Acs::str2Volid(argv[optind]); + + // Move on to the next command-line argument + optind++; + + // Parse DRIVE_SLOT + libraryDriveSlot = Acs::str2DriveId(argv[optind]); +} + +//------------------------------------------------------------------------------ +// processOption +//------------------------------------------------------------------------------ +void cta::acs::AcsDismountCmdLine::processOption(const int opt) { + switch (opt) { + case 'd': + debug = true; + break; + case 'f': + force = TRUE; + break; + case 'h': + help = true; + break; + case 'q': + queryInterval = parseQueryInterval(optarg); + break; + case 't': + timeout = parseTimeout(optarg); + break; + case ':': + return handleMissingParameter(optopt); + case '?': + return handleUnknownOption(optopt); + default: + { + cta::exception::Exception ex; + ex.getMessage() << + "getopt_long returned the following unknown value: 0x" << + std::hex << (int)opt; + throw ex; + } + } // switch(opt) +} + +//------------------------------------------------------------------------------ +// getUsage +//------------------------------------------------------------------------------ +std::string cta::acs::AcsDismountCmdLine::getUsage() throw() { + std::ostringstream usage; + usage << + "Usage:\n" + "\n" + " cta-tape-acs-dismount [options] VID DRIVE_SLOT\n" + "\n" + "Where:\n" + "\n" + " VID The VID of the volume to be dismounted.\n" + "\n" + " DRIVE_SLOT The slot in the tape library where the drive is located.\n" + " The format of DRIVE_SLOT is as follows:\n" + "\n" + " ACS:LSM:panel:transport\n" + "\n" + "Options:\n" + "\n" + " -d|--debug Turn on the printing of debug information.\n" + "\n" + " -f|--force Force the dismount.\n" + "\n" + " -h|--help Print this help message and exit.\n" + "\n" + " -q|--query SECONDS Time to wait between queries to ACS for responses.\n" + " SECONDS must be an integer value greater than 0.\n" + " The default value of SECONDS is " + << ACS_QUERY_INTERVAL << ".\n" + "\n" + " -t|--timeout SECONDS Time to wait for the dismount to conclude. SECONDS\n" + " must be an integer value greater than 0. The\n" + " default value of SECONDS is " + << ACS_CMD_TIMEOUT << ".\n" + "\n" + "Comments to: CTA team\n"; + return usage.str(); +} diff --git a/mediachanger/acs/AcsDismountCmdLine.hpp b/mediachanger/acs/AcsDismountCmdLine.hpp new file mode 100644 index 0000000000000000000000000000000000000000..373955eb64aa007d6a2cce2b8e39f4033d98fdcd --- /dev/null +++ b/mediachanger/acs/AcsDismountCmdLine.hpp @@ -0,0 +1,112 @@ +/* + * 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/>. + */ + +#pragma once + +#include "AcsCmdLine.hpp" + +extern "C" { +#include "acssys.h" +#include "acsapi.h" +} + +#include <string> + +namespace cta { +namespace acs { + +/** + * Data type used to store the results of parsing the command-line. + */ +struct AcsDismountCmdLine: public AcsCmdLine { + /** + * True if the debug option has been set. + */ + bool debug; + + /** + * True if the dismount should be forced. + * + * Forcing a dismount means dismounting the tape in the specified drive + * without checking the volume identifier of the tape. + */ + BOOLEAN force; + + /** + * True if the help option has been set. + */ + bool help; + + /** + * Time in seconds to wait between queries to ACS for responses. + */ + int queryInterval; + + /** + * Time in seconds to wait for the dismount to conclude. + */ + int timeout; + + /** + * The volume identifier of the tape to be mounted. + */ + VOLID volId; + + /** + * The slot in the tape library where the drive is located. + */ + DRIVEID libraryDriveSlot; + + /** + * Constructor. + * + * Initialises all boolean member-variables to false, all integer + * member-variables to 0 and the volume identifier to an empty string. + */ + AcsDismountCmdLine() throw(); + + /** + * Constructor. + * + * Parses the specified command-line arguments. + * + * @param argc Argument count from the executable's entry function: main(). + * @param argv Argument vector from the executable's entry function: main(). + */ + AcsDismountCmdLine(const int argc, char *const *const argv); + + /** + * Gets the usage message that describes the comamnd line. + * + * @return The usage message. + */ + static std::string getUsage() throw(); + +private: + + /** + * Processes the specified option that was returned by getopt_long(). + * + * @param opt The option that was returned by getopt_long(). + */ + void processOption(const int opt); + +}; // class AcsDismountCmdLine + +} // namespace acs +} // namespace cta diff --git a/mediachanger/acs/AcsDismountCmdMain.cpp b/mediachanger/acs/AcsDismountCmdMain.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cacd1534b6d1b92ae2bfba40d53c4489c6224bda --- /dev/null +++ b/mediachanger/acs/AcsDismountCmdMain.cpp @@ -0,0 +1,69 @@ +/* + * 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 "AcsDismountCmd.hpp" +#include "AcsDismountCmdLine.hpp" +#include "AcsImpl.hpp" + +#include <iostream> + +/** + * An exception throwing version of main(). + * + * @param argc The number of command-line arguments including the program name. + * @param argv The command-line arguments. + * @return The exit value of the program. + */ +static int exceptionThrowingMain(const int argc, char *const *const argv); + +//------------------------------------------------------------------------------ +// main +//------------------------------------------------------------------------------ +int main(const int argc, char *const *const argv) { + using namespace cta; + + std::string errorMessage; + + try { + return exceptionThrowingMain(argc, argv); + } catch(cta::exception::Exception &ex) { + errorMessage = ex.getMessage().str(); + } catch(std::exception &se) { + errorMessage = se.what(); + } catch(...) { + errorMessage = "An unknown exception was thrown"; + } + + // Reaching this point means the command has failed, ane exception was throw + // and errorMessage has been set accordingly + + std::cerr << "Aborting: " << errorMessage << std::endl; + return 1; +} + +//------------------------------------------------------------------------------ +// exceptionThrowingMain +//------------------------------------------------------------------------------ +static int exceptionThrowingMain(const int argc, char *const *const argv) { + using namespace cta; + + acs::AcsImpl acs; + acs::AcsDismountCmd cmd(std::cin, std::cout, std::cerr, acs); + + return cmd.exceptionThrowingMain(argc, argv); +} diff --git a/mediachanger/acs/AcsImpl.cpp b/mediachanger/acs/AcsImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3aa961b099c3188587e05a82e5f4e8b05a35536b --- /dev/null +++ b/mediachanger/acs/AcsImpl.cpp @@ -0,0 +1,78 @@ +/* + * 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 "AcsImpl.hpp" + +#include <errno.h> +#include <sstream> +#include <string.h> + +//------------------------------------------------------------------------------ +// destructor +//------------------------------------------------------------------------------ +cta::acs::AcsImpl::~AcsImpl() throw() { +} + +//------------------------------------------------------------------------------ +// mount +//------------------------------------------------------------------------------ +STATUS cta::acs::AcsImpl::mount( + const SEQ_NO seqNumber, + const LOCKID lockId, + const VOLID &volId, + const DRIVEID &driveId, + const BOOLEAN readOnly, + const BOOLEAN bypass) + throw() { + return acs_mount(seqNumber, lockId, volId, driveId, readOnly, bypass); +} + +//------------------------------------------------------------------------------ +// dismount +//------------------------------------------------------------------------------ +STATUS cta::acs::AcsImpl::dismount( + const SEQ_NO seqNumber, + const LOCKID lockId, + const VOLID &volId, + const DRIVEID &driveId, + const BOOLEAN force) + throw() { + return acs_dismount(seqNumber, lockId, volId, driveId, force); +} + +//------------------------------------------------------------------------------ +// response +//------------------------------------------------------------------------------ +STATUS cta::acs::AcsImpl::response( + const int timeout, + SEQ_NO &seqNumber, + REQ_ID &reqId, + ACS_RESPONSE_TYPE &rType, + ALIGNED_BYTES rBuf) throw() { + return acs_response(timeout, &seqNumber, &reqId, &rType, rBuf); +} + +//------------------------------------------------------------------------------ +// queryVolume +//------------------------------------------------------------------------------ +STATUS cta::acs::AcsImpl::queryVolume( + const SEQ_NO seqNumber, + VOLID (&volIds)[MAX_ID], + const unsigned short count) throw() { + return acs_query_volume(seqNumber, volIds, count); +} diff --git a/mediachanger/acs/AcsImpl.hpp b/mediachanger/acs/AcsImpl.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7adcb117a003879dc4e0719618680a83b59e7893 --- /dev/null +++ b/mediachanger/acs/AcsImpl.hpp @@ -0,0 +1,117 @@ +/* + * 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/>. + */ + +#pragma once + +#include "Acs.hpp" + +namespace cta { +namespace acs { + +/** + * Concrete class that wraps the ACLS C-API. + */ +class AcsImpl: public Acs { +public: + /** + * Destructor. + */ + ~AcsImpl() throw(); + + /** + * C++ wrapper around the acs_mount() function of the ACSLS C-API. + * + * @param seqNumber Client supplied sequence number. + * @param lockId Lock identifier or 0 meaning no lock. + * @param volId The identifier of the volume to be mounted. + * @param driveId The ID of the drive into which the volume is to be mounted. + * @param readOnly Set to true to request the volume be mounted for read-only + * access. + * @param bypass Set to true to override the ACSLS verification of + * compatibility between the drive and the media type of the volume. + * @return status value returned by acs_mount(). + */ + STATUS mount( + const SEQ_NO seqNumber, + const LOCKID lockId, + const VOLID &volId, + const DRIVEID &driveId, + const BOOLEAN readOnly, + const BOOLEAN bypass) + throw(); + + /** + * C++ wrapper around the acs_dismount() function of the ACSLS C-API. + * + * @param seqNumber Client supplied sequence number. + * @param lockId Lock identifier or 0 meaning no lock. + * @param volId The identifier of the volume to be mounted. + * @param driveId The ID of the drive into which the volume is to be mounted. + * @param force Set to true if the dismount should be forced. Forcing a + * dismount means dismounting the volume from the specified drive without + * checking the identifier of the volume. + * @return status value returned by acs_dismount(). + */ + STATUS dismount( + const SEQ_NO seqNumber, + const LOCKID lockId, + const VOLID &volId, + const DRIVEID &driveId, + const BOOLEAN force) + throw(); + + /** + * C++ wrapper around the acs_response() function of the ACSLS C-API. + * + * @param timeout Time in seconds to wait for a response. A value of -1 + * means block indefinitely and an a value of 0 means poll for the existence + * of a response. + * @param seqNumber Output parameter. If a response exists then seqNumber + * is set. + * @param reqId Output parameter. For an acknowledge response reqId is set + * to the request identifier of the original request. For an intermediate or + * final response reqId will be set to 0. + * @param rType Output parameter. Set to the type of the response. + * @param rBuf Output parameter. Set to the response information. + * @return status value returned by acs_response(). + */ + STATUS response( + const int timeout, + SEQ_NO &seqNumber, + REQ_ID &reqId, + ACS_RESPONSE_TYPE &rType, + ALIGNED_BYTES rBuf) throw(); + + /** + * C++ wrapper around the acs_query_volume() function of the ACSLS C-API. + * + * @param seqNumber Client supplied sequence number. + * @param volIds Array of the volume identifiers to be queried. + * @param count The number of volume identifiers contained iwthin the volId + * parameter. + * @return status value returned by acs_response(). + */ + STATUS queryVolume( + const SEQ_NO seqNumber, + VOLID (&volIds)[MAX_ID], + const unsigned short count) throw(); + +}; // class AcsImpl + +} // namespace acs +} // namespace cta diff --git a/mediachanger/acs/AcsLibraryInteraction.cpp b/mediachanger/acs/AcsLibraryInteraction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c311ad9eef824e4e2e6b18eee25808e30da82a65 --- /dev/null +++ b/mediachanger/acs/AcsLibraryInteraction.cpp @@ -0,0 +1,160 @@ + +/* + * 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 "AcsLibraryInteraction.hpp" +#include "../../log.hpp" + +#include <stdlib.h> + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +cta::acs::AcsLibraryInteraction::AcsLibraryInteraction( + Acs &acs) throw(): m_acs(acs) { +} + +//------------------------------------------------------------------------------ +// destructor +//------------------------------------------------------------------------------ +cta::acs::AcsLibraryInteraction::~AcsLibraryInteraction() throw() { +} + + +//------------------------------------------------------------------------------ +// requestResponsesUntilFinal +//------------------------------------------------------------------------------ +void cta::acs::AcsLibraryInteraction::requestResponsesUntilFinal( + const SEQ_NO requestSeqNumber, + ALIGNED_BYTES (&buf)[MAX_MESSAGE_SIZE / sizeof(ALIGNED_BYTES)], + const int queryInterval, const int timeout) const + { + ACS_RESPONSE_TYPE responseType = RT_NONE; + int elapsedTime = 0; + do { + const int remainingTime = timeout - elapsedTime; + const int responseTimeout = remainingTime > queryInterval ? + queryInterval : remainingTime; + + const time_t startTime = time(NULL); + responseType = requestResponse(responseTimeout, requestSeqNumber, buf); + elapsedTime += time(NULL) - startTime; + + if(RT_ACKNOWLEDGE == responseType) { + log::write(LOG_DEBUG,"Received RT_ACKNOWLEDGE"); + } + + if(elapsedTime >= timeout) { + cta::exception::RequestFailed ex; + ex.getMessage() << "Timed out after " << timeout << " seconds"; + throw ex; + } + } while(RT_FINAL != responseType); + + log::write(LOG_DEBUG,"Received RT_FINAL"); +} + +//------------------------------------------------------------------------------ +// requestResponse +//------------------------------------------------------------------------------ +ACS_RESPONSE_TYPE cta::acs::AcsLibraryInteraction::requestResponse( + const int timeout, const SEQ_NO requestSeqNumber, + ALIGNED_BYTES (&buf)[MAX_MESSAGE_SIZE / sizeof(ALIGNED_BYTES)]) const + { + SEQ_NO responseSeqNumber = 0; + REQ_ID reqId = (REQ_ID)0; + ACS_RESPONSE_TYPE responseType = RT_NONE; + + std::stringstream dbgMsg; + dbgMsg << "Calling Acs::response() for requestSeqNumber=" << requestSeqNumber; + log::write(LOG_DEBUG, dbgMsg.str()); + + const STATUS s = m_acs.response(timeout, responseSeqNumber, reqId, + responseType, buf); + + dbgMsg.str(""); + dbgMsg << "Acs::response() for requestSeqNumber=" << requestSeqNumber << + " returned responseSeqNumber=" << responseSeqNumber << " and status " << + acs_status(s); + log::write(LOG_DEBUG,dbgMsg.str()); + + switch(s) { + case STATUS_SUCCESS: + checkResponseSeqNumber(requestSeqNumber, responseSeqNumber); + return responseType; + case STATUS_PENDING: + return RT_NONE; + default: + cta::exception::RequestFailed ex; + ex.getMessage() << "Failed to request response: " << acs_status(s); + throw ex; + } +} + +//------------------------------------------------------------------------------ +// checkSeqNumber +//------------------------------------------------------------------------------ +void cta::acs::AcsLibraryInteraction::checkResponseSeqNumber( + const SEQ_NO requestSeqNumber, const SEQ_NO responseSeqNumber) const + { + if(requestSeqNumber != responseSeqNumber) { + cta::exception::Mismatch ex; + ex.getMessage() << ": Sequence number mismatch: requestSeqNumber=" + << requestSeqNumber << " responseSeqNumber=" << responseSeqNumber; + throw ex; + } +} + +//------------------------------------------------------------------------------ +// volumeStatusAsString +//------------------------------------------------------------------------------ +std::string cta::acs::AcsLibraryInteraction::volumeStatusAsString( + const QU_VOL_STATUS &s) const throw() { + + std::ostringstream os; + os << "vid=" << s.vol_id.external_label << " "; + os << "media_types.dat=" << (int)s.media_type << " "; + + switch(s.location_type) { + case LOCATION_CELL: { + os << "location=cell" << " "; + const CELLID &cellId = s.location.cell_id; + os << "acs=" << (int)cellId.panel_id.lsm_id.acs << " "; + os << "lsm=" << (int)cellId.panel_id.lsm_id.lsm << " "; + os << "panel=" << (int)cellId.panel_id.panel << " "; + os << "raw=" << (int)cellId.row << " "; + os << "column=" << (int)cellId.col << " "; + break; + } + case LOCATION_DRIVE: { + os << "location=drive" << " "; + const DRIVEID &driveId = s.location.drive_id; + os << "acs=" << (int)driveId.panel_id.lsm_id.acs << " "; + os << "lsm=" << (int)driveId.panel_id.lsm_id.lsm << " "; + os << "panel=" << (int)driveId.panel_id.panel << " "; + os << "column=" << (int)driveId.drive << " "; + break; + } + default: + os << "location=UNKNOWN" << " "; + break; + } + + os << "status=" << acs_status(s.status); + return os.str(); +} diff --git a/mediachanger/acs/AcsLibraryInteraction.hpp b/mediachanger/acs/AcsLibraryInteraction.hpp new file mode 100644 index 0000000000000000000000000000000000000000..363516364992a0657ca6d3c3a4540e27680a76a3 --- /dev/null +++ b/mediachanger/acs/AcsLibraryInteraction.hpp @@ -0,0 +1,117 @@ +/* + * 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/>. + */ + +#pragma once + +#include "common/exception/Mismatch.hpp" +#include "common/exception/RequestFailed.hpp" +#include "Acs.hpp" + +#include <string> + +extern "C" { +#include "acssys.h" +#include "acsapi.h" +} + +namespace cta { +namespace acs { + +/** + * Abstract class implementing common code and data structures for mount + * for read-only access, mount for read/write access and dismount requests + * that interact with ACS compatible tape libraries. + */ +class AcsLibraryInteraction { +public: + /** + * Constructor. + * + * @param acs Wrapper around the ACSLS C-API. + */ + AcsLibraryInteraction(Acs &acs) throw(); + + /** + * Pure-virtual destructor to guarantee this class is abstract. + */ + virtual ~AcsLibraryInteraction() throw() = 0; + +protected: + + /** + * Requests responses from ACSLS in a loop until the RT_FINAL response is + * received. + * + * @param requestSeqNumber The sequemce number that was sent in the initial + * request to the ACSLS. + * @param buf Output parameter. Message buffer into which the RT_FINAL + * response shall be written. + * @param queryInterval Time in seconds to wait between queries to ACS for + * responses. + * @param timeout The time in seconds to spend trying to get the RT_FINAL + * response. + */ + void requestResponsesUntilFinal(const SEQ_NO requestSeqNumber, + ALIGNED_BYTES (&buf)[MAX_MESSAGE_SIZE / sizeof(ALIGNED_BYTES)], + const int queryInterval, const int timeout) const + ; + + /** + * Sends a request for a response to the ACSLS. + * + * @param timeout The timeout. + * @param requestSeqNumber The sequemce number that was sent in the initial + * request to the ACSLS. + * @param buf Output parameter. The response message if there is one. + * @return The type of the response message if there is one or RT_NONE if + * there isn't one. + */ + ACS_RESPONSE_TYPE requestResponse(const int timeout, + const SEQ_NO requestSeqNumber, + ALIGNED_BYTES (&buf)[MAX_MESSAGE_SIZE / sizeof(ALIGNED_BYTES)]) const + ; + + /** + * Throws cta::exception::Mismatch if the specified request and + * response sequence-numbers do not match. + * + * @param requestSeqNumber Request sequence-number. + * @param responseSeqNumber Response sequence-number. + */ + void checkResponseSeqNumber(const SEQ_NO requestSeqNumber, + const SEQ_NO responseSeqNumber) const ; + + /** + * Converts the specified volume status to a human readable representation. + * + * @param s The volume status. + * @return The string presentation of the volume status. + */ + std::string volumeStatusAsString(const QU_VOL_STATUS &s) const throw(); + + /** + * Wrapper around the ACSLS C-API. + */ + Acs &m_acs; + +}; // class AcsLibraryInteraction + +} // namespace acs +} // namespace cta + + diff --git a/mediachanger/acs/AcsMountCmd.cpp b/mediachanger/acs/AcsMountCmd.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ebf2950c9e4a9ef292a294e8478d145d56d2203 --- /dev/null +++ b/mediachanger/acs/AcsMountCmd.cpp @@ -0,0 +1,133 @@ +/* + * 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 "AcsMountCmd.hpp" +#include "AcsMountCmdLine.hpp" + +#include <getopt.h> +#include <iostream> + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +cta::acs::AcsMountCmd::AcsMountCmd( + std::istream &inStream, std::ostream &outStream, std::ostream &errStream, + Acs &acs) throw(): + AcsCmd(inStream, outStream, errStream, acs) { +} + +//------------------------------------------------------------------------------ +// destructor +//------------------------------------------------------------------------------ +cta::acs::AcsMountCmd::~AcsMountCmd() throw() { + // Do nothing +} + +//------------------------------------------------------------------------------ +// exceptionThrowingMain +//------------------------------------------------------------------------------ +int cta::acs::AcsMountCmd::exceptionThrowingMain(const int argc, + char *const *const argv) { + try { + m_cmdLine = AcsMountCmdLine(argc, argv); + } catch(cta::exception::Exception ex) { + m_err << ex.getMessage().str() << std::endl; + m_err << std::endl; + m_err << m_cmdLine.getUsage() << std::endl; + return 1; + } + + // Display the usage message to standard out and exit with success if the + // user requested help + if(m_cmdLine.help) { + m_out << AcsMountCmdLine::getUsage(); + return 0; + } + + // Setup debug mode to be on or off depending on the command-line arguments + m_debugBuf.setDebug(m_cmdLine.debug); + + m_dbg << "query = " << m_cmdLine.queryInterval << std::endl; + m_dbg << "readonly = " << bool2Str(m_cmdLine.readOnly) << std::endl; + m_dbg << "timeout = " << m_cmdLine.timeout << std::endl; + m_dbg << "VID = " << m_cmdLine.volId.external_label << std::endl; + m_dbg << "DRIVE_SLOT = " << m_acs.driveId2Str(m_cmdLine.libraryDriveSlot) + << std::endl; + + syncMount(); + + return 0; +} + +//------------------------------------------------------------------------------ +// syncMount +//------------------------------------------------------------------------------ +void cta::acs::AcsMountCmd::syncMount() { + const SEQ_NO requestSeqNumber = 1; + ALIGNED_BYTES buf[MAX_MESSAGE_SIZE / sizeof(ALIGNED_BYTES)]; + + try { + sendMountRequest(requestSeqNumber); + requestResponsesUntilFinal(requestSeqNumber, buf, m_cmdLine.queryInterval, + m_cmdLine.timeout); + processMountResponse(buf); + } catch(cta::exception::Exception &ex) { + cta::exception::MountFailed mf; + mf.getMessage() << "Failed to mount volume " << + m_cmdLine.volId.external_label << ": " << ex.getMessage().str(); + throw mf; + } +} + +//------------------------------------------------------------------------------ +// sendMountRequest +//------------------------------------------------------------------------------ +void cta::acs::AcsMountCmd::sendMountRequest(const SEQ_NO seqNumber) { + const LOCKID lockId = 0; // No lock + const BOOLEAN bypass = FALSE; + + m_dbg << "Calling Acs::mount()" << std::endl; + const STATUS s = m_acs.mount(seqNumber, lockId, m_cmdLine.volId, + m_cmdLine.libraryDriveSlot, m_cmdLine.readOnly, bypass); + m_dbg << "Acs::mount() returned " << acs_status(s) << std::endl; + + if(STATUS_SUCCESS != s) { + cta::exception::MountFailed ex; + ex.getMessage() << "Failed to send request to mount volume " << + m_cmdLine.volId.external_label << " into drive " << + m_acs.driveId2Str(m_cmdLine.libraryDriveSlot) << ": readOnly=" << + (m_cmdLine.readOnly ? "TRUE" : "FALSE") << ": " << acs_status(s); + throw ex; + } +} + +//------------------------------------------------------------------------------ +// processMountResponse +//------------------------------------------------------------------------------ +void cta::acs::AcsMountCmd::processMountResponse( + ALIGNED_BYTES (&buf)[MAX_MESSAGE_SIZE / sizeof(ALIGNED_BYTES)]) + { + const ACS_MOUNT_RESPONSE *const msg = (ACS_MOUNT_RESPONSE *)buf; + + if(STATUS_SUCCESS != msg->mount_status) { + cta::exception::MountFailed ex; + ex.getMessage() << "Status of mount response is not success: " << + acs_status(msg->mount_status); + throw ex; + } +} diff --git a/mediachanger/acs/AcsMountCmd.hpp b/mediachanger/acs/AcsMountCmd.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9aa38dec4d68bbab9f32b9a85892ec250c33a06e --- /dev/null +++ b/mediachanger/acs/AcsMountCmd.hpp @@ -0,0 +1,103 @@ +/* + * 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/>. + */ + +#pragma once + +#include "AcsCmd.hpp" +#include "AcsMountCmdLine.hpp" +#include "common/exception/InvalidArgument.hpp" +#include "common/exception/MissingOperand.hpp" +#include "common/exception/MountFailed.hpp" + +#include <stdint.h> + +namespace cta { +namespace acs { + +/** + * The class implementing the mount command. + */ +class AcsMountCmd: public AcsCmd { +public: + + /** + * Constructor. + * + * @param inStream Standard input stream. + * @param outStream Standard output stream. + * @param errStream Standard error stream. + * @param acs Wrapper around the ACSLS C-API. + */ + AcsMountCmd(std::istream &inStream, std::ostream &outStream, + std::ostream &errStream, Acs &acs) throw(); + + /** + * Destructor. + */ + virtual ~AcsMountCmd() throw(); + + /** + * The entry function of the command. + * + * @param argc The number of command-line arguments. + * @param argv The command-line arguments. + * @return The exit value of the program. + */ + int exceptionThrowingMain(const int argc, char *const *const argv); + +protected: + + /** + * Mounts the tape with the specified VID into the drive with the specified + * drive ID. + * + * This method does not return until the mount has either suceeded, failed or + * the specified timeout has been reached. + */ + void syncMount(); + + /** + * Sends the mount request to ACSLS. + * + * @param seqNumber The sequence number to be used in the request. + */ + void sendMountRequest(const SEQ_NO seqNumber); + + /** + * Throws cta::exception::DismountFailed if the mount was not + * successful. + * + * @param buf The mount-response message. + */ + void processMountResponse( + ALIGNED_BYTES (&buf)[MAX_MESSAGE_SIZE / sizeof(ALIGNED_BYTES)]); + +private: + + /** + * The parsed command-line. + * + * The value of this member variable is set within the main() method of this + * class. + */ + AcsMountCmdLine m_cmdLine; + +}; // class AcsMountCmd + +} // namespace acs +} // namespace cta diff --git a/mediachanger/acs/AcsMountCmdLine.cpp b/mediachanger/acs/AcsMountCmdLine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c33decac3c1f763ed02491643798a191e4c0b293 --- /dev/null +++ b/mediachanger/acs/AcsMountCmdLine.cpp @@ -0,0 +1,177 @@ +/* + * 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 "Acs.hpp" +#include "AcsMountCmdLine.hpp" +#include "Constants.hpp" +#include "common/exception/InvalidArgument.hpp" +#include "common/exception/MissingOperand.hpp" + +#include <getopt.h> +#include <stdlib.h> +#include <string.h> + +//----------------------------------------------------------------------------- +// constructor +//----------------------------------------------------------------------------- +cta::acs::AcsMountCmdLine::AcsMountCmdLine() throw(): + debug(false), + help(false), + queryInterval(0), + readOnly(FALSE), + timeout(0) { + libraryDriveSlot.panel_id.lsm_id.acs = (ACS)0; + libraryDriveSlot.panel_id.lsm_id.lsm = (LSM)0; + libraryDriveSlot.panel_id.panel = (PANEL)0; + libraryDriveSlot.drive = (DRIVE)0; + memset(volId.external_label, '\0', sizeof(volId.external_label)); +} + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +cta::acs::AcsMountCmdLine::AcsMountCmdLine(const int argc, + char *const *const argv): + debug(false), + help(false), + queryInterval(ACS_QUERY_INTERVAL), + readOnly(FALSE), + timeout(ACS_CMD_TIMEOUT) { + libraryDriveSlot.panel_id.lsm_id.acs = (ACS)0; + libraryDriveSlot.panel_id.lsm_id.lsm = (LSM)0; + libraryDriveSlot.panel_id.panel = (PANEL)0; + libraryDriveSlot.drive = (DRIVE)0; + memset(volId.external_label, '\0', sizeof(volId.external_label)); + + static struct option longopts[] = { + {"debug", 0, NULL, 'd'}, + {"help" , 0, NULL, 'h'}, + {"query" , required_argument, NULL, 'q'}, + {"readonly" , 0, NULL, 'r'}, + {"timeout" , required_argument, NULL, 't'}, + {NULL, 0, NULL, 0} + }; + + // Prevent getopt() from printing an error message if it does not recognize + // an option character + opterr = 0; + + int opt = 0; + while((opt = getopt_long(argc, argv, ":dhq:rt:", longopts, NULL)) != -1) { + processOption(opt); + } + + // There is no need to continue parsing when the help option is set + if(help) { + return; + } + + // Calculate the number of non-option ARGV-elements + const int nbArgs = argc - optind; + + // Check that both VID and DRIVE_SLOT have been specified + if(nbArgs < 2) { + cta::exception::MissingOperand ex; + ex.getMessage() << "Both VID and DRIVE_SLOT must be specified"; + throw ex; + } + + // Parse VID + volId = Acs::str2Volid(argv[optind]); + + // Move on to the next command-line argument + optind++; + + // Parse DRIVE_SLOT + libraryDriveSlot = Acs::str2DriveId(argv[optind]); +} + +//------------------------------------------------------------------------------ +// processOption +//------------------------------------------------------------------------------ +void cta::acs::AcsMountCmdLine::processOption(const int opt) { + switch(opt) { + case 'd': + debug = true; + break; + case 'h': + help = true; + break; + case 'q': + queryInterval = parseQueryInterval(optarg); + break; + case 'r': + readOnly = TRUE; + break; + case 't': + timeout = parseTimeout(optarg); + break; + case ':': + return handleMissingParameter(optopt); + case '?': + return handleUnknownOption(optopt); + default: + { + cta::exception::Exception ex; + ex.getMessage() << + "getopt_long returned the following unknown value: 0x" << + std::hex << (int)opt; + throw ex; + } + } // switch(opt) +} + +//------------------------------------------------------------------------------ +// getUsage +//------------------------------------------------------------------------------ +std::string cta::acs::AcsMountCmdLine::getUsage() throw() { + std::ostringstream usage; + usage << + "Usage:\n" + "\n" + " cta-tape-acs-mount [options] VID DRIVE_SLOT\n" + "\n" + "Where:\n" + "\n" + " VID The VID of the volume to be mounted.\n" + " DRIVE_SLOT The slot in the tape library where the drive is located.\n" + " The format of DRIVE_SLOT is as follows:\n" + "\n" + " ACS:LSM:panel:transport\n" + "\n" + "Options:\n" + "\n" + " -d|--debug Turn on the printing of debug information.\n" + "\n" + " -h|--help Print this help message and exit.\n" + "\n" + " -q|--query SECONDS Time to wait between queries to ACS for responses.\n" + " SECONDS must be an integer value greater than 0.\n" + " The default value of SECONDS is " + << ACS_QUERY_INTERVAL << ".\n" + "\n" + " -r|--readOnly Request the volume is mounted for read-only access\n" + "\n" + " -t|--timeout SECONDS Time to wait for the mount to conclude. SECONDS\n" + " must be an integer value greater than 0. The\n" + " default value of SECONDS is " + << ACS_CMD_TIMEOUT << ".\n" + "\n" + "Comments to: CTA team\n"; + return usage.str(); +} diff --git a/mediachanger/acs/AcsMountCmdLine.hpp b/mediachanger/acs/AcsMountCmdLine.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e9abd303577b937f238d4d9cdab75622fa988ad5 --- /dev/null +++ b/mediachanger/acs/AcsMountCmdLine.hpp @@ -0,0 +1,109 @@ +/* + * 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/>. + */ + +#pragma once + +#include "AcsCmdLine.hpp" + +extern "C" { +#include "acssys.h" +#include "acsapi.h" +} + +#include <string> + +namespace cta { +namespace acs { + +/** + * Data type used to store the results of parsing the command-line. + */ +struct AcsMountCmdLine: public AcsCmdLine { + /** + * True if the debug option has been set. + */ + bool debug; + + /** + * True if the help option has been set. + */ + bool help; + + /** + * Time in seconds to wait between queries to ACS for responses. + */ + int queryInterval; + + /** + * True if the tape is to be mount for read-only access. + */ + BOOLEAN readOnly; + + /** + * Time in seconds to wait for the mount to conclude. + */ + int timeout; + + /** + * The volume identifier of the tape to be mounted. + */ + VOLID volId; + + /** + * The slot in the tape library where the drive is located. + */ + DRIVEID libraryDriveSlot; + + /** + * Constructor. + * + * Initialises all BOOLEAN member-variables to FALSE, all integer + * member-variables to 0 and the volume identifier to an empty string. + */ + AcsMountCmdLine() throw(); + + /** + * Constructor. + * + * Parses the specified command-line arguments. + * + * @param argc Argument count from the executable's entry function: main(). + * @param argv Argument vector from the executable's entry function: main(). + */ + AcsMountCmdLine(const int argc, char *const *const argv); + + /** + * Gets the usage message that describes the comamnd line. + * + * @return The usage message. + */ + static std::string getUsage() throw(); + +private: + + /** + * Processes the specified option that was returned by getopt_long(). + * + * @param opt The option that was returned by getopt_long(). + */ + void processOption(const int opt); + +}; // class AcsMountCmdLine + +} // namespace acs +} // namespace cta diff --git a/mediachanger/acs/AcsMountCmdMain.cpp b/mediachanger/acs/AcsMountCmdMain.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c73a8e26903abc5df42c75b68f3760253cd456a --- /dev/null +++ b/mediachanger/acs/AcsMountCmdMain.cpp @@ -0,0 +1,69 @@ +/* + * 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 "AcsImpl.hpp" +#include "AcsMountCmd.hpp" +#include "AcsMountCmdLine.hpp" + +#include <iostream> + +/** + * An exception throwing version of main(). + * + * @param argc The number of command-line arguments including the program name. + * @param argv The command-line arguments. + * @return The exit value of the program. + */ +static int exceptionThrowingMain(const int argc, char *const *const argv); + +//------------------------------------------------------------------------------ +// main +//------------------------------------------------------------------------------ +int main(const int argc, char *const *const argv) { + using namespace cta; + + std::string errorMessage; + + try { + return exceptionThrowingMain(argc, argv); + } catch(cta::exception::Exception &ex) { + errorMessage = ex.getMessage().str(); + } catch(std::exception &se) { + errorMessage = se.what(); + } catch(...) { + errorMessage = "An unknown exception was thrown"; + } + + // Reaching this point means the command has failed, ane exception was throw + // and errorMessage has been set accordingly + + std::cerr << "Aborting: " << errorMessage << std::endl; + return 1; +} + +//------------------------------------------------------------------------------ +// exceptionThrowingMain +//------------------------------------------------------------------------------ +static int exceptionThrowingMain(const int argc, char *const *const argv) { + using namespace cta; + + acs::AcsImpl acs; + acs::AcsMountCmd cmd(std::cin, std::cout, std::cerr, acs); + + return cmd.exceptionThrowingMain(argc, argv); +} diff --git a/mediachanger/acs/AcsQueryVolumeCmd.cpp b/mediachanger/acs/AcsQueryVolumeCmd.cpp new file mode 100644 index 0000000000000000000000000000000000000000..028a78a3384fc1a44c5f3e220f5f91b983f8b88d --- /dev/null +++ b/mediachanger/acs/AcsQueryVolumeCmd.cpp @@ -0,0 +1,191 @@ +/* + * 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 "AcsQueryVolumeCmd.hpp" +#include "AcsQueryVolumeCmdLine.hpp" +#include "common/exception/QueryVolumeFailed.hpp" +#include <getopt.h> +#include <iostream> +#include <string.h> + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +cta::acs::AcsQueryVolumeCmd::AcsQueryVolumeCmd( + std::istream &inStream, std::ostream &outStream, std::ostream &errStream, + Acs &acs) throw(): + AcsCmd(inStream, outStream, errStream, acs) { +} + +//------------------------------------------------------------------------------ +// destructor +//------------------------------------------------------------------------------ +cta::acs::AcsQueryVolumeCmd::~AcsQueryVolumeCmd() throw() { + // Do nothing +} + +//------------------------------------------------------------------------------ +// exceptionThrowingMain +//------------------------------------------------------------------------------ +int cta::acs::AcsQueryVolumeCmd::exceptionThrowingMain(const int argc, + char *const *const argv) { + try { + m_cmdLine = AcsQueryVolumeCmdLine(argc, argv); + } catch(cta::exception::Exception &ex) { + m_err << ex.getMessage().str() << std::endl; + m_err << std::endl; + m_err << m_cmdLine.getUsage() << std::endl; + return 1; + } + + // Display the usage message to standard out and exit with success if the + // user requested help + if(m_cmdLine.help) { + m_out << AcsQueryVolumeCmdLine::getUsage(); + return 0; + } + + // Setup debug mode to be on or off depending on the command-line arguments + m_debugBuf.setDebug(m_cmdLine.debug); + + m_dbg << "query = " << m_cmdLine.queryInterval << std::endl; + m_dbg << "timeout = " << m_cmdLine.timeout << std::endl; + m_dbg << "VID = " << m_cmdLine.volId.external_label << std::endl; + + syncQueryVolume(); + return 0; +} + +//------------------------------------------------------------------------------ +// syncQueryVolume +//------------------------------------------------------------------------------ +void cta::acs::AcsQueryVolumeCmd::syncQueryVolume() { + const SEQ_NO requestSeqNumber = 1; + ALIGNED_BYTES buf[MAX_MESSAGE_SIZE / sizeof(ALIGNED_BYTES)]; + + try { + sendQueryVolumeRequest(requestSeqNumber); + requestResponsesUntilFinal(requestSeqNumber, buf, m_cmdLine.queryInterval, + m_cmdLine.timeout); + processQueryResponse(m_out, buf); + } catch(cta::exception::Exception &ex) { + cta::exception::QueryVolumeFailed qf; + qf.getMessage() << "Failed to query volume " << + m_cmdLine.volId.external_label << ": " << ex.getMessage().str(); + throw qf; + } +} + +//------------------------------------------------------------------------------ +// sendQueryVolumeRequest +//------------------------------------------------------------------------------ +void cta::acs::AcsQueryVolumeCmd::sendQueryVolumeRequest( + const SEQ_NO seqNumber) { + VOLID volIds[MAX_ID]; + + memset(volIds, '\0', sizeof(volIds)); + strncpy(volIds[0].external_label, m_cmdLine.volId.external_label, + sizeof(volIds[0].external_label)); + volIds[0].external_label[sizeof(volIds[0].external_label) - 1] = '\0'; + + m_dbg << "Calling Acs::queryVolume()" << std::endl; + const STATUS s = m_acs.queryVolume(seqNumber, volIds, 1); + m_dbg << "Acs::queryVolume() returned " << acs_status(s) << std::endl; + + if(STATUS_SUCCESS != s) { + cta::exception::QueryVolumeFailed ex; + ex.getMessage() << "Failed to send query request for volume " << + m_cmdLine.volId.external_label << ": " << acs_status(s); + throw ex; + } +} + +//------------------------------------------------------------------------------ +// processQueryResponse +//------------------------------------------------------------------------------ +void cta::acs::AcsQueryVolumeCmd::processQueryResponse( + std::ostream &os, + ALIGNED_BYTES (&buf)[MAX_MESSAGE_SIZE / sizeof(ALIGNED_BYTES)]) { + + const ACS_QUERY_VOL_RESPONSE *const msg = (ACS_QUERY_VOL_RESPONSE *)buf; + + if(STATUS_SUCCESS != msg->query_vol_status) { + cta::exception::QueryVolumeFailed ex; + ex.getMessage() << "Status of query response is not success: " << + acs_status(msg->query_vol_status); + throw ex; + } + + if((unsigned short)1 != msg->count) { + cta::exception::QueryVolumeFailed ex; + ex.getMessage() << "Query response does not contain a single volume: count=" + << msg->count; + throw ex; + } + + // count is 1 so it is safe to make a reference to the single volume status + const QU_VOL_STATUS &volStatus = msg->vol_status[0]; + + if(strcmp(m_cmdLine.volId.external_label, volStatus.vol_id.external_label)) { + cta::exception::QueryVolumeFailed ex; + ex.getMessage() << + "Volume identifier of query response does not match that of request" + ": requestVID=" << m_cmdLine.volId.external_label << + " responseVID=" << volStatus.vol_id.external_label; + throw ex; + } + + writeVolumeStatus(os, volStatus); +} + +//------------------------------------------------------------------------------ +// writeVolumeStatus +//------------------------------------------------------------------------------ +void cta::acs::AcsQueryVolumeCmd::writeVolumeStatus( + std::ostream &os, const QU_VOL_STATUS &s) throw() { + os << "Volume identifier: " << s.vol_id.external_label << std::endl; + os << "Media type (media_types.dat): " << (int)s.media_type << std::endl; + + switch(s.location_type) { + case LOCATION_CELL: { + os << "Location type: cell" << std::endl; + const CELLID &cellId = s.location.cell_id; + os << "ACS: " << (int)cellId.panel_id.lsm_id.acs << std::endl; + os << "LSM: " << (int)cellId.panel_id.lsm_id.lsm << std::endl; + os << "Panel: " << (int)cellId.panel_id.panel << std::endl; + os << "Row: " << (int)cellId.row << std::endl; + os << "Column: " << (int)cellId.col << std::endl; + break; + } + case LOCATION_DRIVE: { + os << "Location type: drive" << std::endl; + const DRIVEID &driveId = s.location.drive_id; + os << "ACS: " << (int)driveId.panel_id.lsm_id.acs << std::endl; + os << "LSM: " << (int)driveId.panel_id.lsm_id.lsm << std::endl; + os << "Panel: " << (int)driveId.panel_id.panel << std::endl; + os << "Drive: " << (int)driveId.drive << std::endl; + break; + } + default: + os << "Location type: UNKNOWN" << std::endl; + break; + } + + os << "Status: " << acs_status(s.status) << std::endl; +} diff --git a/mediachanger/acs/AcsQueryVolumeCmd.hpp b/mediachanger/acs/AcsQueryVolumeCmd.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b5078f882bf60ec9084d8c0f093bd74011a444e9 --- /dev/null +++ b/mediachanger/acs/AcsQueryVolumeCmd.hpp @@ -0,0 +1,118 @@ +/* + * 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/>. + */ + +#pragma once + +#include "AcsCmd.hpp" +#include "AcsQueryVolumeCmdLine.hpp" +#include "common/exception/InvalidArgument.hpp" +#include "common/exception/MissingOperand.hpp" +#include "common/exception/QueryVolumeFailed.hpp" + + +#include <stdint.h> + +namespace cta { +namespace acs { + +/** + * The class implementing the mount command. + */ +class AcsQueryVolumeCmd: public AcsCmd { +public: + + /** + * Constructor. + * + * @param inStream Standard input stream. + * @param outStream Standard output stream. + * @param errStream Standard error stream. + * @param acs Wrapper around the ACSLS C-API. + */ + AcsQueryVolumeCmd(std::istream &inStream, std::ostream &outStream, + std::ostream &errStream, Acs &acs) throw(); + + /** + * Destructor. + */ + virtual ~AcsQueryVolumeCmd() throw(); + + /** + * The entry function of the command. + * + * @param argc The number of command-line arguments. + * @param argv The command-line arguments. + * @return The exit value of the program. + */ + int exceptionThrowingMain(const int argc, char *const *const argv); + +protected: + + /** + * Queries ACS for information about the volume identifier specified on the + * command-line. + * + * This method does not return until the information has been successfully + * retrieved, an error has occurred or the specified timeout has been + * reached. + * + * @return The volume status of the volume identifier specified on the + * command-line. + */ + void syncQueryVolume(); + + /** + * Sends the query volume request to ACSLS. + * + * @param seqNumber The sequence number to be used in the request. + */ + void sendQueryVolumeRequest(const SEQ_NO seqNumber); + + /** + * Extracts the volume status from the specified query-response message and + * writes it in human-readable form to the specified output stream. + * + * @param os The output stream. + * @param buf The query-response message. + */ + void processQueryResponse(std::ostream &os, + ALIGNED_BYTES (&buf)[MAX_MESSAGE_SIZE / sizeof(ALIGNED_BYTES)]); + + /** + * Writes a human readable representation of the specified volume status to + * the specified output stream. + * + * @param os The output stream. + * @param s The volume status. + */ + void writeVolumeStatus(std::ostream &os, const QU_VOL_STATUS &s) throw(); + +private: + + /** + * The parsed command-line. + * + * The value of this member variable is set within the main() method of this + * class. + */ + AcsQueryVolumeCmdLine m_cmdLine; + +}; // class AcsQueryVolumeCmd + +} // namespace acs +} // namespace cta diff --git a/mediachanger/acs/AcsQueryVolumeCmdLine.cpp b/mediachanger/acs/AcsQueryVolumeCmdLine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..351f5d22fe8c3b51bc70454bb24ba1d9b5e2cd2d --- /dev/null +++ b/mediachanger/acs/AcsQueryVolumeCmdLine.cpp @@ -0,0 +1,149 @@ + +/* + * 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 "Acs.hpp" +#include "AcsQueryVolumeCmdLine.hpp" +#include "Constants.hpp" +#include "common/exception/InvalidArgument.hpp" +#include "common/exception/MissingOperand.hpp" + +#include <getopt.h> +#include <stdlib.h> +#include <string.h> + +//----------------------------------------------------------------------------- +// constructor +//----------------------------------------------------------------------------- +cta::acs::AcsQueryVolumeCmdLine::AcsQueryVolumeCmdLine() + throw(): + debug(FALSE), + help(FALSE), + queryInterval(0), + timeout(0) { + memset(volId.external_label, '\0', sizeof(volId.external_label)); +} + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +cta::acs::AcsQueryVolumeCmdLine::AcsQueryVolumeCmdLine(const int argc, + char *const *const argv): + debug(FALSE), + help(FALSE), + queryInterval(ACS_QUERY_INTERVAL), + timeout(ACS_CMD_TIMEOUT) { + memset(volId.external_label, '\0', sizeof(volId.external_label)); + + static struct option longopts[] = { + {"debug", 0, NULL, 'd'}, + {"help" , 0, NULL, 'h'}, + {"query" , required_argument, NULL, 'q'}, + {"timeout" , required_argument, NULL, 't'}, + {NULL, 0, NULL, 0} + }; + + // Prevent getopt() from printing an error message if it does not recognize + // an option character + opterr = 0; + + int opt = 0; + while((opt = getopt_long(argc, argv, ":dhq:t:", longopts, NULL)) != -1) { + processOption(opt); + } + + // There is no need to continue parsing when the help option is set + if(help) { + return; + } + + // Calculate the number of non-option ARGV-elements + const int nbArgs = argc - optind; + + // Check that VID has been specified + if(nbArgs < 1) { + cta::exception::MissingOperand ex; + ex.getMessage() << "VID must be specified"; + throw ex; + } + + // Parse the VID command-line argument + volId = Acs::str2Volid(argv[optind]); +} + +//------------------------------------------------------------------------------ +// processOption +//------------------------------------------------------------------------------ +void cta::acs::AcsQueryVolumeCmdLine::processOption(const int opt) { + switch(opt) { + case 'd': + debug = true; + break; + case 'h': + help = true; + break; + case 'q': + queryInterval = parseQueryInterval(optarg); + break; + case 't': + timeout = parseTimeout(optarg); + break; + case ':': + return handleMissingParameter(optopt); + case '?': + return handleUnknownOption(optopt); + default: + { + cta::exception::Exception ex; + ex.getMessage() << + "getopt_long returned the following unknown value: 0x" << + std::hex << (int)opt; + throw ex; + } + } // switch(opt) +} + +//------------------------------------------------------------------------------ +// getUsage +//------------------------------------------------------------------------------ +std::string cta::acs::AcsQueryVolumeCmdLine::getUsage() throw() { + std::ostringstream usage; + usage << + "Usage:\n" + " cta-tape-acs-queryvolume [options] VID\n" + "\n" + "Where:\n" + "\n" + " VID The VID of the volume to be queried.\n" + "\n" + "Options:\n" + "\n" + " -d|--debug Turn on the printing of debug information.\n" + " -h|--help Print this help message and exit.\n" + " -q|--query SECONDS Time to wait between queries to ACS for responses.\n" + " SECONDS must be an integer value greater than 0.\n" + " The default value of SECONDS is " + << ACS_QUERY_INTERVAL << ".\n" + " -t|--timeout SECONDS Time to wait for the query to conclude. SECONDS\n" + " must be an integer value greater than 0. The\n" + " default value of SECONDS in " + << ACS_CMD_TIMEOUT << ".\n" + "\n" + "Comments to: CTA team\n"; + return usage.str(); +} diff --git a/mediachanger/acs/AcsQueryVolumeCmdLine.hpp b/mediachanger/acs/AcsQueryVolumeCmdLine.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d327e760399515be826661069184bb9c5aefb8ad --- /dev/null +++ b/mediachanger/acs/AcsQueryVolumeCmdLine.hpp @@ -0,0 +1,99 @@ +/* + * 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/>. + */ + +#pragma once + +#include "AcsCmdLine.hpp" + +extern "C" { +#include "acssys.h" +#include "acsapi.h" +} + +#include <string> + +namespace cta { +namespace acs { + +/** + * Data type used to store the results of parsing the command-line. + */ +struct AcsQueryVolumeCmdLine: public AcsCmdLine { + /** + * True if the debug option has been set. + */ + BOOLEAN debug; + + /** + * True if the help option has been set. + */ + BOOLEAN help; + + /** + * Time in seconds to wait between queries to ACS for responses. + */ + int queryInterval; + + /** + * Time in seconds to wait for the dismount to conclude. + */ + int timeout; + + /** + * The volume identifier of the tape to be mounted. + */ + VOLID volId; + + /** + * Constructor. + * + * Initialises all BOOLEAN member-variables to FALSE, all integer + * member-variables to 0 and the volume identifier to an empty string. + */ + AcsQueryVolumeCmdLine() throw(); + + /** + * Constructor. + * + * Parses the specified command-line arguments. + * + * @param argc Argument count from the executable's entry function: main(). + * @param argv Argument vector from the executable's entry function: main(). + */ + AcsQueryVolumeCmdLine(const int argc, char *const *const argv); + + /** + * Gets the usage message that describes the comamnd line. + * + * @return The usage message. + */ + static std::string getUsage() throw(); + +private: + + /** + * Processes the specified option that was returned by getopt_long(). + * + * @param opt The option that was returned by getopt_long(). + */ + void processOption(const int opt); + +}; // class AcsQueryVolumeCmdLine + +} // namespace acs +} // namespace cta diff --git a/mediachanger/acs/AcsQueryVolumeCmdMain.cpp b/mediachanger/acs/AcsQueryVolumeCmdMain.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ca65595934b013109838ae23910f325cd5176dc7 --- /dev/null +++ b/mediachanger/acs/AcsQueryVolumeCmdMain.cpp @@ -0,0 +1,68 @@ +/* + * 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 "AcsImpl.hpp" +#include "AcsQueryVolumeCmd.hpp" +#include "AcsQueryVolumeCmdLine.hpp" + +#include <iostream> + +/** + * An exception throwing version of main(). + * + * @param argc The number of command-line arguments including the program name. + * @param argv The command-line arguments. + * @param The exit value of the program. + */ +static int exceptionThrowingMain(const int argc, char *const *const argv); + +//------------------------------------------------------------------------------ +// main +//------------------------------------------------------------------------------ +int main(const int argc, char *const *const argv) { + using namespace cta; + std::string errorMessage; + + try { + return exceptionThrowingMain(argc, argv); + } catch(cta::exception::Exception &ex) { + errorMessage = ex.getMessage().str(); + } catch(std::exception &se) { + errorMessage = se.what(); + } catch(...) { + errorMessage = "An unknown exception was thrown"; + } + + // Reaching this point means the command has failed, ane exception was throw + // and errorMessage has been set accordingly + + std::cerr << "Aborting: " << errorMessage << std::endl; + return 1; +} + +//------------------------------------------------------------------------------ +// exceptionThrowingMain +//------------------------------------------------------------------------------ +static int exceptionThrowingMain(const int argc, char *const *const argv) { + using namespace cta; + + acs::AcsImpl acs; + acs::AcsQueryVolumeCmd cmd(std::cin, std::cout, std::cerr, acs); + + return cmd.exceptionThrowingMain(argc, argv); +} diff --git a/mediachanger/acs/CMakeLists.txt b/mediachanger/acs/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..42406cf47b53c4d52cd2859b9e18c813d04740b1 --- /dev/null +++ b/mediachanger/acs/CMakeLists.txt @@ -0,0 +1,146 @@ +# This file is part of the Castor project. +# See http://castor.web.cern.ch/castor +# +# Copyright (C) 2003 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# +# @author Castor Dev team, castor-dev@cern.ch +# + +################################################################################ +# Rules to build and install acsd +################################################################################ + +##add_library( + #castorAcsDaemon + ## Acs.cpp + #AcsDaemon.cpp + #AcsDaemonConfig.cpp + #AcsDaemonMain.cpp + #AcsDismountTape.cpp + #AcsForceDismountTape.cpp + ## AcsImpl.cpp + #AcsLibraryInteraction.cpp + #AcsMessageHandler.cpp + #AcsMountTapeReadOnly.cpp + #AcsMountTapeReadWrite.cpp + #AcsPendingRequests.cpp + #AcsRequest.cpp + #AcsRequestDismountTape.cpp +##) +#add_dependencies(castorAcsDaemon castormessagesprotobuf) + +#target_link_libraries(castorAcsDaemon castortapereactor) +#set_target_properties (castorAcsDaemon PROPERTIES +# COMPILE_FLAGS -I/usr/include/CDK +# COMPILE_DEFINITIONS LINUX) + + +#add_executable(acsd AcsDaemon.cpp) +#set_target_properties (acsd PROPERTIES +# COMPILE_FLAGS -I/usr/include/CDK +# COMPILE_DEFINITIONS LINUX) + +#target_link_libraries( + #acsd + #castorAcsDaemon + #castortapereactor + #castorcommon + #castorserver + # castormessages + #zmq + #${STK_LIBRARIES}) + +#install (TARGETS acsd DESTINATION /usr/bin}) +#CastorInstallAdmManPage (acsd) +#CastorInstallLogrotate (castor-acs-server) +#CastorInstallSysconfigExample (acsd) +#CastorInstallInitScript (acsd) + +################################################################################ +# Rules to build and install castor-tape-acs-dismount +################################################################################ +message(STATUS "Adding cta-tape-acs-dismount target") +set (ACS_DISMOUNT_SRC_FILES + Acs.cpp + AcsCmd.cpp + AcsCmdLine.cpp + AcsImpl.cpp + AcsDismountCmd.cpp + AcsDismountCmdLine.cpp + AcsDismountCmdMain.cpp + CmdLineTool.cpp) +add_executable (cta-tape-acs-dismount ${ACS_DISMOUNT_SRC_FILES}) +set_target_properties (cta-tape-acs-dismount PROPERTIES + COMPILE_FLAGS -I/usr/include/CDK + COMPILE_DEFINITIONS LINUX) +target_link_libraries (cta-tape-acs-dismount + ctamediachanger + ctacommon + ${STK_LIBRARIES}) +install (TARGETS cta-tape-acs-dismount DESTINATION /usr/bin) +install (FILES cta-tape-acs-dismount.1cta DESTINATION /usr/share/man/man1) +#CastorInstallExeManPage(cta-tape-acs-dismount) + +################################################################################ +# Rules to build and install cta-tape-acs-mount +################################################################################ +set (ACS_MOUNT_SRC_FILES + Acs.cpp + AcsCmd.cpp + AcsCmdLine.cpp + AcsImpl.cpp + AcsMountCmd.cpp + AcsMountCmdLine.cpp + AcsMountCmdMain.cpp + CmdLineTool.cpp) +add_executable (cta-tape-acs-mount ${ACS_MOUNT_SRC_FILES}) +set_target_properties (cta-tape-acs-mount PROPERTIES + COMPILE_FLAGS -I/usr/include/CDK + COMPILE_DEFINITIONS LINUX) +target_link_libraries (cta-tape-acs-mount +ctamediachanger +ctacommon +${STK_LIBRARIES}) +install (TARGETS cta-tape-acs-mount DESTINATION /usr/bin) +install (FILES cta-tape-acs-mount.1cta DESTINATION /usr/share/man/man1) +#CastorInstallExeManPage(cta-tape-acs-mount) + +################################################################################ +# Rules to build and install cta-tape-acs-queryvolume +################################################################################ +message(STATUS "Adding cta-tape-acs-queryvolume target") +set (ACS_QUERYVOLUME_SRC_FILES + Acs.cpp + AcsCmd.cpp + AcsCmdLine.cpp + AcsImpl.cpp + AcsQueryVolumeCmd.cpp + AcsQueryVolumeCmdLine.cpp + AcsQueryVolumeCmdMain.cpp + CmdLineTool.cpp) + +add_executable (cta-tape-acs-queryvolume ${ACS_QUERYVOLUME_SRC_FILES}) +target_link_libraries (cta-tape-acs-queryvolume +ctamediachanger +ctacommon +${STK_LIBRARIES}) +set_target_properties (cta-tape-acs-queryvolume PROPERTIES + COMPILE_FLAGS -I/usr/include/CDK + #COMPILE_FLAGS -I/usr/include/STK_INCLUDE_DIR + COMPILE_DEFINITIONS LINUX) +install (TARGETS cta-tape-acs-queryvolume + DESTINATION /usr/bin) +install (FILES cta-tape-acs-queryvolume.1cta DESTINATION /usr/share/man/man1) +#CastorInstallExeManPage(cta-tape-acs-queryvolume) diff --git a/mediachanger/acs/CmdLineTool.cpp b/mediachanger/acs/CmdLineTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..71ccd623f441e9180cae78eb44fbdc8b9e9ad363 --- /dev/null +++ b/mediachanger/acs/CmdLineTool.cpp @@ -0,0 +1,41 @@ +/* + * 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 "CmdLineTool.hpp" + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +cta::acs::CmdLineTool::CmdLineTool(std::istream &inStream, + std::ostream &outStream, std::ostream &errStream) throw(): + m_in(inStream), m_out(outStream), m_err(errStream), m_debugBuf(outStream), + m_dbg(&m_debugBuf) { +} + +//------------------------------------------------------------------------------ +// destructor +//------------------------------------------------------------------------------ +cta::acs::CmdLineTool::~CmdLineTool() throw() { +} + +//------------------------------------------------------------------------------ +// bool2Str +//------------------------------------------------------------------------------ +std::string cta::acs::CmdLineTool::bool2Str(const bool value) const throw() { + return value ? "TRUE" : "FALSE"; +} diff --git a/mediachanger/acs/CmdLineTool.hpp b/mediachanger/acs/CmdLineTool.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2137e16a7e4944f7ee02cf776980fac5bbd1f7d1 --- /dev/null +++ b/mediachanger/acs/CmdLineTool.hpp @@ -0,0 +1,92 @@ +/* + * 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/>. + */ + +#pragma once + +#include "mediachanger/DebugBuf.hpp" + +#include <istream> +#include <ostream> +#include <string> + +namespace cta { +namespace acs { + +/** + * Abstract class implementing common code and data structures for a + * command-line tool. + */ +class CmdLineTool { +public: + /** + * Constructor. + * + * @param inStream Standard input stream. + * @param outStream Standard output stream. + * @param errStream Standard error stream. + */ + CmdLineTool(std::istream &inStream, std::ostream &outStream, std::ostream &errStream) + throw(); + + /** + * Pure-virtual destructor to guarantee this class is abstract. + */ + virtual ~CmdLineTool() throw() = 0; + +protected: + + /** + * Standard input stream. + */ + std::istream &m_in; + + /** + * Standard output stream. + */ + std::ostream &m_out; + + /** + * Standard error stream. + */ + std::ostream &m_err; + + /** + * Debug stream buffer that inserts a standard debug preamble before each + * message-line written to it. + */ + cta::mediachanger::DebugBuf m_debugBuf; + + /** + * Stream used to write debug messages. + * + * This stream will insert a standard debug preamble before each message-line + * written to it. + */ + std::ostream m_dbg; + + /** + * Returns the string representation of the specfied boolean value. + * + * @param value The boolean value. + */ + std::string bool2Str(const bool value) const throw(); + +}; // class CmdLineTool + +} // namespace acs +} // namespace cta diff --git a/mediachanger/acs/Constants.hpp b/mediachanger/acs/Constants.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f6c8056962420efe6502a9a23eab426b6fb0ca4e --- /dev/null +++ b/mediachanger/acs/Constants.hpp @@ -0,0 +1,62 @@ +/* + * 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/>. + */ + +#pragma once + +namespace cta { +namespace acs { + +/** + * The default TCP/IP port on which the CASTOR ACS daemon listens for incoming Zmq + * connections from the tape server. + */ +const unsigned short ACS_PORT = 54521; + +/** + * Default time to wait in seconds between queries to ACS Library for responses. + */ +const int ACS_QUERY_INTERVAL = 10; + +/** + * Default time to wait in seconds for the tape-library command to conclude. + */ +const int ACS_CMD_TIMEOUT = 610; + +/** + * The maximum ACS sequence number value to be used. + */ +const unsigned short ACS_MAX_SEQ = 65535; + +/** + * Default timeout for the response command to the ACS library. + */ +const int ACS_RESPONSE_TIMEOUT = 5; + +/** + * Enumeration of the states of an ACS request. + */ +enum RequestState { + ACS_REQUEST_TO_EXECUTE, + ACS_REQUEST_IS_RUNNING, + ACS_REQUEST_COMPLETED, + ACS_REQUEST_FAILED, + ACS_REQUEST_TO_DELETE}; + +} // namespace acs +} // namespace cta + diff --git a/mediachanger/acs/acsd.init b/mediachanger/acs/acsd.init new file mode 100755 index 0000000000000000000000000000000000000000..c4f78f7857a35ccd47100c5efc345ceecc91ea91 --- /dev/null +++ b/mediachanger/acs/acsd.init @@ -0,0 +1,111 @@ +#! /bin/sh +# +#/****************************************************************************** +# acsd.init +# +# This file is part of the Castor project. +# See http://castor.web.cern.ch/castor +# +# Copyright (C) 2003 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# +# chkconfig: 345 74 31 +# description: Tape server daemon initialisation script +# +# @author castor dev team +#*****************************************************************************/ + +# Source function library. +. /etc/rc.d/init.d/functions + +# Variables +prog="acsd" +export DAEMON_COREFILE_LIMIT="unlimited" +RETVAL=0 + +# Source sysconfig files +if [ -f /etc/sysconfig/castor ]; then + . /etc/sysconfig/castor +fi +if [ -f /etc/sysconfig/$prog ]; then + . /etc/sysconfig/$prog +fi + +start() { + # Run daemon + echo -n $"Starting $prog: " + + cd /var/log/castor + daemon /usr/bin/$prog $ACSD_OPTIONS + + # Write the pid to a file. + RETVAL=$? + if [ $RETVAL -eq 0 ]; then + pid=`ps -eo pid,ppid,comm | egrep " 1 $prog\$" | awk '{print $1}'` + rm -f /var/run/$prog.pid + if [ -n "$pid" ]; then + echo $pid > /var/run/$prog.pid + RETVAL=0 + else + RETVAL=1 + fi + fi + + [ $RETVAL -eq 0 ] && success $"$base startup" || failure $"$base startup" + echo + [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog + return $RETVAL +} + +stop() { + echo -n $"Stopping $prog: " + killproc $prog + + RETVAL=$? + echo + [ -f /var/lock/subsys/$prog ] && rm -f /var/lock/subsys/$prog + return $RETVAL +} + + +restart() { + stop + start +} + +# See how we were called +case "$1" in + + start) + start + ;; + stop) + stop + ;; + status) + status $prog + RETVAL=$? + ;; + restart) + restart + ;; + condrestart) + [ -f /var/lock/subsys/$prog ] && restart || : + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|condrestart}" + exit 1 +esac + +exit $RETVAL diff --git a/mediachanger/acs/acsd.man b/mediachanger/acs/acsd.man new file mode 100644 index 0000000000000000000000000000000000000000..675fa7e74653ebabb594a70a2ea81f26bd5ebba8 --- /dev/null +++ b/mediachanger/acs/acsd.man @@ -0,0 +1,66 @@ +.\" Copyright (C) 2003 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 2 +.\" 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, write to the Free Software +.\" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +.TH ACSD "8castor" "$Date: 2014/03/24 14:44:00 $" CASTOR "CASTOR" +.SH NAME +acsd \- Automated Cartdridge System daemon +.SH SYNOPSIS +.BI "acsd [OPTIONS]" + +.SH DESCRIPTION +\fBacsd\fP is the daemon responsible for controlling ACS mount and ACS dismount +requests. +.P +When \fBacsd\fP is executed it immediately forks with the parent +terminating and the child running in the background. If required the +\fB\-f, \-\-foreground\fP option can be used to stop \fBacsd\fP from +forking and keep the parent process in the foreground. + +.SH OPTIONS +.TP +\fB\-f, \-\-foreground +Remain in the foreground. +.TP +\fB\-h, \-\-help +Prints the usage message. +.TP +\fB\-c, \-\-config <config-file> +Set the location of the CASTOR configuration file (castor.conf). The default location is /etc/castor/castor.conf. + +.SH CASTOR CONFIGURATION PARAMETERS +The acsd daemon reads and uses the following CASTOR configuration +parameters which are specified within the CASTOR configuration file (the +default location is /etc/castor/castor.conf). + +.TP +\fBAcsDaemon CmdTimeout +The maximum time to wait in seconds for a tape-library command to conclude. + +.TP +\fBAcsDaemon Port +The TCP/IP port on which the CASTOR ACS daemon listens for incoming Zmq +connections from the tape server. + +.TP +\fBAcsDaemon QueryInterval +Time to wait in seconds between queries to the tape Library. + +.SH FILES +.TP +.B /etc/castor/castor.conf +Default location of the CASTOR configuration file. +.TP +.B /var/log/castor/acsd.log +Default location of the acsd log file. + +.SH AUTHOR +\fBCASTOR\fP Team <castor.support@cern.ch> diff --git a/mediachanger/acs/acsd.sysconfig b/mediachanger/acs/acsd.sysconfig new file mode 100644 index 0000000000000000000000000000000000000000..2d787142e28cb5a93cf896bb98b2f8fbd00f9414 --- /dev/null +++ b/mediachanger/acs/acsd.sysconfig @@ -0,0 +1,6 @@ +# Arguments for the ACS daemon +# -f keep process in the foreground, do not fork +# -h display help and exit +# -c config file location (castor.conf) +# +#ACSD_OPTIONS= diff --git a/mediachanger/acs/cta-acsd.1cta b/mediachanger/acs/cta-acsd.1cta new file mode 100644 index 0000000000000000000000000000000000000000..b7ab08406df8939d7eb3f9bad69c785c444a9d04 --- /dev/null +++ b/mediachanger/acs/cta-acsd.1cta @@ -0,0 +1,117 @@ +.\" 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/>. +.TH CTA-ACSD "cta" "$Date: 2018/01/10 14:44:00 $" CTA "CTA" +.SH NAME +cta-taped \- Tape server daemon +.SH SYNOPSIS +.BI "cta-taped [OPTIONS]" + +.SH DESCRIPTION +\fBcta-taped\fP is the daemon responsible for controlling one or more tape +drives. +.P +When \fBcta-taped\fP is executed it immediately forks with the parent +terminating and the child running in the background. If required the +\fB\-f, \-\-foreground\fP option can be used to stop \fBcta-taped\fP from +forking and keep the parent process in the foreground. + +.SH TAPE LIBRARY SUPPORT + +CTA supports two types of tape libraries, SCSI compatible ones and Oracle +Automatic Cartridge System (ACS) ones. The cta-taped daemon requires a tape +library daemon to be installed and run on the same tape server as itself. +There are two types of CTA tape library daemons, one for SCSI compatible tape +libraries and one for ACS tape libraries. + +A SCSI compatible tape library requires the following daemon: + +\fBrmcd\fP + +The installation RPM for the \fBrmcd\fP daemon and its manual page is: + +\fBcta-rmc-server-0.0-XX.slc6.x86_64\fP + +The \fBcta-rmcd\fP daemon can be started, stopped and its status queried using +the usual service commands: + +\fBservice cta-rmcd start\fP +.br +\fBservice cta-acsd status\fP +.br +\fBservice cta-acsd stop\fP + +Even though there is a separate daemon for each of the supported tape library +types, there is a single generic set of command-line tools for mounting and +un-mounting tapes: + +\fBcta-tape-mediachanger-mount\fP +.br +\fBcta-tape-mediachanger-dismount\fP + +The installation RPM for these command-line tools and their manual pages is: + +\fBcta-tape-developer-tools-2.1.15-XX.slc6.x86_64\fP + +.SH OPTIONS +.TP +\fB\-f, \-\-foreground +Remain in the foreground. +.TP +\fB\-h, \-\-help +Prints the usage message. +.TP +\fB\-c, \-\-config <config-file> +Set the location of the CTA configuration file (cta.conf). The default location is /etc/cta/cta.conf. + +.SH CTA CONFIGURATION PARAMETERS +The cta-taped daemon reads and uses the following CTA configuration +parameters which are specified within the CTA configuration file (the +default location is /etc/cta/cta.conf). + +.TP +\fBRMC HOST +The host on which the rmcd daemon is running. + +.TP +\fBRMC MAXRQSTATTEMPTS +Maximum number of attempts a retriable RMC request should be issued. + +.TP +\fBTapeServer BlkMoveTimeout +The maximum time in seconds the data-transfer session of tapeserverd can +cease to move data blocks + +.TP +\fBTapeServer BufSize +Size of a memory buffer in the data-transfer cache in bytes (default is 5 +Mebibytes). +## acsd ######################################################################## +# The TCP/IP port on which the CASTOR ACS daemon listens for incoming Zmq +#AcsDaemon Port 54521 +#AcsDaemon QueryInterval 10 +#AcsDaemon CmdTimeout 610 +# The TCP/IP port on which the CTA ACS daemon listens for incoming Zmq +# connections from the tape server. +#AcsDaemon Port 54521 + +# Time to wait in seconds between queries to the tape Library. +#AcsDaemon QueryInterval 10 + +# The maximum time to wait in seconds for a tape-library command to +# conclude. +#AcsDaemon CmdTimeout 610 + +# End-of-File diff --git a/mediachanger/acs/cta-tape-acs-dismount.1cta b/mediachanger/acs/cta-tape-acs-dismount.1cta new file mode 100644 index 0000000000000000000000000000000000000000..76e568a9fc24c9d1b69a0844282e1d8e44d4a536 --- /dev/null +++ b/mediachanger/acs/cta-tape-acs-dismount.1cta @@ -0,0 +1,68 @@ +.\" 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/>. + +.TH CASTOR-TAPE-ACS-DISMOUNT "1cta" "$Date: 2013/10/09 14:00:00 $" CASTOR "CASTOR" +.SH NAME +cta-tape-acs-dismount \- dismount a volume +.SH SYNOPSIS +.BI "cta-tape-acs-dismount [options] VID DRIVE_SLOT" + +.SH DESCRIPTION +\fBWarning\fP, \fBcta-tape-acs-dismount\fP is a developer tool and is +therefore subject to change in and even removal from a future release of CASTOR. +End users should not rely on this tool to operate their CASTOR installation. + +\fBcta-tape-acs-dismount\fP dismounts the volume with the specfied \fBVID\fP +from the drive located in the specified \fBDRIVE_SLOT\fP of the tape library. +The format of \fBDRIVE_SLOT\fP is as follows: + +.B ACS:LSM:panel:transport + +Please note that this command-line tool communicates directly with the CSI of +the ACS system. This command-line tool does not communicate with any CASTOR +daemons. + +.SH OPTIONS +.TP +\fB\-d, \-\-debug +Turns on the printing of debug information. +.TP +\fB\-f, \-\-force +Force the dismount. +.TP +\fB\-h, \-\-help +Prints the usage message. +.TP +\fB\-q, \-\-query SECONDS +Time wait between queries to ACLS for responses. +\fBSECONDS\fP must be an integer value greater than 0. +The default value of \fBSECONDS\fP is 10. +.TP +\fB\-t, \-\-timeout SECONDS +Time to wait for the dismount operation to conclude. +\fBSECONDS\fP must be an integer value greater than 0. +The default value of \fBSECONDS\fP is 610. + +.SH "RETURN CODES" +.TP +\fB 0 +Ok. +.TP +\fB 1 +Command failed. + +.SH AUTHOR +\fBCTA\fP Team diff --git a/mediachanger/acs/cta-tape-acs-mount.1cta b/mediachanger/acs/cta-tape-acs-mount.1cta new file mode 100644 index 0000000000000000000000000000000000000000..a64dff0389c8a8fc76e24c8e5886371bdc1a00fa --- /dev/null +++ b/mediachanger/acs/cta-tape-acs-mount.1cta @@ -0,0 +1,69 @@ + +.\" 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/>. + +.TH CTA-TAPE-ACS-MOUNT "1cta" "$Date: 2013/10/09 14:00:00 $" CTA "CTA" +.SH NAME +cta-tape-acs-mount \- mount a volume +.SH SYNOPSIS +.BI "cta-tape-acs-mount [options] VID DRIVE_SLOT" + +.SH DESCRIPTION +\fBWarning\fP, \fBcta-tape-acs-mount\fP is a developer tool and is therefore +subject to change in and even removal from a future release of CTA. +End users should not rely on this tool to operate their CTA installation. + +\fBcta-tape-acs-mount\fP mounts the volume with the specfied \fBVID\fP into +the drive located in the specified \fBDRIVE_SLOT\fP of the tape library. +The format of \fBDRIVE_SLOT\fP is as follows: + +.B ACS:LSM:panel:transport + +Please note that this command-line tool communicates directly with the CSI of +the ACS system. This command-line tool does not communicate with any CTA +daemons. + +.SH OPTIONS +.TP +\fB\-d, \-\-debug +Turns on the printing of debug information. +.TP +\fB\-h, \-\-help +Prints the usage message. +.TP +\fB\-q, \-\-query SECONDS +Time wait between queries to ACLS for responses. +\fBSECONDS\fP must be an integer value greater than 0. +The default value of \fBSECONDS\fP is 10. +.TP +\fB\-r, \-\-readonly +Request the volume is mounted for read-only access. +.TP +\fB\-t, \-\-timeout SECONDS +Time to wait for the mount operation to conclude. +\fBSECONDS\fP must be an integer value greater than 0. +The default value of \fBSECONDS\fP is 610. + +.SH "RETURN CODES" +.TP +\fB 0 +Ok. +.TP +\fB 1 +Command failed. + +.SH AUTHOR +\fBCTA\fP Team diff --git a/mediachanger/acs/cta-tape-acs-queryvolume.1cta b/mediachanger/acs/cta-tape-acs-queryvolume.1cta new file mode 100644 index 0000000000000000000000000000000000000000..fa0a3705bb61821c4ec0d40f6bb174f4d8333146 --- /dev/null +++ b/mediachanger/acs/cta-tape-acs-queryvolume.1cta @@ -0,0 +1,62 @@ +.\" 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/>. + +.TH CTA-TAPE-ACS-QUERYVOLUME "1cta" "$Date: 2013/10/09 14:00:00 $" CTA "CTA" +.SH NAME +cta-tape-acs-queryvolume \- queries a volume +.SH SYNOPSIS +.BI "cta-tape-acs-queryvolume [options] VID" + +.SH DESCRIPTION +\fBWarning\fP, \fBcastor-tape-acs-queryvolume\fP is a developer tool and is +therefore subject to change in and even removal from a future release of CTA. +End users should not rely on this tool to operate their CTA installation. + +\fBcastor-tape-acs-queryvolume\fP quieries ACS for information about the volume +with the specfied \fBVID\fP. + +Please note that this command-line tool communicates directly with the CSI of +the ACS system. This command-line tool does not communicate with any CTA +daemons. + +.SH OPTIONS +.TP +\fB\-d, \-\-debug +Turns on the printing of debug information. +.TP +\fB\-h, \-\-help +Prints the usage message. +.TP +\fB\-q, \-\-query SECONDS +Time wait between queries to ACLS for responses. +\fBSECONDS\fP must be an integer value greater than 0. +The default values of \fBSECONDS\fP is 610. +.TP +\fB\-t, \-\-timeout SECONDS +Time to wait for the mount operation to conclude. +\fBSECONDS\fP must be an integer value greater than 0. +The default value of \fBSECONDS\fP is 10. + +.SH "RETURN CODES" +.TP +\fB 0 +Ok. +.TP +\fB 1 +Command failed. + +.SH AUTHOR +\fBCTA\fP Team