#!/usr/bin/env python
#
# platforms.py - Module for methods related to variations between
# guest platforms (Cisco CSR1000V, Cisco IOS XRv, etc.)
#
# October 2013, Glenn F. Matthews
# Copyright (c) 2013-2015 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.
"""Handles behavior that varies between guest platforms.
**Classes**
.. autosummary::
:nosignatures:
GenericPlatform
CSR1000V
IOSv
IOSXRv
IOSXRvRP
IOSXRvLC
NXOSv
"""
from .data_validation import ValueUnsupportedError
from .data_validation import ValueTooLowError, ValueTooHighError
import logging
logger = logging.getLogger(__name__)
[docs]class IOSXRv(GenericPlatform):
"""Platform-specific logic for Cisco IOS XRv platform."""
PLATFORM_NAME = "Cisco IOS XRv"
CONFIG_TEXT_FILE = 'iosxr_config.txt'
SECONDARY_CONFIG_TEXT_FILE = 'iosxr_config_admin.txt'
LITERAL_CLI_STRING = None
@classmethod
[docs] def guess_nic_name(cls, nic_number):
"""MgmtEth0/0/CPU0/0, GigabitEthernet0/0/0/0, Gig0/0/0/1, etc."""
if nic_number == 1:
return "MgmtEth0/0/CPU0/0"
else:
return ("GigabitEthernet0/0/0/" + str(nic_number - 2))
@classmethod
[docs] def validate_cpu_count(cls, cpus):
"""IOS XRv supports 1-8 CPUs."""
if cpus < 1:
raise ValueTooLowError("CPUs", cpus, 1)
elif cpus > 8:
raise ValueTooHighError("CPUs", cpus, 8)
@classmethod
[docs] def validate_memory_amount(cls, megabytes):
"""Minimum 3 GB, max 8 GB of RAM."""
if megabytes < 3072:
raise ValueTooLowError("RAM", str(megabytes) + "MB", "3GB")
elif megabytes > 8192:
raise ValueTooHighError("RAM", str(megabytes) + "MB", "8GB")
@classmethod
[docs] def validate_nic_count(cls, count):
"""IOS XRv requires at least one NIC."""
if count < 1:
raise ValueTooLowError("NIC count", count, 1)
@classmethod
[docs] def validate_nic_type(cls, type_string):
"""IOS XRv supports E1000 and virtio NICs."""
cls.valid_list_only("NIC type", type_string.upper(),
["E1000", "VIRTIO"])
@classmethod
[docs] def validate_serial_count(cls, count):
"""IOS XRv supports 1-4 serial ports."""
if count < 1:
raise ValueTooLowError("serial ports", count, 1)
elif count > 4:
raise ValueTooHighError("serial ports", count, 4)
[docs]class IOSXRvRP(IOSXRv):
"""Platform-specific logic for Cisco IOS XRv HA-capable RP."""
PLATFORM_NAME = "Cisco IOS XRv route processor card"
@classmethod
[docs] def guess_nic_name(cls, nic_number):
"""Fabric and management only.
* fabric
* MgmtEth0/{SLOT}/CPU0/0
"""
if nic_number == 1:
return "fabric"
else:
return ("MgmtEth0/{SLOT}/CPU0/" + str(nic_number - 2))
@classmethod
[docs] def validate_nic_count(cls, count):
"""Fabric plus an optional management NIC."""
if count < 1:
raise ValueTooLowError("NIC count", count, 1)
if count > 2:
raise ValueTooHighError("NIC count", count, 2)
[docs]class IOSXRvLC(IOSXRv):
"""Platform-specific logic for Cisco IOS XRv line card."""
PLATFORM_NAME = "Cisco IOS XRv line card"
# No bootstrap config for LCs - they inherit from the RP
CONFIG_TEXT_FILE = None
SECONDARY_CONFIG_TEXT_FILE = None
@classmethod
[docs] def guess_nic_name(cls, nic_number):
"""Fabric interface plus slot-appropriate GigabitEthernet interfaces.
* fabric
* GigabitEthernet0/{SLOT}/0/0
* GigabitEthernet0/{SLOT}/0/1
* etc.
"""
if nic_number == 1:
return "fabric"
else:
return ("GigabitEthernet0/{SLOT}/0/" + str(nic_number - 2))
@classmethod
[docs] def validate_serial_count(cls, count):
"""No serial ports are needed but up to 4 can be used for debugging."""
if count > 4:
raise ValueTooHighError("serial ports", count, 4)
[docs]class CSR1000V(GenericPlatform):
"""Platform-specific logic for Cisco CSR1000V platform."""
PLATFORM_NAME = "Cisco CSR1000V"
CONFIG_TEXT_FILE = 'iosxe_config.txt'
LITERAL_CLI_STRING = 'ios-config'
@classmethod
[docs] def controller_type_for_device(cls, device_type):
"""CSR1000V uses SCSI for hard disks and IDE for CD-ROMs."""
if device_type == 'harddisk':
return 'scsi'
elif device_type == 'cdrom':
return 'ide'
else:
return super(CSR1000V, cls).controller_type_for_device(device_type)
@classmethod
[docs] def guess_nic_name(cls, 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.
"""
return ("GigabitEthernet" + str(nic_number))
@classmethod
[docs] def validate_cpu_count(cls, cpus):
"""CSR1000V supports 1, 2, or 4 CPUs."""
if cpus < 1:
raise ValueTooLowError("CPUs", cpus, 1)
elif cpus > 4:
raise ValueTooHighError("CPUs", cpus, 4)
elif cpus != 1 and cpus != 2 and cpus != 4:
raise ValueUnsupportedError("CPUs", cpus, [1, 2, 4])
@classmethod
[docs] def validate_memory_amount(cls, megabytes):
"""Minimum 2.5 GB, max 8 GB."""
if megabytes < 2560:
raise ValueTooLowError("RAM", str(megabytes) + "MB", "2.5GB")
elif megabytes > 8192:
raise ValueTooHighError("RAM", str(megabytes) + "MB", "8GB")
@classmethod
[docs] def validate_nic_count(cls, count):
"""CSR1000V requires 3 NICs and supports up to 26."""
if count < 3:
raise ValueTooLowError("NICs", count, 3)
elif count > 26:
raise ValueTooHighError("NICs", count, 26)
@classmethod
[docs] def validate_serial_count(cls, count):
"""CSR1000V supports 0-2 serial ports."""
if count < 0:
raise ValueTooLowError("serial ports", count, 0)
elif count > 2:
raise ValueTooHighError("serial ports", count, 2)
[docs]class IOSv(GenericPlatform):
"""Platform-specific logic for Cisco IOSv."""
PLATFORM_NAME = "Cisco IOSv"
CONFIG_TEXT_FILE = 'ios_config.txt'
LITERAL_CLI_STRING = None
# IOSv has no CD-ROM driver so bootstrap configs must be provided on disk.
BOOTSTRAP_DISK_TYPE = 'harddisk'
@classmethod
[docs] def guess_nic_name(cls, nic_number):
"""GigabitEthernet0/0, GigabitEthernet0/1, etc."""
return ("GigabitEthernet0/" + str(nic_number - 1))
@classmethod
[docs] def validate_cpu_count(cls, cpus):
"""IOSv only supports a single CPU."""
if cpus < 1:
raise ValueTooLowError("CPUs", cpus, 1)
elif cpus > 1:
raise ValueTooHighError("CPUs", cpus, 1)
@classmethod
[docs] def validate_memory_amount(cls, megabytes):
"""IOSv has minimum 192 MB (with minimal feature set), max 3 GB."""
if megabytes < 192:
raise ValueTooLowError("RAM", str(megabytes) + "MB", "192MB")
elif megabytes < 384:
# Warn but allow
logger.warning("Less than 384MB of RAM may not be sufficient "
"for some IOSv feature sets")
elif megabytes > 3072:
raise ValueTooHighError("RAM", str(megabytes) + "MB", "3GB")
@classmethod
[docs] def validate_nic_count(cls, count):
"""IOSv supports up to 16 NICs."""
if count < 0:
raise ValueTooLowError("NICs", count, 0)
elif count > 16:
raise ValueTooHighError("NICs", count, 16)
@classmethod
[docs] def validate_nic_type(cls, type_string):
"""IOSv only supports E1000 NICs."""
if type_string.upper() != "E1000":
raise ValueUnsupportedError("NIC type", type_string.upper(),
"E1000")
@classmethod
[docs] def validate_serial_count(cls, count):
"""IOSv requires 1-2 serial ports."""
if count < 1:
raise ValueTooLowError("serial ports", count, 1)
elif count > 2:
raise ValueTooHighError("serial ports", count, 2)
[docs]class NXOSv(GenericPlatform):
"""Platform-specific logic for Cisco NX-OSv (Titanium)."""
PLATFORM_NAME = "Cisco NX-OSv"
CONFIG_TEXT_FILE = 'nxos_config.txt'
LITERAL_CLI_STRING = None
@classmethod
[docs] def guess_nic_name(cls, nic_number):
"""NX-OSv names its NICs a bit interestingly...
* mgmt0
* Ethernet2/1
* Ethernet2/2
* ...
* Ethernet2/48
* Ethernet3/1
* Ethernet3/2
* ...
"""
if nic_number == 1:
return "mgmt0"
else:
return ("Ethernet{0}/{1}".format((nic_number - 2) // 48 + 2,
(nic_number - 2) % 48 + 1))
@classmethod
[docs] def validate_cpu_count(cls, cpus):
"""NX-OSv requires 1-8 CPUs."""
if cpus < 1:
raise ValueTooLowError("CPUs", cpus, 1)
elif cpus > 8:
raise ValueTooHighError("CPUs", cpus, 8)
@classmethod
[docs] def validate_memory_amount(cls, megabytes):
"""NX-OSv requires 2-8 GB of RAM."""
if megabytes < 2048:
raise ValueTooLowError("RAM", str(megabytes) + "MB", "2GB")
elif megabytes > 8192:
raise ValueTooHighError("RAM", str(megabytes) + "MB", "8GB")
@classmethod
[docs] def validate_nic_type(cls, type_string):
"""NX-OSv supports only E1000 and virtio NICs."""
# VMXNET3 is not supported
cls.valid_list_only("NIC type", type_string.upper(),
["E1000", "VIRTIO"])
@classmethod
[docs] def validate_serial_count(cls, count):
"""NX-OSv requires 1-2 serial ports."""
if count < 1:
raise ValueTooLowError("serial ports", count, 1)
elif count > 2:
raise ValueTooHighError("serial ports", count, 2)