1 package CloudStore::API;
7 use base qw(CloudStore::Gearman);
9 use File::Path qw(make_path remove_tree);
11 use Data::Dump qw(dump);
18 $self->{passwd} ||= '/var/lib/extrausers/passwd';
19 $self->{PORT} ||= $ENV{PORT} || die "no PORT in env";
20 $self->{SLICE} ||= $ENV{SLICE} || die "no SLICE in env";
22 $self->{md5} = $self->user_info('md5');
28 my ($self,$login) = @_;
30 my @n = qw/ login passwd uid gid quota comment gecos dir shell expire /;
31 my @p = $login =~ m/^\d+$/ ? getpwuid $login : getpwnam $login;
33 $user->{$_} = shift @p foreach @n;
38 my ( $self, $new_email, $new_passwd, $new_quota ) = @_;
43 open(my $fh, '<', $self->{passwd});
45 my ( $login, $passwd, $uid, $gid, $email, $dir, $shell ) = split(/:/,$_);
46 $max_uid = $uid if $uid > $max_uid;
47 $found = $uid if $email eq $new_email;
53 my $dir = "$self->{SLICE}/$max_uid";
54 warn "# create_user $new_email $new_quota = $max_uid $dir";
55 open(my $fh, '>>', $self->{passwd});
56 print $fh "u$max_uid:$new_passwd:$max_uid:$self->{PORT}:$new_email:$dir:/bin/true\n";
61 chown $max_uid, $self->{PORT}, $dir;
65 # FIXME update quota only on create?
66 $self->gearman_do( 'narada_s1_quota_set' => "$found $new_quota" );
72 my ($path,$opts) = @_;
73 $path =~ s{/[^/]+$}{};
74 make_path $path unless -d $path;
78 my ( $self,$user, $dir ) = @_;
79 $user = $self->user_info($user) unless ref $user eq 'HASH';
81 if ( exists $user->{dir} ) {
82 $path = $user->{dir} . '/' . $dir;
84 die "no dir in ", dump $user;
87 # warn "## user_dir $path";
94 my $path = $self->user_dir( $user => '.log');
95 my $line = join('#',@_);
96 open(my $fh, '>>', $path);
99 warn "## $path $line\n";
100 $user = $self->user_info($user) unless ref $user eq 'HASH';
104 my ( $self, $user ) = @_;
105 $user = $self->user_info($user) unless ref $user eq 'HASH';
106 my $path = $self->user_dir( $user => '.log');
108 open(my $fh, '<', $path);
111 my @v = split(/#/,$_);
112 $sum->{ $v[0] } += $v[1];
113 $sum->{_usage} += $v[1];
115 my ( $usage, $quota ) = split(/ /,
116 $self->gearman_do( 'narada_s1_quota_get' => $user->{uid} )
118 $sum->{_usage} += $usage;
119 $sum->{_quota} = $quota;
120 warn "## usage ",dump($user, $sum), $/;
125 my ( $self, $f_uid,$f_path, $t_uid,$t_path ) = @_;
127 my $f = $self->user_info($f_uid);
128 my $t = $self->user_info($t_uid);
130 my $f_full = "$f->{dir}/$f_path";
131 my $t_full = "$t->{dir}/$t_path";
133 mkbasepath $t_full, { uid => $t->{uid} };
135 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat $f_full;
136 if ( $uid == $f->{uid} ) {
137 warn "# send_file - move $f_uid $f_path to pool\n";
138 chown $self->{md5}->{uid}, $self->{md5}->{gid}, $f_full;
139 chmod oct("0444"), $f_full;
140 $self->append( $f, 'sent', -s $f_full, $t->{uid}, $f_path );
141 } elsif ( $uid == $self->{md5}->{uid} ) {
142 warn "# send_file - shared $f_full\n";
145 $self->delete( $t, $t_path ) if -e $t_full;
147 link $f_full, $t_full;
148 $self->append( $t, 'recv', -s $t_full, $f->{uid}, $t_path );
152 my ( $self, $user, $from, $to ) = @_;
153 $user = $self->user_info($user) unless ref $user eq 'HASH';
155 $self->append( $user, 'rename', $from, $to );
160 my ( $self, $user, $path ) = @_;
161 $user = $self->user_info($user) unless ref $user eq 'HASH';
163 my $deleted_size = 0;
164 my $full_path = "$user->{dir}/$path";
166 if ( -d $full_path ) {
172 my ($uid,$size) = (stat($_))[4,7];
173 warn "## find $uid $size $_\n";
174 if ( $uid == $self->{md5}->{uid} ) {
175 $deleted_size += $size;
179 remove_tree $full_path;
181 $deleted_size += -s $full_path;
185 warn "delete $deleted_size bytes shared\n";
187 $self->append( $user, 'delete', -$deleted_size, $user->{uid}, $path );