• 产品与解决方案
  • 行业解决方案
  • 服务
  • 支持
  • 合作伙伴
  • 新华三人才研学中心
  • 关于我们

02-虚拟化技术配置举例

目录

04-IRF零配置举例

本章节下载 04-IRF零配置举例  (267.29 KB)

04-IRF零配置举例


1  简介

本文档主要介绍了如何通过自动配置和Python功能使设备自动组成IRF。

2  配置前提

本文档中的配置均是在实验室环境下进行的配置和验证,配置前设备的所有参数均采用出厂时的缺省配置。如果您已经对设备进行了配置,为了保证配置效果,请确认现有配置和以下举例中的配置不冲突。

本文档假设使用的设备均处于独立运行模式。

本文档假设您已了解IRF、Python和自动配置的特性。

3  使用限制

只有相同型号的机框之间才能建立IRF。建议您在进行IRF零配置时的所有成员设备上均使用相同的单板配置方案,即选用的单板数量及型号、安装槽位号、以及对应 单板的工作模式设置等都保持一致。

4  配置举例

4.1  组网需求

图1所示,某公司两台设备Device A和Device B放置在距离网络管理员较远的地方,所有设备的物理连接已经完成。为了简少网络配置的工作量,需要该公司的管理员通过设备的IRF零配置功能对两台设备进行一定的初始配置。现要求通过IRF零配置实现以下功能:

·     Device A和Device B自动组成IRF。

·     网络管理员能够通过Telnet方式远程登录Device A和Device B组成的IRF设备。

·     登录Device A和Device B虚拟成的IRF设备时需要密码认证。

图1 IRF零配置组网图

 

4.2  配置思路

·     为了保证IRF零配置的成功执行,需要在Device A和Device B上电启动之前按图1所示将网络环境搭建完成,将进行IRF零配置所需的文件准备好并存储在HTTP服务器上,同时要保证DHCP服务器上已经配置完成。Device A和Device B启动时会先从HTTP server下载Python脚本,然后根据Python脚本中的命令控制整个IRF零配置的流程。关于IRF零配置的所需文件的详细介绍,请参见“4.4.2  准备HTTP Server上的配置文件

·     当设备初次上电会自动进入自动配置的流程;当设备中不存在下次启动配置文件的时候,设备启动以后也可以进入到自动配置的流程。

·     为了使设备能成功组成IRF,必须保证Device A和Device B所使用的软件版本相同,所以Python脚本中添加了为Device A和Device B加载相同的启动软件版本的内容。

4.3  适用产品及版本

表1 适用产品及版本

产品

软件版本

S12500G-AF

Release 8053P05及以上版本

S12500CR

Release 8053P05及以上版本

S10500X-G

Release 7753P05及以上版本

S7500X-G

Release 7753P05及以上版本

S7000X

Release 7753P05及以上版本

 

4.4  配置步骤

4.4.1  Device C的配置

# 启动DHCP服务,创建名称为1的DHCP地址池,配置地址池动态分配IP地址的网段为192.168.1.0/24。

<DeviceC> system-view

[DeviceC] dhcp enable

[DeviceC] dhcp server ip-pool 1

[DeviceC-dhcp-pool-1] network 192.168.1.0 24

# 配置DHCP客户端远程启动文件为HTTP形式的URL。

[DeviceC-dhcp-pool-1] bootfile-name http://192.168.1.40/device.py

[DeviceC-dhcp-pool-1] quit

4.4.2  准备HTTP Server上的配置文件

(1)     创建Python脚本device.py并保存到HTTP服务器上。Python脚本是设备进行IRF零配置操作的主要文件,需要用户自行准备并保存在HTTP服务器上。Python脚本需要完成的主要操作:

·     判断Flash是否存在足够的存储空间(请用户根据实际情况进行判断);

·     从HTTP服务器下载配置文件;

·     从HTTP服务器下载启动软件包;

·     从HTTP服务器下载sn.txt文件;

·     配置设备下次启动时使用的启动软件包;

·     解析sn.txt文件并修改设备的IRF成员编号;

·     配置设备下次启动时使用的配置文件;

·     重新启动设备。

Python脚本的具体内容如下(Python脚本中标注有简单的中文注释,使用时请将中文注释删除):

#!usr/bin/python

 

import comware

from time import strftime,gmtime,sleep

import signal

import os

import string

import commands

import hashlib

 

#python_config_file_mode

#'python_static'

#python_serial_number

#U can use 2 modes to obtain the config file

#- 'python_static'

#- 'python_serial_number'

python_config_file_mode = "python_serial_number"

 

#配置本次软件升级设备flash所需的最小剩余空间,单位为KB

#Required space to copy config kickstart and system image in KB

required_space = 500000

 

#配置HTTP服务器的相关参数:用户名、密码、HTTP服务器IP地址、VPN实例名称、登录的超时时间

#transfer information

username = ""

password = ""

hostname = "192.168.1.40"

protocol = "http"

vrf = ""

config_timeout = 120

irf_timeout = 120

image_timeout = 2100

 

#HTTP服务器的下载路径

#Server File Path

server_path = ""

 

#下载到本地设备时,存放到Flash根目录下

#Loacl File path

local_path = "flash:/"

 

#下载到设备之后的配置文件名

#Local config name

config_local_name = "startup.cfg"

 

#HTTP服务器上的配置文件名

#Server config name

config_server_name = "startup.cfg"

 

#下载到本地的启动软件包

#Local boot name

boot_local_name = "switch.ipe"

 

#HTTP服务器上的启动软件包

#Server boot name

boot_server_name = " switch.ipe"

 

#下载到本地的SN文件名

#Local irf name

irf_local_name = "sn.txt"

 

#HTTP服务器上的sn文件名

#Server irf name

irf_server_name = "sn.txt"

 

#设备本地上记录升级日志的log文件名

python_log_name = ""

 

#在设备上记录升级日志的方法

#Write Log File

def write2Log(info):

  global python_log_name, local_path

  if python_log_name == "":

    try:

      python_log_name = "%s%s_python_%s_script.log" %(local_path, strftime("%Y%m%d%H%M%S", gmtime()), os.getpid())

    except Exception as inst:

      print inst

  fd = open(python_log_name, "a")

  fd.write(info)

  fd.flush()

  fd.close()

 

#获取设备的chassis号和slot号,与前面定义的local_path变量,共同计算出文件本地的存放路径

# get path according to the Chassis and Slot

def getPath(chassisID, slotID):

  global local_path

  path = ""

  obj = comware.get_self_slot()

  if (obj[0] == chassisID) and (obj[1] == slotID):

    return local_path

  if chassisID != -1:

    path = "chassis%d#" % chassisID

  if slotID != -1:

    path = "%sslot%d#%s" %(path, slotID, local_path)

  return path

 

#删除下载到本地的文件

#Remove File

def removeFile(filename):

  try:

    os.remove(filename)

  except os.error:

    pass

 

#计算该设备需要删除的文件数量

#Cleanup one device temp files

def cleanDeviceFiles(str, oDevNode):

  global config_local_name, boot_local_name, irf_local_name

  sFilePath = getPath(oDevNode[0], oDevNode[1])

  if str == "error":

    removeFile("%s%s" %(sFilePath, config_local_name))

  removeFile("%s%s" %(sFilePath, boot_local_name))

  removeFile("%s%s" %(sFilePath, irf_local_name))

  removeFile("%s%s.md5" %(sFilePath, config_local_name))

  removeFile("%s%s.md5" %(sFilePath, boot_local_name))

  removeFile("%s%s.md5" %(sFilePath, irf_local_name))

  write2Log("\ndelete %s all files\n" %sFilePath)

  print "\ndelete %s all files" %sFilePath

 

#Cleanup files

def cleanupFiles(str):

  aSlotRange = []

  if ("get_standby_slot" in dir(comware)):

    aSlotRange = aSlotRange + comware.get_standby_slot()

     

  aSlotRange.append(comware.get_self_slot())

  i = 0

  while i < len(aSlotRange):

    if(aSlotRange[i] != None):

      cleanDeviceFiles(str, aSlotRange[i])

    i = i + 1

 

#计算设备flash上的剩余空间大小

#Verify if free space is available to download config, boot-loader image

def verifyfreespace(path):

  global required_space

  try:

    s = os.statvfs(path)

    freespace = (s.f_bavail * s.f_frsize) /1024

    write2Log("\nthe %s free space is %s" %(path, freespace))

    print "\n####the %s free space is %s####" %(path, freespace)

    if required_space > freespace:

      write2Log("\nthe %s space is not enough" % path)

      print "\n####the %s space is not enough####" % path

      return False

  except Exception as inst:

    write2Log("\nverify %s free space exception: %s" % (path, inst))

    print "\n####verify %s free space exception: %s####" % (path, inst)

    return False

  return True

 

#判断设备上的剩余空间是否充足

#verify device freespace

def verifyDeviceFree(obj):

  path = getPath(obj[0], obj[1])

  if True != verifyfreespace(path):

    return False

  return True

 

#check all mpu free space

def verifyAllFreeSpace():

  aSlotRange = []

  if ("get_standby_slot" in dir(comware)):

    aSlotRange = aSlotRange + comware.get_standby_slot()

     

  aSlotRange.append(comware.get_self_slot())

  bAllEnough = True

  i = 0

  while i < len(aSlotRange):

    if(aSlotRange[i] != None) and (True != verifyDeviceFree(aSlotRange[i])):

      bAllEnough = False

    i = i + 1

  return bAllEnough

 

def doExit(str):

  if str == "success":

    write2Log("\nThe script is running success!")

    print "\n#### The script is running success! ####"

    cleanupFiles("success")

    comd = "reboot force"

    comware.CLI(comd, False)

    exit(0)

  if str == "error":

    write2Log("\nThe script is running failed!")

    print "\n#### The script is running failed! ####"

    cleanupFiles("error")

    exit(1)

  else:

    exit(0)

 

#获取软件升级时chassis号和slot号参数

#get Chassis and Slot

def getChassisSlot(style):

  if style == "master":

    obj = comware.get_self_slot()

  if len(obj) <= 0:

    write2Log("\nget %s chassis and slot failed" % style)

    print "\n####get %s chassis and slot failed####" % style

    return None

  return obj

 

#获取启动软件包发生错误返回的信息

#signal terminal handler function

def sig_handler_no_exit(signum, function):

  write2Log("\nSIGTERM Handler while configuring boot-loader variables")

  print "\n####SIGTERM Handler while configuring boot-loader variables####"

 

#软件升级过程发生错误时返回的信息

#signal terminal handler

def sigterm_handler(signum, function):

  write2Log("\nSIGTERM Handler")

  print "\n####SIGTERM Handler####"

  cleanupFiles("error")

  doExit("error")

 

#从HTTP服务器上下载文件

#transfer file

def doCopyFile(src = "", des = "", login_timeout = 10):

  global username, password, hostname, protocol, vrf

  print "INFO: Starting Copy of %s" % src

  try:

    removeFile(des)

    obj = comware.Transfer(protocol, hostname, src, des, vrf, login_timeout, username, password)

    if obj.get_error() != None:

      write2Log("\ncopy %s failed: %s" % (src, obj.get_error()))

      print "\n####copy %s failed: %s####" % (src, obj.get_error())

      return False

  except Exception as inst:

    write2Log("\ncopy %s exception: %s" % (src, inst))

    print "\n####copy %s exception: %s####" % (src, inst)

    return False

  write2Log("\ncopy file %s to %s success" % (src, des))

  print "INFO: Completed Copy of %s" % src

  return True

 

#Get MD5SUM from md5ConfigFile

def getMD5SumGiven(keyword, filename):

  try:

    file = open(filename, "r")

    line = file.readline()

    while "" != line:

      if not string.find(line, keyword, 0, len(keyword)):

        line = line.split("=")

        line = line[1]

        line = line.strip()

        file.close()

        return line

      line = file.readline()

    file.close()

  except Exception as inst:

    write2Log("\nget %s md5 exception: %s" % (filename, inst))

    print "\n####get %s md5 exception: %s####" % (filename, inst)

  return ""

 

#verify MD5SUM of the file

def verifyMD5sumofFile(md5sumgiven, filename):

  if md5sumgiven == "":

    write2Log("\nverify %s md5 error: the %s md5 file is error" %(filename, filename))

    print "\n####verify %s md5 error: the %s md5 file is error####" %(filename, filename)

    return False

  try:

    m = hashlib.md5()

    f = open(filename, 'rb')

    buffer = 8192

    while 1:

      chunk = f.read(buffer)

      if not chunk:

        break

      m.update(chunk)

    f.close()

    md5calculated = m.hexdigest()

  except Exception as inst:

    write2Log("\nverify %s md5 exception: %s" % (filename, inst))

    print "\n####verify %s md5 exception: %s####" % (filename, inst)

    return False

  if md5sumgiven == md5calculated:

    return True

  write2Log("\nverify %s md5 error: md5sumgiven is %s filemd5 is %s" %(filename, md5sumgiven, md5calculated))

  print "\n####verify %s md5 error: md5sumgiven is %s filemd5 is %s####" %(filename, md5sumgiven, md5calculated)

  return False

 

#Check MD5 file

def checkFile(src, dest):

  src = "%s.md5" % src

  destmd5 = "%s.md5" % dest

  bFlag = doCopyFile(src, destmd5, 120)

  if (True == bFlag) and (True == verifyMD5sumofFile(getMD5SumGiven("md5sum", destmd5), dest)):

    write2Log("\ncheckFile success: %s" % destmd5)

    print "\n####checkFile success: %s####" % destmd5

    return True

  elif (True != bFlag):

    write2Log("\n%s is not exist! Don't verify the MD5 file!" % destmd5)

    print "INFO: %s is not exist! Don't verify the MD5 file!" % destmd5

    return True

  return False

 

#Get config file according to the mode

def getCfgFileName():

  global config_server_name

  if (python_config_file_mode == "python_serial_number") and (os.environ.has_key('DEV_SERIAL')):

    config_server_name = "%s.cfg" % os.environ['DEV_SERIAL']

    return config_server_name

  else:

    return config_server_name

 

#copy file to all standby slot

def syncFileToStandby(sSrcFile, sFileName):

  try:

    aSlotRange = []

    if ("get_standby_slot" in dir(comware)):

      aSlotRange = aSlotRange + comware.get_standby_slot()

         

    i = 0

    while i < len(aSlotRange):

      if(aSlotRange[i] != None):

        sDestFile = "%s%s" %(getPath(aSlotRange[i][0], aSlotRange[i][1]), sFileName)

        removeFile(sDestFile)

        open(sDestFile,"wb").write(open(sSrcFile,"rb").read())

        write2Log("\nsync file to standby %s" % (sDestFile))

        print "\n####sync file to standby %s####" % (sDestFile)

      i = i + 1

  except Exception as inst:

    write2Log("\nsync file to standby %s exception: %s" % (sSrcFile, inst))

    print "\n####sync file to standby %s exception: %s####" % (sSrcFile, inst)

 

#根据脚本开始处定义的全局变量,下载启动软件包、配置文件、sn文件等

#Procedure to copy config file using global information

def copyAndCheckFile(src, dest, timeout):

  global server_path, local_path

  srcTmp = "%s%s" % (server_path, src)

  sDestFile = "%s%s" % (local_path, dest)

  if (True == doCopyFile(srcTmp, sDestFile, timeout)) and (True == checkFile(srcTmp, sDestFile)):

    syncFileToStandby(sDestFile, dest)

    return True

  else:

    srcTmp = "%sdefault_%s" %(server_path, src)

    if (True == doCopyFile(srcTmp, sDestFile, timeout)) and (True == checkFile(srcTmp, sDestFile)):

      syncFileToStandby(dest)

      return True

  return False

 

# split the Chassis and Slot

def splitChassisSlot(chassisID, slotID):

  chassis_slot = ""

  if chassisID != -1:

    chassis_slot = " chassis %d"  % chassisID

  if slotID != -1:

    chassis_slot = "%s slot %d" %(chassis_slot, slotID)

  return chassis_slot

 

#从HTTP服务器上下载启动软件包

def copyBootImage():

  global image_timeout, local_path, boot_server_name, boot_local_name

  src = "%s" % boot_server_name

  return copyAndCheckFile(src, boot_local_name, image_timeout)

 

#从HTTP服务器上下载配置文件

def copyCfgFile():

  global config_timeout, local_path, config_local_name

  src = "%s" % getCfgFileName()

  return copyAndCheckFile(src, config_local_name, config_timeout)

 

#从HTTP服务器上下载sn.txt文件

def copyIrfStack():

  global irf_timeout, local_path, irf_local_name, irf_server_name

  src = "%s" % irf_server_name

  return copyAndCheckFile(src, irf_local_name, config_timeout)

 

#执行boot-loader命令,为设备指定下次主用启动文件

# Procedure to Install Boot Image

def installBoot(chassis_slot, sFile, style):

  result = None

  write2Log("\ninstall%s%s begin" %(chassis_slot, style))

  print "INFO: Install%s%s Start, Please Wait..." %(chassis_slot, style)

  comd = "boot-loader file %s%s%s" % (sFile, chassis_slot, style)

  try:

    result = comware.CLI(comd, False)

    if result == None:

      write2Log("\nboot-loader file %s%s%s failed" % (sFile, chassis_slot, style))

      print "\n####boot-loader file %s%s%s failed####" % (sFile, chassis_slot, style)

      return False

  except Exception as inst:

    write2Log("\nboot-loader %s exception: %s" % (sFile, inst))

    print "\n####boot-loader %s exception: %s####" % (sFile, inst)

    return False

  return True

 

#Procedure to install boot image

def installBootImage():

  global boot_local_name

  aSlotRange = [comware.get_self_slot()]

  if ("get_standby_slot" in dir(comware)):

    aSlotRange = aSlotRange + comware.get_standby_slot()

  bInstallOk = True

  i = 0

  while i < len(aSlotRange):

    sFile = "%s%s" %(getPath(aSlotRange[0][0], aSlotRange[0][1]), boot_local_name)

    if False == installBoot(splitChassisSlot(aSlotRange[i][0], aSlotRange[i][1]), sFile, " main"):

      bInstallOk = False

    i = i + 1

  return bInstallOk

 

#执行startup saved-configuration命令为设备指定下次启动配置文件

def startupCfg():

  global local_path, config_local_name

  result = None

  dest = "%s%s" %(local_path, config_local_name)

  write2Log("\nstartup saved-configuration %s begin" %dest)

  print "INFO: Startup Saved-configuration Start"

  comd = "startup saved-configuration %s main" % dest

  try:

    result = comware.CLI(comd, False)

    if result == None:

      write2Log("\nstartup saved-configuration %s failed" % dest)

      print "\n####startup saved-configuration %s failed####" % dest

      return False

  except Exception as inst:

    write2Log("\nstartup %s exception: %s" % (dest, inst))

    print "\n####startup %s exception: %s####" % (dest, inst)

    return False

  write2Log("\nstartup saved-configuration %s success" % dest)

  print "INFO: Completed Startup Saved-configuration"

  return True

 

def getIrfCfg(line, num):

  line = line.split()

  number = None

  if 3 == len(line):

    number = line[num]

  else :

    number = None

  return number

 

def getMemberID():

  aMemId = comware.get_self_slot()

  memId = None

  if aMemId[0] == -1 :

    memId = aMemId[1]

  else :

    memId = aMemId[0]

  return memId

 

def getNewMemberID():

  global irf_local_name, local_path, env

  filename = "%s%s" %(local_path, irf_local_name)

  serNum = os.environ['DEV_SERIAL']

  reNum = None

  try:

    file = open(filename, "r")

    line = file.readline()

    while "" != line:

      if (serNum == getIrfCfg(line, 0)):

        file.close()

        reNum = getIrfCfg(line, 2)

        return reNum

      line = file.readline()

    file.close()

  except Exception as inst:

    write2Log("\nget renumberID exception: %s" % inst)

    print "\n####get renumberID exception: %s####" % inst

  write2Log("\nget %s renumberID failed" % filename)

  print "\n#### get %s renumberID failed ####" % filename

  return reNum

 

#判断设备是否是处于已经建立IRF

def isIrfDevice():

  try:

    result = comware.CLI("display irf", False)

    if result == None:

      return False

  except Exception as inst:

    return False

  return True

 

#解析sn.txt文件并使用renumber修改设备的IRF成员编号

def getIrfComd():

  comd = None

  newMemberID = getNewMemberID()

  aMemId = comware.get_self_slot()

  if None == newMemberID:

    return None

  if False == isIrfDevice():

    comd = "system-view ; irf member %s ; chassis convert mode irf" % newMemberID

  else:

    comd = "system-view ; irf member %s renumber %s" % (getMemberID(), newMemberID)

  return comd

 

def stackIrfCfg():

  global env

  if (not os.environ.has_key('DEV_SERIAL')):

    write2Log("\nenviron variable 'DEV_SERIAL' is not found!")

    print "\n####environ variable 'DEV_SERIAL' is not found!####"

    return False

  comd = getIrfComd()

  if None == comd:

    return False

  result = None

  write2Log("\nstartup stack irf begin")

  print "INFO: Startup stack irf Start"

  try:

    result = comware.CLI(comd, False)

    if result == None:

      write2Log("\nstartup stack irf failed: %s" % comd)

      print "\n####startup stack irf failed: %s####" %comd

      return False

  except Exception as inst:

    write2Log("\nstartup stack irf exception: %s command: %s" % (inst, comd))

    print "\n####startup stack irf exception: %s command: %s####" % (inst, comd)

    return False

  write2Log("\nstartup stack irf success")

  print "INFO: Completed Startup Stack Irf"

  return True

 

#check if all standby slots are ready

def ifAllStandbyReady():

  if (("get_slot_range" in dir(comware)) == False):

    return True

     

  aSlotRange = comware.get_slot_range()

  bAllReady = True

  for i in range(aSlotRange["MinSlot"], aSlotRange["MaxSlot"]):

    oSlotInfo =  comware.get_slot_info(i)

    if (oSlotInfo != None) and (oSlotInfo["Role"] == "Standby") and (oSlotInfo["Status"] == "Fail"):

      bAllReady = False

      write2Log("\nSlot %s is not ready!" %i)

      print "\n####Slot %s is not ready!####" %i

  return bAllReady

 

#if have any standby slot was not ready sleep for waiting

def waitStandbyReady():

  while ifAllStandbyReady() == False:

    sleep(10)

 

#python main

 

#when download file user can stop script

waitStandbyReady()

signal.signal(signal.SIGTERM, sigterm_handler)

 

if (True == verifyAllFreeSpace()) and (True == copyBootImage()) and (True == copyCfgFile()) and (True == copyIrfStack()):

  #after download file user can not stop script

  signal.signal(signal.SIGTERM, sig_handler_no_exit)

  if (True == installBootImage()) and (True == startupCfg()) and (True == stackIrfCfg()):

    doExit("success")

doExit("error")

 

(2)     创建配置文件serial_number.cfg(serial_number 为进行IRF零配置设备的序列号,例如下面所使用的配置文件名称)并在保存到HTTP服务器上。配置文件包含了所有设备建立IRF、通过Telnet方式远程登录、登录时密码认证的相关命令。文件内容如下:

·     210235A045B05B0004354.cfg:

#

telnet server enable

#

 irf mac-address persistent timer

 irf auto-update enable

 undo irf link-delay

 irf member 1 priority 1

#

irf-port 1/2

 port group mdc 1 interface HundredGigE3/0/1 mode enhanced

#

interface HundredGigE3/0/1

 port link-mode bridge

#

interface M-GigabitEthernet0/0/0

 ip address 192.168.0.63 255.255.255.0

#

line vty 0 63

 user-role network-admin

 set authentication password simple 123

#

·     210235A045B05B0004350.cfg:

#

telnet server enable

#

 irf mac-address persistent timer

 irf auto-update enable

 undo irf link-delay

 irf member 2 priority 1

#

irf-port 2/1

 port group mdc 1 interface HundredGigE3/0/1 mode enhanced

#

interface HundredGigE3/0/1

 port link-mode bridge

#

interface M-GigabitEthernet0/0/0

 ip address 192.168.0.63 255.255.255.0

#

line vty 0 63

 user-role network-admin

 set authentication password simple 123

#

(3)     创建sn.txt文件并保存在HTTP服务器上。每个设备的主控板都有序列号,sn.txt文件将序列号和成员编号做一对一的映射,以便Pythone脚本能够自动给设备配置指定的成员编号。设备通过运行Python脚本来解析sn.txt文件,然后修改设备的IRF成员编号,并根据自身的成员编号来完成相应的IRF配置。文件内容如下:

sn                         Irf group                  Irf number

210235A045B05B0004354          100                           1

210235A045B05B0004350          100                           2

sn.txt文件中的sn列为设备机框的序列号(serial number),可以通过粘贴在设备机框后面板上的标签查看其序列号,也可以通过在设备上执行display device manuinfo命令进行查看。sn.txt文件中的Irf group列是用来标记IRF组的数字,用户可以自行编辑,不会对设备的配置产生影响。sn.txt文件中的Irf number列为设备在IRF组中的成员编号。

(4)     将软件启动包switch.ipe保存在HTTP服务器上。软件启动包是设备启动、运行的必备软件,使用自动配置进行软件升级,使现有设备(包括主用主控板和备用主控板)的启动软件版本一致,以保证Device A和Device B能够成功建立IRF。

4.4.3  HTTP Server的配置

启动HTTP管理软件,开启HTTP服务(配置过程略)。

4.5  验证配置

下面以Telnet方式登录Device A为例验证设备是否成功完成自动配置,Device B和Device A验证效果相同,不再赘述。

# 登录设备并输入密码进行身份验证。

Password:

******************************************************************************

* Copyright (c) 2004-2019 New H3C Technologies Co., Ltd. All rights reserved.*

* Without the owner's prior written consent,                                 *

* no decompiling or reverse-engineering shall be allowed.                    *

******************************************************************************

 

<DeviceA>

以上信息表明输入密码通过身份验证后,设备登录成功。

# 显示IRF中所有成员设备的相关信息。

<DeviceA> display irf

MemberID  Slot  Role    Priority  CPU-Mac         Description

   1      1     Standby 1         00e0-fc0f-8c02  ---

 *+2      1     Master  1         00e0-fc0f-8c14  ---

--------------------------------------------------

 * indicates the device is the master.

 + indicates the device through which the user logs in.

 

 The Bridge MAC of the IRF is: 000c-1000-1111

 Auto upgrade                : yes

 Mac persistent              : 6 min

 Domain ID                   : 0

 Auto merge                  : yes

 IRF mode                    : enhanced

以上显示信息表明IRF已经成功建立。

4.6  配置文件

·     Device A和Device B:

#

telnet server enable

#

 irf mac-address persistent timer

 irf auto-update enable

 undo irf link-delay

 irf member 1 priority 1

 irf member 2 priority 1

#

irf-port 1/2

port group mdc 1 interface HundredGigE3/0/1 mode enhanced

#

irf-port 2/1

 port group mdc 1 interface HundredGigE3/0/1 mode enhanced

#

interface HundredGigE3/0/1

 port link-mode bridge

#

 

interface M-GigabitEthernet0/0/0

 ip address 192.168.0.63 255.255.255.0

#

line vty 0 63

 user-role network-admin

 set authentication password hash $h$6$40hhbS6PeVJORuQu$X/9nQ9PSpPbtGDukVYGOW2Ao

9yJaekVbzovWv23pEKCVwzqqRP8Elnm1qRm4TEIbAetmwQG5gWyREMC3zRCOaQ==

#

·     Device C:

#

 dhcp enable

#

dhcp server ip-pool 1

 network 192.168.1.0 mask 255.255.255.0

 bootfile-name http://192.168.1.40/device.py

#

5  故障的诊断与排除

5.1  Python脚本无法正常运行

1. 故障现象

进入自动配置流程后,屏幕上打印出“File "autocfgjuQccA", line 5”,脚本中的import signal命令出错。

2. 故障排除

请检查脚本里面的命令前面是否出现了多余的空格或字符,请不要随便修改脚本格式。

5.2  md5文件获取失败

1. 故障现象

从HTTP Server上获取配置文件和程序文件是提示md5文件获取失败或未获取到md5文件。

2. 故障排除

md5文件用于检查HTTP Server上配置文件和程序文件的正确性。脚本中会有md5文件检查的步骤,当HTTP Server上没有配置文件和程序文件对应的md5文件时,会提示未获取到md5文件,此步骤就会被忽略,继续执行下面的脚本,无需关注;当HTTP Server上有配置文件和程序文件对应的md5文件时,请确保md5文件的正确性。

不同款型规格的资料略有差异, 详细信息请向具体销售和400咨询。H3C保留在没有任何通知或提示的情况下对资料内容进行修改的权利!

新华三官网
联系我们