class DataFilterDriver(Driver): def __init__(self, json_data): self.data_filter_params_objs = [DataFilterParams()._from_json(body=k) for k in json_data if json_data is not None and len(json_data) > 0] self.execute_cmds = None self.execute_cmd_api = API(logger=logger) @classmethod def create_driver(cls, json_data): return cls(json_data) def parse(self): """parse the configuration to command""" self.execute_cmds = [data_filter_params_obj._to_iptables_cmd() for data_filter_params_obj in self.data_filter_params_objs] def apply(self): """use api to apply the command""" logger.info("Start configuration of data filtering.") for execute_cmd in self.execute_cmds: if execute_cmd != '': self.execute_cmd_api.execute(execute_cmd) logger.info("Finish configuration of data filtering.")
class PriorityStrategyDriver(Driver): def __init__(self, json_data): self.priority_strategy_params_objs = [PriorityStrategyParams()._from_json(body=k) for k in json_data if json_data is not None and len(json_data) > 0] self.execute_cmds_list = None self.execute_cmd_api = API(logger=logger) @classmethod def create_driver(cls, json_data): return cls(json_data) def parse(self): """parse the configuration to command""" self.execute_cmds_list = [] mark_number = 1 for priority_strategy_params_obj in self.priority_strategy_params_objs: self.execute_cmds_list.append(priority_strategy_params_obj._to_iptables_and_tc_cmds(mark_number)) mark_number += 1 def apply(self): """use api to apply the command""" logger.info("Start configuration of priority strategy.") for execute_cmds in self.execute_cmds_list: for execute_cmd in execute_cmds: if execute_cmds != '': self.execute_cmd_api.execute(execute_cmd) logger.info("Finish configuration of priority strategy.")
def __init__(self, json_data): self.congestion_control_params_objs = [ CongestionControlParams()._from_json(body=k) for k in json_data if json_data is not None and len(json_data) > 0 ] self.execute_cmds_list = None self.execute_cmd_api = API(logger=logger)
class CongestionControlDriver(Driver): def __init__(self, json_data): self.congestion_control_params_objs = [ CongestionControlParams()._from_json(body=k) for k in json_data if json_data is not None and len(json_data) > 0 ] self.execute_cmds_list = None self.execute_cmd_api = API(logger=logger) @classmethod def create_driver(cls, json_data): return cls(json_data) def parse(self): """parse the configuration to command""" # self.execute_cmds_list is a list in list. self.execute_cmds_list = [ congestion_control_params_obj._to_tc_cmds() for congestion_control_params_obj in self.congestion_control_params_objs ] def apply(self): """use api to apply the command""" logger.info("Start configuration of congestion control.") for execute_cmds in self.execute_cmds_list: for execute_cmd in execute_cmds: if execute_cmds != '': self.execute_cmd_api.execute(execute_cmd) logger.info("Finish configuration of congestion control.")
def __init__(self, json_data): self.priority_strategy_params_objs = [PriorityStrategyParams()._from_json(body=k) for k in json_data if json_data is not None and len(json_data) > 0] self.execute_cmds_list = None self.execute_cmd_api = API(logger=logger)
class CongestionControlParams(object): fields = ['nic', 'speed'] execute_cmd_api = API(logger=logger) def as_dict(self): """transform the object to dict""" return { k: getattr(self, k) for k in self.fields if self.obj_attr_is_set(k) } @schemautils.validate_schema(schemas.congestion_control_schema, logger=logger) def _from_json(self, body): """ transform from the json data to object :param body: the json data :type dict :return: """ for field in self.fields: body_field_val = body.get(field, None) if body_field_val is None or len(body_field_val) == 0: continue setattr(self, field, body_field_val) return self def obj_attr_is_set(self, attr): """check if the object has the attribute""" try: getattr(self, attr) except AttributeError: return False else: return True def _to_tc_cmds(self): """ transform from the CongestionControlParams object to tc commands :return: commands of tc :type: list """ self._init_tc_config() cmds = [] cmds.append( 'tc qdisc add dev {} root handle 1: htb default 1 r2q 0'.format( self.nic)) cmds.append( 'tc class add dev {} classid 1:1 htb rate {} ceil {}'.format( self.nic, self.speed, self.speed)) return cmds def _init_tc_config(self): """ initiate qdisc root :return: """ cmd = 'tc qdisc del dev {} root'.format(self.nic) self.execute_cmd_api.execute(cmd)
def __init__(self, json_data): self.data_filter_params_objs = [DataFilterParams()._from_json(body=k) for k in json_data if json_data is not None and len(json_data) > 0] self.execute_cmds = None self.execute_cmd_api = API(logger=logger)
class PriorityStrategyParams(object): fields = [ 'source_mac', 'ip_address', 'port', 'protocol', 'interface', 'priority' ] execute_cmd_api = API(logger=logger) def as_dict(self): """transform the object to dict""" return { k: getattr(self, k) for k in self.fields if self.obj_attr_is_set(k) } @schemautils.validate_schema(schemas.priority_strategy_schema, logger=logger) def _from_json(self, body): """ transform from the json data to object :param body: the json data :type dict :return: """ for field in self.fields: body_field_val = body.get(field, None) if body_field_val is None or len(body_field_val) == 0: continue setattr(self, field, body_field_val) return self def obj_attr_is_set(self, attr): """check if the object has the attribute""" try: getattr(self, attr) except AttributeError: return False else: return True def _to_iptables_and_tc_cmds(self, mark_number): """ transform from the PriorityStrategyParams object to iptables and tc commands :param mark_number: number which should be used to mark the data :type int :return: command of tc and iptables :type: list """ cmds = [] cmds.append(self._to_iptables_cmd(mark_number)) cmds.extend(self._to_tc_cmds(mark_number)) return cmds def _to_iptables_cmd(self, mark_number): """ transform from the PriorityStrategyParams object to iptables command. :param mark_number: number which should be used to mark the data :return: command of iptables :type str """ cmd = 'iptables ' cmd_table = '-t raw -A PREROUTING ' cmd_params = '' cmd_act = '-j MARK --set-mark ' + str(mark_number) if self.obj_attr_is_set('source_mac'): mac_params = getattr(self, 'source_mac') cmd_params += '-m mac --mac-source ' + mac_params + ' ' if self.obj_attr_is_set('port'): if self.obj_attr_is_set('protocol'): if getattr(self, 'protocol') == 'all': logger.error( '\'port\' can not be specified while \'protocol\' is set to \'all\'.', exc_info=True) return '' else: logger.error( '\'port\' can not be specified while \'protocol\' is not set.', exc_info=True) return '' pro = getattr(self, 'protocol') port_params = getattr(self, 'port') if port_params.get( 'src', None) is not None and len(port_params.get('src')) > 0: cmd_params += '-m ' + pro + ' --sport ' + port_params.get( 'src') + ' ' if port_params.get( 'dst', None) is not None and len(port_params.get('dst')) > 0: cmd_params += '-m ' + pro + ' --dport ' + port_params.get( 'dst') + ' ' if self.obj_attr_is_set('protocol'): protocol_params = getattr(self, 'protocol') cmd_params += '-p ' + protocol_params + ' ' if self.obj_attr_is_set('ip_address'): address_params = getattr(self, 'ip_address') if address_params.get( 'src', None) is not None and len(address_params.get('src')) > 0: cmd_params += '-s ' for src_address in address_params.get('src'): cmd_params += src_address + ',' cmd_params = cmd_params.rsplit(',', 1)[0] + ' ' if address_params.get( 'dst', None) is not None and len(address_params.get('dst')) > 0: cmd_params += '-d ' for dst_address in address_params.get('dst'): cmd_params += dst_address + ',' cmd_params = cmd_params.rsplit(',', 1)[0] + ' ' cmd = cmd + cmd_table + cmd_params + cmd_act return cmd def _to_tc_cmds(self, mark_number): """ transform from the PriorityStrategyParams object to tc commands :param mark_number: number which should be used to mark the data :type int :return: commands of tc :type list """ cmds = [] prio_handle = self._get_prio_info() if prio_handle is not None: cmds.append(self._generate_prio_filter(prio_handle, mark_number)) else: htb_info = self._get_htb_info() if htb_info is not None: htb_handle, htb_classid = htb_info prio_handle = str(int(htb_handle) + 1) # create a qdisc prio first before generate filters self.apply_qdisc_prio(htb_classid, prio_handle) cmds.append( self._generate_prio_filter(prio_handle, mark_number)) else: self.init_qdisc() # create a qdisc prio first before generate filters self.apply_qdisc_prio('root', '1') cmds.append(self._generate_prio_filter('1', mark_number)) return cmds def init_qdisc(self): """ Delete all qdisc on root. :return: """ cmd = 'tc qdisc del dev {} root'.format(self.interface) self.execute_cmd_api.execute(cmd) def apply_qdisc_prio(self, parent_handle, handle): """ Configure qdisc for the priority queue. :param parent_handle: parent's handle (such as 1:1) :param handle: handle of self (such as 2) :return: """ cmd = 'tc qdisc add dev {} parent {} handle {}: prio'\ .format(self.interface, parent_handle, handle) self.execute_cmd_api.execute(cmd) def _generate_prio_filter(self, parent_handle, handle): """ Generate filters for the priority queue. :param parent_handle: parent's handle (such as 1) :param handle: handle of self (such as 2) :return: """ priority = self._get_filter_priority() cmd = 'tc filter add dev {} prio 8 parent {}: handle {} fw flowid {}:{}'\ .format(self.interface, parent_handle, handle, parent_handle, priority) return cmd def _get_filter_priority(self): """ Get priority based on the configuration file. :return: """ prio_str = getattr(self, 'priority') if prio_str == 'low': return '3' elif prio_str == 'high': return '1' else: return '2' def _get_prio_info(self): """ Get the handle of the existing prio qdisc. :return: handle of prio qdisc (such as 2) :type str """ ret = subprocess.Popen( 'tc -s qdisc show dev %s | grep " prio " | cut -d " " -f 3' % self.interface, shell=True, stdout=subprocess.PIPE).communicate()[0].strip(':\n') if ret == '': return None else: prio_handle = ret return prio_handle def _get_htb_info(self): """ Get the handle and classid of the existing htb qdisc. :return: handle(such as 1) and classid(such as 1:1) :type str """ ret = subprocess.Popen( 'tc -s qdisc show dev %s | grep " htb " | cut -d " " -f 3' % self.interface, shell=True, stdout=subprocess.PIPE).communicate()[0].strip(':\n') if ret == '': return None else: htb_handle = ret ret = subprocess.Popen( 'tc -s class show dev %s | grep " htb " | cut -d " " -f 3' % self.interface, shell=True, stdout=subprocess.PIPE).communicate()[0].strip('\n') if ret == '': return None else: htb_classid = ret return (htb_handle, htb_classid)