Revision 1ca709c1
b/INSTALL | ||
---|---|---|
133 | 133 |
`utf8-string <http://hackage.haskell.org/package/utf8-string>`_ |
134 | 134 |
libraries; these usually come with the GHC compiler |
135 | 135 |
- `deepseq <http://hackage.haskell.org/package/deepseq>`_ |
136 |
- `curl <http://hackage.haskell.org/package/curl>`_, tested with |
|
137 |
versions 1.3.4 and above |
|
136 | 138 |
|
137 | 139 |
Some of these are also available as package in Debian/Ubuntu:: |
138 | 140 |
|
139 | 141 |
$ apt-get install ghc6 libghc6-json-dev libghc6-network-dev \ |
140 |
libghc6-parallel-dev libghc6-deepseq-dev |
|
142 |
libghc6-parallel-dev libghc6-deepseq-dev \ |
|
143 |
libghc6-curl-dev |
|
141 | 144 |
|
142 | 145 |
Or in newer versions of these distributions (using GHC 7.x):: |
143 | 146 |
|
144 | 147 |
$ apt-get install ghc libghc-json-dev libghc-network-dev \ |
145 |
libghc-parallel-dev libghc-deepseq-dev \
|
|
146 |
libghc-utf8-string-dev |
|
148 |
libghc-parallel-dev libghc-deepseq-dev \ |
|
149 |
libghc-utf8-string-dev libghc-curl-dev
|
|
147 | 150 |
|
148 |
In Fedora, they are available via packages as well::
|
|
151 |
In Fedora, some of them are available via packages as well::
|
|
149 | 152 |
|
150 | 153 |
$ yum install ghc ghc-json-devel ghc-network-devel \ |
151 | 154 |
ghc-parallel-devel ghc-deepseq-devel |
... | ... | |
158 | 161 |
Then install the additional libraries via |
159 | 162 |
``cabal``:: |
160 | 163 |
|
161 |
$ cabal install json network parallel utf8-string |
|
162 |
|
|
163 |
The compilation of the htools components is automatically enabled when |
|
164 |
the compiler and the requisite libraries are found. You can use the |
|
165 |
``--enable-htools`` configure flag to force the selection (at which |
|
166 |
point ``./configure`` will fail if it doesn't find the prerequisites). |
|
167 |
|
|
164 |
$ cabal install json network parallel utf8-string curl |
|
168 | 165 |
|
169 | 166 |
Haskell optional features |
170 | 167 |
~~~~~~~~~~~~~~~~~~~~~~~~~ |
171 | 168 |
|
172 | 169 |
Optionally, more functionality can be enabled if your build machine has |
173 |
a few more Haskell libraries enabled: RAPI access to remote cluster from |
|
174 |
htools (``--enable-htools-rapi``), the ``ganeti-confd`` |
|
175 |
daemon (``--enable-confd``) and the monitoring agent |
|
170 |
a few more Haskell libraries enabled: the ``ganeti-confd`` daemon |
|
171 |
(``--enable-confd``) and the monitoring agent |
|
176 | 172 |
(``--enable-monitoring``). The list of extra dependencies for these is: |
177 | 173 |
|
178 |
- `curl <http://hackage.haskell.org/package/curl>`_, tested with |
|
179 |
versions 1.3.4 and above |
|
180 | 174 |
- `hslogger <http://software.complete.org/hslogger>`_, version 1.1 and |
181 | 175 |
above (note that Debian Squeeze only has version 1.0.9) |
182 | 176 |
- `Crypto <http://hackage.haskell.org/package/Crypto>`_, tested with |
... | ... | |
193 | 187 |
the exception of curl), so you can use either apt:: |
194 | 188 |
|
195 | 189 |
$ apt-get install libghc-hslogger-dev libghc-crypto-dev libghc-text-dev \ |
196 |
libghc-hinotify-dev libghc-regex-pcre-dev libghc-curl-dev \
|
|
190 |
libghc-hinotify-dev libghc-regex-pcre-dev \ |
|
197 | 191 |
libghc-attoparsec-dev libghc-vector-dev |
198 | 192 |
|
199 | 193 |
or ``cabal``:: |
200 | 194 |
|
201 |
$ cabal install hslogger Crypto text hinotify regex-pcre curl \
|
|
195 |
$ cabal install hslogger Crypto text hinotify regex-pcre \ |
|
202 | 196 |
attoparsec vector |
203 | 197 |
|
204 | 198 |
to install them. |
205 | 199 |
|
206 |
The most recent Fedora doesn't provide ``curl``, ``crypto``,
|
|
207 |
``inotify``. So these need to be installed using ``cabal``, if
|
|
208 |
desired. The other packages can be installed via ``yum``::
|
|
200 |
The most recent Fedora doesn't provide ``crypto``, ``inotify``. So these
|
|
201 |
need to be installed using ``cabal``, if desired. The other packages can
|
|
202 |
be installed via ``yum``:: |
|
209 | 203 |
|
210 | 204 |
$ yum install ghc-hslogger-devel ghc-text-devel \ |
211 | 205 |
ghc-regex-pcre-devel |
b/Makefile.am | ||
---|---|---|
770 | 770 |
@rm -f $(notdir $@).tix |
771 | 771 |
$(GHC) --make \ |
772 | 772 |
$(HFLAGS) \ |
773 |
$(HS_NOCURL) $(HS_PARALLEL3) $(HS_REGEX_PCRE) \
|
|
773 |
$(HS_PARALLEL3) $(HS_REGEX_PCRE) \ |
|
774 | 774 |
-osuf $(notdir $@).o -hisuf $(notdir $@).hi \ |
775 | 775 |
$(HEXTRA) $(HEXTRA_INT) $@ |
776 | 776 |
@touch "$@" |
... | ... | |
1844 | 1844 |
$(LN_S) ../hscolour.css $(APIDOC_HS_DIR)/Ganeti/Confd/hscolour.css |
1845 | 1845 |
set -e ; \ |
1846 | 1846 |
cd src; \ |
1847 |
if [ "$(HS_NOCURL)" ]; \ |
|
1848 |
then OPTGHC="--optghc=$(HS_NOCURL)"; \ |
|
1849 |
else OPTGHC=""; \ |
|
1850 |
fi; \ |
|
1847 |
OPTGHC=""; \ |
|
1851 | 1848 |
if [ "$(HS_PARALLEL3)" ]; \ |
1852 | 1849 |
then OPTGHC="$$OPTGHC --optghc=$(HS_PARALLEL3)"; \ |
1853 | 1850 |
fi; \ |
... | ... | |
1871 | 1868 |
rm -f TAGS |
1872 | 1869 |
$(GHC) -e ":etags" -v0 \ |
1873 | 1870 |
$(filter-out -O -Werror,$(HFLAGS)) \ |
1874 |
$(HS_NOCURL) $(HS_PARALLEL3) $(HS_REGEX_PCRE) \
|
|
1871 |
$(HS_PARALLEL3) $(HS_REGEX_PCRE) \ |
|
1875 | 1872 |
$(HS_LIBTEST_SRCS) |
1876 | 1873 |
find . -path './lib/*.py' -o -path './scripts/gnt-*' -o \ |
1877 | 1874 |
-path './daemons/ganeti-*' -o -path './tools/*' -o \ |
b/configure.ac | ||
---|---|---|
467 | 467 |
AC_MSG_WARN([qemu-img not found, using ovfconverter will not be possible]) |
468 | 468 |
fi |
469 | 469 |
|
470 |
# --enable-htools-rapi |
|
471 |
HTOOLS_RAPI= |
|
472 |
AC_ARG_ENABLE([htools-rapi], |
|
473 |
[AS_HELP_STRING([--enable-htools-rapi], |
|
474 |
[enable use of curl in the Haskell code (default: check)])], |
|
475 |
[], |
|
476 |
[enable_htools_rapi=check]) |
|
477 |
|
|
478 | 470 |
# --enable-confd |
479 | 471 |
ENABLE_CONFD= |
480 | 472 |
AC_ARG_ENABLE([confd], |
... | ... | |
517 | 509 |
|
518 | 510 |
# check for modules, first custom/special checks |
519 | 511 |
AC_MSG_NOTICE([checking for required haskell modules]) |
520 |
HS_NOCURL=-DNO_CURL |
|
521 |
if test "$enable_htools_rapi" != no; then |
|
522 |
AC_GHC_PKG_CHECK([curl], [HS_NOCURL=], []) |
|
523 |
if test -n "$HS_NOCURL"; then |
|
524 |
if test "$enable_htools_rapi" = check; then |
|
525 |
AC_MSG_WARN(m4_normalize([The curl library was not found, Haskell |
|
526 |
code will be compiled without RAPI support])) |
|
527 |
else |
|
528 |
AC_MSG_FAILURE(m4_normalize([The curl library was not found, but it has |
|
529 |
been requested])) |
|
530 |
fi |
|
531 |
else |
|
532 |
AC_MSG_NOTICE([Enabling curl/RAPI/RPC usage in Haskell code]) |
|
533 |
fi |
|
534 |
fi |
|
535 |
AC_SUBST(HS_NOCURL) |
|
536 |
|
|
537 | 512 |
HS_PARALLEL3= |
538 | 513 |
AC_GHC_PKG_CHECK([parallel-3.*], [HS_PARALLEL3=-DPARALLEL3], |
539 | 514 |
[AC_GHC_PKG_REQUIRE(parallel)], t) |
540 | 515 |
AC_SUBST(HS_PARALLEL3) |
541 | 516 |
|
542 | 517 |
# and now standard modules |
518 |
AC_GHC_PKG_REQUIRE(curl) |
|
543 | 519 |
AC_GHC_PKG_REQUIRE(json) |
544 | 520 |
AC_GHC_PKG_REQUIRE(network) |
545 | 521 |
AC_GHC_PKG_REQUIRE(mtl) |
... | ... | |
641 | 617 |
;; |
642 | 618 |
esac |
643 | 619 |
]], |
644 |
[[case "x${has_confd}x${HS_NOCURL}x" in
|
|
645 |
xTruexx)
|
|
620 |
[[case "x${has_confd}x" in |
|
621 |
xTruex) |
|
646 | 622 |
enable_split_query=True |
647 | 623 |
;; |
648 | 624 |
*) |
... | ... | |
655 | 631 |
AC_MSG_ERROR([Split queries require the confd daemon]) |
656 | 632 |
fi |
657 | 633 |
|
658 |
if test x$enable_split_query = xTrue -a x$HS_NOCURL != x; then |
|
659 |
AC_MSG_ERROR([Split queries require the htools-rapi feature (curl library)]) |
|
660 |
fi |
|
661 |
|
|
662 | 634 |
if test x$enable_split_query = xTrue; then |
663 | 635 |
AC_MSG_NOTICE([Split query functionality enabled]) |
664 | 636 |
fi |
b/src/Ganeti/HTools/Backend/Rapi.hs | ||
---|---|---|
33 | 33 |
import Control.Exception |
34 | 34 |
import Data.List (isPrefixOf) |
35 | 35 |
import Data.Maybe (fromMaybe) |
36 |
#ifndef NO_CURL |
|
37 | 36 |
import Network.Curl |
38 | 37 |
import Network.Curl.Types () |
39 |
#endif |
|
40 | 38 |
import Control.Monad |
41 | 39 |
import Text.JSON (JSObject, fromJSObject, decodeStrict) |
42 | 40 |
import Text.JSON.Types (JSValue(..)) |
... | ... | |
61 | 59 |
-- | Read an URL via curl and return the body if successful. |
62 | 60 |
getUrl :: (Monad m) => String -> IO (m String) |
63 | 61 |
|
64 |
#ifdef NO_CURL |
|
65 |
getUrl _ = return $ fail "RAPI/curl backend disabled at compile time" |
|
66 |
|
|
67 |
#else |
|
68 |
|
|
69 | 62 |
-- | Connection timeout (when using non-file methods). |
70 | 63 |
connTimeout :: Long |
71 | 64 |
connTimeout = 15 |
... | ... | |
88 | 81 |
CurlOK -> return body |
89 | 82 |
_ -> fail $ printf "Curl error for '%s', error %s" |
90 | 83 |
url (show code)) |
91 |
#endif |
|
92 | 84 |
|
93 | 85 |
-- | Helper to convert I/O errors in 'Bad' values. |
94 | 86 |
ioErrToResult :: IO a -> IO (Result a) |
b/src/Ganeti/Rpc.hs | ||
---|---|---|
1 |
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, CPP,
|
|
1 |
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, |
|
2 | 2 |
BangPatterns, TemplateHaskell #-} |
3 | 3 |
|
4 | 4 |
{-| Implementation of the RPC client. |
... | ... | |
7 | 7 |
|
8 | 8 |
{- |
9 | 9 |
|
10 |
Copyright (C) 2012 Google Inc. |
|
10 |
Copyright (C) 2012, 2013 Google Inc.
|
|
11 | 11 |
|
12 | 12 |
This program is free software; you can redistribute it and/or modify |
13 | 13 |
it under the terms of the GNU General Public License as published by |
... | ... | |
75 | 75 |
import qualified Text.JSON as J |
76 | 76 |
import Text.JSON.Pretty (pp_value) |
77 | 77 |
|
78 |
#ifndef NO_CURL |
|
79 | 78 |
import Network.Curl |
80 | 79 |
import qualified Ganeti.Path as P |
81 |
#endif |
|
82 | 80 |
|
83 | 81 |
import qualified Ganeti.Constants as C |
84 | 82 |
import Ganeti.Objects |
... | ... | |
88 | 86 |
|
89 | 87 |
-- * Base RPC functionality and types |
90 | 88 |
|
91 |
#ifndef NO_CURL |
|
92 | 89 |
-- | The curl options used for RPC. |
93 | 90 |
curlOpts :: [CurlOption] |
94 | 91 |
curlOpts = [ CurlFollowLocation False |
... | ... | |
98 | 95 |
, CurlSSLKeyType "PEM" |
99 | 96 |
, CurlConnectTimeout (fromIntegral C.rpcConnectTimeout) |
100 | 97 |
] |
101 |
#endif |
|
102 | 98 |
|
103 | 99 |
-- | Data type for RPC error reporting. |
104 | 100 |
data RpcError |
105 |
= CurlDisabledError |
|
106 |
| CurlLayerError Node String |
|
101 |
= CurlLayerError Node String |
|
107 | 102 |
| JsonDecodeError String |
108 | 103 |
| RpcResultError String |
109 | 104 |
| OfflineNodeError Node |
... | ... | |
111 | 106 |
|
112 | 107 |
-- | Provide explanation to RPC errors. |
113 | 108 |
explainRpcError :: RpcError -> String |
114 |
explainRpcError CurlDisabledError = |
|
115 |
"RPC/curl backend disabled at compile time" |
|
116 | 109 |
explainRpcError (CurlLayerError node code) = |
117 | 110 |
"Curl error for " ++ nodeName node ++ ", " ++ code |
118 | 111 |
explainRpcError (JsonDecodeError msg) = |
... | ... | |
164 | 157 |
-> IO (ERpcError String) |
165 | 158 |
|
166 | 159 |
executeHttpRequest _ (Left rpc_err) = return $ Left rpc_err |
167 |
#ifdef NO_CURL |
|
168 |
executeHttpRequest _ _ = return $ Left CurlDisabledError |
|
169 |
#else |
|
170 | 160 |
executeHttpRequest node (Right request) = do |
171 | 161 |
cert_file <- P.nodedCertFile |
172 | 162 |
let reqOpts = [ CurlTimeout (fromIntegral $ requestTimeout request) |
... | ... | |
181 | 171 |
return $ case code of |
182 | 172 |
CurlOK -> Right body |
183 | 173 |
_ -> Left $ CurlLayerError node (show code) |
184 |
#endif |
|
185 | 174 |
|
186 | 175 |
-- | Prepare url for the HTTP request. |
187 | 176 |
prepareUrl :: (RpcCall a) => Node -> a -> String |
Also available in: Unified diff