Python을 이용한 NSO 서비스 개발
1. NSO에서 Python 사용하기
Python 사용 이유?
- NSO 서비스 템플릿은 유용하지만 외부 통합에서의 유연성이 부족
- Python은 스크립팅 개발에 권장되는 언어
NSO에서 Python을 사용하는 방법
- Python 스크립팅
- NSO 데이터 저장소에 연결하고 트랜잭션을 사용하여 데이터를 읽고 쓸 수 있음
- 장치 구성 가져오기 또는 구성 보고서 생성과 같은 일회성 작업에 유용
- 서비스 패키지에서 Python 코드 사용
- 외부 시스템 과의 복잡한 계산 및 통합을 코드로 구현
- Python에서 XML 템플릿을 채우고 적용
- NSO의 FASTMAP 알고리즘 사용이 가능(create 메서드 정의시 delete 및 update 작업 자동 처리)
Python API
NSO는 low-level, high-level Python API 제공
- 과거 에이전트 API(MAAPI) - ncs.maapi
- 구성 및 운영 데이터에 대한 트랜잭션 접근을 제공
- local 또는 원격 NSO Python API 인스턴스에 연결 가능
- 트랜잭션 액세스 허용 모듈
import ncs with ncs.maapi.single_write_trans('admin', 'system') as t: t.get_elem('/devices/device{internet-rtr0}/address')
- 데이터 스토어 탐색
- Python의 점 표기법을 사용해 직관적인 탐색 가능
- 탐색 모듈
# 리스트 항목 접근 router = root.devices.device['internet-rtr0'] # 리스트 항목 생성 root.services.l3vpn.create('test-l3vpn') # 존재 여부 확인 'internet-rtr0' in root.devices.device # leaf 값 설정 root.devices.device['internet-rtr0'].address = '10.0.0.1' # 리스트 항목 제거 del root.devices.device['internet-rtr0']
- FASTMAP 서비스 - ncs.application
- 서비스를 포함한 Python 기반 NSO application 개발에 사용
- @Service.create 데코레이터는 NSO가 서비스 인스턴스를 생성하는 데 사용하는 메서드를 표시. NSO의 FASTMAP 알고리즘은 이를 기반으로 삭제 및 업데이트 프로세스를 관리
class ServiceCallbacks(Service): @Service.create def cb_create(self, tctx, root, service, proplist):
- 템플릿 처리 - ncs.template 모듈
- Pyhton 내에서 템플릿 작업을 간소화
- 템플릿 변수를 채우고 코드로 템플릿을 적용할 수 있음
vlan_tvars = ncs.template.Variables() vlan_tvars.add('VLAN-ID', service.vlan_id + 10) vlan_template = ncs.template.Template(service) vlan_template.apply('vlan-template', vlan_tvars)
NSO Python 개발 환경 설정
- 환경 변수
- NCS_DIR: NSO가 설치된 디렉토리 (일반적으로 NSO의 ncsrc 파일을 소싱하여 자동으로 설정)
- LAB_DIR: 랩 명령을 위한 루트 디렉토리
- NCS_RUN_DIR: NSO 런타임 디렉토리
- 설정 단계
- 디렉토리 생성
export LAB_DIR=${HOME}/src mkdir -p ${LAB_DIR} export NCS_RUN_DIR=${LAB_DIR}/nso-instance mkdir -p ${NCS_RUN_DIR} cd ${LAB_DIR}
- Netsim 장치 및 NED 패키지 준비
Netsim은 애뮬레이터로 실제 환경이 있으면 필요 없음.ncs-netsim --dir ${NCS_RUN_DIR}/netsim create-network $NCS_DIR/packages/neds/cisco-ios-cli-3.0 1 dist-rtr ncs-netsim --dir ${NCS_RUN_DIR}/netsim add-to-network $NCS_DIR/packages/neds/cisco-iosxr-cli-3.5 1 core-rtr
- NSO 인스턴스 설정
ncs-setup --dest ${NCS_RUN_DIR} --netsim-dir ${NCS_RUN_DIR}/netsim
- NetSim 장치 및 NSO 시작
cd ${NCS_RUN_DIR} ncs-netsim start ncs
- Netsim을 통해 만든 장치 동기화
ncs_cli -C -u admin devices device core-rtr0 sync-from exit
- 디렉토리 생성
2. 스크립팅을 위한 Python API 사용
참고: Pyhon API 문서 → 일회성 작업을 위해 많이 사용
대화형 Python 인터프리터에서 NSO에 연결
- NSO가 장치에 연결하는 데 필요한 인쇄 관리 주소를 설정
import ncs # Python API와 함께 작동하는 하위 모듈이 포함된 ncs 모듈 가져오기 m = ncs.maapi.Maapi() # 새 Maapi 객체 초기화 m.start_user_session('admin', 'system', []) # 여러 트랜잭션을 허용하는 새 사용자 세션 시작 trans = m.start_read_trans() # 새 읽기 트랜잭션 시작, 이를 사용하여 CDB에 데이터를 쓸 수 없음 root = ncs.maagic.get_root(trans) # Maagic API를 사용하여 CDB의 루트에 접근 for dev in root.devices.device: # Maagic root 객체를 사용하여 NSO의 장치 반복 print(f"Device {dev.name} address {dev.address}") # NSO가 장치 관리에 사용하는 이름과 주소 출력 m.close() # 세션 종료 및 소켓 닫기
- 단일 읽기, 쓰기 트랜잭션만 필요한 경우
import ncs with ncs.maapi.single_write_trans('admin', 'system') as t: root = ncs.maagic.get_root(t) root.devices.device['core-rtr0'].config.hostname = 'test-device' t.apply()
Python 스크립트
- 제공된 매개변수를 기반으로 NSO 장치 추가 스크립트
import argparse import ncs def parse_args(): parser = argparse.ArgumentParser() parser.add_argument('--name', help='device name', required=True) parser.add_argument('--address', help='device address', required=True) parser.add_argument('--ned', help='device NED ID', required=True) parser.add_argument('--port', help='device port', type=int, default=22) parser.add_argument('--desc', help='device description', default='Device created by maagic_create_device.py') parser.add_argument('--auth', help='device authgroup', default='default') return parser.parse_args() def main(args): with ncs.maapi.Maapi() as m: with ncs.maapi.Session(m, 'admin', 'system'): with m.start_write_trans() as t: print(f'Setting the device "{args.name}" configuration...') # Get a reference to the device list root = ncs.maagic.get_root(t) device_list = root.devices.device if args.name not in device_list: device = device_list.create(args.name) device.address = args.address device.port = args.port device.description = args.desc device.authgroup = args.auth dev_type = device.device_type.cli dev_type.ned_id = args.ned device.state.admin_state = 'unlocked' print('Committing the device configuration...') t.apply() print('Device committed!') else: print(f'Device "{args.name}" configuration already exists...') # This transaction is no longer valid - since we are moving # back under ncs.maapi.Session(m, 'admin', 'python') # fetch-host-keys and sync-from does not require a # transaction, continue using the Maapi object root = ncs.maagic.get_root(m) device = root.devices.device[args.name] print('Fetching SSH keys...') output = device.ssh.fetch_host_keys() print(f'Result: {output.result}') print('Syncing configuration...') output = device.sync_from() print(f'Result: {output.result}') if not output.result: print(f'Error: {output.info}') if __name__ == '__main__': main(parse_args())
3. 서비스 패키지에서 Python 사용
서비스 구현 옵션
접근 방식 | 장점 | 단점 |
---|---|---|
YANG + 템플릿 | 구현 속도가 빠름 | 옵션 제한적, 정적 매핑만 가능 |
YANG + Python | 다재다능함, 사용자 정의 알고리즘, 외부 통합 구현 가능 | 매핑 구현 속도가 느림, 장치 모델 변경 시 코드 변경 필요 |
YANG + Python + 템플릿 | 두 접근 방식의 장점 결합 - 복잡한 알고리즘 및 통합은 Python으로, 장치 구성 생성은 템플릿으로 |
- YANG + Python + template 의 방식이 가장 적합
Python 코드 기반 패키지 생성
ncs-make-package --service-skeleton python-and-template --component-class l2vpn.L2vpn l2vpn [developer@nso ~]$ tree l2vpn l2vpn |-- README |-- package-meta-data.xml |-- python | `-- l2vpn | |-- __init__.py | `-- l2vpn.py |-- src | |-- Makefile | `-- yang | `-- l2vpn.yang |-- templates | `-- l2vpn-template.xml `-- test
[developer@nso ~]$ cat l2vpn/package-meta-data.xml <ncs-package xmlns="http://tail-f.com/ns/ncs-packages"> <name>l2vpn</name> <package-version>1.0</package-version> <description>Generated Python package</description> <ncs-min-version>6.2</ncs-min-version> <component> <name>l2vpn</name> <application> <python-class-name>l2vpn.l2vpn.L2vpn</python-class-name> </application> </component> </ncs-package>
class L2vpn(ncs.application.Application): def setup(self): # 애플리케이션 클래스에서 로깅을 설정합니다. 액세스할 수 있습니다 # 'self.log'를 통해 ncs.log.log 인스턴스입니다. self.log.info('L2vpn RUNNING') # 서비스 콜백은 '서비스 포인트'에 대한 등록이 필요합니다, self.register_service('l2vpn-servicepoint', ServiceCal
4. Python 및 템플릿 기반 서비스 만들기
- 기존과 달리 IP 주소 대신 IPv4 접두사 제공
service skeleton 생성
ncs-make-package --no-java --service-skeleton python-and-template --component-class loopback.Loopback --dest ${NCS_RUN_DIR}/packages/loopback loopback
YANG 모델 생성
- ${NCS_RUN_DIR}/packages/loopback/src/yang/loopback.yang
- 초기 구성
module loopback { namespace "http://com/example/loopback"; prefix loopback; import ietf-inet-types { prefix inet; } import tailf-ncs { prefix ncs; } list loopback { key name; uses ncs:service-data; ncs:servicepoint "loopback-servicepoint"; leaf name { type string; } // may replace this with other ways of refering to the devices. leaf-list device { type leafref { path "/ncs:devices/ncs:device/ncs:name"; } } // replace with your own stuff here leaf dummy { type inet:ipv4-address; } } }
- 변경 구성 - 인스턴스 name, device, loopback-intf leaf 추가 필요
module loopback { namespace "http://com/example/loopback"; prefix loopback; import tailf-ncs { prefix ncs; } import ietf-inet-types { prefix inet; } import tailf-common { prefix tailf; } list loopback { key name; uses ncs:service-data; ncs:servicepoint loopback-servicepoint; leaf name { tailf:info "Service instance name"; type string; } leaf device { tailf:info "Device name"; type leafref { path "/ncs:devices/ncs:device/ncs:name"; } } leaf loopback-intf { tailf:info "Loopback interface number"; type uint32; } leaf ip-prefix { tailf:info "IP prefix used to configure an address loopback interface"; type inet:ipv4-prefix; mandatory true; } } }
- YANG 모델을 사용하려면 컴파일 해야하므로 패키지 빌드
make -C ${NCS_RUN_DIR}/packages/loopback/src/
- 초기 구성
ipaddress 모듈 사용
- ip-prefix 사용자가 제공한 리프에서 사용 가능한 IP 주소를 얻으려면 Python 라이브러리의 모듈을 사용
python3 << EOF import ipaddress net = ipaddress.IPv4Network('10.0.0.0/24') address = next(net.hosts()) print(address) EOF
Python 매핑 논리 만들기
- ${NCS_DIR}/packages/loopback/python/loopback/loopback.py
# -*- mode: python; python-indent: 4 -*- # 파일을 Python 코드로 인식하고 4칸 들여쓰기를 사용하도록 지시합니다. import ncs # NSO Python API의 기능을 사용하기 위한 호출 from ncs.application import Service # ncs 라이브러리 내의 application 서브모듈에서 'Service' 클래스를 가져오고, 이를 기반으로 NSO 서비스 로직 구현 # ------------------------ # 서비스 콜백 예시 # ------------------------ class ServiceCallbacks(Service): # 'Service' 클래스를 상속받아 'ServiceCallbacks'라는 새로운 클래스를 정의 # 이 클래스 내부에 NSO 서비스 인스턴스의 실제 로직(생성, 삭제, 업데이트 등)이 구현 # create() 콜백은 NSO FASTMAP 내에서 호출되며 항상 존재 @Service.create # @ 데코레이터로 원래 함수의 기능을 변경하거나 확장하는 기능 (여기서는 FASTMAP 호출을 위해 사용) # 이 데코레이터는 'cb_create' 메서드가 서비스 인스턴스 생성 시 NSO 프레임워크에 의해 호출되어야 하는 콜백 함수임을 등록 # 개발자는 create 메서드만 구현하면 NSO가 update 및 delete를 자동으로 처리 def cb_create(self, tctx, root, service, proplist): # 서비스 생성 로직을 담는 메서드 # self: 클래스 인스턴스 자체를 참조하며, 주로 self.log를 통해 로그를 남기는 데 사용 # tctx: 현재 NSO 트랜잭션에 대한 컨텍스트 정보 # root: NSO의 설정 데이터베이스(CDB) 루트를 가리키는 객체 # service: 현재 처리 중인 서비스 인스턴스의 데이터를 나타내는 객체, 이 객체를 통해 서비스의 입력 파라미터(예: service.ip_prefix)에 접근 가능 # proplist: 여러 콜백 메서드 호출 간에 매개변수를 전달하는 데 사용될 수 있는 속성 목록 self.log.info('Service create(service=', service._path, ')') # 서비스 생성 콜백이 호출되었음을 알리는 정보성 로그 메시지를 출력 # service._path는 현재 서비스 인스턴스의 CDB 경로를 나타내며, 로그에서 서비스의 실행 흐름을 추적하는 데 유용 vars = ncs.template.Variables() # 템플릿에 전달할 변수들을 저장할 객체를 생성 vars.add('DUMMY', '127.0.0.1') # 'DUMMY'라는 변수에 '127.0.0.1' 값을 추가, 변수는 나중에 템플릿 파일에서 사용 template = ncs.template.Template(service) # NSO 템플릿을 처리하기 위한 'Template' 객체를 생성 # 현재 서비스 인스턴스의 컨텍스트 내에서 템플릿이 적용되도록 service 객체를 전달 template.apply('loopback-template', vars) # 'loopback-template'이라는 이름의 XML 템플릿 파일에 'vars' 객체에 정의된 변수들을 적용 # 이 과정에서 템플릿 내의 변수 플레이스홀더가 실제 값으로 채워져 최종 장치 구성이 생성 # ... # 이 부분은 다른 콜백 메서드(예: cb_delete, cb_update)가 생략되었음을 나타냅니다. # FASTMAP 덕분에 create만 구현해도 되지만, 필요에 따라 추가할 수 있습니다. # --------------------------------------------- # NSO에 의해 시작될 컴포넌트 스레드 # --------------------------------------------- class Loopback(ncs.application.Application): # 'ncs.application.Application' 클래스를 상속받는 'Loopback'이라는 클래스를 정의 # 이것은 NSO 애플리케이션의 진입점으로 NSO가 Python 코드를 실행할 때, 이 클래스의 인스턴스를 생성하고 'setup()' 메서드를 호출 def setup(self): # NSO가 애플리케이션을 초기화할 때 호출하는 메서드 # 여기에서 서비스 콜백 등록과 같은 초기 설정을 수행 # 애플리케이션 클래스는 우리를 위해 로깅을 설정, self.log를 통해 접근할 수 있으며 ncs.log.Log 인스턴스 self.log.info('Loopback RUNNING') # 서비스 콜백은 해당 데이터 모델에 지정된 '서비스 포인트' 등록 요구 self.register_service('loopback-servicepoint', ServiceCallbacks) # 'loopback-servicepoint'라는 이름의 서비스 포인트에 'ServiceCallbacks' 클래스를 등록 # 이는 NSO가 YANG 모델에 정의된 'loopback-servicepoint'에 대한 서비스 인스턴스를 처리할 때, # 'ServiceCallbacks' 클래스에 정의된 콜백(예: cb_create)을 호출하도록 지시하는 부분
- FASTMAP 알고리즘을 사용하므로 create 메서드만 구현하면 됨.
- NSO가 cb_create 메서드에 전달하는 매개변수
def cb_create(self, tctx, root, service, proplist): self.log.info('Service create(service=', service._path, ')') ip_prefix = service.ip_prefix
- self: 로그 속성에 접근하는데 사용되며, 이를 사용하여 각 서비스가 갖는 Python 로그에 메시지를 내보낼 수 있음
- tctx: 트랜잭션 컨텍스트 정보
- root: CDB의 루트를 가리키는 MAAGIC 객체. root를 사용하면 데이터 스토어에 저장된 모든 구성 데이터에 접근할 수 있다.
- proplist: 콜백 메서드 호출 간에 매개변수를 전달하는 데 사용할 수 잇는 속성 목록
- 호스트 주소 계산 python
import ncs import ipaddress # 'ipaddress' 모듈은 Python 표준 라이브러리의 일부로, IP 주소, 네트워크, 서브넷 등을 다루는 데 필요한 클래스와 함수를 제공 from ncs.application import Service class ServiceCallbacks(Service): # 'Service' 클래스를 상속받아 'ServiceCallbacks'라는 새로운 클래스를 정의합니다. # 이 클래스 내부에 NSO 서비스 인스턴스에 대한 실제 로직(주로 생성, 업데이트, 삭제)이 구현됩니다. @Service.create # 이 데코레이터는 'cb_create' 메서드가 NSO의 FASTMAP 알고리즘 내에서 호출되어야 하는 # '서비스 생성' 콜백임을 NSO 프레임워크에 등록합니다. def cb_create(self, tctx, root, service, proplist): self.log.info('Service create(service=', service._path, ')') # 서비스 생성 콜백이 호출되었음을 알리는 정보성 로그 메시지를 출력 ip_prefix = service.ip_prefix # 현재 처리 중인 서비스 인스턴스('service' 객체)에서 'ip-prefix'라는 이름의 리프(leaf) 값을 가져와 'ip_prefix' 변수에 저장. 이 값은 사용자가 서비스에 입력한 IP 프리픽스입니다. self.log.debug(f'Value of ip-prefix leaf is {ip_prefix}') # 'ip-prefix' 리프의 값이 무엇인지 디버그 로그 메시지로 출력 net = ipaddress.IPv4Network(ip_prefix) # 'ipaddress' 모듈의 'IPv4Network' 클래스를 사용하여 'ip_prefix' 문자열로부터 IPv4 네트워크 객체를 생성. # 네트워크 주소, 브로드캐스트 주소, 사용 가능한 호스트 범위 등 네트워크에 대한 정보를 포함합니다. ip_address = next(net.hosts())
5. 서비스 템플릿 만들기 및 적용
- 장치 구성 과정
- Python 코드에서 적용된 XML 템플릿 사용
- Python 코드에서 직접 장치 모델에 작성
NSO CLI를 사용해 서비스 템플릿 만들기
- NSO 접속 및 config 변경
ncs_cli -C -u admin config devices device dist-rtr0 config interface Loopback 100 ip address 192.168.10.20 255.255.255.255 # 변경 사항을 출력해서 템플릿에 옮기기 commit dry-run outformat xml end no-confirm exit
- ${NCS_RUN_DIR}/packages/loopback/templates/loopback-template.xml 파일 변경
<config-template xmlns="http://tail-f.com/ns/config/1.0"> <devices xmlns="http://tail-f.com/ns/ncs"> <device> <name>{/device}</name> <config> <interface xmlns="http://tail-f.com/ned/cisco-ios-xr"> <Loopback> <id>{/loopback-intf}</id> <ipv4> <address> <ip>{$IP_ADDRESS}</ip> <mask>255.255.255.255</mask> </address> </ipv4> </Loopback> </interface> <interface xmlns="urn:ios"> <Loopback> <name>{/loopback-intf}</name> <ip> <address> <primary> <address>{$IP_ADDRESS}</address> <mask>255.255.255.255</mask> </primary> </address> </ip> </Loopback> </interface> </config> </device> </devices> </config-template>
Python에서 서비스 템플릿 채우기 및 적용
- Python code
import ncs # NSO의 핵심 API를 포함하는 라이브러리입니다. NSO 데이터 모델, 트랜잭션, 템플릿 등과 상호작용할 때 사용됩니다. import ipaddress # Python 표준 라이브러리로, IP 주소 및 네트워크를 다루는 데 사용됩니다. 여기서는 IP 주소 접두사에서 유효한 IP를 추출하는 데 활용됩니다. from ncs.application import Service # NSO 서비스 콜백 클래스를 정의하는 데 필요한 기본 클래스입니다. # ServiceCallbacks 클래스는 NSO 서비스의 라이프사이클 이벤트를 처리하는 콜백을 정의합니다. # ncs.application.Service를 상속받아 NSO 서비스 프레임워크와 통합됩니다. class ServiceCallbacks(Service): # @Service.create 데코레이터는 이 메서드(cb_create)가 새로운 서비스 인스턴스가 생성될 때 호출되어야 함을 NSO에 알립니다. @Service.create def cb_create(self, tctx, root, service, proplist): # self.log.info는 NSO의 시스템 로그에 정보성 메시지를 기록합니다. # 서비스 인스턴스가 생성되었음을 알리고, 서비스 인스턴스의 경로를 출력합니다. self.log.info('Service create(service=', service._path, ')') # 서비스 모델(YANG)에서 정의된 'ip-prefix' 리프(leaf)의 값을 가져옵니다. # 예를 들어, 서비스 모델에 "leaf ip-prefix { type inet:ipv4-prefix; }"와 같이 정의되어 있을 것입니다. ip_prefix = service.ip_prefix # self.log.debug는 디버깅 목적으로 NSO 로그에 상세 메시지를 기록합니다. # 'ip-prefix' 변수에 어떤 값이 들어왔는지 확인합니다. self.log.debug(f'Value of ip-prefix leaf is {ip_prefix}') # ipaddress.IPv4Network를 사용하여 입력받은 IP 접두사(예: "192.168.1.0/24")를 IPv4 네트워크 객체로 변환합니다. net = ipaddress.IPv4Network(ip_prefix) # net.hosts()는 해당 네트워크 내의 모든 호스트 IP 주소를 포함하는 이터레이터를 반환합니다. # next() 함수를 사용하여 이 이터레이터에서 첫 번째 사용 가능한 호스트 IP 주소를 가져옵니다. # 예를 들어, "192.168.1.0/24"의 경우 "192.168.1.1"이 됩니다. ip_address = next(net.hosts()) # ncs.template.Variables 객체를 생성하여 서비스 템플릿에 전달할 변수들을 정의합니다. vars = ncs.template.Variables() # 'IP_ADDRESS'라는 이름의 변수에 위에서 추출한 ip_address 값을 추가합니다. # 이 'IP_ADDRESS' 변수는 서비스 템플릿 XML 파일에서 {$IP_ADDRESS}와 같이 사용될 수 있습니다. vars.add('IP_ADDRESS', ip_address) # NSO 서비스와 연결된 템플릿 객체를 생성합니다. template = ncs.template.Template(service) # 'loopback-template'이라는 이름의 템플릿을 vars에 정의된 변수들과 함께 적용합니다. # NSO는 이 템플릿을 사용하여 실제 장치에 적용할 Native Configuration을 생성합니다. template.apply('loopback-template', vars) # --------------------------------------------- # COMPONENT THREAD THAT WILL BE STARTED BY NCS. # --------------------------------------------- class Loopback(ncs.application.Application): # setup(self): NSO가 이 애플리케이션을 초기화할 때 호출되는 메서드입니다. def setup(self): # self.log.info: NSO의 시스템 로그에 메시지를 기록합니다. # 애플리케이션이 성공적으로 시작되었음을 알립니다. self.log.info('Loopback RUNNING') # self.register_service('loopback-servicepoint', ServiceCallbacks): # 이 부분이 핵심입니다. NSO에게 'loopback-servicepoint'라는 이름의 서비스 포인트에 # ServiceCallbacks 클래스를 등록하도록 지시합니다. # 서비스 포인트는 YANG 모델에 정의된 특정 지점(path)으로, # 해당 지점에 서비스 인스턴스가 생성되면 등록된 콜백(ServiceCallbacks)이 실행되도록 합니다. # 즉, NSO는 'loopback-servicepoint'와 연결된 서비스 인스턴스가 생성될 때마다 # ServiceCallbacks 클래스의 cb_create 메서드를 호출하게 됩니다. self.register_service('loopback-servicepoint', ServiceCallbacks)
- 서비스 흐름도
6. Python 기반 서비스 문제 해결
Python log
- ncs-python-vm.log
- 각 NSO 패키지는 자체 Python VM에서 시작
- 패키지 reload 또는 redepoly 시 발생하여 서비스 등록을 방해하는 Python 코드의 오류를 기록
- ncs-python-vm-loopback.log
- 개발자가 서비스 코드 내에서 logging 모듈을 사용해 작성하는 패키지별 로그 메시지를 수집
- loopback 서비스 코드에서 self.log.debug와 같이 작성한 메시지가 이 파일에 기록
- log 메시지 저장 예시
class ServiceCallbacks(Service): @Service.create def cb_create(self, tctx, root, service, proplist): self.log.info('Service create(service=', service._path, ')') ip_prefix = service.ip_prefix # 이 줄이 ip-prefix 값을 로그에 기록합니다. self.log.debug(f'Value of ip-prefix leaf is {ip_prefix}') net = ipaddress.IPv4Network(ip_prefix) ip_address = next(net.hosts())
- CLI에서 로그 레벨 설정
- NSO CLI에 연결해 log level-debug 설정
ncs_cli -C -u admin # NSO CLI에 관리자 권한으로 연결 config # 설정 모드로 진입 python-vm logging level level-debug # Python VM 로깅 레벨을 debug로 설정 commit # 변경 사항 커밋 end # 설정 모드 종료
- 패키지 재배포 및 서비스 인스턴스 프로비저닝
packages package loopback redeploy # loopback 패키지를 다시 배포하여 변경 사항 적용 config # 설정 모드로 진입 loopback test device core-rtr0 loopback-intf 202 ip-prefix 192.168.20.0/24 # 새 루프백 서비스 인스턴스 생성 commit # 변경 사항 커밋 end # 설정 모드 종료 exit # CLI 종료
- NSO CLI에 연결해 log level-debug 설정
- Python 코드가 작성한 로그 메시지 보기
ncs_cli -C -u admin config python-vm logging level level-debug commit end