started on git-annex-shell cluster support
Works down to P2P protocol. The question now is, how to handle protocol version negotiation for clusters? Connecting to each node to find their protocol versions and using the lowest would be too expensive with a lot of nodes. So it seems that the cluster needs to pick its own protocol version to use with the client. Then it can either negotiate that same version with the nodes when it comes time to use them, or it can translate between multiple protocol versions. That seems complicated. Thinking it would be ok to refuse to use a node if it is not able to negotiate the same protocol version with it as with the client. That will mean that sometimes need nodes to be upgraded when upgrading the cluster's proxy. But protocol versions rarely change.
This commit is contained in:
parent
c7ad44e4d1
commit
291280ced2
5 changed files with 87 additions and 62 deletions
2
Annex.hs
2
Annex.hs
|
@ -215,7 +215,7 @@ data AnnexState = AnnexState
|
||||||
, urloptions :: Maybe UrlOptions
|
, urloptions :: Maybe UrlOptions
|
||||||
, insmudgecleanfilter :: Bool
|
, insmudgecleanfilter :: Bool
|
||||||
, getvectorclock :: IO CandidateVectorClock
|
, getvectorclock :: IO CandidateVectorClock
|
||||||
, proxyremote :: Maybe (Types.Remote.RemoteA Annex)
|
, proxyremote :: Maybe (Either ClusterUUID (Types.Remote.RemoteA Annex))
|
||||||
}
|
}
|
||||||
|
|
||||||
newAnnexState :: GitConfig -> Git.Repo -> IO AnnexState
|
newAnnexState :: GitConfig -> Git.Repo -> IO AnnexState
|
||||||
|
|
|
@ -21,6 +21,7 @@ import Remote.GCrypt (getGCryptUUID)
|
||||||
import P2P.Protocol (ServerMode(..))
|
import P2P.Protocol (ServerMode(..))
|
||||||
import Git.Types
|
import Git.Types
|
||||||
import Logs.Proxy
|
import Logs.Proxy
|
||||||
|
import Logs.Cluster
|
||||||
import Logs.UUID
|
import Logs.UUID
|
||||||
import Remote
|
import Remote
|
||||||
|
|
||||||
|
@ -193,11 +194,14 @@ checkProxy remoteuuid ouruuid = M.lookup ouruuid <$> getProxies >>= \case
|
||||||
Just proxies ->
|
Just proxies ->
|
||||||
case filter (\p -> proxyRemoteUUID p == remoteuuid) (S.toList proxies) of
|
case filter (\p -> proxyRemoteUUID p == remoteuuid) (S.toList proxies) of
|
||||||
[] -> notconfigured
|
[] -> notconfigured
|
||||||
ps -> do
|
ps -> case mkClusterUUID remoteuuid of
|
||||||
-- This repository may have multiple
|
Just cu -> proxyforcluster cu
|
||||||
-- remotes that access the same repository.
|
Nothing -> proxyfor ps
|
||||||
-- Proxy for the lowest cost one that
|
where
|
||||||
-- is configured to be used as a proxy.
|
-- This repository may have multiple remotes that access the same
|
||||||
|
-- repository. Proxy for the lowest cost one that is configured to
|
||||||
|
-- be used as a proxy.
|
||||||
|
proxyfor ps = do
|
||||||
rs <- concat . byCost <$> remoteList
|
rs <- concat . byCost <$> remoteList
|
||||||
let sameuuid r = uuid r == remoteuuid
|
let sameuuid r = uuid r == remoteuuid
|
||||||
let samename r p = name r == proxyRemoteName p
|
let samename r p = name r == proxyRemoteName p
|
||||||
|
@ -205,9 +209,18 @@ checkProxy remoteuuid ouruuid = M.lookup ouruuid <$> getProxies >>= \case
|
||||||
Nothing -> notconfigured
|
Nothing -> notconfigured
|
||||||
Just r -> do
|
Just r -> do
|
||||||
Annex.changeState $ \st ->
|
Annex.changeState $ \st ->
|
||||||
st { Annex.proxyremote = Just r }
|
st { Annex.proxyremote = Just (Right r) }
|
||||||
return True
|
return True
|
||||||
where
|
|
||||||
|
proxyforcluster cu = do
|
||||||
|
clusters <- getClusters
|
||||||
|
if M.member cu (clusterUUIDs clusters)
|
||||||
|
then do
|
||||||
|
Annex.changeState $ \st ->
|
||||||
|
st { Annex.proxyremote = Just (Left cu) }
|
||||||
|
return True
|
||||||
|
else notconfigured
|
||||||
|
|
||||||
notconfigured = M.lookup remoteuuid <$> uuidDescMap >>= \case
|
notconfigured = M.lookup remoteuuid <$> uuidDescMap >>= \case
|
||||||
Just desc -> giveup $ "not configured to proxy for repository " ++ (fromUUIDDesc desc)
|
Just desc -> giveup $ "not configured to proxy for repository " ++ fromUUIDDesc desc
|
||||||
Nothing -> return False
|
Nothing -> return False
|
||||||
|
|
|
@ -17,6 +17,7 @@ import Annex.UUID
|
||||||
import qualified CmdLine.GitAnnexShell.Checks as Checks
|
import qualified CmdLine.GitAnnexShell.Checks as Checks
|
||||||
import Remote.Helper.Ssh (openP2PShellConnection', closeP2PShellConnection)
|
import Remote.Helper.Ssh (openP2PShellConnection', closeP2PShellConnection)
|
||||||
import Logs.Location
|
import Logs.Location
|
||||||
|
import Logs.Cluster
|
||||||
import qualified Remote
|
import qualified Remote
|
||||||
|
|
||||||
import System.IO.Error
|
import System.IO.Error
|
||||||
|
@ -40,8 +41,12 @@ start theiruuid = startingCustomOutput (ActionItemOther Nothing) $ do
|
||||||
(False, True) -> P2P.ServeAppendOnly
|
(False, True) -> P2P.ServeAppendOnly
|
||||||
(False, False) -> P2P.ServeReadWrite
|
(False, False) -> P2P.ServeReadWrite
|
||||||
Annex.getState Annex.proxyremote >>= \case
|
Annex.getState Annex.proxyremote >>= \case
|
||||||
Nothing -> performLocal theiruuid servermode
|
Nothing ->
|
||||||
Just r -> performProxy theiruuid servermode r
|
performLocal theiruuid servermode
|
||||||
|
Just (Right r) ->
|
||||||
|
performProxy theiruuid servermode r
|
||||||
|
Just (Left clusteruuid) ->
|
||||||
|
performProxyCluster theiruuid clusteruuid servermode
|
||||||
|
|
||||||
performLocal :: UUID -> P2P.ServerMode -> CommandPerform
|
performLocal :: UUID -> P2P.ServerMode -> CommandPerform
|
||||||
performLocal theiruuid servermode = do
|
performLocal theiruuid servermode = do
|
||||||
|
@ -51,35 +56,45 @@ performLocal theiruuid servermode = do
|
||||||
P2P.net $ P2P.sendMessage (P2P.AUTH_SUCCESS myuuid)
|
P2P.net $ P2P.sendMessage (P2P.AUTH_SUCCESS myuuid)
|
||||||
P2P.serveAuthed servermode myuuid
|
P2P.serveAuthed servermode myuuid
|
||||||
runst <- liftIO $ mkRunState $ Serving theiruuid Nothing
|
runst <- liftIO $ mkRunState $ Serving theiruuid Nothing
|
||||||
runFullProto runst conn server >>= \case
|
p2pErrHandler (const p2pDone) (runFullProto runst conn server)
|
||||||
Right () -> done
|
|
||||||
-- Avoid displaying an error when the client hung up on us.
|
|
||||||
Left (ProtoFailureIOError e) | isEOFError e -> done
|
|
||||||
Left e -> giveup (describeProtoFailure e)
|
|
||||||
where
|
|
||||||
done = next $ return True
|
|
||||||
|
|
||||||
performProxy :: UUID -> P2P.ServerMode -> Remote -> CommandPerform
|
performProxy :: UUID -> P2P.ServerMode -> Remote -> CommandPerform
|
||||||
performProxy clientuuid servermode remote = do
|
performProxy clientuuid servermode remote = do
|
||||||
clientrunst <- liftIO (mkRunState $ Serving clientuuid Nothing)
|
clientside <- proxyClientSide clientuuid
|
||||||
let clientside = ClientSide clientrunst (stdioP2PConnection Nothing)
|
getClientProtocolVersion (Remote.uuid remote) clientside
|
||||||
getClientProtocolVersion remote clientside
|
|
||||||
(withclientversion clientside)
|
(withclientversion clientside)
|
||||||
protoerrhandler
|
p2pErrHandler
|
||||||
where
|
where
|
||||||
withclientversion clientside (Just (clientmaxversion, othermsg)) = do
|
withclientversion clientside (Just (clientmaxversion, othermsg)) = do
|
||||||
remoteside <- connectremote clientmaxversion
|
remoteside <- proxySshRemoteSide clientmaxversion remote
|
||||||
proxy done proxymethods servermode clientside remoteside
|
proxy p2pDone proxymethods servermode clientside remoteside
|
||||||
othermsg protoerrhandler
|
othermsg p2pErrHandler
|
||||||
withclientversion _ Nothing = done
|
withclientversion _ Nothing = p2pDone
|
||||||
|
|
||||||
proxymethods = ProxyMethods
|
proxymethods = ProxyMethods
|
||||||
{ removedContent = \u k -> logChange k u InfoMissing
|
{ removedContent = \u k -> logChange k u InfoMissing
|
||||||
, addedContent = \u k -> logChange k u InfoPresent
|
, addedContent = \u k -> logChange k u InfoPresent
|
||||||
}
|
}
|
||||||
|
|
||||||
-- FIXME: Support special remotes.
|
performProxyCluster :: UUID -> ClusterUUID -> P2P.ServerMode -> CommandPerform
|
||||||
connectremote clientmaxversion = mkRemoteSide (Remote.uuid remote) $
|
performProxyCluster clientuuid clusteruuid servermode = do
|
||||||
|
clientside <- proxyClientSide clientuuid
|
||||||
|
getClientProtocolVersion (fromClusterUUID clusteruuid) clientside
|
||||||
|
(withclientversion clientside)
|
||||||
|
p2pErrHandler
|
||||||
|
where
|
||||||
|
withclientversion clientside (Just (clientmaxversion, othermsg)) = do
|
||||||
|
giveup "TODO"
|
||||||
|
withclientversion _ Nothing = p2pDone
|
||||||
|
|
||||||
|
proxyClientSide :: UUID -> Annex ClientSide
|
||||||
|
proxyClientSide clientuuid = do
|
||||||
|
clientrunst <- liftIO (mkRunState $ Serving clientuuid Nothing)
|
||||||
|
return $ ClientSide clientrunst (stdioP2PConnection Nothing)
|
||||||
|
|
||||||
|
-- FIXME: Support special remotes.
|
||||||
|
proxySshRemoteSide :: P2P.ProtocolVersion -> Remote -> Annex RemoteSide
|
||||||
|
proxySshRemoteSide clientmaxversion remote = mkRemoteSide (Remote.uuid remote) $
|
||||||
openP2PShellConnection' remote clientmaxversion >>= \case
|
openP2PShellConnection' remote clientmaxversion >>= \case
|
||||||
Just conn@(P2P.IO.OpenConnection (remoterunst, remoteconn, _)) ->
|
Just conn@(P2P.IO.OpenConnection (remoterunst, remoteconn, _)) ->
|
||||||
return $ Just
|
return $ Just
|
||||||
|
@ -89,10 +104,12 @@ performProxy clientuuid servermode remote = do
|
||||||
)
|
)
|
||||||
_ -> return Nothing
|
_ -> return Nothing
|
||||||
|
|
||||||
protoerrhandler cont a = a >>= \case
|
p2pErrHandler :: (a -> CommandPerform) -> Annex (Either ProtoFailure a) -> CommandPerform
|
||||||
|
p2pErrHandler cont a = a >>= \case
|
||||||
-- Avoid displaying an error when the client hung up on us.
|
-- Avoid displaying an error when the client hung up on us.
|
||||||
Left (ProtoFailureIOError e) | isEOFError e -> done
|
Left (ProtoFailureIOError e) | isEOFError e -> p2pDone
|
||||||
Left e -> giveup (describeProtoFailure e)
|
Left e -> giveup (describeProtoFailure e)
|
||||||
Right v -> cont v
|
Right v -> cont v
|
||||||
|
|
||||||
done = next $ return True
|
p2pDone :: CommandPerform
|
||||||
|
p2pDone = next $ return True
|
||||||
|
|
|
@ -8,14 +8,10 @@
|
||||||
{-# LANGUAGE OverloadedStrings, TupleSections #-}
|
{-# LANGUAGE OverloadedStrings, TupleSections #-}
|
||||||
|
|
||||||
module Logs.Cluster (
|
module Logs.Cluster (
|
||||||
ClusterUUID,
|
module Types.Cluster,
|
||||||
isClusterUUID,
|
|
||||||
fromClusterUUID,
|
|
||||||
ClusterNodeUUID(..),
|
|
||||||
getClusters,
|
getClusters,
|
||||||
loadClusters,
|
loadClusters,
|
||||||
recordCluster,
|
recordCluster,
|
||||||
Clusters(..)
|
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import qualified Annex
|
import qualified Annex
|
||||||
|
|
13
P2P/Proxy.hs
13
P2P/Proxy.hs
|
@ -12,7 +12,6 @@ module P2P.Proxy where
|
||||||
import Annex.Common
|
import Annex.Common
|
||||||
import P2P.Protocol
|
import P2P.Protocol
|
||||||
import P2P.IO
|
import P2P.IO
|
||||||
import qualified Remote
|
|
||||||
import Utility.Metered (nullMeterUpdate)
|
import Utility.Metered (nullMeterUpdate)
|
||||||
|
|
||||||
import Control.Concurrent.STM
|
import Control.Concurrent.STM
|
||||||
|
@ -60,20 +59,20 @@ type ProtoErrorHandled r =
|
||||||
- brought up yet.
|
- brought up yet.
|
||||||
-}
|
-}
|
||||||
getClientProtocolVersion
|
getClientProtocolVersion
|
||||||
:: Remote
|
:: UUID
|
||||||
-> ClientSide
|
-> ClientSide
|
||||||
-> (Maybe (ProtocolVersion, Maybe Message) -> Annex r)
|
-> (Maybe (ProtocolVersion, Maybe Message) -> Annex r)
|
||||||
-> ProtoErrorHandled r
|
-> ProtoErrorHandled r
|
||||||
getClientProtocolVersion remote (ClientSide clientrunst clientconn) cont protoerrhandler =
|
getClientProtocolVersion remoteuuid (ClientSide clientrunst clientconn) cont protoerrhandler =
|
||||||
protoerrhandler cont $ client $ getClientProtocolVersion' remote
|
protoerrhandler cont $ client $ getClientProtocolVersion' remoteuuid
|
||||||
where
|
where
|
||||||
client = liftIO . runNetProto clientrunst clientconn
|
client = liftIO . runNetProto clientrunst clientconn
|
||||||
|
|
||||||
getClientProtocolVersion'
|
getClientProtocolVersion'
|
||||||
:: Remote
|
:: UUID
|
||||||
-> Proto (Maybe (ProtocolVersion, Maybe Message))
|
-> Proto (Maybe (ProtocolVersion, Maybe Message))
|
||||||
getClientProtocolVersion' remote = do
|
getClientProtocolVersion' remoteuuid = do
|
||||||
net $ sendMessage (AUTH_SUCCESS (Remote.uuid remote))
|
net $ sendMessage (AUTH_SUCCESS remoteuuid)
|
||||||
msg <- net receiveMessage
|
msg <- net receiveMessage
|
||||||
case msg of
|
case msg of
|
||||||
Nothing -> return Nothing
|
Nothing -> return Nothing
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue