44import os
55import pwd , grp
66
7-
8- from tilde .ssh import SSHServer , RunCommandProtocol
9-
107from twisted .internet import defer
118from twisted .internet .error import ProcessTerminated
129
10+ from tilde import models
11+ from tilde .ssh import SSHServer , RunCommandProtocol
12+
1313
1414class ServerManager (object ):
1515 def __init__ (self , reactor , servers ):
@@ -62,16 +62,19 @@ def _openConnection(self, name, config):
6262class ShareUpdater (object ):
6363 CMD_STAT = "/usr/bin/stat"
6464 CMD_TEST = "/usr/bin/test"
65- CMD_MKDIR = "/usr/bin/mkdir"
66- CMD_CHOWN = "/usr/bin/chown"
67- CMD_CHMOD = "/usr/bin/chmod"
65+ CMD_MKDIR = "/bin/mkdir"
66+ CMD_CHOWN = "/bin/chown"
67+ CMD_CHMOD = "/bin/chmod"
68+ CMD_RSYNC = "/usr/bin/rsync"
69+ CMD_MOVE = "/bin/mv"
6870
6971 DEF_MODE = 0700
7072 def __init__ (self , server , cfg ):
7173 self .server = server
7274 self .name = cfg .hostname
7375 self .root = cfg .root
7476 self .archive_root = cfg .archive_root
77+ self .trash_root = cfg .trash_root
7578
7679 def __repr__ (self ):
7780 return "<ShareUpdater for {0}>" .format (self .name )
@@ -84,49 +87,6 @@ def get_real_path(self, homepath, base=None):
8487 realpath = os .path .join (base , shareabs )
8588 return realpath
8689
87-
88- def uid_to_name (self , uid = None ):
89- if uid is None :
90- uid = os .getuid ()
91- return pwd .getpwuid (uid ).pw_name
92-
93- def gid_to_name (self , gid = None ):
94- if gid is None :
95- gid = os .getgid ()
96- return grp .getgrgid (gid ).gr_nam
97-
98- def name_to_uid (self , name ):
99- return pwd .getpwnam (name ).pw_uid
100-
101- def name_to_gid (self , name ):
102- return grp .getgrnam (name ).gr_gid
103-
104- def get_user (self , path ):
105- return self .uid_to_name (os .stat (path ).st_uid )
106-
107- def get_group (self , path ):
108- return self .gid_to_name (os .stat (path ).st_gid )
109-
110- def update (self , home , state ):
111- if home .server_name != state .server_name :
112- if home .server_name == self .server :
113- mlog .debug ("req create" )
114- self .create (home , state )
115- elif state .server_name == self .server :
116- mlog .debug ("req remove" )
117- self .remove (home , state )
118- return
119-
120- if home .server_name != self .server :
121- mlog .debug (u"bad server {0} != {1}"
122- .format (home .server_name , self .server ))
123- return
124-
125- if home .path != state .path :
126- self .move (home , state )
127-
128- self .set_perms (home , state )
129-
13090 def exists (self , path ):
13191 d = defer .Deferred ()
13292 cmd = self .server .runCommand (
@@ -164,6 +124,13 @@ def _failed(reason):
164124 cmd .finished .chainDeferred (d )
165125 return d
166126
127+ def _make_parent (self , path ):
128+ parent = os .path .split (os .path .normpath (path ))[0 ]
129+ return self .server .runCommand (
130+ " " .join ([self .CMD_MKDIR , "-p" , parent ])
131+ ).finished
132+
133+
167134 def create_home (self , home ):
168135 d = defer .Deferred ()
169136 realpath = self .get_real_path (home .path )
@@ -176,16 +143,16 @@ def create_home(self, home):
176143 cmd .extend (["&&" ,
177144 self .CMD_CHOWN ,
178145 "{0}:{1}" .format (
179- home .owner . encode ( "utf-8" ) ,
180- (home .group or u'' ). encode ( "utf-8" )),
146+ home .owner ,
147+ (home .group or '' )),
181148 realpath ])
182149
183150 cmd .extend (["&&" ,
184151 self .CMD_CHMOD ,
185152 str_mod ,
186153 realpath ])
187154
188- cmd = self .server .runCommand (cmd )
155+ cmd = self .server .runCommand (" " . join ( cmd ) )
189156
190157 def _success (reason ):
191158 return True
@@ -198,15 +165,47 @@ def _failed(reason):
198165 cmd .finished .chainDeferred (d )
199166 return d
200167
201- def move (self , home , state ):
202- old = self .get_real_path (state .path )
203- new = self .get_real_path (home .path )
204- mlog .info (u"Moving {0} to {1}" .format (old , new ))
205- parent = os .path .split (new )[0 ]
206- if not os .path .exists (parent ):
207- os .makedirs (parent )
208- shutil .move (old , new )
209- state .path = home .path
168+ def sync (self , fromState , to , home , bwlimit = None ):
169+ if fromState .status == models .HomeState .ACTIVE :
170+ src_base = self .root
171+ else :
172+ src_base = self .archive_root
173+
174+ sourcepath = self .get_real_path (fromState .path , src_base )
175+ to_path = to .get_real_path (home .path )
176+
177+ cmd = [self .CMD_RSYNC , "-rlptgo" ]
178+ if bwlimit :
179+ cmd .append ("--bwlimit={0}" .format (bwlimit ))
180+
181+ dest = ":" .join ([to .name , to_path ])
182+ # Trailing slash on source to prevent copying dir inside itself
183+ cmd .extend ([sourcepath + "/" , dest ])
184+
185+ d = self ._make_parent (to_path )
186+ def _then (* r ):
187+ return self .server .runCommand (" " .join (cmd )).finished
188+ d .addBoth (_then )
189+ return d
190+
191+ def archive (self , homestate , toPath ):
192+ if homestate .status != models .HomeState .ACTIVE :
193+ return defer .fail (Exception ("Home must be active to archive" ))
194+
195+ src = self .get_real_path (homestate .path , self .root )
196+ dst = self .get_real_path (toPath , self .archive_root )
197+ return self ._make_parent (dst ).addCallback (lambda * r : self .move (src , dst ))
198+
199+ def move (self , source , dest ):
200+ args = [self .CMD_MOVE , "-T" , "--backup=t" , source , dest ]
201+ cmd = self .server .runCommand (" " .join (args ))
202+
203+
204+
205+ return cmd .finished
206+
207+
208+
210209
211210 def remove (self , home , state ):
212211 realpath = self .get_real_path (home .path )
@@ -236,24 +235,3 @@ def remove(self, home, state):
236235
237236 state .path = None
238237
239- def set_perms (self , home , state ):
240- realpath = self .get_real_path (home .path )
241- if not os .path .exists (realpath ):
242- self .create (home , state )
243-
244- if home .owner :
245- setuid = home .owner
246- numuid = self .name_to_uid (setuid )
247- else :
248- setuid = None
249- numuid = - 1
250-
251- if home .group :
252- setgid = home .group
253- numgid = self .name_to_gid (setgid )
254- else :
255- setgid = None
256- numgid = - 1
257-
258- if setuid or setuid :
259- os .chown (realpath , numuid , numgid )
0 commit comments