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