How to install R1soft Backup Manage Agent on openSUSE

I’ve been having some fun getting the R1soft Backup Manager agent installed on some openSuse servers and so decided to write a blog post on some tips.

First of all you’ll need to download the agent package and install the RPM packages using the command:

rpm -i *.rpm

And you’ll want to get the backup manager’s key using:

serverbackup-setup --get-key [Manager_URL]


You’ll need to install the kernel source package. Use this command:

zypper install kernel-source

You may be getting the following error when trying to run the command “r1soft-setup –get-module”.

Cannot find the kernel-source package for your kernel

And if you enter the command “uname -r” and compare that with the version of the linux headers stored under /usr/src you’ll notice that the versions are different.
This can be resolved be running the following commands:

zypper refresh
zypper update kernel-default kernel-default-base kernel-firmware

That should bring the installed kernel up-to-date with the installed kernel source.

Now all you need to do is run the following command and reboot. You should be all set!

r1soft-setup --get-module


Share Sessions between Google Cloud Endpoints and webapp2

There are some cases where you want to be able to use the Google Cloud Endpoints feature on App Engine but you would also like to be able to access your session data that is managed by webapp2 backed by either memcache or the NDB datastore. Well you can! And here’s how.


You’ll need to import the following modules in your API script. Note that I’m assuming that you’re using NDB backed sessions just like me. If you’re using session_memcache instead of session_ndb this won’t work.

I’m also using werkzeug because it makes it easier to work with the cookie data.

from webapp2_extras import sessions_ndb
import webapp2_extras
import werkzeug
import hashlib
import hmac

Helper Methods

Here are 2 helper methods. One verifies the cookie signature to make sure it’s not been tampered with. You want to make sure that COOKIE_SECRET_KEY is set to the value of secret_key under webapp2_extras.sessions from your webapp2 config.

def compare_hashes(a, b):
    """Checks if two hash strings are identical.

    The intention is to make the running time be less dependant on the size of
    the string.

    :param a:
        String 1.
    :param b:
        String 2.
        True if both strings are equal, False otherwise.
    if len(a) != len(b):
        return False

    result = 0
    for x, y in zip(a, b):
        result |= ord(x) ^ ord(y)

    return result == 0

This is what does all the magic.

def get_current_session(request_state):
    cookies = werkzeug.http.parse_cookie(request_state.headers.get('Cookie'))
    sess_cookie = cookies.get('mc_session')
    parts = sess_cookie.split('|')
    if len(parts) != 3:
        logging.error('Cookie does not have 3 parts')
        return False

    signature =, digestmod=hashlib.sha1)
    sig_hex = signature.hexdigest()
    if compare_hashes(sig_hex, parts[2]):
        logging.error('Cookie signature mismatch!')
        return False

    cookie_data = webapp2_extras.json.b64decode(parts[0])
    return sessions_ndb.Session.get_by_sid(cookie_data['_sid'])

Now in your API method you would simply add the following line:

session = get_current_session(self.request_state)

Now session will contain all your session data. You can for example do session.get(‘mystuff’).

Happy coding!