The first thing I want to separate the connection and the class which knows how to work with device.
The second thing I want to use the Strategy pattern instead of Inheritance due to lack of isolation.
Common class structure:
IOConnection as an interface for working for a particular connection
As examples of a particular connection are SSHConnection and Telnet Connection
DeviceStream adds some logic to basic IOConnection: it understands the end of the output: it recognizes the prompt
LayerManager manages all levels of layers or terminal modes
Layer is an entity for working with a particular layer or terminal mode
Particular set of device type classes (like CiscoIOS, JuniperJunOS) for working with devices. They contain a set of strategy class instances
Try to show the concept of these changes.
Public factory method:
# Public Factory function for creating netdev classes
def create(device_type, connection_type, *args, **kwargs):
# Create IOConnection separately
if connection_type == "ssh":
IOConnection = SSHConnectiom(*args, **kwargs) # As Example for SSHConnection
# Create DeviceStream and all needed instances for a particular device
device_stream = DeviceStream(IOConnection)
# Create Device separately
if device_type == "cisco_ios":
layer_manager = LayerManager(device_stream, cisco_checker)
.add_layer(UserExecMode())
.add_layer(PrivilegeExecMode())
.add_layer(ConfigMode())
return Cisco_IOS(layer_manager)
IOConnection is an abstract class with a public interface which can be used by all particular device type classes.
IOConnection can be implemented in SSHConnection, TelnetConnection and SerialConnection.
DeviceStream adds some logic to IOConnection. It understands the end of the output for commands: it understands the prompt
class DeviceStream():
""" Class which know how to work with the device in a stream mode """
def __init__ (self, IOConnection, prompt_pattern = r"", ):
self._conn = IOConnection
self._prompt_pattern = prompt_pattern
async def send(self, cmd_list):
pass
async def read_until(self, pattern, re_flags, until_prompt=True):
pass
Device type classes are particular classes for working with network devices.
class CiscoIOS():
""" Abstract Device type"""
def __init__ (device_stream, layer_manager):
self._device_stream = device_stream
self._layer_manager = layer_manager
async def send_command(self, cmd_list, terminal_mode):
""" Go to specific terminal mode and run list of commands in there"""
self._layer_manager.switch_to_layer(terminal_mode)
self.device_stream(cmd_list)
async def send_config_set(self, cmd_list):
""" Go to configuration mode and run list of commands in there"""
self._layer_manager.switch_to_layer('config_mode')
self.device_stream(cmd_list)
self._layer_manager.switch_to_layer('privilege exec')
We have universal class LayerManager for working with terminal modes:
class LayerManager():
def __init__(self, device_stream, checker_closure):
self._device_stream = device_stream
self._checker_closure = checker_closure
self._current_layer = None
def add_layer(layer):
self._layers[layer.name] = layer
return self
def switch_to_layer(layer_name):
if self._current_layer is None:
self._current_layer = self.checker_closure()
if self._current_layer == layer_name:
return
# switching to layer
def commit_transaction():
layer = get_layer(self._current_layer)
if layer.transactional:
layer.committer()
def get_layer(layer_name):
pass
Specific function for checking the cisco like terminal modes:
Hello! I want to make the module refactoring.
The first thing I want to separate the connection and the class which knows how to work with device. The second thing I want to use the Strategy pattern instead of Inheritance due to lack of isolation.
Common class structure:
Try to show the concept of these changes.
Public factory method:
IOConnection is an abstract class with a public interface which can be used by all particular device type classes.
IOConnection can be implemented in SSHConnection, TelnetConnection and SerialConnection.
DeviceStream adds some logic to IOConnection. It understands the end of the output for commands: it understands the prompt
Device type classes are particular classes for working with network devices.
We have universal class
LayerManager
for working with terminal modes:Specific function for checking the cisco like terminal modes:
We have universal class
Layer
for working with particular layer/terminal mode:And cisco like layers: