From 6c30fe108b327ca287ce2f71840cfdf3d46736d5 Mon Sep 17 00:00:00 2001 From: Marko Oldenburg Date: Sun, 21 Mar 2021 14:58:08 +0100 Subject: [PATCH] add first Code for LastKeppBackups Fn --- FHEM/98_backupToStorage.pm | 4 +- lib/FHEM/backupToStorage.pm | 173 ++++++++++++++++++++++++++++++++---- 2 files changed, 161 insertions(+), 16 deletions(-) diff --git a/FHEM/98_backupToStorage.pm b/FHEM/98_backupToStorage.pm index e6ab8e2..5ed10e0 100644 --- a/FHEM/98_backupToStorage.pm +++ b/FHEM/98_backupToStorage.pm @@ -58,6 +58,7 @@ sub backupToStorage_Initialize { . 'bTS_Path ' . 'bTS_Proto:http ' . 'bTS_Type:Nextcloud,SynologyFileStation ' + . 'bTS_KeepLastBackups:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 ' . 'disable:1 ' . 'disabledForIntervals'; $hash->{parseParams} = 1; @@ -143,6 +144,7 @@ sub backupToStorage_Initialize {
  • bTS_User - remote User für den Login
  • bTS_Path - remote Path wohin das uploadfile soll. z.B. Nextcloud </FHEM-Backup>
  • bTS_Type - Storage Type, default ist Nextcloud
  • +
  • bTS_Type - Storage Type, default ist Nextcloud

  • @@ -179,7 +181,7 @@ sub backupToStorage_Initialize { ], "release_status": "devepolment", "license": "GPL_2", - "version": "v1.2.3", + "version": "v1.3.1", "author": [ "Marko Oldenburg " ], diff --git a/lib/FHEM/backupToStorage.pm b/lib/FHEM/backupToStorage.pm index 9ffc08f..bf21819 100644 --- a/lib/FHEM/backupToStorage.pm +++ b/lib/FHEM/backupToStorage.pm @@ -2,7 +2,7 @@ # # Developed with Kate # -# (c) 2020 Copyright: Marko Oldenburg (fhemsupport@cooltux.net) +# (c) 2020-2021 Copyright: Marko Oldenburg (fhemsupport@cooltux.net) # All rights reserved # # Special thanks goes to: @@ -150,10 +150,10 @@ sub Define { return $@ unless ( FHEM::Meta::SetInternals($hash) ); use version 0.60; our $VERSION = FHEM::Meta::Get( $hash, 'version' ); - return qq{only one backupToStorage instance allowed} + return q{only one backupToStorage instance allowed} if ( devspec2array('TYPE=backupToStorage') > 1 ) ; # es wird geprüft ob bereits eine Instanz unseres Modules existiert,wenn ja wird abgebrochen - return qq{too few parameters: define backupToStorage} + return q{too few parameters: define backupToStorage} if ( scalar( @{$aArg} ) != 2 ); my $name = shift @$aArg; @@ -170,7 +170,7 @@ sub Undef { my $hash = shift; my $name = shift; - Log3( $name, 3, qq{backupToStorage ($name) - delete device $name} ); + Log3( $name, 3, q{qbackupToStorage ($name) - delete device $name} ); return; } @@ -296,24 +296,28 @@ sub Set { // return qq{set "$name" needs at least one argument}; if ( lc $cmd eq 'addpassword' ) { - return qq{please set Attribut bTS_User first} + return q{please set Attribut bTS_User first} if ( AttrVal( $name, 'bTS_User', 'none' ) eq 'none' ); - return qq{usage: "$cmd" } if ( scalar( @{$aArg} ) != 1 ); + return qq{usage: "$cmd" } + if ( scalar( @{$aArg} ) != 1 ); StorePassword( $hash, $name, $aArg->[0] ); } elsif ( lc $cmd eq 'deletepassword' ) { - return qq{usage: $cmd} if ( scalar( @{$aArg} ) != 0 ); + return qq{usage: $cmd} + if ( scalar( @{$aArg} ) != 0 ); DeletePassword($hash); } elsif ( lc $cmd eq 'active' ) { - return qq{usage: $cmd} if ( scalar( @{$aArg} ) != 0 ); + return qq{usage: $cmd} + if ( scalar( @{$aArg} ) != 0 ); readingsSingleUpdate( $hash, 'state', 'ready', 1 ); } elsif ( lc $cmd eq 'inactive' ) { - return qq{usage: $cmd} if ( scalar( @{$aArg} ) != 0 ); + return qq{usage: $cmd} + if ( scalar( @{$aArg} ) != 0 ); readingsSingleUpdate( $hash, 'state', $cmd, 1 ); } @@ -399,8 +403,8 @@ sub PushToStorage { Log3( $name, 4, qq{backupToStorage ($name) - push to storage function} ); - return - if ( ReadingsAge($name,'fhemBackupFile',1) > 180 ); + return Log3( $name, 4, qq{backupToStorage ($name) - fhemBackupFile Reading to old} ) + if ( ReadingsAge($name,'fhemBackupFile',1) > 3600 ); Log3( $name, 4, qq{backupToStorage ($name) - after readings age return} ); @@ -445,7 +449,70 @@ sub PushToStorage { } Log3( $name, 4, - qq{backupToStorage ($name) - execute command asynchronously (PID="$pid")} + qq{backupToStorage ($name) - execute command asynchronously (PID="$pid"}) + ); + + $hash->{".fhem"}{subprocess} = $subprocess; + + InternalTimer( gettimeofday() + 1, + "FHEM::backupToStorage::PollChild", $hash ); + } + + Log3( $hash, 4, + qq{backupToStorage ($name) - control passed back to main loop.} ); + + return; +} + +sub KeepLastN { + my $hash = shift; + + my $name = $hash->{NAME}; + + Log3( $name, 4, qq{backupToStorage ($name) - Keep Last N at Storage function} ); + + + if ( $hash->{STORAGETYPE} eq 'SynologyFileStation' ) { + + + } + else { + require "SubProcess.pm"; + my $subprocess = SubProcess->new( { onRun => \&CleanUp } ); + + my $backupFile = ReadingsVal( $name, 'fhemBackupFile', 'none' ); + + my @fileNameAtStorage_array = split( '/', $backupFile ); + my $fileNameAtStorage = $fileNameAtStorage_array[$#fileNameAtStorage_array]; + + $subprocess->{curl} = qx(which curl); + chomp($subprocess->{curl}); + $subprocess->{type} = $hash->{STORAGETYPE}; + $subprocess->{host} = AttrVal( $name, 'bTS_Host', '' ); + $subprocess->{user} = AttrVal( $name, 'bTS_User', '' ); + $subprocess->{pass} = ReadPassword( $hash, $name ); + $subprocess->{path} = AttrVal( $name, 'bTS_Path', '' ); + $subprocess->{fileNameAtStorage} = $fileNameAtStorage; + $subprocess->{proto} = AttrVal( $name, 'bTS_Proto', 'https' ); + $subprocess->{loglevel} = AttrVal( $name, 'verbose', 3 ); + $subprocess->{keeplastn} = AttrVal( $name, 'bTS_KeepLastBackups', 5 ); + + my $pid = $subprocess->run(); + + readingsSingleUpdate( $hash, 'state', ' clean up pass last N in progress', 1 ); + + if ( !defined($pid) ) { + Log3( $name, 1, + qq{backupToStorage ($name) - Cannot execute command asynchronously} ); + + CleanSubprocess($hash); + readingsSingleUpdate( $hash, 'state', + 'Cannot execute command asynchronously', 1 ); + return undef; + } + + Log3( $name, 4, + qq{backupToStorage ($name) - execute command asynchronously (PID="$pid"}) ); $hash->{".fhem"}{subprocess} = $subprocess; @@ -540,7 +607,7 @@ sub ExecuteNCupload { my $subprocess = shift; my $command = $subprocess->{curl}; - $command .= ' -k -u '; + $command .= ' -k -X PUT -u '; $command .= $subprocess->{user} . ':' . $subprocess->{pass}; $command .= ' -T ' . $subprocess->{backupfile}; $command .= ' "' . $subprocess->{proto} . '://'; @@ -555,6 +622,81 @@ sub ExecuteNCupload { return ExecuteCommand($command); } +sub CleanUp { + my $subprocess = shift; + my $response = {}; + + if ( $subprocess->{type} eq 'Nextcloud' ) { + my ($returnString,$returnCode) = ExecuteCleanUp($subprocess); + + print 'backupToStorage File Upload - FileUpload Nextcloud, returnCode: ' + . $returnCode + . ' , returnString: ' + . $returnString . "\n" + if ( $subprocess->{loglevel} > 4 ); + + + if ( $returnString =~ /100\s\s?[0-9].*\s100\s\s?[0-9].*/m + and $returnString =~ /\s\s(.*)<\/o:hint>/m ) { + $response->{ncUpload} = $1; + } + elsif ( $returnString =~ /100\s\s?[0-9].*\s100\s\s?[0-9].*/m ) { + $response->{ncUpload} = 'upload successfully'; + } + elsif ( $returnString =~ /(curl:\s.*)/ ){ + $response->{ncUpload} = $1; + } + else { + $response->{ncUpload} = 'unknown error'; + } + } + + my $json = eval { encode_json($response) }; + if ($@) { + print 'backupToStorage File Upload backupToStorage - JSON error: $@' + . "\n"; + $json = '{"jsonerror":"$@"}'; + } + + $subprocess->writeToParent($json); + + return; +} + +sub ExecuteNCfetchFileList { + my $subprocess = shift; + + my $command = $subprocess->{curl}; + $command .= ' -k -X PROPFIND -u '; + $command .= $subprocess->{user} . ':' . $subprocess->{pass}; + $command .= ' "' . $subprocess->{proto} . '://'; + $command .= $subprocess->{host}; + $command .= '/remote.php/dav/files/'; + $command .= $subprocess->{user}; + $command .= $subprocess->{path}; + $command .= '" --data \'\''; + + return ExecuteCommand($command); +} + +sub ExecuteNCremoveFile { + my $subprocess = shift; + + my $command = $subprocess->{curl}; + $command .= ' -k -X DELETE -u '; + $command .= $subprocess->{user} . ':' . $subprocess->{pass}; + $command .= ' "' . $subprocess->{proto} . '://'; + $command .= $subprocess->{host}; + $command .= '/remote.php/dav/files/'; + $command .= $subprocess->{user}; + $command .= $subprocess->{path}; + $command .= '/'; + $command .= $subprocess->{fileNameAtStorage}; + $command .= '"'; + + return ExecuteCommand($command); +} + sub ExecuteCommand { my $command = join q{ }, @_; return ( $_ = qx{$command 2>&1}, $? >> 8 ); @@ -598,9 +740,10 @@ sub StorePassword { my $err = setKeyValue( $index, $enc_pwd ); DoTrigger( $name, 'password add' ); - return qq{error while saving the password - $err} if ( defined($err) ); + return qq{error while saving the password - $err} + if ( defined($err) ); - return qq{password successfully saved}; + return q{password successfully saved}; } sub ReadPassword {