Source code for pyhandle.client.batchhandleclient

'''
This class provides methods to create batch file that contains different operations on Handle.
The batch file is executed by the hdl-genericbatch (hdl-genericbatch <batchfile>).

Author Sofiane Bendoukha (DKRZ), 2017.
'''
from __future__ import absolute_import

import logging
import os
from os.path import expanduser

from pyhandle.batchhsexceptions import BatchFileExistsException
from pyhandle.pyhandleclient import HandleClient
from pyhandle.clientcredentials import PIDClientCredentials

from .. import util

LOGGER = logging.getLogger(__name__)
LOGGER.addHandler(util.NullHandler())

class BatchHandleClient(HandleClient):
    '''The BatchHandleClient class'''

    HANDLE_CLIENT = 'batch'
    HOME_DIRECTORY = expanduser("~")
    _default_batch_file_path = HOME_DIRECTORY + '/handle_batch'

[docs] def __init__(self, **args): ''' Initialize the batch client and set the path for the batch file. :param credentials: Optional. As json file in form {"user":"user", "password":"password"} :param args: Optional. This includes different parameters concerning the batch file, such as the PATH. ''' LOGGER.debug('\n' + 60 * '*' + '\nInstantiation of BatchHandleClient\n' + 60 * '*') super(BatchHandleClient, self).__init__() self.__all_args = args self.__batch_file_path = args['batch_file_path'] if self.__batch_file_path is None: self.__batch_file_path = self._default_batch_file_path
[docs] def create_batch_file(self, overwrite=False): ''' Creates a batch file in a directory specified by the user or in the default directory (./pyhandle/batch/handle_batch). :param overwrite: Optional. If set to True, the existing batch file will be overwritten. Defaults to False. :raises: :exc:`~pyhandle.batchhsexceptions.BatchFileExistsException` Only if overwrite is not set or set to False. ''' LOGGER.debug('BatchHandleClient') batch_file_path = self.get_batch_file_path() if overwrite: batch_file = os.fdopen(os.open(batch_file_path, os.O_CREAT | os.O_WRONLY), "w") batch_file.seek(0) batch_file.truncate() else: try: batch_file = os.fdopen(os.open(batch_file_path, os.O_CREAT | os.O_WRONLY | os.O_EXCL), "w") batch_file.close() except Exception as exc: if exc.args[0] == 17: msg = 'Could not create batch file, already exists' LOGGER.error(msg + ', as it already exists.') raise BatchFileExistsException(file=self.get_batch_file_path(), msg=msg)
[docs] def register_handle_batch(self, handle, location, hdl_admin_index, admin_handle, perm): ''' This method creates a simple Handle record including a Handle value to define the administrator of the Handle and the value for the location (URL).. Operation name is 'CREATE'. The first line is composed of the following: CREATE + space + handle_name. :param handle: The full name of the handle to be registered (prefix and suffix) :param location: The URL of the data entity to be referenced :param hdl_admin_index: Unique index number :param admin_handle: Administrator of the Handle :param perm: permissions :raises: :exc:`~pyhandle.batchhsexceptions.BatchFileExistsException`. ''' LOGGER.debug("Creating a handle (batch)") if self.check_if_file_exists(self.get_batch_file_path()): with open(self.get_batch_file_path(), 'a') as bfile: bfile.write('\nCREATE ' + handle + '\n100 HS_ADMIN 86400 1110 ADMIN ' + str(hdl_admin_index) + ':' + perm + ':' + admin_handle) with open(self.get_batch_file_path(), 'a') as bfile: bfile.write('\n\nADD ' + handle + '\n1 URL 86400 1110 UTF8 ' + location) else: msg = 'does not exists' raise BatchFileExistsException(file=self.get_batch_file_path(), msg=msg)
[docs] def delete_handle(self, handle): ''' This method deletes an existing Handle and its records. Operation name 'DELETE'. :param handle: Handle name to be deleted :raises: :exc:`~pyhandle.batchhsexceptions.BatchFileExistsException`. ''' LOGGER.debug("Deleting a handle (batch)") if self.check_if_file_exists(self.get_batch_file_path()): with open(self.get_batch_file_path(), 'a') as bfile: bfile.write('\nDELETE ' + handle) else: msg = 'does not exists' raise BatchFileExistsException(file=self.get_batch_file_path(), msg=msg)
[docs] def modify_handle_value(self, handle, **kvpairs): ''' This method changes Handle values for an existing Handle. Operation name 'MODIFY' :param handle: Handle whose record is to be modified :param kvpairs: Contains the unique index number, Handle value type and the value data :raises: :exc:`~pyhandle.batchhsexceptions.BatchFileExistsException`. ''' LOGGER.debug("Modifying a value of handle (batch)") if kvpairs: self.type = kvpairs['type'] self.index = kvpairs['index'] self.data = kvpairs['data'] if self.check_if_file_exists(self.get_batch_file_path()): with open(self.get_batch_file_path(), 'a') as bfile: bfile.write('\nMODIFY ' + handle + '\n' + str(self.index) + ' ' + self.type + ' 86400 1110 UTF8 ' + self.data) else: msg = 'does not exists' raise BatchFileExistsException(file=self.get_batch_file_path(), msg=msg)
[docs] def add_handle_value(self, handle, **kvpairs): ''' The method adds new handle values to an existing handle. Operation name 'ADD'. :param handle: The handle where the new value will be added :param kvpairs: Contains the unique index number, Handle value type and the value data :raises: :exc:`~pyhandle.batchhsexceptions.BatchFileExistsException`. ''' LOGGER.debug("Add handle value") if kvpairs: self.type = kvpairs['type'] self.index = kvpairs['index'] self.data = kvpairs['data'] if self.check_if_file_exists(self.get_batch_file_path()): with open(self.get_batch_file_path(), 'a') as bfile: bfile.write('\nADD ' + handle + '\n' + str(self.index) + ' ' + self.type + ' 86400 1110 UTF8 ' + self.data) else: msg = 'does not exists' raise BatchFileExistsException(file=self.get_batch_file_path(), msg=msg)
[docs] def delete_handle_value(self, handle, value_index): ''' This method removes one or more handle values from an existing handle. Operation name 'REMOVE'. :param handle: Handle from whose record the entry should be deleted. :param value_index: The index of the value :raises: :exc:`~pyhandle.batchhsexceptions.BatchFileExistsException`. ''' LOGGER.debug("Delete handle value") if self.check_if_file_exists(self.get_batch_file_path()): if len(value_index) == 1: with open(self.get_batch_file_path(), 'a') as bfile: bfile.write('\nREMOVE ' + str(value_index[0]) + ':' + handle) else: with open(self.get_batch_file_path(), 'a') as bfile: for key in range(len(value_index)): bfile.write('\nREMOVE ' + str(value_index[key]) + ':' + handle) else: msg = 'does not exists' raise BatchFileExistsException(file=self.get_batch_file_path(), msg=msg)
[docs] def authenticate_seckey(self, user, password): ''' Secret key authentication. Operation name 'AUTHENTICATE'. :param user: This must be a handle value reference in the format "index:prefix/suffix". :param password: This is the password stored as secret key in the actual Handle value the username points to. :param credentials: Optional. When credentials are :raises: :exc:`~pyhandle.batchhsexceptions.BatchFileExistsException`. ''' LOGGER.debug("Authenticate with SECKEY") if self.check_if_file_exists(self.get_batch_file_path()): with open(self.get_batch_file_path(), 'a') as bfile: bfile.write('\nAUTHENTICATE SECKEY:' + user + '\n' + password) else: msg = 'does not exists' raise BatchFileExistsException(file=self.get_batch_file_path(), msg=msg)
[docs] def authenticate_pubkey(self, user, priv_key_path, passphrase=None): ''' Private key authentication. Operation name 'AUTHENTICATE'. :param user: admin_index:admin_handle :param pubkey_path: private_key_file_path :param passphrase: If your private key was created and encrypted by passphrase :raises: :exc:`~pyhandle.batchhsexceptions.BatchFileExistsException`. ''' LOGGER.debug("Authenticate with PUBKEY") if self.check_if_file_exists(self.get_batch_file_path()): if passphrase: with open(self.get_batch_file_path(), 'w+') as bfile: bfile.write('AUTHENTICATE PUBKEY:' + user + '\n' + priv_key_path + '|' + passphrase) else: with open(self.get_batch_file_path(), 'w+') as bfile: bfile.write('AUTHENTICATE PUBKEY:' + user + '\n' + priv_key_path) else: msg = 'does not exists' raise BatchFileExistsException(file=self.get_batch_file_path(), msg=msg)
[docs] def authenticate_with_credentials(self, credentials, auth_type): ''' Set the credentials for seckey and pubkey authentication. :param credentials: A credentials object, see separate class PIDClientCredentials. :param auth_type: Set authentication type to 'seckey' (username:password) or to pubkey (privatekey | passphrase). ''' if isinstance(credentials, PIDClientCredentials): self.credentials = credentials.get_all_args() else: self.credentials = credentials self.username = credentials.get_username() self.password = credentials.get_password() self.private_key = credentials.get_path_to_private_key() self.passphrase = credentials.get_key_passphrase() if auth_type == "seckey": self.authenticate_seckey(self.username, self.password) if auth_type == "pubkey": self.authenticate_pubkey(self.username, self.private_key, passphrase=self.passphrase)
[docs] def get_all_args(self): return self.__all_args
[docs] def get_batch_file_path(self): return self.__batch_file_path
[docs] def check_if_file_exists(self, file_path): if os.path.isfile(file_path): return True return False