This commit is contained in:
Yvan Watchman 2019-12-25 16:37:43 +00:00 committed by GitHub
commit 4dbdc5e722
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 642 additions and 649 deletions

9
.gitignore vendored
View File

@ -1,3 +1,6 @@
urbackup_server_web_api_wrapper.egg-info/*
dist/urbackup-server-web-api-wrapper-*.zip
urbackup_api/__pycache__/*
urbackup_server_web_api_wrapper.egg-info/*
dist/urbackup-server-web-api-wrapper-*.zip
urbackup_api/__pycache__/*
test.py
*.pyc
__pycache__

View File

@ -1,2 +1,2 @@
include README.md
include README.md
include LICENSE.txt

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
requests
urllib3

View File

@ -1,2 +1,2 @@
[metadata]
[metadata]
description-file = README.md

158
setup.py
View File

@ -1,79 +1,79 @@
# Always prefer setuptools over distutils
from setuptools import setup, find_packages
# To use a consistent encoding
from codecs import open
from os import path
here = path.abspath(path.dirname(__file__))
# Get the long description from the README file
with open(path.join(here, 'README.md'), encoding='utf-8') as f:
long_description = f.read()
setup(
name='urbackup-server-web-api-wrapper',
# Versions should comply with PEP440. For a discussion on single-sourcing
# the version across setup.py and the project code, see
# https://packaging.python.org/en/latest/single_source_version.html
version='0.6',
description='Python wrapper to access and control an UrBackup server',
long_description=long_description,
# The project's main homepage.
url='https://github.com/uroni/urbackup-server-python-web-api-wrapper',
# Author details
author='Martin Raiber',
author_email='martin@urbackup.org',
# Choose your license
license='Apache License 2.0',
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers
classifiers=[
# How mature is this project? Common values are
# 3 - Alpha
# 4 - Beta
# 5 - Production/Stable
'Development Status :: 3 - Alpha',
# Indicate who your project is intended for
'Intended Audience :: Developers',
# Pick your license as you wish (should match "license" above)
'License :: OSI Approved :: Apache Software License',
# Specify the Python versions you support here. In particular, ensure
# that you indicate whether you support Python 2, Python 3 or both.
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
],
# What does your project relate to?
keywords='urbackup web api client',
# You can just specify the packages manually here if your project is
# simple. Or you can use find_packages().
packages=find_packages(exclude=['contrib', 'docs', 'tests']),
# Alternatively, if you want to distribute just a my_module.py, uncomment
# this:
# py_modules=["my_module"],
# List run-time dependencies here. These will be installed by pip when
# your project is installed. For an analysis of "install_requires" vs pip's
# requirements files see:
# https://packaging.python.org/en/latest/requirements.html
install_requires=[],
# List additional groups of dependencies here (e.g. development
# dependencies). You can install these using the following syntax,
# for example:
# $ pip install -e .[dev,test]
extras_require={
'dev': [],
'test': [],
}
)
# Always prefer setuptools over distutils
from setuptools import setup, find_packages
# To use a consistent encoding
from codecs import open
from os import path
here = path.abspath(path.dirname(__file__))
# Get the long description from the README file
with open(path.join(here, 'README.md'), encoding='utf-8') as f:
long_description = f.read()
setup(
name='urbackup-server-web-api-wrapper',
# Versions should comply with PEP440. For a discussion on single-sourcing
# the version across setup.py and the project code, see
# https://packaging.python.org/en/latest/single_source_version.html
version='0.7',
description='Python wrapper to access and control an UrBackup server',
long_description=long_description,
# The project's main homepage.
url='https://github.com/uroni/urbackup-server-python-web-api-wrapper',
# Author details
author='Martin Raiber',
author_email='martin@urbackup.org',
# Choose your license
license='Apache License 2.0',
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers
classifiers=[
# How mature is this project? Common values are
# 3 - Alpha
# 4 - Beta
# 5 - Production/Stable
'Development Status :: 3 - Alpha',
# Indicate who your project is intended for
'Intended Audience :: Developers',
# Pick your license as you wish (should match "license" above)
'License :: OSI Approved :: Apache Software License',
# Specify the Python versions you support here. In particular, ensure
# that you indicate whether you support Python 2, Python 3 or both.
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
],
# What does your project relate to?
keywords='urbackup web api client',
# You can just specify the packages manually here if your project is
# simple. Or you can use find_packages().
packages=find_packages(exclude=['contrib', 'docs', 'tests']),
# Alternatively, if you want to distribute just a my_module.py, uncomment
# this:
# py_modules=["my_module"],
# List run-time dependencies here. These will be installed by pip when
# your project is installed. For an analysis of "install_requires" vs pip's
# requirements files see:
# https://packaging.python.org/en/latest/requirements.html
install_requires=[],
# List additional groups of dependencies here (e.g. development
# dependencies). You can install these using the following syntax,
# for example:
# $ pip install -e .[dev,test]
extras_require={
'dev': [],
'test': [],
}
)

View File

@ -1,12 +1,12 @@
import urbackup_api
server = urbackup_api.urbackup_server("http://127.0.0.1:55414/x", "admin", "foo")
for action in server.get_actions():
a = action["action"]
if a ==server.action_full_file or a==server.action_resumed_full_file:
print("Running full file backup: "+action["name"])
print("Stopping...")
import urbackup_api
server = urbackup_api.urbackup_server("http://127.0.0.1:55414/x", "admin", "foo")
for action in server.get_actions():
a = action["action"]
if a ==server.action_full_file or a==server.action_resumed_full_file:
print("Running full file backup: "+action["name"])
print("Stopping...")
server.stop_action(action)

View File

@ -1,72 +1,72 @@
import urbackup_api
import datetime
import time
server = urbackup_api.urbackup_server("http://127.0.0.1:55414/x", "admin", "foo")
for extra_client in server.get_extra_clients():
server.remove_extra_client(extra_client["id"])
computernames = """2.2.2.2
3.3.3.3"""
for line in computernames:
server.add_extra_client(line)
clients = server.get_status()
usage = server.get_usage()
if len(clients) != len(usage):
print("Failed to retreive usage or status information. Length of both lists is different.")
# Uncomment to format time differently
# locale.setlocale(locale.LC_TIME, "german")
diff_time = 3*24*60*60 # 3 days
for client in clients:
if client["lastbackup"]=="-" or client["lastbackup"] < time.time() - diff_time:
if client["lastbackup"]=="-" or client["lastbackup"]==0:
lastbackup = "Never"
else:
lastbackup = datetime.datetime.fromtimestamp(client["lastbackup"]).strftime("%x %X")
print("Last file backup at {lastbackup} of client {clientname} is older than three days".format(
lastbackup=lastbackup, clientname=client["name"] ) )
#if server.start_incr_file_backup("Johnwin7test-PC2"):
# print("Started file backup successfully")
#else:
# print("Failed to start file backup")
if not server.get_livelog():
print("Failed to get livelog contents"
settings = server.get_client_settings("Johnwin7test-PC2")
for key in settings:
print("{key}={value}".format(key=key, value=settings[key]))
print("Authkey: "+server.get_client_authkey("Johnwin7test-PC2"))
if server.change_client_setting("Johnwin7test-PC2", "max_image_incr", "40"):
print("Changed setting successfully")
else:
print("Failed to change setting")
settings = server.get_global_settings()
for key in settings:
print("Global: {key}={value}".format(key=key, value=settings[key]))
if server.set_global_setting("max_image_incr", "40"):
print("Changed global setting successfully")
else:
print("Failed to change global setting")
import urbackup_api
import datetime
import time
server = urbackup_api.urbackup_server("http://127.0.0.1:55414/x", "admin", "foo")
for extra_client in server.get_extra_clients():
server.remove_extra_client(extra_client["id"])
computernames = """2.2.2.2
3.3.3.3"""
for line in computernames:
server.add_extra_client(line)
clients = server.get_status()
usage = server.get_usage()
if len(clients) != len(usage):
print("Failed to retreive usage or status information. Length of both lists is different.")
# Uncomment to format time differently
# locale.setlocale(locale.LC_TIME, "german")
diff_time = 3*24*60*60 # 3 days
for client in clients:
if client["lastbackup"]=="-" or client["lastbackup"] < time.time() - diff_time:
if client["lastbackup"]=="-" or client["lastbackup"]==0:
lastbackup = "Never"
else:
lastbackup = datetime.datetime.fromtimestamp(client["lastbackup"]).strftime("%x %X")
print("Last file backup at {lastbackup} of client {clientname} is older than three days".format(
lastbackup=lastbackup, clientname=client["name"] ) )
#if server.start_incr_file_backup("Johnwin7test-PC2"):
# print("Started file backup successfully")
#else:
# print("Failed to start file backup")
if not server.get_livelog():
print("Failed to get livelog contents"
settings = server.get_client_settings("Johnwin7test-PC2")
for key in settings:
print("{key}={value}".format(key=key, value=settings[key]))
print("Authkey: "+server.get_client_authkey("Johnwin7test-PC2"))
if server.change_client_setting("Johnwin7test-PC2", "max_image_incr", "40"):
print("Changed setting successfully")
else:
print("Failed to change setting")
settings = server.get_global_settings()
for key in settings:
print("Global: {key}={value}".format(key=key, value=settings[key]))
if server.set_global_setting("max_image_incr", "40"):
print("Changed global setting successfully")
else:
print("Failed to change global setting")

View File

@ -1,482 +1,470 @@
import http.client as http
import json
from urllib.parse import urlparse
from urllib.parse import urlencode
from base64 import b64encode
import hashlib
import socket
import shutil
import os
import binascii
import logging
logger = logging.getLogger('urbackup-server-python-api-wrapper')
class urbackup_server:
def __init__(self, server_url, server_username, server_password):
self._server_url=server_url
self._server_username=server_username
self._server_password=server_password
#If you have basic authentication via .htpasswd
server_basic_username = ''
server_basic_password = ''
_session=""
_logged_in = False
_lastlogid = 0
def _get_response(self, action, params, method="POST"):
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json; charset=UTF-8'
}
if('server_basic_username' in globals() and len(self.server_basic_username)>0):
userAndPass = b64encode(str.encode(self.server_basic_username+":"+self.server_basic_password)).decode("ascii")
headers['Authorization'] = 'Basic %s' % userAndPass
curr_server_url=self._server_url+"?"+urlencode({"a": action});
if(len(self._session)>0):
params["ses"]=self._session
if method==None:
method = 'POST'
if method=="GET":
curr_server_url+="&"+urlencode(params);
target = urlparse(curr_server_url)
if method=='POST':
body = urlencode(params)
else:
body = ''
http_timeout = 10*60;
if(target.scheme=='http'):
h = http.HTTPConnection(target.hostname, target.port, timeout=http_timeout)
elif(target.scheme=='https'):
h = http.HTTPSConnection(target.hostname, target.port, timeout=http_timeout)
else:
logger.error('Unkown scheme: '+target.scheme)
raise Exception("Unkown scheme: "+target.scheme)
h.request(
method,
target.path+"?"+target.query,
body,
headers)
return h.getresponse();
def _get_json(self, action, params = {}):
tries = 50
while tries>0:
response = self._get_response(action, params)
if(response.status == 200):
break
tries=tries-1
if(tries==0):
return None
else:
logger.error("API call failed. Retrying...")
data = response.read();
response.close()
return json.loads(data.decode("utf-8","ignore"))
def _download_file(self, action, outputfn, params):
response = self.get_response(action, params, "GET");
if(response.status!=200):
return False
with open(outputfn, 'wb') as outputf:
shutil.copyfileobj(response, outputf)
return True
def _md5(self, s):
return hashlib.md5(s.encode()).hexdigest()
def login(self):
if( not self._logged_in):
logger.debug("Trying anonymous login...")
login = self._get_json("login", {});
if(not login or 'success' not in login or not login['success']):
logger.debug("Logging in...")
salt = self._get_json("salt", {"username": self._server_username})
if( not salt or not ('ses' in salt) ):
logger.warning('Username does not exist')
return False
self._session = salt["ses"];
if( 'salt' in salt ):
password_md5_bin = hashlib.md5((salt["salt"]+self._server_password).encode()).digest()
password_md5 = binascii.hexlify(password_md5_bin).decode()
if "pbkdf2_rounds" in salt:
pbkdf2_rounds = int(salt["pbkdf2_rounds"])
if pbkdf2_rounds>0:
password_md5 = binascii.hexlify(hashlib.pbkdf2_hmac('sha256', password_md5_bin,
salt["salt"].encode(), pbkdf2_rounds)).decode()
password_md5 = self._md5(salt["rnd"]+password_md5)
login = self._get_json("login", { "username": self._server_username,
"password": password_md5 })
if(not login or 'success' not in login or not login['success']):
logger.warning('Error during login. Password wrong?')
return False
else:
self._logged_in=True
return True
else:
return False
else:
self._logged_in=True
self._session = login["session"];
return True
else:
return True
def get_client_status(self, clientname):
if not self.login():
return None
status = self._get_json("status")
if not status:
return None
if not "status" in status:
return None
for client in status["status"]:
if (client["name"] == clientname):
return client;
logger.warning("Could not find client status. No permission?")
return None
def download_installer(self, installer_fn, new_clientname):
if not self.login():
return False
new_client = self._get_json("add_client", { "clientname": new_clientname})
if "already_exists" in new_client:
status = self.get_client_status(new_clientname)
if status == None:
return False
return self._download_file("download_client", installer_fn,
{"clientid": status["id"] })
if not "new_authkey" in new_client:
return False
return self._download_file("download_client", installer_fn,
{"clientid": new_client["new_clientid"],
"authkey": new_client["new_authkey"]
})
def add_client(self, clientname):
if not self.login():
return None
ret = self._get_json("add_client", { "clientname": clientname})
if ret==None or "already_exists" in ret:
return None
return ret
def get_global_settings(self):
if not self.login():
return None
settings = self._get_json("settings", {"sa": "general"} )
if not settings or not "settings" in settings:
return None
return settings["settings"]
def set_global_setting(self, key, new_value):
if not self.login():
return False
settings = self._get_json("settings", {"sa": "general"} )
if not settings or not "settings" in settings:
return False
settings["settings"][key] = new_value
settings["settings"]["sa"] = "general_save"
ret = self._get_json("settings", settings["settings"])
return ret!=None and "saved_ok" in ret
def get_client_settings(self, clientname):
if not self.login():
return None
client = self.get_client_status(clientname)
if client == None:
return None
clientid = client["id"];
settings = self._get_json("settings", {"sa": "clientsettings",
"t_clientid": clientid})
if not settings or not "settings" in settings:
return None
return settings["settings"]
def change_client_setting(self, clientname, key, new_value):
if not self.login():
return False
client = self.get_client_status(clientname)
if client == None:
return False
clientid = client["id"];
settings = self._get_json("settings", {"sa": "clientsettings",
"t_clientid": clientid})
if not settings or not "settings" in settings:
return False
settings["settings"][key] = new_value
settings["settings"]["overwrite"] = "true"
settings["settings"]["sa"] = "clientsettings_save"
settings["settings"]["t_clientid"] = clientid
ret = self._get_json("settings", settings["settings"])
return ret!=None and "saved_ok" in ret
def get_client_authkey(self, clientname):
if not self.login():
return None
settings = self.get_client_settings(clientname)
if settings:
return settings["internet_authkey"]
return None
def get_server_identity(self):
if not self.login():
return None
status = self._get_json("status")
if not status:
return None
if not "server_identity" in status:
return None
return status["server_identity"]
def get_status(self):
if not self.login():
return None
status = self._get_json("status")
if not status:
return None
if not "status" in status:
return None
return status["status"]
def get_livelog(self, clientid = 0):
if not self.login():
return None
log = self._get_json("livelog", {"clientid": clientid, "lastid": self._lastlogid})
if not log:
return None
if not "logdata" in log:
return None
self._lastlogid = log["logdata"][-1]['id']
return log["logdata"]
def get_usage(self):
if not self.login():
return None
usage = self._get_json("usage")
if not usage:
return None
if not "usage" in usage:
return None
return usage["usage"]
def get_extra_clients(self):
if not self.login():
return None
status = self._get_json("status")
if not status:
return None
if not "extra_clients" in status:
return None
return status["extra_clients"]
def _start_backup(self, clientname, backup_type):
client_info = self.get_client_status(clientname)
if not client_info:
return False
ret = self._get_json("start_backup", {"start_client": client_info["id"],
"start_type": backup_type } );
if ( ret==None
or "result" not in ret
or len(ret["result"])!=1
or "start_ok" not in ret["result"][0]
or not ret["result"][0]["start_ok"] ):
return False
return True
def start_incr_file_backup(self, clientname):
return self._start_backup(clientname, 'incr_file');
def start_full_file_backup(self, clientname):
return self._start_backup(clientname, 'full_file');
def start_incr_image_backup(self, clientname):
return self._start_backup(clientname, 'incr_image');
def start_full_image_backup(self, clientname):
return self._start_backup(clientname, 'full_image');
def add_extra_client(self, addr):
if not self.login():
return None
ret = self._get_json("status", {"hostname": addr } );
if not ret:
return False
return True
def remove_extra_client(self, ecid):
if not self.login():
return None
ret = self._get_json("status", {"hostname": ecid,
"remove": "true" } );
if not ret:
return False
return True
action_incr_file = 1
action_full_file = 2
action_incr_image = 3
action_full_image = 4
action_resumed_incr_file = 5
action_resumed_full_file = 6
action_file_restore = 8
action_image_restore = 9
action_client_update = 10
action_check_db_integrity = 11
action_backup_db = 12
action_recalc_stats = 13
def get_actions(self):
if not self.login():
return None
ret = self._get_json("progress")
if not ret or not "progress" in ret:
return None
return ret["progress"]
def stop_action(self, action):
if (not "clientid" in action
or not "id" in action):
return False
if not self.login():
return None
ret = self._get_json("progress",
{"stop_clientid": action["clientid"],
"stop_id": action["id"]})
if not ret or not "progress" in ret:
return False
return True
import json
import requests
from base64 import b64encode
import hashlib
import socket
import shutil
import os
import binascii
import logging
logger = logging.getLogger('urbackup-server-python-api-wrapper')
"""Backwards compatible imports"""
try:
import urllib
except ImportError:
import urllib.parse
class urbackup_server:
#If you have basic authentication via .htpasswd
server_basic_username = ''
server_basic_password = ''
action_incr_file = 1
action_full_file = 2
action_incr_image = 3
action_full_image = 4
action_resumed_incr_file = 5
action_resumed_full_file = 6
action_file_restore = 8
action_image_restore = 9
action_client_update = 10
action_check_db_integrity = 11
action_backup_db = 12
action_recalc_stats = 13
_session = ''
_logged_in = False
_lastlogid = 0
def __init__(self, url, username, password):
self._server_url = url
self._server_username = username
self._server_password = password
def _get_response(self, action, params, method='POST'):
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json; charset=UTF-8'
}
if('server_basic_username' in globals() and len(self.server_basic_username)>0):
userAndPass = b64encode(
str.encode('%s:%s' % (self.server_basic_username, self.server_basic_password))
).decode('ascii')
headers['Authorization'] = 'Basic %s' % userAndPass
try:
action_url = '%s?%s' % (self._server_url, urllib.urlencode({'a': action}))
except AttributeError:
action_url = '%s?%s' % (self._server_url, urllib.parse.urlencode({'a': action}))
if(len(self._session)>0):
params['ses'] = self._session
if method == 'POST':
r = requests.post(
action_url,
data=params
)
elif method == 'GET':
r = requests.get(
action_url,
params=params
)
else:
raise Exception('Request with method \'%s\' has not been implemented yet.' % method)
return r
def _get_json(self, action, params = {}):
tries = 50
while tries>0:
response = self._get_response(action, params)
if(response.status_code == 200):
break
tries -= 1
if tries <= 0:
return None
else:
logger.error('API call failed. Retrying...')
return response.json()
def _download_file(self, action, outputfn, params):
req = self._get_response(action, params, 'GET');
if req.status_code != 200:
return False
with open(outputfn, 'wb') as stream:
for chunk in req.iter_content(chunk_size=128):
stream.write(chunk)
return True
def _md5(self, s):
return hashlib.md5(s.encode()).hexdigest()
def login(self):
if not self._logged_in:
logger.debug('Trying anonymous login...')
login = self._get_json('login', {});
if not login or 'success' not in login or not login['success'] :
logger.debug('Logging in...')
salt = self._get_json('salt', {'username': self._server_username})
if not salt or not ('ses' in salt):
logger.warning('Username does not exist')
return False
self._session = salt['ses'];
if 'salt' in salt:
password_md5_bin = hashlib.md5((salt['salt']+self._server_password).encode()).digest()
password_md5 = binascii.hexlify(password_md5_bin).decode()
if 'pbkdf2_rounds' in salt:
pbkdf2_rounds = int(salt['pbkdf2_rounds'])
if pbkdf2_rounds>0:
password_md5 = binascii.hexlify(hashlib.pbkdf2_hmac('sha256', password_md5_bin,
salt['salt'].encode(), pbkdf2_rounds)).decode()
password_md5 = self._md5(salt['rnd']+password_md5)
login = self._get_json('login', {
'username': self._server_username,
'password': password_md5 })
if not login or 'success' not in login or not login['success']:
logger.warning('Error during login. Password wrong?')
return False
else:
self._logged_in = True
return True
else:
return False
else:
self._logged_in = True
self._session = login['session'];
return True
else:
return True
def get_client_status(self, clientname):
if not self.login():
return None
status = self._get_json('status')
if not status:
return None
if not 'status' in status:
return None
for client in status['status']:
if client['name'] == clientname:
return client;
logger.warning('Could not find client status. No permission?')
return None
def download_installer(self, installer_fn, new_clientname, os='linux'):
"""Download installer for os, defaults to linux"""
if not os.lower() in ['linux', 'osx', 'mac', 'windows']:
raise Exception('OS not supported')
if not self.login():
return False
new_client = self._get_json('add_client', {'clientname': new_clientname})
if 'already_exists' in new_client:
status = self.get_client_status(new_clientname)
if status == None:
return False
return self._download_file('download_client', installer_fn, {'clientid': status['id'] })
if not 'new_authkey' in new_client:
return False
return self._download_file('download_client', installer_fn,
{
'clientid': new_client['new_clientid'],
'authkey': new_client['new_authkey'],
'os': os
})
def add_client(self, clientname):
if not self.login():
return None
ret = self._get_json('add_client', { 'clientname': clientname})
if ret==None or 'already_exists' in ret:
return None
return ret
def get_global_settings(self):
if not self.login():
return None
settings = self._get_json('settings', {'sa': 'general'} )
if not settings or not 'settings' in settings:
return None
return settings['settings']
def set_global_setting(self, key, new_value):
if not self.login():
return False
settings = self._get_json('settings', {'sa': 'general'} )
if not settings or not 'settings' in settings:
return False
settings['settings'][key] = new_value
settings['settings']['sa'] = 'general_save'
ret = self._get_json('settings', settings['settings'])
return ret != None and 'saved_ok' in ret
def get_client_settings(self, clientname):
if not self.login():
return None
client = self.get_client_status(clientname)
if client == None:
return None
clientid = client['id'];
settings = self._get_json('settings', {'sa': 'clientsettings',
't_clientid': clientid})
if not settings or not 'settings' in settings:
return None
return settings['settings']
def change_client_setting(self, clientname, key, new_value):
if not self.login():
return False
client = self.get_client_status(clientname)
if client == None:
return False
clientid = client['id'];
settings = self._get_json('settings', {'sa': 'clientsettings',
't_clientid': clientid})
if not settings or not 'settings' in settings:
return False
settings['settings'][key] = new_value
settings['settings']['overwrite'] = 'true'
settings['settings']['sa'] = 'clientsettings_save'
settings['settings']['t_clientid'] = clientid
ret = self._get_json('settings', settings['settings'])
return ret != None and 'saved_ok' in ret
def get_client_authkey(self, clientname):
if not self.login():
return None
settings = self.get_client_settings(clientname)
if settings:
return settings['internet_authkey']
return None
def get_server_identity(self):
if not self.login():
return None
status = self._get_json('status')
if not status:
return None
if not 'server_identity' in status:
return None
return status['server_identity']
def get_status(self):
if not self.login():
return None
status = self._get_json('status')
if not status:
return None
if not 'status' in status:
return None
return status['status']
def get_livelog(self, clientid = 0):
if not self.login():
return None
log = self._get_json('livelog', {'clientid': clientid, 'lastid': self._lastlogid})
if not log:
return None
if not 'logdata' in log:
return None
self._lastlogid = log['logdata'][-1]['id']
return log['logdata']
def get_usage(self):
if not self.login():
return None
usage = self._get_json('usage')
if not usage:
return None
if not 'usage' in usage:
return None
return usage['usage']
def get_extra_clients(self):
if not self.login():
return None
status = self._get_json('status')
if not status:
return None
if not 'extra_clients' in status:
return None
return status['extra_clients']
def _start_backup(self, clientname, backup_type):
client_info = self.get_client_status(clientname)
if not client_info:
return False
ret = self._get_json('start_backup', {'start_client': client_info['id'],
'start_type': backup_type } );
if ( ret == None
or 'result' not in ret
or len(ret['result'])!=1
or 'start_ok' not in ret['result'][0]
or not ret['result'][0]['start_ok']):
return False
return True
def start_incr_file_backup(self, clientname):
return self._start_backup(clientname, 'incr_file');
def start_full_file_backup(self, clientname):
return self._start_backup(clientname, 'full_file');
def start_incr_image_backup(self, clientname):
return self._start_backup(clientname, 'incr_image');
def start_full_image_backup(self, clientname):
return self._start_backup(clientname, 'full_image');
def add_extra_client(self, addr):
if not self.login():
return None
ret = self._get_json('status', {'hostname': addr } )
if not ret:
return False
return True
def remove_extra_client(self, ecid):
if not self.login():
return None
ret = self._get_json('status', {'hostname': ecid,
'remove': 'true' })
if not ret:
return False
return True
def get_actions(self):
if not self.login():
return None
ret = self._get_json('progress')
if not ret or not 'progress' in ret:
return None
return ret['progress']
def stop_action(self, action):
if (not 'clientid' in action
or not 'id' in action):
return False
if not self.login():
return None
ret = self._get_json('progress',
{'stop_clientid': action['clientid'],
'stop_id': action['id']})
if not ret or not 'progress' in ret:
return False
return True