Cloud-Init for VMs in private and public Clouds

Initialize VMs in a vSphere private Cloud using Cloud-Init

Cloud-Init Datasource for VMware GuestInfo is deprecated

The Web is full of explanations, how to use „Cloud-Init Datasource for VMware GuestInfo“ but https://github.com/vmware-archive/cloud-init-vmware-guestinfo it is deprecated.

It is now integrated natively into Cloud-Init

Cloud-Init 21.3 has been released https://discourse.ubuntu.com/t/release-of-cloud-init-21-3/23857 which integrates this software.

New name:

I’d expect it to be in the current Ubuntu 21.10 (Impish Indri) https://cloud-images.ubuntu.com/impish/current/ – the release notes for 21.10 don’t specify the exact version.

Ubuntu 20.04 (Focal Fossa) is still at cloud-init 20.1-10 according to https://wiki.ubuntu.com/FocalFossa/ReleaseNotes which is too old.

Prepare a VM-Template

Unfortunately Ubuntu provides the „cloud“-images in OVA-Format.

Create VM-Template from OVA

Deploy

  • impish-server-cloudimg-amd64.ova

as

  • VM
  • keep all settings set to default

Customize VM

  • disable (or remove) the „Serial“-port
  • disable vApp-Properties
    • those would break the cloud-init process later on
    • VM=>Configure
    • Settings=>vApp-Options
    • disable [ ] vApp-Properties

Convert to Template

  • VM-Template „ubuntu-impish-21.10-cloudimg“.

Clone a VM from this VM-Template

This shouldn’t be done manually, I’d suggest using terraform

Verify that Cloud-Init 21.3 is available and the „VMware“-Datasource is included

Cloud-Init Version

Release 21.3 is available:

ubuntu@ubuntu:~$ cloud-init --version
/usr/bin/cloud-init 21.3-1-g6803368d-0ubuntu3

Check the Cloud-Init Datasource

Datasource „vmware“ is included:

ubuntu@ubuntu:~$ cloud-id
vmware

Enable ESXi-Host as VNC-Server to access a vSphere-VM remotely

I prefer accessing VMs using SSH or RDP directly. Sometimes, the IP-Address of the VM isn’t reachable, or protocols for remoteaccess need to be disabled for security reasons.

In these cases, if an IP-connection to the ESXi-Server is available this could be an option to use the ESXi hypervisor as VNC-Server to provide access to VM keyboard, video, mouse…

Three VM advanced Configuration Parameters need to be set:

  • „password“ is optional, but mRemoteNG as VNC-Client doesn’t work without password set.
RemoteDisplay.vnc.enabled = TRUE
RemoteDisplay.vnc.port = <TCP-Port>
RemoteDisplay.vnc.password = <Passwort>

Compile PuTTY on your own

The beginning: Source Code

Find the original source archive at https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html or get the Windows-Archive directly here: https://the.earth.li/~sgtatham/putty/latest/putty-src.zip

Modify the Source Code

For example: Tweak the modal „Fatal Connection Error“ Dialog: Relax PuTTY: Suppress „Fatal Error“ Dialog

Next step: GCC-Compiler

I’d chose MinGW to compile native Windows Applications: MinGW as build-environment for native Windows Applications

Compile it

Using MinGw:

run MinGw

In PuTTY it’s all prepared for us – go to the „windows“ subdirectory:

  • mingw32-make -f Makefile.mgw
C:\Program Files\mingw-w64\x86_64-8.1.0-win32-seh-rt_v6-rev0>echo off
Microsoft Windows [Version 10.0.19042.1110]
(c) Microsoft Corporation. Alle Rechte vorbehalten.

C:\> cd C:\\Users\\user\\Downloads\\putty-src_0-76\

C:\Users\user\Downloads\putty-src_0-76> cd windows

C:\Users\user\Downloads\putty-src_0-76\windows> mingw32-make -f Makefile.mgw
gcc  -Wall -O2 -std=gnu99 -Wvla -D_WINDOWS -DWIN32S_COMPAT -D_NO_OLDNAMES -D__USE_MINGW_ANSI_STDIO=1 -I.././ -I../charset/ -I../windows/ -I../unix/ -D_WIN32_IE=0x0500 -DWINVER=0x0500 -D_WIN32_WINDOWS=0x0410 -D_WIN32_WINNT=0x0500  -c ../ssh2userauth.c
gcc -s -o plink.exe -Wl,-Map,plink.map agentf.o aqsync.o \
        be_all_s.o be_misc.o callback.o clicons.o cmdline.o conf.o \
        console.o cproxy.o ecc.o errsock.o ldisc.o logging.o \
        mainchan.o marshal.o memory.o misc.o miscucs.o mpint.o \
        noterm.o nullplug.o pgssapi.o pinger.o plink.res.o portfwd.o \
        proxy.o raw.o rlogin.o sessprep.o settings.o ssh.o ssh1bpp.o \
        ssh1censor.o ssh1connection.o ssh1connection-client.o \
        ssh1login.o ssh2bpp.o ssh2bpp-bare.o ssh2censor.o \
        ssh2connection.o ssh2connection-client.o ssh2kex-client.o \
        ssh2transhk.o ssh2transport.o ssh2userauth.o sshaes.o \
        ssharcf.o sshargon2.o sshauxcrypt.o sshblake2.o sshblowf.o \
        sshccp.o sshcommon.o sshcrc.o sshcrcda.o sshdes.o sshdh.o \
        sshdss.o sshecc.o sshgssc.o sshhmac.o sshmac.o sshmd5.o \
        sshprng.o sshpubk.o sshrand.o sshrsa.o sshsh256.o sshsh512.o \
        sshsha.o sshsha3.o sshshare.o sshutils.o sshverstring.o \
        sshzlib.o stripctrl.o supdup.o telnet.o timing.o tree234.o \
        utils.o version.o wcwidth.o wildcard.o wincapi.o \
        wincliloop.o wincons.o windefs.o wingss.o winhandl.o \
        winhsock.o winmisc.o winmiscs.o winnet.o winnohlp.o \
        winnoise.o winnojmp.o winnpc.o winnps.o winpgntc.o \
        winplink.o winproxy.o winsecur.o winselcli.o winser.o \
        winshare.o winstore.o wintime.o winucs.o winx11.o x11fwd.o \
        -ladvapi32 -lcomdlg32 -lgdi32 -limm32 -lole32 -lshell32 \
        -luser32
gcc -s -o pscp.exe -Wl,-Map,pscp.map agentf.o aqsync.o be_misc.o \
        be_ssh.o callback.o clicons.o cmdline.o conf.o console.o \
        cproxy.o ecc.o errsock.o logging.o mainchan.o marshal.o \
        memory.o misc.o miscucs.o mpint.o nullplug.o pgssapi.o \
        pinger.o portfwd.o proxy.o pscp.o pscp.res.o psftpcommon.o \
        settings.o sftp.o sftpcommon.o ssh.o ssh1bpp.o ssh1censor.o \
        ssh1connection.o ssh1connection-client.o ssh1login.o \
        ssh2bpp.o ssh2bpp-bare.o ssh2censor.o ssh2connection.o \
        ssh2connection-client.o ssh2kex-client.o ssh2transhk.o \
        ssh2transport.o ssh2userauth.o sshaes.o ssharcf.o \
        sshargon2.o sshauxcrypt.o sshblake2.o sshblowf.o sshccp.o \
        sshcommon.o sshcrc.o sshcrcda.o sshdes.o sshdh.o sshdss.o \
        sshecc.o sshgssc.o sshhmac.o sshmac.o sshmd5.o sshprng.o \
        sshpubk.o sshrand.o sshrsa.o sshsh256.o sshsh512.o sshsha.o \
        sshsha3.o sshshare.o sshutils.o sshverstring.o sshzlib.o \
        stripctrl.o timing.o tree234.o utils.o version.o wcwidth.o \
        wildcard.o wincapi.o wincliloop.o wincons.o windefs.o \
        wingss.o winhandl.o winhsock.o winmisc.o winmiscs.o winnet.o \
        winnohlp.o winnoise.o winnojmp.o winnpc.o winnps.o \
        winpgntc.o winproxy.o winsecur.o winselcli.o winsftp.o \
        winshare.o winstore.o wintime.o winucs.o x11fwd.o -ladvapi32 \
        -lcomdlg32 -lgdi32 -limm32 -lole32 -lshell32 -luser32
gcc -s -o psftp.exe -Wl,-Map,psftp.map agentf.o aqsync.o \
        be_misc.o be_ssh.o callback.o clicons.o cmdline.o conf.o \
        console.o cproxy.o ecc.o errsock.o logging.o mainchan.o \
        marshal.o memory.o misc.o miscucs.o mpint.o nullplug.o \
        pgssapi.o pinger.o portfwd.o proxy.o psftp.o psftp.res.o \
        psftpcommon.o settings.o sftp.o sftpcommon.o ssh.o ssh1bpp.o \
        ssh1censor.o ssh1connection.o ssh1connection-client.o \
        ssh1login.o ssh2bpp.o ssh2bpp-bare.o ssh2censor.o \
        ssh2connection.o ssh2connection-client.o ssh2kex-client.o \
        ssh2transhk.o ssh2transport.o ssh2userauth.o sshaes.o \
        ssharcf.o sshargon2.o sshauxcrypt.o sshblake2.o sshblowf.o \
        sshccp.o sshcommon.o sshcrc.o sshcrcda.o sshdes.o sshdh.o \
        sshdss.o sshecc.o sshgssc.o sshhmac.o sshmac.o sshmd5.o \
        sshprng.o sshpubk.o sshrand.o sshrsa.o sshsh256.o sshsh512.o \
        sshsha.o sshsha3.o sshshare.o sshutils.o sshverstring.o \
        sshzlib.o stripctrl.o timing.o tree234.o utils.o version.o \
        wcwidth.o wildcard.o wincapi.o wincliloop.o wincons.o \
        windefs.o wingss.o winhandl.o winhsock.o winmisc.o \
        winmiscs.o winnet.o winnohlp.o winnoise.o winnojmp.o \
        winnpc.o winnps.o winpgntc.o winproxy.o winsecur.o \
        winselcli.o winsftp.o winshare.o winstore.o wintime.o \
        winucs.o x11fwd.o -ladvapi32 -lcomdlg32 -lgdi32 -limm32 \
        -lole32 -lshell32 -luser32
gcc -mwindows -s -o putty.exe -Wl,-Map,putty.map agentf.o \
        aqsync.o be_all_s.o be_misc.o callback.o cmdline.o conf.o \
        config.o cproxy.o dialog.o ecc.o errsock.o ldisc.o logging.o \
        mainchan.o marshal.o memory.o minibidi.o misc.o miscucs.o \
        mpint.o nullplug.o pgssapi.o pinger.o portfwd.o proxy.o \
        putty.res.o raw.o rlogin.o sessprep.o settings.o sizetip.o \
        ssh.o ssh1bpp.o ssh1censor.o ssh1connection.o \
        ssh1connection-client.o ssh1login.o ssh2bpp.o ssh2bpp-bare.o \
        ssh2censor.o ssh2connection.o ssh2connection-client.o \
        ssh2kex-client.o ssh2transhk.o ssh2transport.o \
        ssh2userauth.o sshaes.o ssharcf.o sshargon2.o sshauxcrypt.o \
        sshblake2.o sshblowf.o sshccp.o sshcommon.o sshcrc.o \
        sshcrcda.o sshdes.o sshdh.o sshdss.o sshecc.o sshgssc.o \
        sshhmac.o sshmac.o sshmd5.o sshprng.o sshpubk.o sshrand.o \
        sshrsa.o sshsh256.o sshsh512.o sshsha.o sshsha3.o sshshare.o \
        sshutils.o sshverstring.o sshzlib.o stripctrl.o supdup.o \
        telnet.o terminal.o timing.o tree234.o utils.o version.o \
        wcwidth.o wildcard.o wincapi.o wincfg.o winctrls.o windefs.o \
        windlg.o window.o wingss.o winhandl.o winhelp.o winhsock.o \
        winjump.o winmisc.o winmiscs.o winnet.o winnoise.o winnpc.o \
        winnps.o winpgntc.o winprint.o winproxy.o winsecur.o \
        winselgui.o winser.o winshare.o winstore.o wintime.o \
        winucs.o winutils.o winx11.o x11fwd.o -ladvapi32 -lcomdlg32 \
        -lgdi32 -limm32 -lole32 -lshell32 -luser32

C:\Users\user\Downloads\putty-src_0-76\windows>

Check the result

C:\Users\user\Downloads\putty-src_0-76\windows> dir putty.exe
 Datenträger in Laufwerk C: ist Windows
 Volumeseriennummer: 1E1B-0142

 Verzeichnis von C:\Users\user\Downloads\putty-src_0-76\windows

16.08.2021  20:16           981.504 putty.exe
               1 Datei(en),        981.504 Bytes
               0 Verzeichnis(se), 265.798.283.264 Bytes frei

C:\Users\user\Downloads\putty-src_0-76\windows>

EXEcute it

C:\Users\user\Downloads\putty-src_0-76\windows> putty.exe
Putty 0.76 – compiled on my own using „gcc 8.1.0“

Final thought: Donate PuTTY

It is possible 😉 to donate to the original PuTTY developers – look here: https://www.chiark.greenend.org.uk/~sgtatham/putty/faq.html#faq-donations

MinGW as build-environment for native Windows Applications

It is possible to complie open source software like „PuTTY“ using the famous gcc open source compiler.

Choose your favourite MinGW „distribution“

There are several  „distribution“-like packages available on the web.

I found https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/installer/mingw-w64-install.exe/download which worked „out of the box“.

Install MinGw

Just a few settings to think about, I chose:

I changed from the default-settings:

  • Version:8.1.0
  • Architecture:i686
  • Threads:posix
  • Exception:dwarf
  • Build Revision:0

to

  • Architecture:x86_64
  • Threads:win32
  • Exception:seh

Check the Windows „PATH“-Environment Variable

I should contain C:\\Program Files\\mingw-w64\\x86\_64-8.1.0-win32-seh-rt\_v6-rev0\\mingw64\\bin

Run a „MinGW-Terminal“

Using the following shortcut

OVF/OVA-Properties

When deploying Virtual-Machines by OVF/OVA-Files in automated manner, eg. using PowerShell of Terraform, it’s crucial to set all individual deployment parameters using the provisioning system.

Discover the available Properties using

  • PowerShell
  • OFV-Tool

Using PowerShell

Create a vCenter-Connection

PS C:\Program Files\PowerShell\7>

$VIServer = "vcenter.lab.local"
$VIUsername = "administrator@vsphere.local"
$VIPassword = "VMware!23"

$viConnection = Connect-VIServer $VIServer -User $VIUsername -Password $VIPassword

Retrieve the OVF-Config-Object

PS C:\Program Files\PowerShell\7>

$OVA = "T:\csr1000v-universalk9.16.09.01.ova"

$ovfconfig = Get-OvfConfiguration -Server $viConnection $OVA
$ovfconfigHashTable = $ovfconfig.ToHashTable()

Display all contained Properties („=Keys“)

PS C:\Program Files\PowerShell\7>

$ovfconfigHashTable.Keys | Sort-Object

com.cisco.csr1000v.domain-name.1
com.cisco.csr1000v.enable-scp-server.1
com.cisco.csr1000v.enable-ssh-server.1
com.cisco.csr1000v.hostname.1
com.cisco.csr1000v.license.1
com.cisco.csr1000v.login-password.1
com.cisco.csr1000v.login-username.1
com.cisco.csr1000v.mgmt-interface.1
com.cisco.csr1000v.mgmt-ipv4-addr.1
com.cisco.csr1000v.mgmt-ipv4-gateway.1
com.cisco.csr1000v.mgmt-ipv4-network.1
com.cisco.csr1000v.mgmt-vlan.1
com.cisco.csr1000v.pnsc-agent-local-port.1
com.cisco.csr1000v.pnsc-ipv4-addr.1
com.cisco.csr1000v.pnsc-shared-secret-key.1
com.cisco.csr1000v.privilege-password.1
com.cisco.csr1000v.remote-mgmt-ipv4-addr.1
com.cisco.csr1000v.resource-template.1
DeploymentOption
NetworkMapping.GigabitEthernet1
NetworkMapping.GigabitEthernet2
NetworkMapping.GigabitEthernet3

Deployment-Option?

PS C:\Program Files\PowerShell\7>

$ovfconfig.DeploymentOption

Key                : DeploymentOption
Value              :
DefaultValue       : 1CPU-4GB
OvfTypeDescription : string["1CPU-4GB", "2CPU-4GB", "4CPU-4GB", "4CPU-8GB"]
Description        : Small
                     Minimal hardware profile - 1 vCPU, 4 GB RAM

                     Medium
                     Medium hardware profile - 2 vCPUs, 4 GB RAM

                     Large
                     Large hardware profile - 4 vCPUs, 4 GB RAM

                     Large + DRAM Upgrade
                     Large hardware profile (requires purchase of DRAM upgrade SKU) - 4 vCPUs, 8 GB RAM

Using OVF-Tool

OVFTOOL.EXE, provided by VMware (Download OVFTOOL) allows to inspect existing OVA/OFV-Files, too.

T:\"C:\Program Files\VMware\VMware OVF Tool\ovftool.exe" --verifyOnly csr1000v-universalk9.16.09.01.ova
OVF version:   1.0
VirtualApp:    false
Name:          Cisco CSR 1000V Cloud Services Router
Version:       16.09.01
Full Version:  Cisco IOS-XE Software, version 16.09.01
Vendor:        Cisco Systems, Inc.
Product URL:   http://www.cisco.com/en/US/products/ps12559/index.html
Vendor URL:    http://www.cisco.com

Download Size:  413.23 MB

Deployment Sizes:
  Flat disks:   8.40 GB
  Sparse disks: 692.60 MB

Networks:
  Name:        GigabitEthernet1
  Description: Data network 1

  Name:        GigabitEthernet2
  Description: Data network 2

  Name:        GigabitEthernet3
  Description: Data network 3

Virtual Machines:
  Name:               Cisco CSR 1000V Cloud Services Router
  Operating System:   other3xlinux64guest
  Virtual Hardware:
    Families:         vmx-10 vmx-11 vmx-13
    Number of CPUs:   1
    Cores per socket: 1
    Memory:           4.00 GB

    Disks:
      Index:          0
      Instance ID:    3001
      Capacity:       8.00 GB
      Disk Types:     SCSI-VirtualSCSI

    NICs:
      Adapter Type:   VMXNET3
      Connection:     GigabitEthernet1

      Adapter Type:   VMXNET3
      Connection:     GigabitEthernet2

      Adapter Type:   VMXNET3
      Connection:     GigabitEthernet3

Properties:
  ClassId:     com.cisco.csr1000v
  Key:         hostname
  InstanceId   1
  Category:    1. Bootstrap Properties
  Label:       Router Name
  Type:        string(..63)
  Description: Hostname of this router

  ClassId:     com.cisco.csr1000v
  Key:         login-username
  InstanceId   1
  Category:    1. Bootstrap Properties
  Label:       Login Username
  Type:        string(..64)
  Description: Username for remote login

  ClassId:     com.cisco.csr1000v
  Key:         login-password
  InstanceId   1
  Category:    1. Bootstrap Properties
  Label:       Login Password
  Type:        password(..25)
  Description: 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.

  ClassId:     com.cisco.csr1000v
  Key:         mgmt-interface
  InstanceId   1
  Category:    1. Bootstrap Properties
  Label:       Management Interface
  Type:        string
  Description: Management interface (such as "GigabitEthernet1" or
               "GigabitEthernet1.100")
  Value:       GigabitEthernet1

  ClassId:     com.cisco.csr1000v
  Key:         mgmt-vlan
  InstanceId   1
  Category:    1. Bootstrap Properties
  Label:       Management VLAN
  Type:        string(..5)
  Description: Management dot1Q VLAN (requires specifying a subinterface such
               as "GigabitEthernet1.100" for the Management Interface)

  ClassId:     com.cisco.csr1000v
  Key:         mgmt-ipv4-addr
  InstanceId   1
  Category:    1. Bootstrap Properties
  Label:       Management Interface IPv4 Address/Mask
  Type:        string(..33)
  Description: 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

  ClassId:     com.cisco.csr1000v
  Key:         mgmt-ipv4-gateway
  InstanceId   1
  Category:    1. Bootstrap Properties
  Label:       Management IPv4 Gateway
  Type:        string(..16)
  Description: IPv4 gateway address (such as "192.0.2.1") for management
               interface, or "dhcp" to configure via DHCP

  ClassId:     com.cisco.csr1000v
  Key:         mgmt-ipv4-network
  InstanceId   1
  Category:    1. Bootstrap Properties
  Label:       Management IPv4 Network
  Type:        string(..33)
  Description: 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.

  ClassId:     com.cisco.csr1000v
  Key:         pnsc-ipv4-addr
  InstanceId   1
  Category:    1. Bootstrap Properties
  Label:       PNSC IPv4 Address
  Type:        string(..15)
  Description: IPv4 address without mask (such as "192.0.2.110") of PNSC
               service controller

  ClassId:     com.cisco.csr1000v
  Key:         pnsc-agent-local-port
  InstanceId   1
  Category:    1. Bootstrap Properties
  Label:       PNSC Agent Local Port
  Type:        string(..5)
  Description: PNSC service agent SSL port (on local CSR) 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.

  ClassId:     com.cisco.csr1000v
  Key:         pnsc-shared-secret-key
  InstanceId   1
  Category:    1. Bootstrap Properties
  Label:       PNSC Shared Secret Key
  Type:        password(..64)
  Description: 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.

  ClassId:     com.cisco.csr1000v
  Key:         remote-mgmt-ipv4-addr
  InstanceId   1
  Category:    1. Bootstrap Properties
  Label:       Remote Management IPv4 Address (optional, deprecated)
  Type:        string(..15)
  Description: 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.

  ClassId:     com.cisco.csr1000v
  Key:         enable-scp-server
  InstanceId   1
  Category:    2. Features
  Label:       Enable SCP Server
  Type:        boolean
  Description: Enable IOS SCP server feature
  Value:       False

  ClassId:     com.cisco.csr1000v
  Key:         enable-ssh-server
  InstanceId   1
  Category:    2. Features
  Label:       Enable SSH Login and Disable Telnet Login
  Type:        boolean
  Description: Enable remote login via SSH and disable remote login via telnet.
               Requires login-username and login-password to be set!
  Value:       False

  ClassId:     com.cisco.csr1000v
  Key:         privilege-password
  InstanceId   1
  Category:    3. Additional Configuration Properties
  Label:       Enable Password
  Type:        password(..25)
  Description: 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.

  ClassId:     com.cisco.csr1000v
  Key:         domain-name
  InstanceId   1
  Category:    3. Additional Configuration Properties
  Label:       Domain Name
  Type:        string(..238)
  Description: Network domain name (such as "cisco.com")

  ClassId:     com.cisco.csr1000v
  Key:         license
  InstanceId   1
  Category:    3. Additional Configuration Properties
  Label:       License boot level
  Type:        string(..30)
  Description: Configure license boot level(such as ax, security, appx, ipbase,
               lite, vacs)
  Value:       ax

  ClassId:     com.cisco.csr1000v
  Key:         resource-template
  InstanceId   1
  Category:    3. Additional Configuration Properties
  Label:       Resource template
  Type:        string(..30)
  Description: Configure Resource template(service_plane_medium,
               service_plane_heavy or default)
  Value:       default

Deployment Options:
  Id:          1CPU-4GB  (default)
  Label:       Small
  Description: Minimal hardware profile - 1 vCPU, 4 GB RAM

  Id:          2CPU-4GB
  Label:       Medium
  Description: Medium hardware profile - 2 vCPUs, 4 GB RAM

  Id:          4CPU-4GB
  Label:       Large
  Description: Large hardware profile - 4 vCPUs, 4 GB RAM

  Id:          4CPU-8GB
  Label:       Large + DRAM Upgrade
  Description: Large hardware profile (requires purchase of DRAM upgrade SKU) -
               4 vCPUs, 8 GB RAM

References:
  File:  csr1000v_harddisk.vmdk
  File:  bdeo.sh
  File:  README-OVF.txt
  File:  README-BDEO.txt
  File:  cot.tgz
  File:  csr1000v-universalk9.16.09.01-vga.iso

OVF-Tool – Extra-Config?

Error: OVF Package is not supported by target:
 - Line -1: Unsupported value 'ethernet0.rxDataRingEnabled' for attribute 'key' on element 'ExtraConfig'.
 - Line -1: Unsupported value 'ethernet1.rxDataRingEnabled' for attribute 'key' on element 'ExtraConfig'.
 - Line -1: Unsupported value 'ethernet2.rxDataRingEnabled' for attribute 'key' on element 'ExtraConfig'.
 - Line -1: Unsupported value 'ethernet3.rxDataRingEnabled' for attribute 'key' on element 'ExtraConfig'.
 - Line -1: Unsupported value 'isolation.tools.diskWiper.disable' for attribute 'key' on element 'ExtraConfig'.
 - Line -1: Unsupported value 'isolation.tools.memSchedFakeSampleStats.disable' for attribute 'key' on element 'ExtraConfig'.
 - Line -1: Unsupported value 'isolation.tools.diskShrink.disable' for attribute 'key' on element 'ExtraConfig'.
 - Line -1: Unsupported value 'isolation.tools.vmxDnDVersionGet.disable' for attribute 'key' on element 'ExtraConfig'.
 - Line -1: Unsupported value 'isolation.tools.unityActive.disable' for attribute 'key' on element 'ExtraConfig'.
 - Line -1: Unsupported value 'isolation.tools.guestDnDVersionSet.disable' for attribute 'key' on element 'ExtraConfig'.
 - Line -1: Unsupported value 'snapshot.maxSnapshots' for attribute 'key' on element 'ExtraConfig'.
 - Line -1: Unsupported value 'RemoteDisplay.maxConnections' for attribute 'key' on element 'ExtraConfig'.

The CLI-Switch „–allowExtraConfig“ enables the support for ExtraConfig-Key/Values:

T:\>"C:\Program Files\VMware\VMware OVF Tool\ovftool.exe" --verifyOnly --allowExtraConfig nsx-unified-appliance-3.1.3.5.0.19068437.ova
The provided certificate is in valid period
Source is signed and the certificate validates
Certificate information:
  CertIssuer:/C=US/ST=California/L=Palo Alto/O=VMware, Inc.
  CertSubject:/C=US/ST=California/L=Palo Alto/O=VMware, Inc.
  -----BEGIN CERTIFICATE-----
  MIIDyzCCArOgAwIBAgIJAKH7xLtwMqSZMA0GCSqGSIb3DQEBBQUAME0xCzAJBgNV
  BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlQYWxvIEFsdG8x
  FTATBgNVBAoTDFZNd2FyZSwgSW5jLjAeFw0xMDAyMjYyMjE3NDFaFw0yNjAxMDMy
  MjE3NDFaME0xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRIwEAYD
  VQQHEwlQYWxvIEFsdG8xFTATBgNVBAoTDFZNd2FyZSwgSW5jLjCCASAwDQYJKoZI
  hvcNAQEBBQADggENADCCAQgCggEBALU9NUtC39fqG7yo2XAswUmtli9uA+31uAMw
  9FFHAEv/it8pzBQZ/4r+2bN+GnXOWhuDd1K4ApKMRvoO4LwQfZxrkx4pXrsu0gdb
  4OunHw0D8MrdzSoob8Js/uq+IJ+8Bhsc6b7RzTUt9HeDWzHasAJVgMsjehGt23ay
  9FKOT6dVD6D/Xi3qJnB/4t/XNS6L63dC3ea4guzKDyLaXIP5bf/m56jvVImFjhhT
  W2ASbnEUlZIVrEuyVcdG7e3FvZufE553JmHL0YG/0m5bIHXKRzBRx0D3HHOAzOKw
  kkOnxJHSTN4Hz8hSYCWvzUAjSYL3Q8qiTd7GHJ2ynsRnu3KlzKUCAQOjga8wgaww
  HQYDVR0OBBYEFHg8KQJdm8NPQDmYP41uEgKG+VNwMH0GA1UdIwR2MHSAFHg8KQJd
  m8NPQDmYP41uEgKG+VNwoVGkTzBNMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
  aWZvcm5pYTESMBAGA1UEBxMJUGFsbyBBbHRvMRUwEwYDVQQKEwxWTXdhcmUsIElu
  Yy6CCQCh+8S7cDKkmTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCP
  nVEBVF2jYEsgaTJ1v17HNTVTD5pBPfbQk/2vYVZEWL20PtJuLeSWwoo5+TnCSp69
  i9n1Hpm9JWHjyb1Lba8Xx7VC4FferIyxt0ivRm9l9ouo/pQAR8xyqjTg1qfr5V8S
  fZElKbjpzSMPrxLwF77h+YB+YjqWAJpVV+fAkAvK7K9vMiFgW60teZBxVW/XlmG0
  IJaSUWSI3/A+bA6fuIy8PMmpQMtm0droHrCnViAVRhMMgEC/doMH1GqUSmoiyQ1G
  PifLAp5wV5/HV+S9AGrb8HGdWIvW+kBgmCl0wSf2JFYm1bpq30CVE4EC0MAY1mJG
  vSqQGIbCybw5KTCXRQ8d
  -----END CERTIFICATE-----


OVF version:   1.0
VirtualApp:    false
Name:          nsx-unified-appliance
Version:       3.1.3.5
Full Version:  3.1.3.5.0.19068437
Vendor:        VMware, Inc

Download Size:  8.37 GB

Deployment Sizes:
  Flat disks:   300.00 GB
  Sparse disks: 4.74 GB

Networks:
  Name:        Network 1
  Description: Network 1

Virtual Machines:
  Name:               nsx-unified-appliance
  Operating System:   ubuntu64guest
  Virtual Hardware:
    Families:         vmx-10 vmx-11 vmx-13
    Number of CPUs:   6
    Cores per socket: 1
    Memory:           24.00 GB

    Disks:
      Index:          0
      Instance ID:    5
      Capacity:       200.00 GB
      Disk Types:     SCSI-lsilogic

      Index:          1
      Instance ID:    6
      Capacity:       100.00 GB
      Disk Types:     SCSI-lsilogic

    NICs:
      Adapter Type:   VmxNet3
      Connection:     Network 1

Properties:
  Key:         nsx_passwd_0
  Category:    Application
  Label:       System Root User Password
  Type:        password(12..)
  Description: The password for root user for this VM.
               Please follow the password complexity rule as below:
                   - minimum of 12 characters in length
                   - >=1 uppercase character
                   - >=1 lowercase character
                   - >=1 numeric character
                   - >=1 special character
                   - >=5 unique characters
                   - default password complexity rules as enforced by the Linux
               PAM module
                   NOTE: Password strength validation will occur during VM
               boot.  If the password does not meet the above criteria then
               login as root user for the change password prompt to appear.


  Key:         nsx_cli_passwd_0
  Category:    Application
  Label:       CLI "admin" User Password
  Type:        password(12..)
  Description: The password for default CLI user for this VM.
               Please follow the password complexity rule as below:
                   - minimum of 12 characters in length
                   - >=1 uppercase character
                   - >=1 lowercase character
                   - >=1 numeric character
                   - >=1 special character
                   - >=5 unique characters
                   - default password complexity rules as enforced by the Linux
               PAM module
                   NOTE: Password strength validation will occur during VM
               boot.  If the password does not meet the above criteria then
               login as admin user for the change password prompt to appear.


  Key:         nsx_cli_audit_passwd_0
  Category:    Application
  Label:       CLI "audit" User Password
  Type:        password
  Description: The password for audit CLI user for this VM.
               Please follow the password complexity rule as below:
                   - minimum of 12 characters in length
                   - >=1 uppercase character
                   - >=1 lowercase character
                   - >=1 numeric character
                   - >=1 special character
                   - >=5 unique characters
                   - default password complexity rules as enforced by the Linux
               PAM module
                   NOTE: Password strength validation will occur during VM
               boot.  If the password does not meet the above criteria then
               login as admin user and use the NSX CLI command "set user audit"
               to change the audit user password.


  Key:         nsx_cli_username
  Category:    Application
  Label:       CLI "admin" username (default: admin)
  Type:        string
  Description: Username of administrator user.

  Key:         nsx_cli_audit_username
  Category:    Application
  Label:       CLI "audit" username (default: audit)
  Type:        string
  Description: Username of auditor user.

  Key:         extraPara
  Category:    Application
  Label:       Optional parameters
  Type:        password
  Description: For internal use only.


  Key:         nsx_hostname
  Category:    Network properties
  Label:       Hostname
  Type:        string(1..)
  Description: The hostname for this VM.
                   NOTE: Underscores in hostname are not allowed.  If hostname
               contains underscore, then the appliance gets deployed with
               'nsx-manager' as hostname.


  Key:         nsx_role
  Category:    Network properties
  Label:       Rolename
  Type:        string["NSX Manager","nsx-cloud-service-manager","NSX Global
               Manager"]
  Description: The role for this VM. Currently supports
               'nsx-cloud-service-manager', 'NSX Global Manager' OR 'NSX
               Manager' as rolename.

  Value:       NSX Manager

  Key:         nsx_ip_0
  Category:    Network properties
  Label:       Management Network IPv4 Address
  Type:        string(1..)
  Description: The IPv4 Address for the first interface.

  Key:         nsx_netmask_0
  Category:    Network properties
  Label:       Management Network Netmask
  Type:        string(1..)
  Description: The netmask for the first interface.

  Key:         nsx_gateway_0
  Category:    Network properties
  Label:       Default IPv4 Gateway
  Type:        string
  Description: The default gateway for this VM.

  Key:         nsx_dns1_0
  Category:    DNS
  Label:       DNS Server list
  Type:        string
  Description: The space separated DNS server list for this VM (valid only if
               an IPv4 address is specified for the first interface).
                   NOTE: At most three name servers can be configured (first 3
               name servers passed in list will be used and all other will be
               ignored)


  Key:         nsx_domain_0
  Category:    DNS
  Label:       Domain Search List
  Type:        string
  Description: The space separated domain search list for this VM (valid only
               if an IPv4 address is specified for the first interface).

  Key:         nsx_ntp_0
  Category:    Services Configuration
  Label:       NTP Server List
  Type:        string
  Description: The NTP server list(space separated) for this VM.

  Key:         nsx_isSSHEnabled
  Category:    Services Configuration
  Label:       Enable SSH
  Type:        boolean
  Description: Enabling SSH service is not recommended for security reasons.
  Value:       False

  Key:         nsx_allowSSHRootLogin
  Category:    Services Configuration
  Label:       Allow root SSH logins
  Type:        boolean
  Description: Allowing root SSH logins is not recommended for security
               reasons.
  Value:       False

  Key:         nsx_swIntegrityCheck
  Category:    Services Configuration
  Label:       Software Integrity Checker
  Type:        boolean
  Description: Software Integrity Checker is required only for NDcPP 2.2
  Value:       False

  Key:         mpIp
  Category:    Internal Properties - Do not set these parameters.
  Label:       Manager IP
  Type:        string
  Description: For internal use only. Do not set this parameter.


  Key:         mpToken
  Category:    Internal Properties - Do not set these parameters.
  Label:       Manager Token
  Type:        password
  Description: For internal use only. Do not set this parameter.


  Key:         mpThumbprint
  Category:    Internal Properties - Do not set these parameters.
  Label:       Manager Thumbprint
  Type:        string
  Description: For internal use only. Do not set this parameter.


  Key:         mpNodeId
  Category:    Internal Properties - Do not set these parameters.
  Label:       Manager Node ID
  Type:        string
  Description: For internal use only. Do not set this parameter.


  Key:         mpClusterId
  Category:    Internal Properties - Do not set these parameters.
  Label:       Cluster ID of First Manager Cluster
  Type:        string
  Description: For internal use only. Do not set this parameter.


Deployment Options:
  Id:          extra_small
  Label:       ExtraSmall
  Description:
               IMPORTANT: This configuration is only supported for the
               nsx-cloud-service-manager role.

               This configuration requires the following:
               * 2 vCPU
               * 8GB RAM
               * 300GB Storage
               * VM hardware version 10 or greater (vSphere 5.5 or greater)


  Id:          small
  Label:       Small
  Description:
               IMPORTANT: This configuration is supported for Global Manager
               Production deployment

               This configuration requires the following:
               * 4 vCPU
               * 16GB RAM
               * 300GB Storage
               * VM hardware version 10 or greater (vSphere 5.5 or greater)


  Id:          medium  (default)
  Label:       Medium
  Description:
               IMPORTANT: This configuration is supported for Local Manager
               Production deployment ('NSX Manager' role)
                          This is supported for Global Manager Production
               deployment (but not required)

               This configuration requires the following:
               * 6 vCPU
               * 24GB RAM
               * 300GB Storage
               * VM hardware version 10 or greater (vSphere 5.5 or greater)


  Id:          large
  Label:       Large
  Description:
               IMPORTANT: This configuration is supported for Local Manager
               Production deployment ('NSX Manager' role)
                          This is supported for Global Manager Production
               deployment (but not required)

               This configuration requires the following:
               * 12 vCPU
               * 48GB RAM
               * 300GB Storage
               * VM hardware version 10 or greater (vSphere 5.5 or greater)


References:
  File:  nsx-unified-appliance.vmdk
  File:  nsx-unified-appliance-secondary.vmdk


Provision a Cisco CSR1000V-Router as Virtual-Box-VM with sliptreamed Configuration, wait until it’s up and open an Putty-SSH-Connection

The existing Windows-Comman-Script has been enhanced so it now

  • waits until the Router-VM is up
  • got an IP-Address assigned using DHCP.

For Demonstration-Purposes an SSH-Connection will be established.

  • The public-key of my laptop-ssh-client is part of the slipstreamed Router-Configuration.

Deploy a Router-VM with hostname „CSY“.

C:\RH\work\entwicklung\csr1000v-provision-in-virtualbox>CSR1000v-Virtual-Box.cmd CSY
Virtual machine 'CSY' is created and registered.
UUID: 915a7495-0728-4fc5-9c4c-21b3106a07e5
Settings file: 'c:\RH\LAB\VM\CSY\CSY.vbox'
Creating ISO image at c:\RH\LAB\VM\CSY\CSY_config.iso, 1 Files, Size: 8,00 KB
100%
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Medium created. UUID: b79d708a-0a0a-4866-853b-3ac45c6a6127
Waiting for VM "CSY" to power on...
VM "CSY" has been successfully started.
Waiting for VM "CSY" to be initialized...
Router "CSY" up and running, using IP=192.168.56.102
Establishing SSH-Connection as "labuser"
Done

Establish an SSH-Connection to the discovered Router-IP:

Have a look to the startup-config used:

This is the „CMD“-Script used:

@echo off

: Ronald Heitmann

:set VM=CSR1000vX
:set /p VM="Enter CSR1000v Hostname:"
: Parameter given? Use it as VM-Name
set VM=%1
if not defined VM set /p VM="Enter CSR1000v Hostname:"

:echo %VM%

set PUTTYUSER=labuser
set PUTTYPK=C:\RH\work\putty\labuser.ppk


set BASE=c:\RH\LAB\VM

set ISO=C:\Downloads\csr1000v-universalk9.16.09.0x.iso

: Create VM
:VBoxManage createvm --name %VM% --ostype "Linux_64" --basefolder %BASE% --register
VBoxManage createvm --name %VM% --ostype "Linux26_64" --basefolder %BASE% --register

:now the Path in the Filesystem to ...LOC... exists
set LOC=%BASE%\%VM%

: Create ISO containing slipstreamed config-file
: use UNXTOOLS "sed" to customize the "hostname"-Command
:
set CFGISO=%LOC%\%VM%_config.iso
set CFGSRC=C:\RH\LAB\VM\iosxe_config.txt
set CFGTXT=%LOC%\iosxe_config.txt
cat %CFGSRC% | sed "s/HOSTNAME/%VM%/g" > %CFGTXT%
"%ProgramFiles(x86)%"\CDBurnerXP\cdbxpcmd.exe --burn-data -file:%CFGTXT% -iso:%CFGISO% -format:iso

: Customize VM
VBoxManage modifyvm %VM% --memory 4096
VBoxManage modifyvm %VM% --vram 16
VBoxManage modifyvm %VM% --pae on --paravirtprovider default --hwvirtex on --nestedpaging on

: Storage
VBoxManage createhd --filename %LOC%\%VM%.vdi --size 8192
VBoxManage storagectl %VM% --name "IDE-CTL" --add ide --portcount 2 --bootable on
VBoxManage storageattach %VM% --storagectl IDE-CTL --port 0 --device 0 --type hdd --medium %LOC%\%VM%.vdi
VBoxManage storageattach %VM% --storagectl IDE-CTL --port 1 --device 0 --type dvddrive --medium %ISO%
VBoxManage storageattach %VM% --storagectl IDE-CTL --port 1 --device 1 --type dvddrive --medium %CFGISO%
VBoxManage modifyvm %VM% --boot1=dvd --boot2=disk --boot3=none --boot4=none

: Serial-Interfaces via "Pipe"
VBoxManage modifyvm %VM% --uartmode1 server \\.\pipe\%VM%
VBoxManage modifyvm %VM% --uart1 0x3f8 4
VBoxManage modifyvm %VM% --uartmode2 server \\.\pipe\%VM%_diag
VBoxManage modifyvm %VM% --uart2 0x2f8 4

: Audio
VBoxManage modifyvm %VM% --audio none

: NICs
VBoxManage modifyvm %VM% --nic1 nat --nic2 hostonly --nic3 hostonly --nic4 hostonly
VBoxManage modifyvm %VM% --nictype1 virtio --nictype2 virtio --nictype3 virtio --nictype4 virtio
VBoxManage modifyvm %VM% --nicpromisc1 allow-all --nicpromisc2 allow-all --nicpromisc3 allow-all --nicpromisc4 allow-all
VBoxManage modifyvm %VM% --hostonlyadapter2 "VirtualBox Host-Only Ethernet Adapter"
VBoxManage modifyvm %VM% --hostonlyadapter3 "VirtualBox Host-Only Ethernet Adapter"
VBoxManage modifyvm %VM% --hostonlyadapter4 "VirtualBox Host-Only Ethernet Adapter"

: Set the VM-Logo for the VirtualBox-Inventory
VBoxManage modifyvm %VM% --iconfile C:\RH\LAB\72px-Cisco_logo.svg.png

: Boot the VM, it'l reboot once to apply the running-config
VBoxManage startvm %VM% --type headless

: Wait for the VM to be fully initialized
: - with DHCP-IP-Address at "Gig 2"
: - and store this IP-Address in Variable VMIP
echo Waiting for VM "%VM%" to be initialized...
for /f %%I in ('python WaitForCDPNeighbor.py -n %VM% -c -i "VirtualBox Host-Only Ethernet Adapter" 2^> nul') do @(set VMIP=%%I)

echo Router "%VM%" up and running, using IP=%VMIP%

: Connect to Router using Putty/SSH
echo Establishing SSH-Connection as "%PUTTYUSER%"
start putty -ssh -i %PUTTYPK% %PUTTYUSER%@%VMIP%

echo Done

WaitForCDPNeighbor.py enhanced: Wait for CDP Hostname with usable connected IP-Address.

The following version adds a „-c“ option: „Connected IP-Address“-Check.

  • the script exits, when the Router-VM is up and running and has an usable IP-Address

The Script still checks all CDP-Packets received at the specified Interface:

  • If the Sender has the correct „Hostname“ it reads the CDP-Management-IP-Address announced.
  • This IP-Address has to be within the IP-Range of any connected IP-Network at the specified Interface.

So it’ll be possible to establish a SSH-Session to the router-VM.

C:\> echo %VM%
CSX

C:\> python WaitForCDPNeighbor.py -n %VM% -c -i "VirtualBox Host-Only Ethernet Adapter"
192.168.56.101
#! /usr/bin/env python

# Ronald Heitmann
#
import argparse

from scapy.all import *
load_contrib("cdp")

from netaddr import IPNetwork, IPAddress

from netifaces import AF_INET, AF_INET6, AF_LINK
import netifaces

# returns a list of all IP-Adresses bound to the specified Interface "if_name"
def get_connected(if_name):
  if_id = ""
  networks = []

  for i in ifaces.data.keys():
    iface = ifaces.data[i]
    wname = iface.data['name']
    if wname == if_name:
      if_id = i
      addresses = netifaces.ifaddresses(i)
      if AF_INET in addresses:
        for addr in netifaces.ifaddresses(i)[AF_INET]:
          #print(addr)
          ipnetwork = IPNetwork(addr["addr"]+"/"+addr["netmask"]).cidr
          networks.append(ipnetwork)
  #print(networks)
  return networks

# checks, if the IP-Address "ip" is within the subnet-range of any network contained in the list "networks"

def is_IP_connected(ip, networks):
  found = False
  ipnetwork = IPNetwork(ip).cidr

  for n in networks:
    if (ipnetwork in n):
      found = True

  return found

  
def main():

    # Parse CLI-Arguments
    parser = argparse.ArgumentParser(description='Wait for a CDP-Neighbor.')
    parser.add_argument("-i", "--interface", help="monitored interface", default="VirtualBox Host-Only Ethernet Adapter")
    parser.add_argument("-n", "--hostname", help="Neighbor to wait for", required=True)
    parser.add_argument("-c", "--connected", help="wait, until CDP-Neighbor announces an directly-connected IP-Address", action='store_true')
    args = parser.parse_args()

    #looking for a specific hostname
    #
    hostname = ""
    wait_for_hostname = args.hostname

    #watching for CDP-Packets from this host on a specific interface
    #the router-IP should use a directly-connected IP-Address
    ip = "0.0.0.0"
    wait_for_connected = args.connected
    
    interface=args.interface
    networks = get_connected(interface)
    #print(networks) 

    #CDP
    capturefilter="ether dst 01:00:0c:cc:cc:cc"

    while not((hostname == wait_for_hostname) and (not(wait_for_connected) or is_IP_connected(ip,networks))):
      p=sniff(iface=interface, count=1, filter=capturefilter)
      pkt=p[0]
      #print("Packet received",pkt.show())

      #is this a CDP-Packet containing a hostname?
      if (CDPMsgDeviceID in pkt):
        #is this the CDP-Neighbor we're looking for?
        device=pkt["CDPMsgDeviceID"].val.decode()
        hostname=device.split(".")[0]
        #print("Hostname:",hostname)

        if (hostname == wait_for_hostname):
          #is this a CDP-Packet containing a management-IP-Address?
          if (CDPAddrRecordIPv4 in pkt):
            ip=pkt["CDPAddrRecordIPv4"].addr
            #print("IP-Address found:",ip)

    #return the IP-Address to the calling application or the CLI
    return ip

if __name__ == "__main__":
    print(main())

Python Scapy: Wait for CDP-Neighbor

After provisioning a new Cisco CSR1000V-Router this script

  • waits until the router is fully deployed
  • got it’s Management-IP-Address assigned via DHCP.

and returns this Management IP-Address.

  1. Prepare
  2. First, install „netaddr“-package.

    • needed to check, if the management-IP of the CDP-Neighbor is in the correct IP-Subnet
    C:\RH>pip install netaddr
    Collecting netaddr
      Downloading https://files.pythonhosted.org/packages/ba/97/ce14451a9fd7bdb5a397abf99b24a1a6bb7a1a440b019bebd2e9a0dbec74/netaddr-0.7.19-py2.py3-none-any.whl (1.6MB)
        100% |████████████████████████████████| 1.6MB 4.0MB/s
    Installing collected packages: netaddr
    Successfully installed netaddr-0.7.19
    
  3. the „wait-for-CDP“-Script
  4. Obviously far to much hard-coded stuff, just as an example 😉 waiting for a CDP-Neighbor to appear with the following properties:

    • hostname „CSR-A“
    • an IP-Address within the network „192.168.56.0 /24“
    • at the interface

    • VirtualBox Host-Only-Network
    #! /usr/bin/env python
    
    from scapy.all import *
    load_contrib("cdp")
    
    from netaddr import IPNetwork, IPAddress
    
    # run it for max. 99 Packets
    ip = "0.0.0.0"
    wait_for_hostname = "CSR-A"
    wait_for_host_in_network = "192.168.56.0/24"
    
    interface="VirtualBox Host-Only Ethernet Adapter"
    capturefilter="ether dst 01:00:0c:cc:cc:cc"
    
    while not(IPAddress(ip) in IPNetwork(wait_for_host_in_network)):
      p=sniff(iface=interface, count=1, filter=capturefilter)
      pkt=p[0]
      #print("Packet received",pkt.show())
    
      #is this a CDP-Packet containing a hostname?
      if (CDPMsgDeviceID in pkt):
        #is this the CDP-Neighbor we're looking for?
        device=pkt["CDPMsgDeviceID"].val.decode()
        hostname=device.split(".")[0]
        #print("Hostname:",hostname)
    
        if (hostname == wait_for_hostname):
          #is this a CDP-Packet containing a management-IP-Address?
          if (CDPAddrRecordIPv4 in pkt):
            ip=pkt["CDPAddrRecordIPv4"].addr
            #print("IP-Address found:",ip)
    
    #return the IP-Address to the calling application or the CLI
    print(ip)
    
  5. Provision a new CSR1000V Router named „CSR-A“
  6. C:\RH>CSR1000v-Virtual-Box.cmd
    Enter CSR1000v Hostname:CSR-A
    Virtual machine 'CSR-A' is created and registered.
    UUID: 8a9c969e-3895-4a7c-9cbc-5f5551bf1b7b
    Settings file: 'c:\RH\LAB\VM\CSR-A\CSR-A.vbox'
    Creating ISO image at c:\RH\LAB\VM\CSR-A\config.iso, 1 Files, Size: 8,00 KB
    100%
    0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
    Medium created. UUID: 55ea8df5-7e3c-4485-8e08-9302cb61a09d
    Waiting for VM "CSR-A" to power on...
    VM "CSR-A" has been successfully started.
    
  7. Run the „wait-for-CDP-Neighbor“-Script
  8. In a second CMD-Box, and… Be patient, of course.

    C:\RH>python wait-for-cdpneighbor.py
    192.168.56.101
    
  9. Or store the returned IP-Address in an Shell-Variable „ROUTER-IP“/li>
    C:\RH>for /f %I in ('python wait-for-cdpneighbor.py 2^> nul') do @(set ROUTER-IP=%I)
    
  10. and pass it to putty – using public-key authentication
  11. The Public-Key for user „labuser“ is part of my baseline-config used to provision the virtual-router.

    C:\RH>putty -ssh -i C:\RH\work\putty-rsa-key\labuser.ppk labuser@%ROUTER-IP%
    

    Works, this is a nice preparation for an automated virtual ansible-lab, too!

Python Scapy: CDP-Monitor

Watch and decode Cisco Discovery Protocol Packetes.

  1. CDP Monitor-Script
  2. Inspired by the Scapy ARP-Monitor i created an CDP-Monitor displaying hostname and an optional Management-IP-Address.

    #! /usr/bin/env python
    from scapy.all import *
    load_contrib("cdp")
    
    def cdp_monitor_callback(pkt):
      ip = "0.0.0.0"
      if (CDPMsgDeviceID in pkt):
        device=pkt["CDPMsgDeviceID"].val.decode()
        hostname=device.split(".")[0]
        if (CDPAddrRecordIPv4 in pkt):
          ip=pkt["CDPAddrRecordIPv4"].addr
        return "Device: {0} IP: {1}".format(hostname,ip)
    
    interface="VirtualBox Host-Only Ethernet Adapter"
    capturefilter="ether dst 01:00:0c:cc:cc:cc"
    
    # run it for max. 99 Packets
    p=sniff(prn=cdp_monitor_callback, iface=interface, count=99, filter=capturefilter, store=0)
    
  3. Real-Life Example
    • Run this script:
    • C:\RH>python
      Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)] on win32
      Type "help", "copyright", "credits" or "license" for more information.
      >>> #! /usr/bin/env python
      ... from scapy.all import *
      >>> load_contrib("cdp")
      >>>
      >>> def cdp_monitor_callback(pkt):
      ...   ip = "0.0.0.0"
      ...   if (CDPMsgDeviceID in pkt):
      ...     device=pkt["CDPMsgDeviceID"].val.decode()
      ...     hostname=device.split(".")[0]
      ...     if (CDPAddrRecordIPv4 in pkt):
      ...       ip=pkt["CDPAddrRecordIPv4"].addr
      ...     return "Device: {0} IP: {1}".format(hostname,ip)
      ...
      >>> interface="VirtualBox Host-Only Ethernet Adapter"
      >>> capturefilter="ether dst 01:00:0c:cc:cc:cc"
      >>>
      >>> # run it for max. 99 Packets
      ... p=sniff(prn=cdp_monitor_callback, iface=interface, count=99, filter=capturefilter, store=0)
      
    • Open another CMD-Window to spin up a new CSR1000V-Router:
    • C:\RH\work\entwicklung\csr1000v-provision-in-virtualbox>CSR1000v-Virtual-Box.cmd
      Enter CSR1000v Hostname:CSR-CDPTEST-A
      Virtual machine 'CSR-CDPTEST-A' is created and registered.
      UUID: eaa931bd-9db4-4a78-b263-754d4bb300a0
      Settings file: 'c:\RH\LAB\VM\CSR-CDPTEST-A\CSR-CDPTEST-A.vbox'
      Creating ISO image at c:\RH\LAB\VM\CSR-CDPTEST-A\config.iso, 1 Files, Size: 8,00 KB
      100%
      0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
      Medium created. UUID: 3019216e-2e61-435a-95f2-3d26312c3ed9
      Waiting for VM "CSR-CDPTEST-A" to power on...
      VM "CSR-CDPTEST-A" has been successfully started.
      
    • Go back to the „python“-Screen and wait:
    • >>> # run it for max. 99 Packets
      ... p=sniff(prn=cdp_monitor_callback, iface=interface, count=99, filter=capturefilter, store=0)
      Device: CSR-CDPTEST-A IP: 0.0.0.0
      Device: CSR-CDPTEST-A IP: 0.0.0.0
      Device: CSR-CDPTEST-A IP: 0.0.0.0
      Device: CSR-CDPTEST-A IP: 0.0.0.0
      Device: CSR-CDPTEST-A IP: 0.0.0.0
      Device: CSR-CDPTEST-A IP: 10.0.2.15
      Device: CSR-CDPTEST-A IP: 10.0.2.15
      Device: CSR-CDPTEST-A IP: 10.0.2.15
      

      It works, the IOS-XE CSR1000V-Router is installed and it got it’s baseline-config applied:

      • Hostname
      • Interface set to „ip address dhcp“
      • CDP enabled

      takes some time, but these first CDP-Packets captured were not sent in 60s interval, so don’t be scared 😉

Python Scapy: Capturing „Cisco Discovery Protocol (CDP)“

It’s hard to believe, how easy it is to capture (and to craft) LAN-Data using Python Scapy.

I need to capture CDP-Packets and to extract information like the hostname of the sender and it’s IP-Address.

As an modification of the „ARP-Monitor“-example taken from the manual Using scapy in your tools.

  1. Scapy Installation
  2. nothing special: pip install

    C:\RH>pip install scapy
    Collecting scapy
      Downloading https://files.pythonhosted.org/packages/68/01/b9943984447e7ea6f8948e90c1729b78161c2bb3eef908430638ec3f7296/scapy-2.4.0.tar.gz (3.1MB)
        100% |████████████████████████████████| 3.1MB 420kB/s
      In the tar file C:\Users\RONALD~1.HEI\AppData\Local\Temp\pip-unpack-4jm9kde1\scapy-2.4.0.tar.gz the member scapy-2.4.0/README is invalid: unable to resolve link inside archive
    Installing collected packages: scapy
      Running setup.py install for scapy ... done
    Successfully installed scapy-2.4.0
    
  3. Python: Install Scapy
  4. C:\RH>python
    Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    
    >>> from scapy.all import *
    
  5. Example: List all Interfaces of my Laptop
  6. >>> ifaces
    INDEX  IFACE                                     IP            MAC
    20     VirtualBox Host-Only Ethernet Adapter     192.168.56.1  0A:00:27:00:00:14
    22     Intel(R) Dual Band Wireless-AC 8265       172.20.10.2   IntelCor:BD:10:37
    4      Intel(R) Ethernet Connection (4) I219-LM  47.11.17.10   BayNetwo:00:DE:11
    
    >>> for i in ifaces.data.keys():
    ...     iface = ifaces.data[i]
    ...     name = str(iface.name)
    ...     wname = iface.data['netid']
    ...     mac = str(iface.mac)
    ...     ip  = str(iface.ip)
    ...     print("DESCR:{0}, NAME:{1}, MAC:{2}, IP:{3}".format(wname,name,mac,ip))
    ...
    DESCR:Wi-Fi, NAME:Intel(R) Dual Band Wireless-AC 8265, MAC:74:70:FD:BD:10:37, IP:172.20.10.2
    DESCR:VirtualBox Host-Only Network, NAME:VirtualBox Host-Only Ethernet Adapter, MAC:0A:00:27:00:00:14, IP:192.168.56.1
    DESCR:ETH_DELL, NAME:Intel(R) Ethernet Connection (4) I219-LM, MAC:00:00:81:00:DE:11, IP:47.11.17.10
    
  7. Capture 10 Packets on a specific interface
  8. The "NAME" is needed as interface-handle
    >>> interface="VirtualBox Host-Only Ethernet Adapter"
    
    >>> p=sniff(iface=interface, count=10)
    >>> p.display()
    0000 Ether / IP / UDP 192.168.56.1:17500 > 255.255.255.255:17500 / Raw
    0001 Ether / IP / UDP 192.168.56.1:17500 > 255.255.255.255:17500 / Raw
    0002 Ether / IP / UDP 192.168.56.1:17500 > 192.168.56.255:17500 / Raw
    0003 Ether / IP / UDP 192.168.56.1:17500 > 255.255.255.255:17500 / Raw
    0004 Ether / IP / UDP 192.168.56.1:17500 > 255.255.255.255:17500 / Raw
    0005 Ether / IP / UDP 192.168.56.100:bootps > 255.255.255.255:bootpc / BOOTP / DHCP
    0006 Ether / IP / UDP 192.168.56.102:50472 > 255.255.255.255:10067 / Raw
    0007 Ether / IP / UDP 192.168.56.103:49580 > 255.255.255.255:10067 / Raw
    0008 Ether / IP / UDP 192.168.56.1:17500 > 255.255.255.255:17500 / Raw
    0009 Ether / IP / UDP 192.168.56.1:17500 > 255.255.255.255:17500 / Raw
    
  9. Capture CDP-Packets
  10. Capture CDP
    
    >>> p=sniff(iface=interface, count=2, filter="ether dst 01:00:0c:cc:cc:cc")
    >>> p
    <Sniffed: TCP:0 UDP:0 ICMP:0 Other:2>
    >>> p.display()
    0000 802.3 08:00:27:c9:d5:7e > 01:00:0c:cc:cc:cc / LLC / SNAP / Raw
    0001 802.3 08:00:27:c9:d5:7e > 01:00:0c:cc:cc:cc / LLC / SNAP / Raw
    
  11. Decode CDP (with inactive dissector)
  12. >>> p[0].display()
    ###[ 802.3 ]###
      dst       = 01:00:0c:cc:cc:cc
      src       = 08:00:27:c9:d5:7e
      len       = 386
    ###[ LLC ]###
         dsap      = 0xaa
         ssap      = 0xaa
         ctrl      = 3
    ###[ SNAP ]###
            OUI       = 0xc
            code      = 0x2000
    ###[ Raw ]###
               load      = '\x02\xb4\x91\x18\x00\x01\x00\x13CSR-A.lab.local\x00\x05\x01\x05Cisco IOS Software [Fuji], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.9.1, RELEASE SOFTWARE (fc2)\nTechnical Support: http://www.cisco.com/techsupport\nCopyright (c) 1986-2018 by Cisco Systems, Inc.\nCompiled Tue 17-Jul-18 16:57 by mcpre\x00\x06\x00\x12cisco CSR1000V\x00\x02\x00\x11\x00\x00\x00\x01\x01\x01\xcc\x00\x04\xc0\xa88e\x00\x03\x00\x14GigabitEthernet2\x00\x04\x00\x08\x00\x00\x00!\x00\x07\x00\t\n\x00\x02\x00\x18\x00\x0b\x00\x05\x01\x00\x16\x00\x11\x00\x00\x00\x01\x01\x01\xcc\x00\x04\xc0\xa88e'
    
  13. Activate the CDP-Parser
  14. >>> list_contrib()
    avs                 : AVS WLAN Monitor Header                  status=loads
    bgp                 : BGP v0.1                                 status=loads
    carp                : CARP                                     status=loads
    cdp                 : Cisco Discovery Protocol                 status=loads
    chdlc               : Cisco HDLC and SLARP                     status=loads
    coap                : Constrained Application Protocol (CoAP)  status=loads
    diameter            : Diameter                                 status=loads
    dtp                 : DTP                                      status=loads
    eigrp               : EIGRP                                    status=loads
    etherip             : EtherIP                                  status=loads
    gsm_um              : PPI                                      status=loads
    gtp                 : GTP                                      status=loads
    gtp_v2              : GTPv2                                    status=loads
    homeplugav          : HomePlugAV Layer                         status=loads
    http2               : HTTP/2 (RFC 7540, RFC 7541)              status=loads
    icmp_extensions     : ICMP Extensions                          status=loads
    igmp                : IGMP/IGMPv2                              status=loads
    igmpv3              : IGMPv3                                   status=loads
    ikev2               : IKEv2                                    status=loads
    isis                : ISIS                                     status=loads
    ldp                 : Label Distribution Protocol (LDP)        status=loads
    lldp                : LLDP                                     status=loads
    macsec              : -                                        status=?
    modbus              : ModBus Protocol                          status=loads
    mpls                : MPLS                                     status=loads
    mqtt                : -                                        status=?
    nsh                 : NSH Protocol                             status=loads
    openflow            : Openflow v1.0                            status=loads
    openflow3           : Openflow v1.3                            status=loads
    ospf                : OSPF                                     status=loads
    pnio                : ProfinetIO base layer                    status=loads
    pnio_rtc            : ProfinetIO Real-Time Cyclic (RTC)        status=loads
    ppi                 : PPI                                      status=loads
    ppi_cace            : PPI CACE                                 status=loads
    ppi_geotag          : PPI GEOLOCATION                          status=loads
    ripng               : RIPng                                    status=loads
    rsvp                : RSVP                                     status=loads
    sebek               : Sebek                                    status=loads
    send                : Secure Neighbor Discovery (SEND) (ICMPv6) status=loads
    skinny              : Skinny Call Control Protocol (SCCP)      status=loads
    spbm                : SBPM                                     status=loads
    tacacs              : TACACS+ Protocol                         status=loads
    tzsp                : TZSP                                     status=loads
    ubberlogger         : Ubberlogger dissectors                   status=loads
    vqp                 : VLAN Query Protocol                      status=loads
    vtp                 : VLAN Trunking Protocol (VTP)             status=loads
    wpa_eapol           : WPA EAPOL dissector                      status=loads
    
    >>> load_contrib("cdp")
    
  15. Capture again and display CDP-Information as cleartext
  16. >>> load_contrib("cdp")
    
    >>> p=sniff(iface=interface, count=1, filter=capturefilter)
    >>>
    >>>
    >>> p[0].show()
    ###[ 802.3 ]###
      dst       = 01:00:0c:cc:cc:cc
      src       = 08:00:27:c9:d5:7e
      len       = 386
    ###[ LLC ]###
         dsap      = 0xaa
         ssap      = 0xaa
         ctrl      = 3
    ###[ SNAP ]###
            OUI       = 0xc
            code      = 0x2000
    ###[ Cisco Discovery Protocol version 2 ]###
               vers      = 2
               ttl       = 180
               cksum     = 0x9118
               \msg       \
                |###[ Device ID ]###
                |  type      = Device ID
                |  len       = 19
                |  val       = 'CSR-A.lab.local'
                |###[ Software Version ]###
                |  type      = Software Version
                |  len       = 261
                |  val       = 'Cisco IOS Software [Fuji], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.9.1, RELEASE SOFTWARE (fc2)\nTechnical Support: http://www.cisco.com/techsupport\nCopyright (c) 1986-2018 by Cisco Systems, Inc.\nCompiled Tue 17-Jul-18 16:57 by mcpre'
                |###[ Platform ]###
                |  type      = Platform
                |  len       = 18
                |  val       = 'cisco CSR1000V'
                |###[ Addresses ]###
                |  type      = Addresses
                |  len       = 17
                |  naddr     = 1
                |  \addr      \
                |   |###[ CDP Address IPv4 ]###
                |   |  ptype     = NLPID
                |   |  plen      = 1
                |   |  proto     = '\xcc'
                |   |  addrlen   = 4
                |   |  addr      = 192.168.56.101
                |###[ Port ID ]###
                |  type      = Port ID
                |  len       = 20
                |  iface     = 'GigabitEthernet2'
                |###[ Capabilities ]###
                |  type      = Capabilities
                |  len       = 8
                |  cap       = Router+IGMPCapable
                |###[ IP Prefix ]###
                |  type      = IP Prefix
                |  len       = 9
                |  defaultgw = 10.0.2.0
                |###[ CDP Generic Message ]###
                |  type      = 0x1800
                |  len       = 2816
                |  val       = '\x05\x01\x00\x16\x00\x11\x00\x00\x00\x01\x01\x01\xcc\x00\x04\xc0\xa88e'
    
  17. Decode CDP-Hostname
  18. >>> device=p[0]["CDPMsgDeviceID"].val.decode()
    >>> device
    'CSR-A.lab.local'
    >>> hostname=device.split(".")[0]
    >>> hostname
    'CSR-A'
    
  19. Decode CDP-Management-IP-Address
  20. >>> ip=p[0]["CDPAddrRecordIPv4"]
    >>> ip.addr
    '192.168.56.101'