diff --git a/INSTALL b/INSTALL
index 4308c5dece7411d9ecd78af60eb1d3275d775592..03e936323fab8ac6fe85d43407c30489e76553d6 100644
--- a/INSTALL
+++ b/INSTALL
@@ -113,11 +113,9 @@ dependencies.
Haskell requirements
~~~~~~~~~~~~~~~~~~~~
-If you want to enable the `htools` component, which is recommended on
-bigger deployments (this give you automatic instance placement, cluster
-balancing, etc.), then you need to have a Haskell compiler installed on
-your build machine (but this is not required on the machines which are
-just going to run Ganeti). More specifically:
+Starting with Ganeti 2.7, the Haskell GHC compiler and a few base
+libraries are required in order to build Ganeti (but not to run and
+deploy Ganeti on production machines). More specifically:
- `GHC `_ version 6.12 or higher
- or even better, `The Haskell Platform
@@ -128,75 +126,82 @@ just going to run Ganeti). More specifically:
network library
- `parallel `_, a parallel
programming library (note: tested with up to version 3.x)
-- `curl `_, bindings for the
- curl library, only needed if you want these tools to connect to remote
- clusters (as opposed to the local one)
- `bytestring `_ and
`utf8-string `_
libraries; these usually come with the GHC compiler
-- `regex-pcre `_,
- bindings for the ``pcre`` library
+- `deepseq `_
Some of these are also available as package in Debian/Ubuntu::
$ apt-get install ghc6 libghc6-json-dev libghc6-network-dev \
- libghc6-parallel-dev libghc6-curl-dev
-
-Or in Fedora running::
+ libghc6-parallel-dev libghc6-deepseq-dev
- $ yum install ghc ghc-json-devel ghc-network-devel ghc-parallel-devel
+Or in newer versions of these distributions (using GHC 7.x)::
-The most recent Fedora doesn't provide ``ghc-curl``. So this needs to be
-installed using ``cabal`` or alternatively htools can be build without
-curl support.
+ $ apt-get install ghc libghc-json-dev libghc-network-dev \
+ libghc-parallel-dev libghc-deepseq-dev \
+ libghc-utf8-string-dev
-Note that more recent versions have switched to GHC 7.x and the packages
-were renamed::
+In Fedora, they are available via packages as well::
- $ apt-get install ghc libghc-json-dev libghc-network-dev \
- libghc-parallel-dev libghc-curl-dev \
- libghc-regex-pcre-dev libghc-utf8-string-dev
+ $ yum install ghc ghc-json-devel ghc-network-devel \
+ ghc-parallel-devel ghc-deepseq-devel
If using a distribution which does not provide them, first install
-the Haskell platform. You can also install ``cabal`` manualy::
+the Haskell platform. You can also install ``cabal`` manually::
$ apt-get install cabal-install
Then install the additional libraries via
``cabal``::
- $ cabal install json network parallel curl regex-pcre utf8-string
+ $ cabal install json network parallel utf8-string
The compilation of the htools components is automatically enabled when
the compiler and the requisite libraries are found. You can use the
``--enable-htools`` configure flag to force the selection (at which
point ``./configure`` will fail if it doesn't find the prerequisites).
-In Ganeti version 2.6, one of the daemons (``ganeti-confd``) is shipped
-in two versions: the Python default version (which has no extra
-dependencies), and an experimental Haskell version. This latter version
-can be enabled via the ``./configure`` flag ``--enable-confd=haskell``
-and a few has extra dependencies:
+Haskell optional features
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Optionally, more functionality can be enabled if your build machine has
+a few more Haskell libraries enabled: RAPI access to remote cluster from
+htools (``--enable-htools-rapi``) and enabling the ``ganeti-confd``
+daemon (``--enable-confd``). The list of extra dependencies for these
+is:
+
+- `curl `_, tested with
+ versions 1.3.4 and above
- `hslogger `_, version 1.1 and
above (note that Debian Squeeze only has version 1.0.9)
- `Crypto `_, tested with
version 4.2.4
- `text `_
- `hinotify `_
+- `regex-pcre `_,
+ bindings for the ``pcre`` library
-These libraries are available in Debian Wheezy (but not in Squeeze), so
-you can use either apt::
+These libraries are available in Debian Wheezy (but not in Squeeze, with
+the exception of curl), so you can use either apt::
$ apt-get install libghc-hslogger-dev libghc-crypto-dev libghc-text-dev \
- libghc-hinotify-dev
+ libghc-hinotify-dev libghc-regex-pcre-dev libghc-curl-dev
or ``cabal``::
- $ cabal install hslogger Crypto text hinotify
+ $ cabal install hslogger Crypto text hinotify regex-pcre curl
to install them.
+The most recent Fedora doesn't provide ``curl``, ``crypto``,
+``inotify``. So these need to be installed using ``cabal``, if
+desired. The other packages can be installed via ``yum``::
+
+ $ yum install ghc-hslogger-devel ghc-text-devel \
+ ghc-regex-pcre-devel
+
.. _cabal-note:
.. note::
If one of the cabal packages fails to install due to unfulfilled
diff --git a/Makefile.am b/Makefile.am
index 15874a7fc65d5762cf099dcf90aa57ca5ebb4a51..3333c6f70431fd829710cc777f17fc2b851c2020 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -601,18 +601,15 @@ install-exec-hook:
endif
$(HS_ALL_PROGS): %: %.hs $(HS_LIBTEST_SRCS) $(HS_BUILT_SRCS) Makefile
- @if [ -z "$(HTOOLS)" ]; then \
- echo "Error: htools compilation disabled at configure time" 1>&2 ;\
- exit 1; \
- fi
- @if [ "$(notdir $@)" = "test" ] && [ -z "$(GHC_PKG_QUICKCHECK)" ]; then \
- echo "Error: cannot run unittests without the QuickCheck library (see devnotes.rst)" 1>&2; \
+ @if [ "$(notdir $@)" = "test" ] && [ "$(HTOOLS_NODEV)" ]; then \
+ echo "Error: cannot run unittests without the development" \
+ " libraries (see devnotes.rst)" 1>&2; \
exit 1; \
fi
@rm -f $(notdir $@).tix
$(GHC) --make \
$(HFLAGS) \
- $(HTOOLS_NOCURL) $(HTOOLS_PARALLEL3) \
+ $(HTOOLS_NOCURL) $(HTOOLS_PARALLEL3) $(HTOOLS_REGEX_PCRE) \
-osuf $(notdir $@).o -hisuf $(notdir $@).hi \
$(HEXTRA) $(HEXTRA_INT) $@
@touch "$@"
@@ -1234,11 +1231,7 @@ lib/_autoconf.py: Makefile | stamp-directories
echo "NODED_GROUP = '$(NODED_GROUP)'"; \
echo "DISK_SEPARATOR = '$(DISK_SEPARATOR)'"; \
echo "QEMUIMG_PATH = '$(QEMUIMG_PATH)'"; \
- if [ "$(HTOOLS)" ]; then \
- echo "HTOOLS = True"; \
- else \
- echo "HTOOLS = False"; \
- fi; \
+ echo "HTOOLS = True"; \
echo "ENABLE_CONFD = $(ENABLE_CONFD)"; \
echo "XEN_CMD = '$(XEN_CMD)'"; \
echo "ENABLE_SPLIT_QUERY = $(ENABLE_SPLIT_QUERY)"; \
@@ -1593,6 +1586,9 @@ hs-apidoc: $(HS_BUILT_SRCS)
if [ "$(HTOOLS_PARALLEL3)" ]; \
then OPTGHC="$$OPTGHC --optghc=$(HTOOLS_PARALLEL3)"; \
fi; \
+ if [ "$(HTOOLS_REGEX_PCRE)" ]; \
+ then OPTGHC="$$OPTGHC --optghc=$(HTOOLS_REGEX_PCRE)"; \
+ fi; \
RELSRCS="$(HS_LIB_SRCS:htools/%=%) $(patsubst htools/%,%,$(filter htools/%,$(HS_BUILT_SRCS)))"; \
for file in $$RELSRCS; do \
hfile=`echo $$file|sed 's/\\.hs$$//'`.html; \
@@ -1610,7 +1606,7 @@ TAGS: $(GENERATED_FILES)
rm -f TAGS
$(GHC) -e ":etags" -v0 \
$(filter-out -O -Werror,$(HFLAGS)) \
- $(HTOOLS_NOCURL) $(HTOOLS_PARALLEL3) \
+ $(HTOOLS_NOCURL) $(HTOOLS_PARALLEL3) $(HTOOLS_REGEX_PCRE) \
$(HS_LIBTEST_SRCS)
find . -path './lib/*.py' -o -path './scripts/gnt-*' -o \
-path './daemons/ganeti-*' -o -path './tools/*' -o \
diff --git a/autotools/ac_ghc_pkg.m4 b/autotools/ac_ghc_pkg.m4
new file mode 100644
index 0000000000000000000000000000000000000000..702666e2e4748a1840eb406c6dfb6bde716bdbb9
--- /dev/null
+++ b/autotools/ac_ghc_pkg.m4
@@ -0,0 +1,77 @@
+#####
+
+# Copyright (C) 2012 Google Inc.
+#
+# 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., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+#####
+#
+# SYNOPSIS
+#
+# AC_GHC_PKG_CHECK(modname, action_found, action_not_found, extended)
+#
+# DESCRIPTION
+#
+# Checks for a Haskell (GHC) module. If found, execute the second
+# argument, if not found, the third one.
+#
+# If the fourth argument is non-empty, then the check will be some
+# via 'ghc-pkg list' (which supports patterns), otherwise it will
+# use just 'ghc-pkg latest'.
+#
+#
+#####
+
+AC_DEFUN([AC_GHC_PKG_CHECK],[
+ if test -z $GHC_PKG; then
+ AC_MSG_ERROR([GHC_PKG not defined])
+ fi
+ AC_MSG_CHECKING([haskell library $1])
+ if test -n "$4"; then
+ GHC_PKG_RESULT=$($GHC_PKG --simple-output list '$1'|tail -n1)
+ else
+ GHC_PKG_RESULT=$($GHC_PKG latest '$1' 2>/dev/null)
+ fi
+ if test -n "$GHC_PKG_RESULT"; then
+ AC_MSG_RESULT($GHC_PKG_RESULT)
+ $2
+ else
+ AC_MSG_RESULT([no])
+ $3
+ fi
+])
+
+#####
+#
+# SYNOPSIS
+#
+# AC_GHC_PKG_REQUIRE(modname, extended)
+#
+# DESCRIPTION
+#
+# Checks for a Haskell (GHC) module, and abort if not found. If the
+# second argument is non-empty, then the check will be some via
+# 'ghc-pkg list' (which supports patterns), otherwise it will use
+# just 'ghc-pkg latest'.
+#
+#
+#####
+
+AC_DEFUN([AC_GHC_PKG_REQUIRE],[
+ AC_GHC_PKG_CHECK($1, [],
+ [AC_MSG_FAILURE([Required Haskell module $1 not found])],
+ $2)
+])
diff --git a/configure.ac b/configure.ac
index b603562ac471688b8ce68498cb7e898ae5a3096c..70695eeebf83f98379fac1511133fd576d736a9f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -310,45 +310,6 @@ then
fi
AC_SUBST(SYSLOG_USAGE, $SYSLOG)
-# --enable-htools
-HTOOLS=
-AC_ARG_ENABLE([htools],
- [AS_HELP_STRING([--enable-htools],
- [enable use of htools (needs GHC and libraries, default: check)])],
- [],
- [enable_htools=check])
-
-# --enable-htools-rapi
-HTOOLS_RAPI=
-AC_ARG_ENABLE([htools-rapi],
- [AS_HELP_STRING([--enable-htools-rapi],
- [enable use of RAPI in htools (needs curl, default: no)])],
- [],
- [enable_htools_rapi=check])
-
-# --enable-confd
-ENABLE_CONFD=
-AC_ARG_ENABLE([confd],
- [AS_HELP_STRING([--enable-confd],
- [enable the ganeti-confd daemon (default: yes)])],
- [[case "$enableval" in
- no)
- enable_confd=False
- ;;
- yes|haskell)
- enable_confd=True
- ;;
- *)
- echo "Invalid value for enable-confd '$enableval'"
- exit 1
- ;;
- esac
- ]],
- [enable_confd=True])
-AC_SUBST(ENABLE_CONFD, $enable_confd)
-
-AM_CONDITIONAL([ENABLE_CONFD], [test x$enable_confd = xTrue])
-
# --with-disk-separator=...
AC_ARG_WITH([disk-separator],
[AS_HELP_STRING([--with-disk-separator=STRING],
@@ -430,97 +391,113 @@ then
AC_MSG_WARN([qemu-img not found, using ovfconverter will not be possible])
fi
-if test "$enable_htools" != "no"; then
+# --enable-htools-rapi
+HTOOLS_RAPI=
+AC_ARG_ENABLE([htools-rapi],
+ [AS_HELP_STRING([--enable-htools-rapi],
+ [enable use of curl in the Haskell code (default: check)])],
+ [],
+ [enable_htools_rapi=check])
+
+# --enable-confd
+ENABLE_CONFD=
+AC_ARG_ENABLE([confd],
+ [AS_HELP_STRING([--enable-confd],
+ [enable the ganeti-confd daemon (default: check)])],
+ [],
+ [enable_confd=check])
# Check for ghc
AC_ARG_VAR(GHC, [ghc path])
AC_PATH_PROG(GHC, [ghc], [])
if test -z "$GHC"; then
- if test "$enable_htools" != "check"; then
- AC_MSG_FAILURE([ghc not found, htools compilation will not possible])
- fi
+ AC_MSG_FAILURE([ghc not found, compilation will not possible])
fi
# Check for ghc-pkg
-HTOOLS_MODULES=
AC_ARG_VAR(GHC_PKG, [ghc-pkg path])
AC_PATH_PROG(GHC_PKG, [ghc-pkg], [])
if test -z "$GHC_PKG"; then
- if test "$enable_htools" != "check"; then
- AC_MSG_FAILURE([ghc-pkg not found, htools compilation will not be possible])
- fi
-else
- # check for modules
- AC_MSG_NOTICE([checking for required haskell modules])
- HTOOLS_NOCURL=-DNO_CURL
- if test "$enable_htools_rapi" != "no"; then
- AC_MSG_CHECKING([curl])
- GHC_PKG_CURL=$($GHC_PKG latest curl)
- if test -z "$GHC_PKG_CURL"; then
- if test "$enable_htools_rapi" = "check"; then
- AC_MSG_WARN(m4_normalize([The curl library not found, htools will be
- compiled without RAPI support]))
- else
- AC_MSG_FAILURE(m4_normalize([The curl library was not found, but it has
- been requested]))
- fi
+ AC_MSG_FAILURE([ghc-pkg not found, compilation will not be possible])
+fi
+
+# check for modules, first custom/special checks
+AC_MSG_NOTICE([checking for required haskell modules])
+HTOOLS_NOCURL=-DNO_CURL
+if test "$enable_htools_rapi" != "no"; then
+ AC_GHC_PKG_CHECK([curl], [HTOOLS_NOCURL=], [])
+ if test -n "$HTOOLS_NOCURL"; then
+ if test "$enable_htools_rapi" = "check"; then
+ AC_MSG_WARN(m4_normalize([The curl library was not found, Haskell
+ code will be compiled without RAPI support]))
else
- HTOOLS_NOCURL=
+ AC_MSG_FAILURE(m4_normalize([The curl library was not found, but it has
+ been requested]))
fi
- AC_MSG_RESULT($GHC_PKG_CURL)
- fi
- AC_SUBST(GHC_PKG_CURL)
- AC_SUBST(HTOOLS_NOCURL)
- AC_MSG_CHECKING([parallel])
- GHC_PKG_PARALLEL=$($GHC_PKG --simple-output list 'parallel-3.*')
- if test -n "$GHC_PKG_PARALLEL"
- then
- HTOOLS_PARALLEL3=-DPARALLEL3
else
- GHC_PKG_PARALLEL=$($GHC_PKG --simple-output list 'parallel-2.*')
- fi
- if test -z "$GHC_PKG_PARALLEL"
- then
- GHC_PKG_PARALLEL=$($GHC_PKG --simple-output list 'parallel-1.*')
- fi
- AC_SUBST(GHC_PKG_PARALLEL)
- AC_SUBST(HTOOLS_PARALLEL3)
- AC_MSG_RESULT($GHC_PKG_PARALLEL)
- AC_MSG_CHECKING([json])
- GHC_PKG_JSON=$($GHC_PKG latest json)
- AC_MSG_RESULT($GHC_PKG_JSON)
- AC_MSG_CHECKING([network])
- GHC_PKG_NETWORK=$($GHC_PKG latest network)
- AC_MSG_RESULT($GHC_PKG_NETWORK)
- AC_MSG_CHECKING([QuickCheck 2.x])
- GHC_PKG_QUICKCHECK=$($GHC_PKG --simple-output list 'QuickCheck-2.*')
- AC_MSG_RESULT($GHC_PKG_QUICKCHECK)
- if test -z "$GHC_PKG_PARALLEL" || test -z "$GHC_PKG_JSON" || \
- test -z "$GHC_PKG_NETWORK"; then
- if test "$enable_htools" != "check"; then
- AC_MSG_FAILURE(m4_normalize([Required Haskell modules not found, htools
- compilation disabled]))
- fi
- else
- # we leave the other modules to be auto-selected
- HTOOLS_MODULES="-package $GHC_PKG_PARALLEL"
- fi
- if test -z "$GHC_PKG_QUICKCHECK"; then
- AC_MSG_WARN(m4_normalize([The QuickCheck 2.x module was not found,
- you won't be able to run Haskell unittests]))
+ AC_MSG_NOTICE([Enabling curl/RAPI/RPC usage in Haskell code])
fi
fi
-AC_SUBST(HTOOLS_MODULES)
-AC_SUBST(GHC_PKG_QUICKCHECK)
-
-if test "$enable_htools" != "no"; then
- if test -z "$GHC" || test -z "$HTOOLS_MODULES"; then
- AC_MSG_WARN(m4_normalize([Haskell compiler/required libraries not found,
- htools compilation disabled]))
+AC_SUBST(HTOOLS_NOCURL)
+
+HTOOLS_PARALLEL3=
+AC_GHC_PKG_CHECK([parallel-3.*], [HTOOLS_PARALLEL3=-DPARALLEL3],
+ [AC_GHC_PKG_REQUIRE(parallel)], t)
+AC_SUBST(HTOOLS_PARALLEL3)
+
+# and now standard modules
+AC_GHC_PKG_REQUIRE(json)
+AC_GHC_PKG_REQUIRE(network)
+AC_GHC_PKG_REQUIRE(mtl)
+AC_GHC_PKG_REQUIRE(bytestring)
+AC_GHC_PKG_REQUIRE(utf8-string)
+
+# extra modules for confd functionality
+HTOOLS_REGEX_PCRE=-DNO_REGEX_PCRE
+has_confd=False
+if test "$enable_confd" != "no"; then
+ CONFD_PKG=
+ AC_GHC_PKG_CHECK([regex-pcre], [HTOOLS_REGEX_PCRE=],
+ [CONFD_PKG="$CONFD_PKG regex-pcre"])
+ AC_GHC_PKG_CHECK([hslogger], [], [CONFD_PKG="$CONFD_PKG hslogger"])
+ AC_GHC_PKG_CHECK([Crypto], [], [CONFD_PKG="$CONFD_PKG Crypto"])
+ AC_GHC_PKG_CHECK([text], [], [CONFD_PKG="$CONFD_PKG text"])
+ AC_GHC_PKG_CHECK([hinotify], [], [CONFD_PKG="$CONFD_PKG hinotify"])
+ if test -z "$CONFD_PKG"; then
+ has_confd=True
else
- HTOOLS=yes
+ if test "$enable_confd" = "check"; then
+ AC_MSG_WARN(m4_normalize([The required extra libraries for confd were
+ not found ($CONFD_PKG), confd disabled]))
+ else
+ AC_MSG_FAILURE(m4_normalize([The confd functionality was requested, but
+ required libraries were not found:
+ $CONFD_PKG]))
+ fi
fi
fi
+AC_SUBST(HTOOLS_REGEX_PCRE)
+if test "$has_confd" = "True"; then
+ AC_MSG_NOTICE([Enabling confd usage])
+fi
+AC_SUBST(ENABLE_CONFD, $has_confd)
+AM_CONDITIONAL([ENABLE_CONFD], [test x$has_confd = xTrue])
+
+# development modules
+HTOOLS_NODEV=
+AC_GHC_PKG_CHECK([QuickCheck-2.*], [], [HTOOLS_NODEV=1], t)
+AC_GHC_PKG_CHECK([test-framework-0.6*], [], [HTOOLS_NODEV=1], t)
+AC_GHC_PKG_CHECK([test-framework-hunit], [], [HTOOLS_NODEV=1])
+AC_GHC_PKG_CHECK([test-framework-quickcheck2], [], [HTOOLS_NODEV=1])
+if test -n "$HTOOLS_NODEV"; then
+ AC_MSG_WARN(m4_normalize([Required development modules were not found,
+ you won't be able to run Haskell unittests]))
+else
+ AC_MSG_NOTICE([Haskell development modules found, unittests enabled])
+fi
+AC_SUBST(HTOOLS_NODEV)
+
+HTOOLS=yes
AC_SUBST(HTOOLS)
# --enable-split-query
@@ -541,7 +518,7 @@ AC_ARG_ENABLE([split-query],
;;
esac
]],
- [[case "x${enable_confd}x${HTOOLS_NOCURL}x" in
+ [[case "x${has_confd}x${HTOOLS_NOCURL}x" in
xTruexx)
enable_split_query=True
;;
@@ -551,7 +528,7 @@ AC_ARG_ENABLE([split-query],
esac]])
AC_SUBST(ENABLE_SPLIT_QUERY, $enable_split_query)
-if test x$enable_split_query = xTrue -a x$enable_confd != xTrue; then
+if test x$enable_split_query = xTrue -a x$has_confd != xTrue; then
AC_MSG_ERROR([Split queries require the confd daemon])
fi
@@ -592,8 +569,6 @@ if test -z "$HLINT"; then
AC_MSG_WARN([hlint not found, checking code will not be possible])
fi
-fi # end if enable_htools, define automake conditions
-
if test "$HTOOLS" != "yes" && test "$ENABLE_CONFD" = "True"; then
AC_MSG_ERROR(m4_normalize([cannot enable ganeti-confd if
htools support is not enabled]))
diff --git a/doc/devnotes.rst b/doc/devnotes.rst
index 718ca7541aa70077d3fa6a8740b04f3ec4e4003d..014f2cd404049d4b5a9470c404b5103883748ba7 100644
--- a/doc/devnotes.rst
+++ b/doc/devnotes.rst
@@ -86,7 +86,9 @@ required ones from the quick install document) via::
Or alternatively via ``cabal``::
- $ cabal install quickcheck hscolour hlint shelltestrunner
+ $ cabal install QuickCheck HUnit \
+ test-framework test-framework-quickcheck2 test-framework-hunit \
+ hscolour hlint shelltestrunner
Configuring for development