cluster support in http API server

Wired it up and it seems to basically work, although the test suite is
not fully passing.

Note that --jobs currently gets multiplied by the number of nodes in the
cluster, which is probably not good.
This commit is contained in:
Joey Hess 2024-07-28 10:16:35 -04:00
parent 8ec174408e
commit 1259ad89b6
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
3 changed files with 71 additions and 41 deletions

View file

@ -58,9 +58,9 @@ proxyCluster clusteruuid proxydone servermode clientside protoerrhandler = do
(withclientbypass protocolversion) (protoerrhandler noop) (withclientbypass protocolversion) (protoerrhandler noop)
withclientbypass protocolversion (bypassuuids, othermsg) = do withclientbypass protocolversion (bypassuuids, othermsg) = do
(selectnode, closenodes) <- clusterProxySelector clusteruuid (selectnode, closenodes, concurrencyconfig) <-
protocolversion bypassuuids clusterProxySelector clusteruuid
concurrencyconfig <- getConcurrencyConfig protocolversion bypassuuids
proxystate <- liftIO mkProxyState proxystate <- liftIO mkProxyState
let proxyparams = ProxyParams let proxyparams = ProxyParams
{ proxyMethods = mkProxyMethods { proxyMethods = mkProxyMethods
@ -75,7 +75,11 @@ proxyCluster clusteruuid proxydone servermode clientside protoerrhandler = do
proxy proxydone proxyparams othermsg proxy proxydone proxyparams othermsg
(protoerrhandler closenodes) (protoerrhandler closenodes)
clusterProxySelector :: ClusterUUID -> ProtocolVersion -> Bypass -> Annex (ProxySelector, Annex ()) clusterProxySelector
:: ClusterUUID
-> ProtocolVersion
-> Bypass
-> Annex (ProxySelector, Annex (), ConcurrencyConfig)
clusterProxySelector clusteruuid protocolversion (Bypass bypass) = do clusterProxySelector clusteruuid protocolversion (Bypass bypass) = do
nodeuuids <- (fromMaybe S.empty . M.lookup clusteruuid . clusterUUIDs) nodeuuids <- (fromMaybe S.empty . M.lookup clusteruuid . clusterUUIDs)
<$> getClusters <$> getClusters
@ -116,7 +120,8 @@ clusterProxySelector clusteruuid protocolversion (Bypass bypass) = do
-- proxied to the client. -- proxied to the client.
, proxyLOCKCONTENT = const (pure Nothing) , proxyLOCKCONTENT = const (pure Nothing)
} }
return (proxyselector, closenodes) concurrencyconfig <- getConcurrencyConfig
return (proxyselector, closenodes, concurrencyconfig)
where where
-- Nodes of the cluster have remote.name.annex-cluster-node -- Nodes of the cluster have remote.name.annex-cluster-node
-- containing its name. -- containing its name.

View file

@ -30,6 +30,7 @@ import CmdLine.Action (startConcurrency)
import Utility.ThreadScheduler import Utility.ThreadScheduler
import Utility.HumanTime import Utility.HumanTime
import Annex.Proxy import Annex.Proxy
import Annex.Cluster
import qualified P2P.Proxy as Proxy import qualified P2P.Proxy as Proxy
import qualified Types.Remote as Remote import qualified Types.Remote as Remote
@ -233,21 +234,21 @@ withP2PConnections workerpool proxyconnectionpoolsize a = do
Right (Left reason) -> return $ Left $ Right (Left reason) -> return $ Left $
ConnectionFailed $ ConnectionFailed $
fromMaybe "unknown uuid" reason fromMaybe "unknown uuid" reason
Right (Right (Right proxyremote)) -> Right (Right (Right proxyremote)) -> proxyconnection $
openProxyConnectionToRemote workerpool openProxyConnectionToRemote workerpool
(connectionProtocolVersion connparams) (connectionProtocolVersion connparams)
(connectionBypass connparams) bypass proxyremote
proxyremote Right (Right (Left clusteruuid)) -> proxyconnection $
>>= \case openProxyConnectionToCluster workerpool
Right conn -> proxyConnection proxyconnectionpoolsize relv connparams workerpool proxypool conn (connectionProtocolVersion connparams)
Left ex -> return $ Left $ bypass clusteruuid
ConnectionFailed $ show ex Left ex -> return $ Left $
Right (Right (Left clusteruuid)) -> ConnectionFailed $ show ex
undefined -- XXX todo where
{- bypass = P2P.Bypass $ S.fromList $ connectionBypass connparams
openProxyConnectionToCluster clusteruuid proxyconnection openconn = openconn >>= \case
>>= proxyConnection clusteruuid relv connparams workerpool Right conn -> proxyConnection proxyconnectionpoolsize
-} relv connparams workerpool proxypool conn
Left ex -> return $ Left $ Left ex -> return $ Left $
ConnectionFailed $ show ex ConnectionFailed $ show ex
@ -353,16 +354,14 @@ proxyConnection proxyconnectionpoolsize relv connparams workerpool proxypool pro
asyncworker <- async $ asyncworker <- async $
inAnnexWorker' workerpool $ do inAnnexWorker' workerpool $ do
proxystate <- liftIO Proxy.mkProxyState proxystate <- liftIO Proxy.mkProxyState
concurrencyconfig <- Proxy.noConcurrencyConfig
let proxyparams = Proxy.ProxyParams let proxyparams = Proxy.ProxyParams
{ Proxy.proxyMethods = mkProxyMethods { Proxy.proxyMethods = mkProxyMethods
, Proxy.proxyState = proxystate , Proxy.proxyState = proxystate
, Proxy.proxyServerMode = connectionServerMode connparams , Proxy.proxyServerMode = connectionServerMode connparams
, Proxy.proxyClientSide = Proxy.ClientSide proxyfromclientrunst proxyfromclientconn , Proxy.proxyClientSide = Proxy.ClientSide proxyfromclientrunst proxyfromclientconn
, Proxy.proxyUUID = proxyConnectionRemoteUUID proxyconn , Proxy.proxyUUID = proxyConnectionRemoteUUID proxyconn
, Proxy.proxySelector = Proxy.singleProxySelector $ , Proxy.proxySelector = proxyConnectionSelector proxyconn
proxyConnectionRemoteSide proxyconn , Proxy.proxyConcurrencyConfig = proxyConnectionConcurrency proxyconn
, Proxy.proxyConcurrencyConfig = concurrencyconfig
, Proxy.proxyClientProtocolVersion = connectionProtocolVersion connparams , Proxy.proxyClientProtocolVersion = connectionProtocolVersion connparams
} }
let proxy mrequestmessage = case mrequestmessage of let proxy mrequestmessage = case mrequestmessage of
@ -397,9 +396,7 @@ proxyConnection proxyconnectionpoolsize relv connparams workerpool proxypool pro
} }
where where
protoerrhandler cont a = a >>= \case protoerrhandler cont a = a >>= \case
Left _ -> Left _ -> proxyConnectionCloser proxyconn
Proxy.closeRemoteSide $
proxyConnectionRemoteSide proxyconn
Right v -> cont v Right v -> cont v
proxydone = return () proxydone = return ()
@ -407,8 +404,7 @@ proxyConnection proxyconnectionpoolsize relv connparams workerpool proxypool pro
requestcomplete () = return () requestcomplete () = return ()
closeproxyconnection = closeproxyconnection =
void . inAnnexWorker' workerpool . void . inAnnexWorker' workerpool . proxyConnectionCloser
Proxy.closeRemoteSide . proxyConnectionRemoteSide
data Locker = Locker data Locker = Locker
{ lockerThread :: Async () { lockerThread :: Async ()
@ -523,29 +519,56 @@ inAnnexWorker' poolv annexaction = do
data ProxyConnection = ProxyConnection data ProxyConnection = ProxyConnection
{ proxyConnectionRemoteUUID :: UUID { proxyConnectionRemoteUUID :: UUID
, proxyConnectionRemoteSide :: Proxy.RemoteSide , proxyConnectionSelector :: Proxy.ProxySelector
, proxyConnectionCloser :: Annex ()
, proxyConnectionConcurrency :: Proxy.ConcurrencyConfig
, proxyConnectionLastUsed :: POSIXTime , proxyConnectionLastUsed :: POSIXTime
} }
deriving (Show)
instance Show ProxyConnection where
show pc = unwords
[ "ProxyConnection"
, show (proxyConnectionRemoteUUID pc)
, show (proxyConnectionLastUsed pc)
]
openedProxyConnection
:: UUID
-> Proxy.ProxySelector
-> Annex ()
-> Proxy.ConcurrencyConfig
-> IO ProxyConnection
openedProxyConnection u selector closer concurrency = do
now <- getPOSIXTime
return $ ProxyConnection u selector closer concurrency now
openProxyConnectionToRemote openProxyConnectionToRemote
:: AnnexWorkerPool :: AnnexWorkerPool
-> P2P.ProtocolVersion -> P2P.ProtocolVersion
-> [UUID] -> P2P.Bypass
-> Remote -> Remote
-> IO (Either SomeException ProxyConnection) -> IO (Either SomeException ProxyConnection)
openProxyConnectionToRemote workerpool clientmaxversion bypass remote = openProxyConnectionToRemote workerpool clientmaxversion bypass remote =
inAnnexWorker' workerpool (proxyRemoteSide clientmaxversion bypass' remote) >>= \case inAnnexWorker' workerpool $ do
Left ex -> return (Left ex) remoteside <- proxyRemoteSide clientmaxversion bypass remote
Right remoteside -> do concurrencyconfig <- Proxy.noConcurrencyConfig
now <- getPOSIXTime liftIO $ openedProxyConnection (Remote.uuid remote)
return $ Right $ (Proxy.singleProxySelector remoteside)
ProxyConnection (Remote.uuid remote) remoteside now (Proxy.closeRemoteSide remoteside)
where concurrencyconfig
bypass' = P2P.Bypass (S.fromList bypass)
openProxyConnectionToCluster :: ClusterUUID -> IO ProxyConnection openProxyConnectionToCluster
openProxyConnectionToCluster cu = error "XXX" -- TODO :: AnnexWorkerPool
-> P2P.ProtocolVersion
-> P2P.Bypass
-> ClusterUUID
-> IO (Either SomeException ProxyConnection)
openProxyConnectionToCluster workerpool clientmaxversion bypass clusteruuid =
inAnnexWorker' workerpool $ do
(proxyselector, closenodes, concurrencyconfig) <-
clusterProxySelector clusteruuid clientmaxversion bypass
liftIO $ openedProxyConnection (fromClusterUUID clusteruuid)
proxyselector closenodes concurrencyconfig
type ProxyConnectionPool = (Integer, M.Map ProxyConnectionPoolKey [ProxyConnection]) type ProxyConnectionPool = (Integer, M.Map ProxyConnectionPoolKey [ProxyConnection])

View file

@ -28,7 +28,9 @@ Planned schedule of work:
## work notes ## work notes
* Make http server support clusters. * http proxying for a local git remote seems to probably not work
* git-annex testremote cluster
* Support proxying to git remotes using annex+http urls. * Support proxying to git remotes using annex+http urls.
(Current documentation says proxying only works with ssh remotes, (Current documentation says proxying only works with ssh remotes,