Python case for backuping the CE switch configuration automatically Highlighted

Latest reply: Nov 6, 2019 18:45:22 192 2 3 0

Networking Requirements

As shown in the next figure, the remote server is an FTP server. SwitchA and the FTP server have reachable routes to each other. The administrator requires SwitchA to automatically back up the configuration file to the FTP server every time the configuration is modified and saved, reducing manual backup workload.

NOTE:


The FTP protocol will bring risk to device security. The SFTP mode is recommended.


imgDownload?uuid=ad99e662ae8e47329baa8cf


Configuration Roadmap

The configuration roadmap is as follows:

  1. Make a Python script that can obtain and send the current configuration file to an FTP server.

  2. Upload the Python script to SwitchA and install the script.

  3. Bind the Python script to a command assistant and set the trigger condition of the assistant to the configuration change event. Then the assistant can run the Python script automatically when the configuration file changes.

Procedure

  1. Make a Python script.


    # Create a Python script named backupconfig.py. For details about the script format, see Example of backupconfig.py script. This Python script implements the following functions:


    1. Obtains the current configuration using the APIs described in the RESTful API Reference.

    2. Sends the current configuration file to the FTP server.

  2. Upload and install the Python script.


    # Assume that the Python script is saved on the FTP server. Upload the Python script to SwitchA using FTP.

<HUAWEI> system-view
[~HUAWEI] sysname SwitchA
[*HUAWEI] commit
[~SwitchA] quit
<SwitchA> ftp 192.168.20.1Trying 192.168.20.1 ...
Press CTRL + K to abort
Connected to 192.168.20.1.
220 FTP Server ready.
User(192.168.20.1:(none)):ftpuser331 Password required for ftpuser.
Enter password:
230 User ftpuser logged in.
[ftp] binary200 Type set to I.
[ftp] get backupconfig.py213 3659
200 Port command successful.
150 Opening data connection for backupconfig.py.
\     100% [***********]
226 File sent ok

FTP: 3659 byte(s) received in 1.610 second(s) 2.219Kbyte(s)/sec.
[ftp] bye221 Goodbye.

# Install the Python script on SwitchA.

<SwitchA> ops install file backupconfig.py

# After the Python script is installed, run the ops run python file-name command to manually run the script and check whether there is a backup configuration file in the FTP server. If the backup configuration file exists, the script can implement the configuration file backup function.


3. Configure a command assistant.


# Create a command assistant and set the trigger condition of the assistant to the configuration file change event (cfg_file_change). Bind the Python script backupconfig.py to the assistant.

<SwitchA> system-view[~SwitchA] ops[~SwitchA-ops] assistant backup_config[*SwitchA-ops-assistant-backup_config] condition event feature configuration name cfg_file_change[*SwitchA-ops-assistant-backup_config] execute 1 python backupconfig.py[*SwitchA-ops-assistant-backup_config] commit[~SwitchA-ops-assistant-backup_config] return

4. Verify the configuration.


# Verify the assistant configuration.

<SwitchA> display ops assistant verbose name backup_configAssistant information
  Name                 : backup_config
  State                : ready
  Type                 : command
  Default assistant    : no
 Running statistics
  Running times        : 0
  Queue size/(free)    : 10/(10)
  Skip for queue full  : 0
  Skip for delay       : 0
  Skip for suppression : 0
  Skip for error       : 0
 Execute information
  Task abstract        : backupconfig.py
 Trigger control
  Occurs threshold     : 1
  Period (s)           : 30
  Delay (s)            : 0
  Suppress max         : 0
  Hits in period       : 0
 Condition information
  Correlate expression :
  Condition tag        :
    Condition type     : event
    Subscribe result   : success
    Occurs threshold   : 0
    Period (s)         : 0
    Hits in period     : 0

# After the configuration is complete, run the save command to save the configuration, and then check whether a backup configuration file is saved in the FTP server.


Example of backupconfig.py script

#!/usr/bin/env python

import traceback
import httplib
import string

class OPSConnection(object):
    """Make an OPS connection instance."""

    def __init__(self, host, port = 80):
        self.host = host
        self.port = port
        self.headers = {
            "Content-type": "text/xml",
            "Accept":       "text/xml"
            }
        self.conn = None

    def close(self):
        """Close the connection"""
        self.conn.close()

    def create(self, uri, req_data):
        """Create operation"""
        ret = self.rest_call("POST", uri, req_data)
        return ret

    def delete(self, uri, req_data):
        """Delete operation"""
        ret = self.rest_call("DELETE", uri, req_data)
        return ret

    def get(self, uri, req_data = None):
        """Get operation"""
        ret = self.rest_call("GET", uri, req_data)
        return ret

    def set(self, uri, req_data):
        """Set operation"""
        ret = self.rest_call("PUT", uri, req_data)
        return ret

    def rest_call(self, method, uri, req_data):
        """REST call"""
        print('|---------------------------------- request: ----------------------------------|')
        print('%s %s HTTP/1.1\n' % (method, uri))
        if req_data == None:
            body = ""
        else:
            body = req_data
            print(body)
        if self.conn:
            self.conn.close()
        self.conn = httplib.HTTPConnection(self.host, self.port)

        self.conn.request(method, uri, body, self.headers)
        response = self.conn.getresponse()
        response.status = httplib.OK    # stub code
        ret = (response.status, response.reason, response.read())
        print('|---------------------------------- response: ---------------------------------|')
        print('HTTP/1.1 %s %s\n\n%s' % ret)
        print('|------------------------------------------------------------------------------|')
        return ret

def get_startup_info(ops_conn):
    """Get startup info. """

    uri = "/cfg/startupInfos/startupInfo"
    req_data = \
'''<?xml version="1.0" encoding="UTF-8"?>
<startupInfo>
</startupInfo>
'''
    ret, _, rsp_data = ops_conn.get(uri, req_data)
    if ret != httplib.OK:
        return None

    return rsp_data

def backup_file(ops_conn,cfgFileName):
	"""Copy configuration."""

	uri = "/ftpc/ftpcTransferFiles/ftpcTransferFile"
	str_temp = string.Template(
'''<?xml version="1.0" encoding="UTF-8"?>
<ftpcTransferFile>
	<serverIpv4Address>192.168.20.1</serverIpv4Address>
	<commandType>put</commandType>
	<userName>ftpuser</userName>
	<password>pwd123</password>
	<localFileName>$srcFileName</localFileName>
	<remoteFileName>$desFileName</remoteFileName>
</ftpcTransferFile>
''')

	req_data = str_temp.substitute(srcFileName = cfgFileName,desFileName = cfgFileName.strip('flash:/'))
	ret, _, rsp_data = ops_conn.create(uri, req_data)
	if ret != httplib.OK:
		return None
	return rsp_data

def main():
    """The main function."""

    host = "localhost"
    try:
        ops_conn = OPSConnection(host)
        print('+-------------------------- Open a OPS connection. ----------------------------+')
        rsp_data = get_startup_info(ops_conn)
        if rsp_data is not None:
            cfgFileName = rsp_data[rsp_data.find("curStartupFile")+15 : rsp_data.find("/curStartupFile")-1]
            backup_file(ops_conn,cfgFileName)
        ops_conn.close()
        print('+-------------------------- Close a OPS connection. ---------------------------+')
        return
    except:
        errinfo = traceback.format_exc()
        print(errinfo)
        return

if __name__ == "__main__":
    main()

backupconfig.py script description

#!/usr/bin/env python

import traceback
import httplib
import string

In Python knowledge, the import field is used to import modules. A module is a file of some functions and classes to achieve some purposes.

You can import modules according to service requirements.

class OPSConnection(object):
    """Make an OPS connection instance."""    def __init__(self, host, port = 80):
        self.host = host
        self.port = port
        self.headers = {
            "Content-type": "text/xml",
            "Accept":       "text/xml"
            }
        self.conn = None    def close(self):
        """Close the connection"""
        self.conn.close()    def create(self, uri, req_data):
        """Create operation"""
        ret = self.rest_call("POST", uri, req_data)
        return ret    def delete(self, uri, req_data):
        """Delete operation"""
        ret = self.rest_call("DELETE", uri, req_data)
        return ret    def get(self, uri, req_data = None):
        """Get operation"""
        ret = self.rest_call("GET", uri, req_data)
        return ret    def set(self, uri, req_data):
        """Set operation"""
        ret = self.rest_call("PUT", uri, req_data)
        return ret    def rest_call(self, method, uri, req_data):
        """REST call"""
        print('|---------------------------------- request: ----------------------------------|')
        print('%s %s HTTP/1.1\n' % (method, uri))
        if req_data == None:
            body = ""
        else:
            body = req_data
            print(body)
        if self.conn:
            self.conn.close()
        self.conn = httplib.HTTPConnection(self.host, self.port)

        self.conn.request(method, uri, body, self.headers)
        response = self.conn.getresponse()
        response.status = httplib.OK    # stub code
        ret = (response.status, response.reason, response.read())
        print('|---------------------------------- response: ---------------------------------|')
        print('HTTP/1.1 %s %s\n\n%s' % ret)
        print('|------------------------------------------------------------------------------|')
        return ret

OPSConnection is a class used to invoke RESTful API. This class defines some methods to perform the operations of setting up an HTTP connection:

  • def __init__(): is an initialization class that creates an HTTP connection.

  • def close(): closes an HTTP connection.

  • def create(): creates device resources.

  • def delete(): deletes device resources.

  • def get(): queries device resources.

  • def set(): modifies device resources.

  • def rest_call(): invokes classes internally.

You can invoke this part of script without modifying it.

def get_startup_info(ops_conn):
    """Get startup info. """    uri = "/cfg/startupInfos/startupInfo" req_data = \
'''<?xml version="1.0" encoding="UTF-8"?>
<startupInfo>
</startupInfo>
'''
 ret, _, rsp_data = ops_conn.get(uri, req_data)
    if ret != httplib.OK:
        return None

    return rsp_data

Defines the function for querying device startup information.

uri = "/cfg/startupInfos/startupInfo" indicates the uniform resource identifier (URI) of the object to be managed. For details, see RESTful API.

req_data = indicates the request to be sent.

ret, _, rsp_data = ops_conn.get(uri, req_data) indicates a request to get some data. For details, see the request methods defined in the OPSConnection class.

rsp_data indicates the data sent by the device in response to the request.

def backup_file(ops_conn,cfgFileName):
	"""Copy configuration."""

	uri = "/ftpc/ftpcTransferFiles/ftpcTransferFile"
	str_temp = string.Template(
'''<?xml version="1.0" encoding="UTF-8"?>
<ftpcTransferFile>
	<serverIpv4Address>192.168.20.1</serverIpv4Address>
	<commandType>put</commandType>
	<userName>ftpuser</userName>
	<password>pwd123</password>
	<localFileName>$srcFileName</localFileName>
	<remoteFileName>$desFileName</remoteFileName>
</ftpcTransferFile>
''')

	req_data = str_temp.substitute(srcFileName = cfgFileName,desFileName = cfgFileName.strip('flash:/'))
	ret, _, rsp_data = ops_conn.create(uri, req_data)
	if ret != httplib.OK:
		return None
	return rsp_data

Define the function used to back up the configuration file to a server. The function format is similar to get_startup_info().

def main():
    """The main function."""    host = "localhost"
    try:        ops_conn = OPSConnection(host)
        print('+-------------------------- Open a OPS connection. ----------------------------+')        rsp_data = get_startup_info(ops_conn)
        if rsp_data is not None:
            cfgFileName = rsp_data[rsp_data.find("curStartupFile")+15 : rsp_data.find("/curStartupFile")-1]
            backup_file(ops_conn,cfgFileName)        ops_conn.close()
        print('+-------------------------- Close a OPS connection. ---------------------------+')
        return
    except:
        errinfo = traceback.format_exc()
        print(errinfo)
        return

if __name__ == "__main__":
    main()
  • main() function defines the operations to be performed by this script. You can modify the function according to service requirements.

    host = indicates a loop address. Currently, RESTful API can only be invoked within the device. That is, the value is localhost.

    ops_conn = OPSConnection(host) indicates the operation of setting up an HTTP connection.

    rsp_data = get_startup_info(ops_conn) indicates the operation of invoking functions.

    ops_conn.close() indicates the operation of closing an HTTP connection.

Configuration Files

  • Configuration file of SwitchA

#
sysname SwitchA
#
ops
 assistant backup_config
  execute 1 python backupconfig.py
  condition event feature configuration name CFG_FILE_CHANGE
#
return

Regards!

  • x
  • convention:

Popeye_Wang
Admin Created Oct 23, 2019 02:34:42 Helpful(0) Helpful(0)

Thank you for sharing.
  • x
  • convention:

wissal
MVE Created Nov 6, 2019 18:45:22 Helpful(0) Helpful(0)

Nice, it's very useful.
  • x
  • convention:

Telecommunications%20engineer%2C%20currently%20senior%20project%20manager%20at%20an%20operator%2C%20partner%20of%20Huawei%2C%20in%20the%20radio%20access%20network%20department%2C%20for%2020%20years%20I%20managed%20several%20types%20of%20projects%2C%20for%20the%20different%20nodes%20of%20the%20network.

Comment

Reply
You need to log in to reply to the post Login | Register

Notice Notice: To protect the legitimate rights and interests of you, the community, and third parties, do not release content that may bring legal risks to all parties, including but are not limited to the following:
  • Politically sensitive content
  • Content concerning pornography, gambling, and drug abuse
  • Content that may disclose or infringe upon others ' commercial secrets, intellectual properties, including trade marks, copyrights, and patents, and personal privacy
Do not share your account and password with others. All operations performed using your account will be regarded as your own actions and all consequences arising therefrom will be borne by you. For details, see " Privacy."
If the attachment button is not available, update the Adobe Flash Player to the latest version!
Login and enjoy all the member benefits

Login and enjoy all the member benefits

Login