@ -66,8 +66,7 @@ class Cliconf(CliconfBase):
' line ' - commands are matched line by line
' line ' - commands are matched line by line
' strict ' - command lines are matched with respect to position
' strict ' - command lines are matched with respect to position
' exact ' - command lines must be an equal match
' exact ' - command lines must be an equal match
' none ' - will not compare the candidate configuration with
' none ' - will not compare the candidate configuration with the running configuration
the running configuration on the remote device
: param diff_ignore_lines : Use this argument to specify one or more lines that should be
: param diff_ignore_lines : Use this argument to specify one or more lines that should be
ignored during the diff . This is used for lines in the configuration
ignored during the diff . This is used for lines in the configuration
that are automatically updated by the system . This argument takes
that are automatically updated by the system . This argument takes
@ -90,9 +89,16 @@ class Cliconf(CliconfBase):
"""
"""
diff = { }
diff = { }
device_operations = self . get_device_operations ( )
device_operations = self . get_device_operations ( )
option_values = self . get_option_values ( )
if candidate is None and not device_operations [ ' supports_onbox_diff ' ] :
if candidate is None and not device_operations [ ' supports_onbox_diff ' ] :
raise ValueError ( ' candidate configuration is required to generate diff ' )
raise ValueError ( " candidate configuration is required to generate diff " )
if match not in option_values [ ' diff_match ' ] :
raise ValueError ( " ' match ' value %s in invalid, valid values are %s " % ( match , option_values [ ' diff_match ' ] ) )
if replace not in option_values [ ' diff_replace ' ] :
raise ValueError ( " ' replace ' value %s in invalid, valid values are %s " % ( replace , option_values [ ' diff_replace ' ] ) )
# prepare candidate configuration
# prepare candidate configuration
candidate_obj = NetworkConfig ( indent = 1 )
candidate_obj = NetworkConfig ( indent = 1 )
@ -118,19 +124,22 @@ class Cliconf(CliconfBase):
return json . dumps ( diff )
return json . dumps ( diff )
@enable_mode
@enable_mode
def edit_config ( self , candidate , check_mode = False , replace = None ) :
def edit_config ( self , candidate = None , commit = True , replace = False , diff = False , comment = None ) :
if not candidate :
if not candidate :
raise ValueError ( ' must provide a candidate config to load ' )
raise ValueError ( " must provide a candidate config to load " )
if commit not in ( True , False ) :
raise ValueError ( " ' commit ' must be a bool, got %s " % commit )
if check_mode not in ( True , False ) :
if replac e not in ( True , False ) :
raise ValueError ( ' `check_mode` must be a bool, got %s ' % check_mode )
raise ValueError ( " ' replace ' must be a bool, got %s " % replac e)
op tions = self . get_ option_value s( )
op era tions = self . get_ device_ opera tions( )
if replace and replace not in op tions[ ' replace' ] :
if replace and not op era tions[ ' supports_ replace' ] :
raise ValueError ( ' `replace` value %s in invalid, valid values are %s ' % ( replace , options [ ' replace ' ] ) )
raise ValueError ( " configuration replace is not supported on ios " )
results = [ ]
results = [ ]
if not check_mode :
if commit :
for line in chain ( [ ' configure terminal ' ] , to_list ( candidate ) ) :
for line in chain ( [ ' configure terminal ' ] , to_list ( candidate ) ) :
if not isinstance ( line , collections . Mapping ) :
if not isinstance ( line , collections . Mapping ) :
line = { ' command ' : line }
line = { ' command ' : line }
@ -140,16 +149,23 @@ class Cliconf(CliconfBase):
results . append ( self . send_command ( * * line ) )
results . append ( self . send_command ( * * line ) )
results . append ( self . send_command ( ' end ' ) )
results . append ( self . send_command ( ' end ' ) )
return results [ 1 : - 1 ]
def get ( self , command , prompt = None , answer = None , sendonly = False ) :
diff_config = None
return self . send_command ( command , prompt = prompt , answer = answer , sendonly = sendonly )
if diff :
diff_config = candidate
return diff_config , results [ 1 : - 1 ]
def get ( self , command = None , prompt = None , answer = None , sendonly = False ) :
if not command :
raise ValueError ( ' must provide value of command to execute ' )
return self . send_command ( command = command , prompt = prompt , answer = answer , sendonly = sendonly )
def get_device_info ( self ) :
def get_device_info ( self ) :
device_info = { }
device_info = { }
device_info [ ' network_os ' ] = ' ios '
device_info [ ' network_os ' ] = ' ios '
reply = self . get ( ' show version ' )
reply = self . get ( command = ' show version ' )
data = to_text ( reply , errors = ' surrogate_or_strict ' ) . strip ( )
data = to_text ( reply , errors = ' surrogate_or_strict ' ) . strip ( )
match = re . search ( r ' Version ( \ S+) ' , data )
match = re . search ( r ' Version ( \ S+) ' , data )
@ -168,47 +184,50 @@ class Cliconf(CliconfBase):
def get_device_operations ( self ) :
def get_device_operations ( self ) :
return {
return {
' supports_ replace' : True ,
' supports_ diff_ replace' : True ,
' supports_commit ' : False ,
' supports_commit ' : False ,
' supports_rollback ' : False ,
' supports_rollback ' : False ,
' supports_defaults ' : True ,
' supports_defaults ' : True ,
' supports_onbox_diff ' : False ,
' supports_onbox_diff ' : False ,
' supports_commit_comment ' : False ,
' supports_commit_comment ' : False ,
' supports_multiline_delimiter ' : False ,
' supports_multiline_delimiter ' : False ,
' support_ match' : True ,
' support_ diff_ match' : True ,
' support_diff_ignore_lines ' : True ,
' support_diff_ignore_lines ' : True ,
' supports_generate_diff ' : True ,
' supports_generate_diff ' : True ,
' supports_replace ' : False
}
}
def get_option_values ( self ) :
def get_option_values ( self ) :
return {
return {
' format ' : [ ' text ' ] ,
' format ' : [ ' text ' ] ,
' match' : [ ' line ' , ' strict ' , ' exact ' , ' none ' ] ,
' diff_ match' : [ ' line ' , ' strict ' , ' exact ' , ' none ' ] ,
' replace' : [ ' line ' , ' block ' ]
' diff_ replace' : [ ' line ' , ' block ' ]
}
}
def get_capabilities ( self ) :
def get_capabilities ( self ) :
result = dict ( )
result = dict ( )
result [ ' rpc ' ] = self . get_base_rpc ( ) + [ ' edit_banner ' ]
result [ ' rpc ' ] = self . get_base_rpc ( ) + [ ' edit_banner ' , ' get_diff ' ]
result [ ' network_api ' ] = ' cliconf '
result [ ' network_api ' ] = ' cliconf '
result [ ' device_info ' ] = self . get_device_info ( )
result [ ' device_info ' ] = self . get_device_info ( )
result [ ' device_operations ' ] = self . get_device_operations ( )
result [ ' device_operations ' ] = self . get_device_operations ( )
result . update ( self . get_option_values ( ) )
result . update ( self . get_option_values ( ) )
return json . dumps ( result )
return json . dumps ( result )
def edit_banner ( self , banners , multiline_delimiter = " @ " , c heck_mode = False ) :
def edit_banner ( self , candidate= None , multiline_delimiter = " @ " , c ommit= True , diff = False ) :
"""
"""
Edit banner on remote device
Edit banner on remote device
: param banners : Banners to be loaded in json format
: param banners : Banners to be loaded in json format
: param multiline_delimiter : Line delimiter for banner
: param multiline_delimiter : Line delimiter for banner
: param c heck_mode : Boolean value that indicates if the device candidate
: param c ommit : Boolean value that indicates if the device candidate
configuration should be pushed in the running configuration or discarded .
configuration should be pushed in the running configuration or discarded .
: param diff : Boolean flag to indicate if configuration that is applied on remote host should
generated and returned in response or not
: return : Returns response of executing the configuration command received
: return : Returns response of executing the configuration command received
from remote host
from remote host
"""
"""
banners_obj = json . loads ( banners )
banners_obj = json . loads ( candidate )
results = [ ]
results = [ ]
if not check_mode :
if commit :
for key , value in iteritems ( banners_obj ) :
for key , value in iteritems ( banners_obj ) :
key + = ' %s ' % multiline_delimiter
key + = ' %s ' % multiline_delimiter
for cmd in [ ' config terminal ' , key , value , multiline_delimiter , ' end ' ] :
for cmd in [ ' config terminal ' , key , value , multiline_delimiter , ' end ' ] :
@ -218,7 +237,11 @@ class Cliconf(CliconfBase):
time . sleep ( 0.1 )
time . sleep ( 0.1 )
results . append ( self . send_command ( ' \n ' ) )
results . append ( self . send_command ( ' \n ' ) )
return results [ 1 : - 1 ]
diff_banner = None
if diff :
diff_banner = candidate
return diff_banner , results [ 1 : - 1 ]
def _extract_banners ( self , config ) :
def _extract_banners ( self , config ) :
banners = { }
banners = { }