from baculak8s.io.packet_definitions import *
from baculak8s.plugins.plugin import *
-CONNECTION_ERROR_TEMPLATE = "Error connecting to the chosen Data Source. %s."
+CONNECTION_ERROR_TEMPLATE = "Error connecting to the chosen Data Source. {error}."
HOST_NOT_FOUND_CONNECTION_ERROR = "404 Not found. Name or service not known"
HOST_TIMEOUT_ERROR = "Host connection timeout. Maximum retries exceeded"
AUTH_FAILED_CONNECTION_ERROR = "Authentication Failed"
def __get_connection_error_message(self, error_code):
if error_code == ERROR_HOST_NOT_FOUND:
- return CONNECTION_ERROR_TEMPLATE % HOST_NOT_FOUND_CONNECTION_ERROR
+ return CONNECTION_ERROR_TEMPLATE.format(error=HOST_NOT_FOUND_CONNECTION_ERROR)
elif error_code == ERROR_HOST_TIMEOUT:
- return CONNECTION_ERROR_TEMPLATE % HOST_TIMEOUT_ERROR
+ return CONNECTION_ERROR_TEMPLATE.format(error=HOST_TIMEOUT_ERROR)
elif error_code == ERROR_AUTH_FAILED:
- return CONNECTION_ERROR_TEMPLATE % AUTH_FAILED_CONNECTION_ERROR
+ return CONNECTION_ERROR_TEMPLATE.format(error=AUTH_FAILED_CONNECTION_ERROR)
elif error_code == ERROR_SSL_FAILED:
- return CONNECTION_ERROR_TEMPLATE % SSL_ERROR
+ return CONNECTION_ERROR_TEMPLATE.format(error=SSL_ERROR)
elif error_code == ERROR_CONNECTION_REFUSED:
- return CONNECTION_ERROR_TEMPLATE % CONNECTION_REFUSED_TEMPLATE
+ return CONNECTION_ERROR_TEMPLATE.format(error=CONNECTION_REFUSED_TEMPLATE)
else:
- return CONNECTION_ERROR_TEMPLATE % UNEXPECTED_CONNECTION_ERROR
+ return CONNECTION_ERROR_TEMPLATE.format(error=UNEXPECTED_CONNECTION_ERROR)
def send_eod(self):
packet_header = EOD_PACKET + b"\n"
bytes_content = packet_content.encode()
packet_length = str(len(bytes_content)).zfill(6)
- packet_header = "%s%s\n" % (status, packet_length)
+ packet_header = "{}{}\n".format(status, packet_length)
sys.stdout.buffer.write(packet_header.encode())
sys.stdout.buffer.write(bytes_content)
FNAME_WITHOUT_FSOURCE_ERROR = "Invalid FNAME packet. It should have information about the Files Source."
XATTR_ERROR_TEMPLATE = "Error while transferring files extended attributes to the chosen Data Source" \
- "\nFile: %s\nBucket: %s.\n"
+ "\nFile: {}\nBucket: {}.\n"
ACL_ERROR_TEMPLATE = "Error while transferring files access control list to the chosen Data Source" \
- "\nFile: %s\nBucket: %s.\n"
+ "\nFile: {}\nBucket: {}.\n"
FILE_ERROR_TEMPLATE = "Error while transferring file content to the chosen Data Source" \
- "\n\tFile: %s\n\tNamespace: %s\n\tdetails: %s"
+ "\n\tFile: {}\n\tNamespace: {}\n\tdetails: {}"
BUCKET_ERROR_TEMPLATE = "Error while creating a Bucket on the chosen Data Source" \
- "Bucket: %s.\n"
+ "Bucket: {}.\n"
COMMA_SEPARATOR_NOT_SUPPORTED = "Comma separator not supported yet."
header = self.read_line()
if not header:
raise ValueError("Packet Header not found")
- logging.debug('io.read_data: ' + str(header))
+ logging.debug('io.read_data: {}'.format(header))
if header == EOD_PACKET:
Log.save_received_eod(header)
return None
import baculak8s
PLUGIN_WORKING = os.getenv("PLUGIN_WORKING", "/opt/bacula/working/kubernetes")
-PRE_JOB_LOG_NAME_TEMPLATE = "pre_job_%s.log"
-LOG_NAME_TEMPLATE = "%s_%s_%s.log"
+PRE_JOB_LOG_NAME_TEMPLATE = "pre_job_{}.log"
+LOG_NAME_TEMPLATE = "{pid}_{job_id}_{job_name}.log"
class LogConfig(object):
os.makedirs(PLUGIN_WORKING)
# The Log File starts with a "Pre Job" name
- file_name = PRE_JOB_LOG_NAME_TEMPLATE % os.getpid()
+ file_name = PRE_JOB_LOG_NAME_TEMPLATE.format(os.getpid())
file_name = os.path.join(PLUGIN_WORKING, file_name)
logging.basicConfig(filename=file_name, level=logging.DEBUG, filemode='w+', format='%(levelname)s:[%(pathname)s:%(lineno)d in %(funcName)s] %(message)s')
@staticmethod
def _create(job_info):
pid = os.getpid()
- old_name = PRE_JOB_LOG_NAME_TEMPLATE % pid
- new_name = LOG_NAME_TEMPLATE % (pid, job_info["jobid"], job_info["name"])
+ old_name = PRE_JOB_LOG_NAME_TEMPLATE.format(pid)
+ new_name = LOG_NAME_TEMPLATE.format(pid=pid, job_id=job_info["jobid"], job_name=job_info["name"])
old_name = os.path.join(PLUGIN_WORKING, old_name)
new_name = os.path.join(PLUGIN_WORKING, new_name)
if os.path.isfile(old_name):
@staticmethod
def _delete_pre_job_log():
pid = os.getpid()
- pre_job_log_file = PRE_JOB_LOG_NAME_TEMPLATE % pid
+ pre_job_log_file = PRE_JOB_LOG_NAME_TEMPLATE.format(pid)
pre_job_log_file = os.path.join(PLUGIN_WORKING, pre_job_log_file)
if os.path.isfile(pre_job_log_file):
os.remove(pre_job_log_file)
@staticmethod
def save_received_packet(packet_header, packet_content):
- message = "Received Packet\n%s\n%s\n" % (packet_header.decode(), packet_content)
+ message = "Received Packet\n{}\n{}\n".format(packet_header.decode(), packet_content)
logging.debug(message)
@staticmethod
@staticmethod
def save_sent_packet(packet_header, packet_content):
- message = "Sent Packet\n%s%s" % (packet_header, packet_content)
+ message = "Sent Packet\n{}{}".format(packet_header, packet_content)
logging.debug(message)
@staticmethod
def save_exit_code(exit_code):
- message = "Backend finished with Exit Code: %s" % exit_code
+ message = "Backend finished with Exit Code: {}".format(exit_code)
logging.debug(message)
@staticmethod
from baculak8s.plugins.k8sbackend.baculaannotations import BaculaAnnotationsClass
from baculak8s.util.respbody import parse_json_descr
-PATTERN_NOT_FOUND = "No matches found for pattern %s"
+PATTERN_NOT_FOUND = "No matches found for pattern {}"
NO_PV_FOUND = "No required Persistent Volumes found at the cluster"
NO_SC_FOUND = "No required Storage Classes found at the cluster"
NO_NS_FOUND = "No required Namespaces found at the cluster"
# Assures that all patterns got at least one match
for pattern in patterns:
if pattern not in matches:
- error_msg = PATTERN_NOT_FOUND % pattern
+ error_msg = PATTERN_NOT_FOUND.format(pattern)
self._handle_error(error_msg)
error_msg = RESTORE_RES_ERR.format(parse_json_descr(response))
self._handle_error(error_msg)
else:
- error_msg = FILE_ERROR_TEMPLATE % (file_info.name, file_info.namespace, response['error'])
+ error_msg = FILE_ERROR_TEMPLATE.format(file_info.name, file_info.namespace, response['error'])
self._handle_error(error_msg)
else:
if file_info.size != 0 or file_info.objtype == K8SObjType.K8SOBJ_PVCDATA:
if objtype is not None:
if objtype == K8SObjType.K8SOBJ_NAMESPACE:
# namespace
- return '/%s/%s/%s/%s.%s' % (defaultk8spath, K8SObjType.pathdict[K8SObjType.K8SOBJ_NAMESPACE],
+ return '/{}/{}/{}/{}.{}'.format(defaultk8spath, K8SObjType.pathdict[K8SObjType.K8SOBJ_NAMESPACE],
nsname, name, defaultk8sext)
if objtype == K8SObjType.K8SOBJ_PVOLUME:
# persistent volume
- return '/%s/%s/%s.%s' % (defaultk8spath, K8SObjType.pathdict[K8SObjType.K8SOBJ_PVOLUME],
+ return '/{}/{}/{}.{}'.format(defaultk8spath, K8SObjType.pathdict[K8SObjType.K8SOBJ_PVOLUME],
name, defaultk8sext)
if objtype == K8SObjType.K8SOBJ_STORAGECLASS:
# storage class
- return '/%s/%s/%s.%s' % (defaultk8spath, K8SObjType.pathdict[K8SObjType.K8SOBJ_STORAGECLASS],
+ return '/{}/{}/{}.{}'.format(defaultk8spath, K8SObjType.pathdict[K8SObjType.K8SOBJ_STORAGECLASS],
name, defaultk8sext)
if objtype == K8SObjType.K8SOBJ_PVCDATA:
# PVC Data tar archive here
- return '/%s/%s/%s/%s/%s.%s' % (defaultk8spath, K8SObjType.pathdict[K8SObjType.K8SOBJ_NAMESPACE],
+ return '/{}/{}/{}/{}/{}.{}'.format(defaultk8spath, K8SObjType.pathdict[K8SObjType.K8SOBJ_NAMESPACE],
nsname, K8SObjType.pathdict[K8SObjType.K8SOBJ_PVCDATA],
name, defaultk8sarchext)
# other objects
- return '/%s/%s/%s/%s/%s.%s' % (defaultk8spath, K8SObjType.pathdict[K8SObjType.K8SOBJ_NAMESPACE],
+ return '/{}/{}/{}/{}/{}.{}'.format(defaultk8spath, K8SObjType.pathdict[K8SObjType.K8SOBJ_NAMESPACE],
nsname, K8SObjType.pathdict[objtype], name, defaultk8sext)
return None
# handle namespaced objects
objtype.update({'namespace': fnames[2]})
filename = fnames[3]
- if filename.endswith('.%s' % defaultk8sext):
+ if filename.endswith('.{}'.format(defaultk8sext)):
objtype.update({'obj': K8SObjType.K8SOBJ_NAMESPACE})
elif filename == K8SObjType.K8SOBJ_PVCS_Path:
# handle pvcs both config and data
filename = fnames[4]
- if filename.endswith('.%s' % defaultk8sext):
+ if filename.endswith('.{}'.format(defaultk8sext)):
# this is a config file
objtype.update({'obj': K8SObjType.K8SOBJ_PVOLCLAIM})
else:
namespaces = corev1api.list_namespace(watch=False)
for ns in namespaces.items:
nslist[ns.metadata.name] = {
- 'fi': FileInfo(name="/%s/%s" % (K8SObjType.K8SOBJ_NAMESPACE_Path, ns.metadata.name),
+ 'fi': FileInfo(name="/{}/{}".format(K8SObjType.K8SOBJ_NAMESPACE_Path, ns.metadata.name),
ftype=DIRECTORY,
size=0,
uid=0, gid=0,
pvsize = pv.spec.capacity['storage']
logging.debug("pvsize: {} / {}".format(type(pvsize), pvsize))
pvlist[pvname] = {
- 'fi': FileInfo(name="/%s/%s" % (K8SObjType.K8SOBJ_PVOLUME_Path, pvname),
+ 'fi': FileInfo(name="/{}/{}".format(K8SObjType.K8SOBJ_PVOLUME_Path, pvname),
ftype=NOT_EMPTY_FILE,
size=k8s_size_to_int(pvsize),
uid=0, gid=0,
# logging.debug(storageclass)
for sc in storageclass.items:
sclist[sc.metadata.name] = {
- 'fi': FileInfo(name="/%s/%s" % (K8SObjType.K8SOBJ_STORAGECLASS_Path, sc.metadata.name),
+ 'fi': FileInfo(name="/{}/{}".format(K8SObjType.K8SOBJ_STORAGECLASS_Path, sc.metadata.name),
ftype=NOT_EMPTY_FILE,
size=1024, # arbitrary file size
uid=0, gid=0,
method_name = 'upload_' + str(K8SObjType.methoddict.get(file_info.objtype))
method = getattr(self, method_name, None)
if method is None:
- return {'error': 'Invalid object type: %s' % file_info.objtype}
+ return {'error': 'Invalid object type: {}'.format(file_info.objtype)}
if file_info.objcache is None:
current_file = self.check_file(file_info)
if isinstance(current_file, dict) and 'error' in current_file:
method_name = '_check_' + str(K8SObjType.methoddict.get(file_info.objtype))
method = getattr(self, method_name, None)
if method is None:
- return {'error': 'Invalid object type: %s' % file_info.objtype}
+ return {'error': 'Invalid object type: {}'.format(file_info.objtype)}
return method(file_info)
def __exec_check_object(self, action, check_connection=True):
if groups["fraction"] is None:
groups["fraction"] = 0
else:
- groups["fraction"] = int(float("0.%s" % groups["fraction"]) * 1e6)
+ groups["fraction"] = int(float("0.{}".format(groups["fraction"])) * 1e6)
try:
return datetime(int(groups["year"]), int(groups["month"]), int(groups["day"]),
int(groups["hour"]), int(groups["minute"]), int(groups["second"]),
int(groups["fraction"]), tz)
except Exception as e:
- raise ParseError("Failed to create a valid datetime record due to: %s"
- % e)
+ raise ParseError("Failed to create a valid datetime record due to: {}".format(e))
expected_name = file["name"]
if len(splitted) > 1:
path = "/".join(splitted[1:])
- expected_name = "%s/%s" % (path, expected_name)
+ expected_name = "{}/{}".format(path, expected_name)
self.assertIn(expected_name, uploaded_names)
self.assertIn(file['size'], uploaded_bytes)
def __create_containers(self, amount):
for i in range(0, amount):
- self.swift_connection.put_container("container=%s" % i)
+ self.swift_connection.put_container("container={}".format(i))
def test_should_list_container_metadata(self):
container_name = "cats"
class HandshakePacketBuilder(PacketTestUtil):
- def build(self, packet_content="Hello %s 1" % BACKEND_PLUGIN_TYPE):
+ def build(self, packet_content="Hello {} 1".format(BACKEND_PLUGIN_TYPE)):
return self.command_packet(packet_content)
packet = JobInfoStartPacketBuilder().build()
packet += self.command_packet("Name=az_14125_bcjn")
packet += self.command_packet("JobID=334")
- packet += self.command_packet("Type=%s" % job_type.upper())
+ packet += self.command_packet("Type={}".format(job_type.upper()))
if where is not None:
- packet += self.command_packet("Where=%s" % where)
+ packet += self.command_packet("Where={}".format(where))
if since is not None:
- packet += self.command_packet("Since=%s" % since)
+ packet += self.command_packet("Since={}".format(since))
if replace is not None:
- packet += self.command_packet("Replace=%s" % replace)
+ packet += self.command_packet("Replace={}".format(replace))
packet += self.eod_packet()
return packet
password=True,
passfile=None):
packet = PluginParamsStartPacketBuilder().build()
- packet += self.command_packet("User=%s" % BACKEND_PLUGIN_USER)
- packet += self.command_packet("URL=%s" % BACKEND_PLUGIN_URL)
+ packet += self.command_packet("User={}".format(BACKEND_PLUGIN_USER))
+ packet += self.command_packet("URL={}".format(BACKEND_PLUGIN_URL))
if password:
- packet += self.command_packet("Password=%s" % BACKEND_PLUGIN_PWD)
+ packet += self.command_packet("Password={}".format(BACKEND_PLUGIN_PWD))
if includes is not None:
for include in includes:
- packet += self.command_packet("include=%s" % include)
+ packet += self.command_packet("include={}".format(include))
if regex_includes is not None:
for regex_include in regex_includes:
- packet += self.command_packet("regex_include=%s" % regex_include)
+ packet += self.command_packet("regex_include={}".format(regex_include))
if excludes is not None:
for exclude in excludes:
- packet += self.command_packet("exclude=%s" % exclude)
+ packet += self.command_packet("exclude={}".format(exclude))
if regex_excludes is not None:
for regex_exclude in regex_excludes:
- packet += self.command_packet("regex_exclude=%s" % regex_exclude)
+ packet += self.command_packet("regex_exclude={}".format(regex_exclude))
if segment_size is not None:
- packet += self.command_packet("be_object_segment_size=%s" % segment_size)
+ packet += self.command_packet("be_object_segment_size={}".format(segment_size))
if restore_local_path is not None:
- packet += self.command_packet("restore_local_path=%s" % restore_local_path)
+ packet += self.command_packet("restore_local_path={}".format(restore_local_path))
if passfile is not None:
- packet += self.command_packet("passfile=%s" % passfile)
+ packet += self.command_packet("passfile={}".format(passfile))
packet += self.command_packet("debug=1")
packet += self.eod_packet()
def without_url(self):
packet = PluginParamsStartPacketBuilder().build()
- packet += self.command_packet("User=%s" % BACKEND_PLUGIN_USER)
- packet += self.command_packet("Password=%s" % BACKEND_PLUGIN_PWD)
+ packet += self.command_packet("User={}".format(BACKEND_PLUGIN_USER))
+ packet += self.command_packet("Password={}".format(BACKEND_PLUGIN_PWD))
packet += self.eod_packet()
return packet
def without_user(self):
packet = PluginParamsStartPacketBuilder().build()
- packet += self.command_packet("Password=%s" % BACKEND_PLUGIN_PWD)
- packet += self.command_packet("URL=%s" % BACKEND_PLUGIN_URL)
+ packet += self.command_packet("Password={}".format(BACKEND_PLUGIN_PWD))
+ packet += self.command_packet("URL={}".format(BACKEND_PLUGIN_URL))
packet += self.eod_packet()
return packet
def without_pwd(self):
packet = PluginParamsStartPacketBuilder().build()
- packet += self.command_packet("User=%s" % BACKEND_PLUGIN_USER)
- packet += self.command_packet("URL=%s" % BACKEND_PLUGIN_URL)
+ packet += self.command_packet("User={}".format(BACKEND_PLUGIN_USER))
+ packet += self.command_packet("URL={}".format(BACKEND_PLUGIN_URL))
packet += self.eod_packet()
return packet
if fname_without_fsource:
file_source = ""
else:
- file_source = "@%s" % BACKEND_PLUGIN_TYPE
+ file_source = "@{}".format(BACKEND_PLUGIN_TYPE)
if where:
- packet = self.command_packet('FNAME:%s/%s/%s/%s' % (where, file_source, bucket, file['name']))
+ packet = self.command_packet('FNAME:{}/{}/{}/{}'.format(where, file_source, bucket, file['name']))
else:
- packet = self.command_packet('FNAME:%s/%s/%s' % (file_source, bucket, file['name']))
- packet += self.command_packet('STAT:F %s 0 0 %s 1 473' % (file['size'], DEFAULT_FILE_MODE))
+ packet = self.command_packet('FNAME:{}/{}/{}'.format(file_source, bucket, file['name']))
+ packet += self.command_packet('STAT:F {} 0 0 {} 1 473'.format(file['size'], DEFAULT_FILE_MODE))
if "modified-at" not in file:
file["modified-at"] = 2222222222
- packet += self.command_packet('TSTAMP:1111111111 %s 3333333333' % file["modified-at"])
+ packet += self.command_packet('TSTAMP:1111111111 {} 3333333333'.format(file["modified-at"]))
packet += self.eod_packet()
return packet
return packet
def bucket_info(self, bucket):
- packet = self.command_packet('FNAME:@%s/%s/' % (BACKEND_PLUGIN_TYPE, bucket['name']))
+ packet = self.command_packet('FNAME:@{}/{}/'.format(BACKEND_PLUGIN_TYPE, bucket['name']))
if "modified-at" not in bucket:
bucket["modified-at"] = 2222222222
- packet += self.command_packet('STAT:D 12345 0 0 %s 1 473' % DEFAULT_DIR_MODE)
- packet += self.command_packet('TSTAMP:1111111111 %s 3333333333' % bucket["modified-at"])
+ packet += self.command_packet('STAT:D 12345 0 0 {} 1 473'.format(DEFAULT_DIR_MODE))
+ packet += self.command_packet('TSTAMP:1111111111 {} 3333333333'.format(bucket["modified-at"]))
packet += self.eod_packet()
return packet
class PacketTestUtil(object):
def data_packet(self, data):
- packet = ("D%s\n" % str(len(data)).zfill(6)).encode()
+ packet = ("D{}\n".format(str(len(data)).zfill(6)).encode())
packet += data
return packet
def command_packet(self, packet_content):
packet_content += "\n"
- packet_header = "C%s\n" % str(len(packet_content)).zfill(6)
+ packet_header = "C{}\n".format(str(len(packet_content)).zfill(6))
return (packet_header + packet_content).encode()
def eod_packet(self):