427 lines
14 KiB
Python
427 lines
14 KiB
Python
'''-------------------------------------------------------------------------
|
|
Copyright IBM Corp. 2015, 2015 All Rights Reserved
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
Limitations under the License.
|
|
-------------------------------------------------------------------------'''
|
|
|
|
'''===========================================================================
|
|
15-Jul-2014 evgenyl Initial implementation.
|
|
21-Jul-2014 evgenyl Extending API: create_service_datagram,
|
|
get_first_file_of_type
|
|
28-Jul-2014 evgenyl Bugfix in create_service_datagram - meta shall be
|
|
dictionary of dictionaries
|
|
==========================================================================='''
|
|
|
|
import json
|
|
import os
|
|
import syslog
|
|
|
|
from SBusFileDescription import SBUS_FD_OUTPUT_OBJECT
|
|
from SBusStorletCommand import SBUS_CMD_NOP
|
|
|
|
'''------------------------------------------------------------------------'''
|
|
|
|
|
|
class SBusDatagram(object):
|
|
'''@summary: This class aggregates data to be transferred
|
|
|
|
using SBus functionality.
|
|
'''
|
|
|
|
command_dict_key_name_ = 'command'
|
|
task_id_dict_key_name_ = 'taskId'
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
def __init__(self):
|
|
'''@summary: CTOR
|
|
|
|
@ivar e_command_ : A command to Storlet Daemon.
|
|
@type e_command_ : Integer. SBusStorletCommand enumerated value.
|
|
@ivar h_files_: List of open file descriptors.
|
|
@type h_files_: List of integers.
|
|
@ivar n_files_: Quantity of file descriptors.
|
|
@type n_files_: Integer.
|
|
@ivar files_metadata_: Meta-data for the file descriptors.
|
|
@type files_metadata_: List of Dictionaries String-to-String.
|
|
@ivar exec_params_: Auxiliary parameters for e_command_.
|
|
@type exec_params_: Dictionary String-to-String.
|
|
|
|
@invariant: Quantity of entries in files_metadata_ list
|
|
is the same as in h_files_, i.e. n_files_.
|
|
'''
|
|
self.e_command_ = SBUS_CMD_NOP
|
|
self.task_id_ = None
|
|
self.h_files_ = None
|
|
self.n_files_ = 0
|
|
self.files_metadata_ = None
|
|
self.exec_params_ = None
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
@staticmethod
|
|
def create_service_datagram(command,
|
|
outfd):
|
|
'''@summary: Datagram static factory.
|
|
|
|
Create "service" datagram, i.e.
|
|
- command shall be one of
|
|
{PING, START/STOP/STATUS-DAEMON}
|
|
- single output file descriptor
|
|
|
|
@param command: Command to send
|
|
@type command: SBusStorletCommand
|
|
@param outfd: Output stream for command execution results
|
|
@type outfd: File descriptor or Integer
|
|
|
|
@return: A datagram with the required data
|
|
@rtype: SBusDatagram
|
|
'''
|
|
dtg = SBusDatagram()
|
|
dtg.set_command(command)
|
|
meta = {}
|
|
meta[0] = {'type': SBUS_FD_OUTPUT_OBJECT}
|
|
files = []
|
|
if isinstance(outfd, file):
|
|
files.append(outfd.fileno())
|
|
else:
|
|
files.append(outfd)
|
|
dtg.set_files(files)
|
|
dtg.set_metadata(meta)
|
|
return dtg
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
def from_raw_data(self,
|
|
h_files,
|
|
str_json_metadata,
|
|
str_json_params):
|
|
'''@summary: CTOR
|
|
|
|
Construct object from file list and
|
|
two JSON-encoded strings.
|
|
|
|
@param h_files: List of file descriptors.
|
|
@type h_files: List of integers.
|
|
@param str_json_metadata: JSON encoding of file descriptors meta-data.
|
|
@type str_json_metadata: String.
|
|
@param str_json_params: JSON encoding for execution parameters.
|
|
@type str_json_params: String.
|
|
|
|
@rtype: void
|
|
'''
|
|
self.set_files(h_files)
|
|
self.extract_metadata(str_json_metadata)
|
|
self.extract_params(str_json_params)
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
def extract_metadata(self,
|
|
str_json_metadata):
|
|
'''@summary: Extract files_metadata array
|
|
|
|
of dictionaries form a JSON string
|
|
@requires: n_files_ has to be se
|
|
|
|
@param str_json_metadata: JSON encoding of file descriptors meta-data.
|
|
@type str_json_metadata: String.
|
|
|
|
@rtype: void
|
|
'''
|
|
if self.get_num_files() > 0:
|
|
all_metadata = json.loads(str_json_metadata)
|
|
self.files_metadata_ = []
|
|
for i in range(self.get_num_files()):
|
|
str_curr_metadata = all_metadata[str(i)]
|
|
self.files_metadata_.append(json.loads(str_curr_metadata))
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
def extract_params(self, str_json_params):
|
|
'''@summary: Extract command field and exec_params
|
|
|
|
dictionary form a JSON string
|
|
@param str_json_params: JSON encoding for the execution parameters.
|
|
@type str_json_params: string.
|
|
|
|
@rtype: void
|
|
'''
|
|
ext_params = json.loads(str_json_params)
|
|
cmd = self.command_dict_key_name_
|
|
tid = self.task_id_dict_key_name_
|
|
if cmd in ext_params:
|
|
self.e_command_ = ext_params[cmd]
|
|
ext_params.pop(cmd, None)
|
|
elif tid in ext_params:
|
|
self.task_id_ = ext_params[tid]
|
|
ext_params.pop(tid, None)
|
|
else:
|
|
self.e_command_ = SBUS_CMD_NOP
|
|
b_exec_params_is_not_empty = len(ext_params.keys()) > 0
|
|
if b_exec_params_is_not_empty:
|
|
self.exec_params_ = ext_params.copy()
|
|
else:
|
|
self.exec_params_ = None
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
def get_params_and_cmd_as_json(self):
|
|
'''@summary: Convert command field and execution parameters
|
|
|
|
dictionary into JSON as the following -
|
|
1. Copy exec_params_. Initialize the combined dictionary.
|
|
2. Push the next pair into the combined dictionary
|
|
key - 'command'
|
|
value - e_command_
|
|
|
|
@return: JSON encoded representation of exec_params_ and command_
|
|
@rtype: string
|
|
'''
|
|
exec_params = {}
|
|
if self.exec_params_:
|
|
exec_params = self.exec_params_.copy()
|
|
cmd = self.command_dict_key_name_
|
|
exec_params[cmd] = self.e_command_
|
|
if self.task_id_:
|
|
tid = self.task_id_dict_key_name_
|
|
exec_params[tid] = self.task_id_
|
|
str_result = json.dumps(exec_params)
|
|
return str_result
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
def get_files_metadata_as_json(self):
|
|
'''@summary: Encode the list of dictionaries into JSON as the following
|
|
|
|
1. Create a combined dictionary (Integer-to-String)
|
|
Key - index in the original list
|
|
Value - JSON encoding of the certain dictionary
|
|
2. Encode the combined dictionary into JSON
|
|
|
|
@return: List of dictionaries into a JSON string.
|
|
@rtype: string
|
|
'''
|
|
all_metadata = {}
|
|
str_result = None
|
|
for i in range(self.get_num_files()):
|
|
all_metadata[str(i)] = json.dumps(self.files_metadata_[i])
|
|
if self.get_num_files() > 0:
|
|
str_result = json.dumps(all_metadata)
|
|
return str_result
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
def get_num_files(self):
|
|
'''@summary: Getter.
|
|
|
|
@return: The quantity of file descriptors.
|
|
@rtype: integer
|
|
'''
|
|
return self.n_files_
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
def get_files(self):
|
|
'''@summary: Getter.
|
|
|
|
@return: The list of file descriptors.
|
|
@rtype: List of integers
|
|
'''
|
|
return self.h_files_
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
def set_files(self, h_files):
|
|
'''@summary: Setter.
|
|
|
|
Assign file handlers list and update n_files_ field
|
|
|
|
@param h_files: File descriptors.
|
|
@type h_files: List of integers
|
|
|
|
@rtype: void
|
|
'''
|
|
if not h_files:
|
|
self.n_files_ = 0
|
|
else:
|
|
self.n_files_ = len(h_files)
|
|
self.h_files_ = None
|
|
if 0 < self.n_files_:
|
|
self.h_files_ = []
|
|
for i in range(self.n_files_):
|
|
if isinstance(h_files[i], file):
|
|
self.h_files_.append(h_files[i].fileno())
|
|
else:
|
|
self.h_files_.append(h_files[i])
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
def get_first_file_of_type(self, file_type):
|
|
'''@summary: Iterate through file list and metadata.
|
|
|
|
Find the first file with the required type
|
|
|
|
@param file_type: The file type to look for
|
|
@type file_type: Integer, SBusFileDescription enumerator
|
|
|
|
@return: File descriptor or None if not found
|
|
@rtype: File
|
|
'''
|
|
required_file = None
|
|
for i in range(self.get_num_files()):
|
|
if (self.get_metadata()[i])['type'] == file_type:
|
|
try:
|
|
required_file = os.fdopen(self.get_files()[i], 'w')
|
|
except IOError as err:
|
|
syslog.syslog(syslog.LOG_DEBUG,
|
|
'Failed to open file: %s' % err.strerror)
|
|
return required_file
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
def get_metadata(self):
|
|
'''@summary: Getter.
|
|
|
|
@return: The list of meta-data dictionaries.
|
|
@rtype: List of dictionaries
|
|
'''
|
|
return self.files_metadata_
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
def set_metadata(self, metadata):
|
|
'''@summary: Setter.
|
|
|
|
Assign file_metadata_ field
|
|
|
|
@param metadata: File descriptors meta-data dictionaries.
|
|
@type metadata: List of dictionaries
|
|
|
|
@rtype: void
|
|
'''
|
|
self.files_metadata_ = metadata
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
def get_exec_params(self):
|
|
'''@summary: Getter.
|
|
|
|
@return: The execution parameters dictionary.
|
|
@rtype: Dictionary
|
|
'''
|
|
return self.exec_params_
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
def set_exec_params(self, params):
|
|
'''@summary: Setter.
|
|
|
|
Assign execution parameters dictionary.
|
|
|
|
@param params: Execution parameters to assign
|
|
@type params: Dictionary
|
|
|
|
@rtype: void
|
|
|
|
'''
|
|
self.exec_params_ = params
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
def add_exec_param(self, param_name, param_value):
|
|
'''@summary: Add a single pair to the exec_params_ dictionary
|
|
|
|
Don't change if the parameter exists already
|
|
|
|
@param param_name: Execution parameter name to be added
|
|
@type param_name: string
|
|
@param param_value: Execution parameter value
|
|
@type param_value: Unknown
|
|
|
|
@return: False if param_name exists already
|
|
@rtype: boolean
|
|
'''
|
|
b_status = True
|
|
if not self.get_exec_params():
|
|
exec_params = {}
|
|
exec_params[param_name] = param_value
|
|
self.set_exec_params(exec_params)
|
|
elif param_name in self.get_exec_params():
|
|
b_status = False
|
|
else:
|
|
self.get_exec_params()[param_name] = param_value
|
|
return b_status
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
def get_command(self):
|
|
'''@summary: Getter.
|
|
|
|
@return: The Storlet Daemon command.
|
|
@rtype: SBusStorletCommand
|
|
'''
|
|
return self.e_command_
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
def set_command(self, cmd):
|
|
'''@summary: Setter.
|
|
|
|
Assign Storlet Daemon command.
|
|
|
|
@param cmd: Command to assign
|
|
@type cmd: SBusStorletCommand enumerator
|
|
|
|
@rtype: void
|
|
'''
|
|
self.e_command_ = cmd
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
def get_task_id(self):
|
|
'''@summary: Getter.
|
|
|
|
@return: The task id.
|
|
@rtype: string
|
|
'''
|
|
return self.task_id_
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
def set_task_id(self, taskId):
|
|
'''@summary: Setter.
|
|
|
|
Assign task id
|
|
|
|
@param taskId: Command to assign
|
|
@type taskId: string
|
|
|
|
@rtype: void
|
|
'''
|
|
self.task_id_ = taskId
|
|
|
|
'''--------------------------------------------------------------------'''
|
|
|
|
@staticmethod
|
|
def dictionaies_equal(d1, d2):
|
|
'''@summary: Check whether two dictionaries has the same content.
|
|
|
|
The order of the entries is not considered.
|
|
|
|
@return: The answer to the above
|
|
@rtype: boolean.
|
|
'''
|
|
diffr = set(d1.items()) ^ set(d2.items())
|
|
return (0 == len(diffr))
|
|
|
|
'''============================ END OF FILE ==============================='''
|