From a9660360b95bfdc4a8d651f52d9a5832ff36882d Mon Sep 17 00:00:00 2001 From: Will Lester Date: Tue, 12 Jul 2022 13:32:52 -0500 Subject: [PATCH 1/2] Add support for Cisco Catalyst 8000v --- AUTHORS.txt | 1 + COT/platforms/__init__.py | 2 + COT/platforms/cisco_c8000v.py | 93 +++++++ COT/platforms/tests/test_cisco_c8000v.py | 99 +++++++ COT/tests/c8000v.ovf | 335 +++++++++++++++++++++++ COT/tests/cot_testcase.py | 2 + docs/COT.platforms.cisco_c8000v.rst | 4 + 7 files changed, 536 insertions(+) create mode 100644 COT/platforms/cisco_c8000v.py create mode 100644 COT/platforms/tests/test_cisco_c8000v.py create mode 100644 COT/tests/c8000v.ovf create mode 100644 docs/COT.platforms.cisco_c8000v.rst diff --git a/AUTHORS.txt b/AUTHORS.txt index 9bde88b..5c6c80b 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -6,3 +6,4 @@ Kevin A. Keim Quol Fontana Jusheng Feng Subba Srinivas +Will Lester \ No newline at end of file diff --git a/COT/platforms/__init__.py b/COT/platforms/__init__.py index fe812e4..a771298 100644 --- a/COT/platforms/__init__.py +++ b/COT/platforms/__init__.py @@ -36,6 +36,7 @@ COT.platforms.platform COT.platforms.cisco_csr1000v + COT.platforms.cisco_c8000v COT.platforms.cisco_iosv COT.platforms.cisco_iosxrv COT.platforms.cisco_iosxrv_9000 @@ -50,6 +51,7 @@ from .platform import Platform from .cisco_csr1000v import CSR1000V +from .cisco_c8000v import C8000V from .cisco_iosv import IOSv from .cisco_iosxrv import IOSXRv, IOSXRvRP, IOSXRvLC from .cisco_iosxrv_9000 import IOSXRv9000 diff --git a/COT/platforms/cisco_c8000v.py b/COT/platforms/cisco_c8000v.py new file mode 100644 index 0000000..f37eece --- /dev/null +++ b/COT/platforms/cisco_c8000v.py @@ -0,0 +1,93 @@ +# September 2016, Glenn F. Matthews +# Copyright (c) 2013-2017 the COT project developers. +# See the COPYRIGHT.txt file at the top-level directory of this distribution +# and at https://github.com/glennmatthews/cot/blob/master/COPYRIGHT.txt. +# +# This file is part of the Common OVF Tool (COT) project. +# It is subject to the license terms in the LICENSE.txt file found in the +# top-level directory of this distribution and at +# https://github.com/glennmatthews/cot/blob/master/LICENSE.txt. No part +# of COT, including this file, may be copied, modified, propagated, or +# distributed except according to the terms contained in the LICENSE.txt file. + +"""Platform logic for the Cisco C8000V virtual router.""" + +import logging + +from COT.platforms.platform import Platform, Hardware +from COT.data_validation import ValueUnsupportedError, ValidRange + +logger = logging.getLogger(__name__) + + +class C8000V(Platform): + """Platform-specific logic for Cisco C8000V platform.""" + + PLATFORM_NAME = "Cisco C8000V" + + CONFIG_TEXT_FILE = 'iosxe_config.txt' + LITERAL_CLI_STRING = 'ios-config' + # CSR1000v doesn't 'officially' support E1000, but it mostly works + SUPPORTED_NIC_TYPES = ["E1000", "virtio", "VMXNET3"] + + HARDWARE_LIMITS = Platform.HARDWARE_LIMITS.copy() + HARDWARE_LIMITS.update({ + Hardware.cpus: ValidRange(1, 8), # but see below + Hardware.memory: ValidRange(2560, 8192), + Hardware.nic_count: ValidRange(3, 26), + Hardware.serial_count: ValidRange(0, 2), + }) + + def controller_type_for_device(self, device_type): + """C8000V uses SCSI for hard disks and IDE for CD-ROMs. + + Args: + device_type (str): 'harddisk' or 'cdrom' + Returns: + str: 'ide' for CD-ROM, 'scsi' for hard disk + """ + if device_type == 'harddisk': + return 'scsi' + elif device_type == 'cdrom': + return 'ide' + else: + return super(C8000V, self).controller_type_for_device( + device_type) + + def guess_nic_name(self, nic_number): + """GigabitEthernet1, GigabitEthernet2, etc. + + .. warning:: + In all current CSR releases, NIC names start at "GigabitEthernet1". + Some early versions started at "GigabitEthernet0" but we don't + support that. + + Args: + nic_number (int): Nth NIC to name. + Returns: + str: such as + + * "GigabitEthernet1" + * "GigabitEthernet2" + * etc. + """ + return "GigabitEthernet" + str(nic_number) + + def validate_cpu_count(self, cpus): + """C8000V supports 1, 2, 4, or 8 CPUs. + + Args: + cpus (int): Number of CPUs. + + Raises: + ValueTooLowError: if ``cpus`` is less than 1 + ValueTooHighError: if ``cpus`` is more than 8 + ValueUnsupportedError: if ``cpus`` is an unsupported value + between 1 and 8 + """ + super(C8000V, self).validate_cpu_count(cpus) + if cpus not in [1, 2, 4, 8]: + raise ValueUnsupportedError("CPUs", cpus, [1, 2, 4, 8]) + + +Platform.PRODUCT_PLATFORM_MAP['com.cisco.c8000v'] = C8000V diff --git a/COT/platforms/tests/test_cisco_c8000v.py b/COT/platforms/tests/test_cisco_c8000v.py new file mode 100644 index 0000000..186dd7e --- /dev/null +++ b/COT/platforms/tests/test_cisco_c8000v.py @@ -0,0 +1,99 @@ +# test_cisco_c8000v.py - Unit test cases for Cisco C8000V platform +# +# October 2016, Glenn F. Matthews +# Copyright (c) 2014-2017 the COT project developers. +# See the COPYRIGHT.txt file at the top-level directory of this distribution +# and at https://github.com/glennmatthews/cot/blob/master/COPYRIGHT.txt. +# +# This file is part of the Common OVF Tool (COT) project. +# It is subject to the license terms in the LICENSE.txt file found in the +# top-level directory of this distribution and at +# https://github.com/glennmatthews/cot/blob/master/LICENSE.txt. No part +# of COT, including this file, may be copied, modified, propagated, or +# distributed except according to the terms contained in the LICENSE.txt file. + +"""Unit test cases for C8000V platform.""" + +from COT.platforms.cisco_c8000v import C8000V +from COT.data_validation import ( + ValueUnsupportedError, ValueTooLowError, ValueTooHighError +) +from COT.platforms.tests import PlatformTests + + +class TestC8000V(PlatformTests.PlatformTest): + """Test cases for Cisco C8000V platform handling.""" + + cls = C8000V + product_string = "com.cisco.c8000v" + + def test_controller_type_for_device(self): + """Test platform-specific logic for device controllers.""" + self.assertEqual(self.ins.controller_type_for_device('harddisk'), + 'scsi') + self.assertEqual(self.ins.controller_type_for_device('cdrom'), + 'ide') + # fallthrough to parent class + self.assertEqual(self.ins.controller_type_for_device('dvd'), + 'ide') + + def test_nic_name(self): + """Test NIC name construction.""" + self.assertEqual(self.ins.guess_nic_name(1), + "GigabitEthernet1") + self.assertEqual(self.ins.guess_nic_name(2), + "GigabitEthernet2") + self.assertEqual(self.ins.guess_nic_name(3), + "GigabitEthernet3") + self.assertEqual(self.ins.guess_nic_name(4), + "GigabitEthernet4") + + def test_cpu_count(self): + """Test CPU count limits.""" + self.assertRaises(ValueTooLowError, self.ins.validate_cpu_count, 0) + self.ins.validate_cpu_count(1) + self.ins.validate_cpu_count(2) + self.assertRaises(ValueUnsupportedError, + self.ins.validate_cpu_count, 3) + self.ins.validate_cpu_count(4) + self.assertRaises(ValueUnsupportedError, + self.ins.validate_cpu_count, 5) + self.assertRaises(ValueUnsupportedError, + self.ins.validate_cpu_count, 6) + self.assertRaises(ValueUnsupportedError, + self.ins.validate_cpu_count, 7) + self.ins.validate_cpu_count(8) + self.assertRaises(ValueTooHighError, self.ins.validate_cpu_count, 9) + + def test_memory_amount(self): + """Test RAM allocation limits.""" + self.assertRaises(ValueTooLowError, + self.ins.validate_memory_amount, 2559) + self.ins.validate_memory_amount(2560) + self.ins.validate_memory_amount(8192) + self.assertRaises(ValueTooHighError, + self.ins.validate_memory_amount, 8193) + + def test_nic_count(self): + """Test NIC range limits.""" + self.assertRaises(ValueTooLowError, self.ins.validate_nic_count, 2) + self.ins.validate_nic_count(3) + self.ins.validate_nic_count(26) + self.assertRaises(ValueTooHighError, self.ins.validate_nic_count, 27) + + def test_nic_type(self): + """Test NIC valid and invalid types.""" + self.assertRaises(ValueUnsupportedError, + self.ins.validate_nic_type, "E1000e") + self.ins.validate_nic_type("E1000") + self.assertRaises(ValueUnsupportedError, + self.ins.validate_nic_type, "PCNet32") + self.ins.validate_nic_type("virtio") + self.ins.validate_nic_type("VMXNET3") + + def test_serial_count(self): + """Test serial port range limits.""" + self.assertRaises(ValueTooLowError, self.ins.validate_serial_count, -1) + self.ins.validate_serial_count(0) + self.ins.validate_serial_count(2) + self.assertRaises(ValueTooHighError, self.ins.validate_serial_count, 3) diff --git a/COT/tests/c8000v.ovf b/COT/tests/c8000v.ovf new file mode 100644 index 0000000..a1518e0 --- /dev/null +++ b/COT/tests/c8000v.ovf @@ -0,0 +1,335 @@ + + + + + + + + + + Virtual disk information + + + + + The list of logical networks + + Data network 1 + + + Data network 2 + + + Data network 3 + + + + Configuration Profiles + + Small - 8GB Disk + Minimal hardware profile - 1 vCPU, 4 GB RAM, 8 GB Disk + + + Medium - 8GB Disk + Medium hardware profile - 2 vCPUs, 4 GB RAM, 8 GB Disk + + + Large - 8GB Disk + Large hardware profile - 4 vCPUs, 4 GB RAM, 8 GB Disk + + + Large + DRAM Upgrade - 8GB Disk + Large hardware profile (requires purchase of DRAM upgrade SKU) - 4 vCPUs, 8 GB RAM, 8 GB Disk + + + Small- 16GB Disk + Minimal hardware profile - 1 vCPU, 4 GB RAM, 16 GB Disk + + + Medium - 16GB Disk + Medium hardware profile - 2 vCPUs, 4 GB RAM, 16 GB Disk + + + Large - 16GB Disk + Large hardware profile - 4 vCPUs, 4 GB RAM, 16 GB Disk + + + Large + DRAM Upgrade - 16GB Disk + Large hardware profile (requires purchase of DRAM upgrade SKU) - 4 vCPUs, 8 GB RAM, 16 GB Disk + + + + A virtual machine + Cisco Catalyst 8000V Edge Router + + The kind of installed guest operating system + Cisco IOS-XE Software + + + Virtual hardware requirements + + Virtual Hardware Family + 0 + vmx-10 vmx-11 vmx-13 + + + hertz * 10^6 + Number of Virtual CPUs + 1 virtual CPU(s) + 1 + 3 + 1 + DMTF:x86:64 + DMTF:x86:SSE2 DMTF:x86:SSE3 DMTF:x86:SSSE3 + 1 + + + hertz * 10^6 + Number of Virtual CPUs + 2 virtual CPU(s) + 1 + 3 + 2 + DMTF:x86:64 + DMTF:x86:SSE2 DMTF:x86:SSE3 DMTF:x86:SSSE3 + 1 + + + hertz * 10^6 + Number of Virtual CPUs + 4 virtual CPU(s) + 1 + 3 + 4 + DMTF:x86:64 + DMTF:x86:SSE2 DMTF:x86:SSE3 DMTF:x86:SSSE3 + 1 + + + byte * 2^20 + Memory Size + 4096MB of memory + 2 + 4 + 4096 + + + byte * 2^20 + Memory Size + 8192MB of memory + 2 + 4 + 8192 + + + 0 + SCSI Controller + SCSI Controller 0 + 3 + VirtualSCSI + 6 + + + 1 + IDE Controller + VirtualIDEController 0 + 4 + 5 + + + 0 + Hard Drive + ovf:/disk/vmdisk2 + 5 + 3 + 17 + + + 0 + Hard Drive + ovf:/disk/vmdisk1 + 5 + 3 + 17 + + + 0 + true + CD-ROM 1 + ovf:/file/c8000v-universalk9_vga.17.05.01a.iso + 6 + 4 + 15 + + + 1 + false + CD-ROM 2 + 7 + 4 + 15 + + + 11 + true + GigabitEthernet1 + NIC representing GigabitEthernet1 + GigabitEthernet1 + 8 + VMXNET3 + 10 + + + 12 + true + GigabitEthernet2 + NIC representing GigabitEthernet2 + GigabitEthernet2 + 9 + VMXNET3 + 10 + + + 13 + true + GigabitEthernet3 + NIC representing GigabitEthernet3 + GigabitEthernet3 + 10 + VMXNET3 + 10 + + + + + + + + + + + + + + + + + + + + + Information about the installed software + Cisco C8000V + Cisco Systems, Inc. + 17.05.01a + Cisco IOS-XE Software, version 17.05.01a + http://www.cisco.com/en/US/products/ps12559/index.html + http://www.cisco.com + + DO NOT CHANGE THIS VALUE + + 1. Bootstrap Properties + + Router Name + Hostname of this router + + + Login Username + Username for remote login + + + Login Password + Password for remote login. +WARNING: While this password will be stored securely within IOS, the plain-text password will be recoverable from the OVF descriptor file. + + + Domain Name + Network domain name (such as "cisco.com") + + + Management Interface + Management interface (such as "GigabitEthernet1" or "GigabitEthernet1.100") + + + Management VLAN + Management dot1Q VLAN (requires specifying a subinterface such as "GigabitEthernet1.100" for the Management Interface) + + + Management Interface IPv4 Address/Mask + IPv4 address and mask for management interface (such as "192.0.2.100/24" or "192.0.2.100 255.255.255.0"), or "dhcp" to configure via DHCP + + + Management IPv4 Gateway + IPv4 gateway address (such as "192.0.2.1") for management interface, or "dhcp" to configure via DHCP + + + Management IPv4 Network + IPv4 Network (such as "192.168.2.0/24" or "192.168.2.0 255.255.255.0") that the management gateway should route to. + + + PNSC IPv4 Address + IPv4 address without mask (such as "192.0.2.110") of PNSC service controller + + + PNSC Agent Local Port + PNSC service agent SSL port (on local C8000V) to receive policies from service manager. +The port shall be in the range of [55001, 61000] if shared IP is used, i.e., Remote Management IPv4 Address is not configured. + + + + PNSC Shared Secret Key + PNSC service controller shared secret key (8-64 characters) for PNSC agent to get SSL certificate from the controller. +WARNING: While this password will be stored securely within IOS, the plain-text password will be recoverable from the OVF descriptor file. + + + Remote Management IPv4 Address (optional, deprecated) + Secondary IPv4 address without mask (such as "192.0.2.101") for access to remote management features (REST API, etc.). This should be in the same IP subnet as the Management Interface IPv4 Address entered above. +Warning: THIS IS A DEPRECATED OPTION IN THIS RELEASE. + + 2. Features + + Enable SCP Server + Enable IOS SCP server feature + + + Enable SSH Login and Disable Telnet Login + Enable remote login via SSH and disable remote login via telnet. Requires login-username and login-password to be set! + + + Enable SDWAN Feature + Disabled: fill out section 3. Enabled: fill out section 4. + + 3. Non-SDWAN Configuration Properties + + Enable Password + Password for privileged (enable) access. +WARNING: While this password will be stored securely within IOS, the plain-text password will be recoverable from the OVF descriptor file. + + + License boot level + Configure license boot level(such as ax, security, appx, ipbase, lite, vacs) + + + Resource template + Configure Resource template(service_plane_medium, service_plane_heavy or default) + + 4. SDWAN Configuration Properties + + vBond Server IPv4 Address + Address of the vBond server + + + OTP + One Time Password + + + UUID + Universally Unique Identifier + + + Organization + Organization Name + + + + diff --git a/COT/tests/cot_testcase.py b/COT/tests/cot_testcase.py index 2390fe6..2675e67 100644 --- a/COT/tests/cot_testcase.py +++ b/COT/tests/cot_testcase.py @@ -235,6 +235,8 @@ class COTTestCase(unittest.TestCase): # noqa: N801 csr_ovf = _localfile("csr1000v.ovf") # CSR1000V OVF as of 2017 csr_ovf_2017 = _localfile("csr1000v_2017.ovf") + # C8000V OVF + c8000_ovf = _localfile("c8000v.ovf") # v0.9 OVF v09_ovf = _localfile("v0.9.ovf") # v2.0 OVF from VirtualBox diff --git a/docs/COT.platforms.cisco_c8000v.rst b/docs/COT.platforms.cisco_c8000v.rst new file mode 100644 index 0000000..31fcb2d --- /dev/null +++ b/docs/COT.platforms.cisco_c8000v.rst @@ -0,0 +1,4 @@ +``COT.platforms.cisco_c8000v`` module +======================================= + +.. automodule:: COT.platforms.cisco_c8000v From b001fbab0caffc2b87f453edeb2fa24676dbef82 Mon Sep 17 00:00:00 2001 From: Will Lester Date: Tue, 12 Jul 2022 13:40:13 -0500 Subject: [PATCH 2/2] Memory and vNIC count updated --- COT/platforms/cisco_c8000v.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/COT/platforms/cisco_c8000v.py b/COT/platforms/cisco_c8000v.py index f37eece..001a778 100644 --- a/COT/platforms/cisco_c8000v.py +++ b/COT/platforms/cisco_c8000v.py @@ -33,8 +33,8 @@ class C8000V(Platform): HARDWARE_LIMITS = Platform.HARDWARE_LIMITS.copy() HARDWARE_LIMITS.update({ Hardware.cpus: ValidRange(1, 8), # but see below - Hardware.memory: ValidRange(2560, 8192), - Hardware.nic_count: ValidRange(3, 26), + Hardware.memory: ValidRange(4096, 8192), + Hardware.nic_count: ValidRange(3, 8), Hardware.serial_count: ValidRange(0, 2), })