diff --git a/nested-labvm/atd-docker/coder/Dockerfile b/nested-labvm/atd-docker/coder/Dockerfile
index ae82a1c67..8690214f7 100644
--- a/nested-labvm/atd-docker/coder/Dockerfile
+++ b/nested-labvm/atd-docker/coder/Dockerfile
@@ -5,7 +5,7 @@ RUN sudo apt update && \
RUN sudo pip3 install --upgrade pip
-RUN sudo pip3 install pyeapi jsonrpclib-pelix shyaml
+RUN sudo pip3 install pyeapi jsonrpclib-pelix shyaml ansible-pylibssh
RUN wget --quiet https://raw.githubusercontent.com/aristanetworks/ansible-avd/devel/ansible_collections/arista/avd/requirements.txt
@@ -16,7 +16,7 @@ RUN wget --quiet https://raw.githubusercontent.com/aristanetworks/ansible-avd/de
RUN sudo pip3 install -r requirements-dev.txt
# Install arista.avd, community.general and ansible.posix ansible-galaxy collections with upgrade flag if already exists
-RUN ansible-galaxy collection install arista.avd --upgrade
+RUN ansible-galaxy collection install arista.avd --force
RUN ansible-galaxy collection install community.general --upgrade
diff --git a/nested-labvm/atd-docker/cvpUpdater/Dockerfile b/nested-labvm/atd-docker/cvpUpdater/Dockerfile
index 882590611..557ab365d 100644
--- a/nested-labvm/atd-docker/cvpUpdater/Dockerfile
+++ b/nested-labvm/atd-docker/cvpUpdater/Dockerfile
@@ -9,8 +9,9 @@ RUN curl -SsL https://github.com/boxboat/fixuid/releases/download/v0.5/fixuid-0.
printf "user: arista\ngroup: arista\npaths:\n - /home/arista\n - /home/arista/CVP_DATA\n" > /etc/fixuid/config.yml
RUN pip install rcvpapi \
- ruamel.yaml
-
+ ruamel.yaml \
+ cvprac paramiko scp
+
RUN mkdir -p /home/arista/CVP_DATA
WORKDIR /home/arista
diff --git a/nested-labvm/atd-docker/cvpUpdater/src/cvpUpdater.py b/nested-labvm/atd-docker/cvpUpdater/src/cvpUpdater.py
index 8243b3595..d07cc8a37 100644
--- a/nested-labvm/atd-docker/cvpUpdater/src/cvpUpdater.py
+++ b/nested-labvm/atd-docker/cvpUpdater/src/cvpUpdater.py
@@ -1,9 +1,11 @@
#!/usr/bin/env python
-
+from cvprac.cvp_client import CvpClient
from ruamel.yaml import YAML
from rcvpapi.rcvpapi import *
-import requests, json
+from paramiko import SSHClient
+from paramiko import AutoAddPolicy
+from scp import SCPClient
from os import path, listdir, system
from sys import exit
from time import sleep
@@ -20,6 +22,7 @@
# Temporary file_path location for CVP Custom info
cvp_file = '/home/arista/cvp/cvp_info.yaml'
+
# ==================================
# Start of Global Functions
# ==================================
@@ -198,6 +201,9 @@ def main():
cvpPassword = atd_yaml['login_info']['jump_host']['pw']
while not cvp_clnt:
try:
+ cvprac_clnt = CvpClient()
+ cvprac_clnt.api.request_timeout = 180
+ cvprac_clnt.connect([atd_yaml['nodes']['cvp'][0]['ip']], cvpUsername, cvpPassword)
cvp_clnt = CVPCON(atd_yaml['nodes']['cvp'][0]['ip'], cvpUsername, cvpPassword)
pS("OK","Connected to CVP at {0}".format(atd_yaml['nodes']['cvp'][0]['ip']))
except:
@@ -220,6 +226,30 @@ def main():
pS("INFO", "CVP will be bare and no configuration.")
return(True)
if cvp_clnt:
+ # ==========================================
+ # Check the current version to see if a
+ # token needs to be generated
+ # ==========================================
+ _version = cvprac_clnt.api.get_cvp_info()
+ _version = _version['version'].split('.')
+ _version_major = float(f"{_version[0]}.{_version[1]}")
+ # Perform check if it is a cEOS based topo and 2022.2 or later CVP
+ if _version_major >= 2022.2 and (atd_yaml['eos_type'] == 'ceos' or atd_yaml['eos_type'] == 'container-labs'):
+ pS("INFO", "Generating a token for onboarding...")
+ _token_response = cvprac_clnt.api.create_enroll_token("24h")
+ _token_path = path.expanduser(f"~/token")
+ with open(f"{_token_path}", 'w') as token_out:
+ token_out.write(_token_response['data'])
+ for _node in eos_info:
+ with SSHClient() as ssh:
+ ssh.set_missing_host_key_policy(AutoAddPolicy())
+ ssh.connect(_node.ip, username=cvpUsername, password=cvpPassword,)
+ with SCPClient(ssh.get_transport()) as scp:
+ pS("INFO", f"Transferring token to {_node.hostname}")
+ scp.put(f"{_token_path}", "/tmp/token")
+ else:
+ pS("INFO", f"Version does not require a token for onboarding...")
+
# ==========================================
# Check to see how many nodes have connected
# ==========================================
@@ -391,4 +421,4 @@ def main():
else:
pS("OK","CVP is already configured")
while True:
- sleep(600)
+ sleep(600)
\ No newline at end of file
diff --git a/nested-labvm/atd-docker/docker-compose.yml b/nested-labvm/atd-docker/docker-compose.yml
index 2016be13c..0a11b5875 100644
--- a/nested-labvm/atd-docker/docker-compose.yml
+++ b/nested-labvm/atd-docker/docker-compose.yml
@@ -24,7 +24,7 @@ services:
- /home/arista/arista-dir:/home/arista:rw
login:
container_name: atd-login
- image: us.gcr.io/atd-testdrivetraining-dev/atddocker_login:1.0.5
+ image: us.gcr.io/atd-testdrivetraining-dev/atddocker_login:1.0.16
user: $ArID:$ArGD
restart: always
hostname: devbox
@@ -41,7 +41,7 @@ services:
- /var/run/libvirt/libvirt-sock:/var/run/libvirt/libvirt-sock:ro
cvpupdater:
container_name: atd-cvpupdater
- image: us.gcr.io/atd-testdrivetraining-dev/atddocker_cvpupdater:1.0.0
+ image: us.gcr.io/atd-testdrivetraining-dev/atddocker_cvpupdater:2.0.2
user: $ArID:$ArGD
restart: always
environment:
@@ -53,7 +53,7 @@ services:
- cvp_dir:/home/arista/CVP_DATA:rw
gitconfigletsync:
container_name: atd-gitconfigletsync
- image: us.gcr.io/atd-testdrivetraining-dev/atddocker_gitconfigletsync:1.0.0
+ image: us.gcr.io/atd-testdrivetraining-dev/atddocker_gitconfigletsync:2.0.0
user: $ArID:$ArGD
restart: always
environment:
@@ -85,7 +85,7 @@ services:
- /opt/ceos:/opt/ceos:rw
uilanding:
container_name: atd-uilanding
- image: us.gcr.io/atd-testdrivetraining-dev/atddocker_uilanding:1.0.0
+ image: us.gcr.io/atd-testdrivetraining-dev/atddocker_uilanding:1.0.16
restart: always
environment:
- PYTHONUNBUFFERED=1
@@ -93,17 +93,46 @@ services:
- /etc/atd:/etc/atd:ro
- /opt/atd:/opt/atd:ro
- /home/arista/arista-dir/apps/uilanding:/opt/modules:ro
+ - /home/arista/arista-dir/menus:/opt/menus:rw
+ - /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- atd_nginx
labguides:
container_name: atd-labguides
- image: us.gcr.io/atd-testdrivetraining-dev/atddocker_labguides:1.0.0
+ image: us.gcr.io/atd-testdrivetraining-dev/atddocker_labguides:1.0.1
restart: always
environment:
- PYTHONUNBUFFERED=1
volumes:
- /etc/atd:/etc/atd:ro
- /opt/atd:/opt/atd:ro
+ - /opt/labguides/web/:/root/labguides/web/:rw
+ networks:
+ - atd_nginx
+ syslog:
+ container_name: atd-syslog
+ image: us.gcr.io/atd-testdrivetraining-dev/atddocker_syslog:1.0.1
+ restart: always
+ environment:
+ - PYTHONUNBUFFERED=1
+ volumes:
+ - /home/arista/arista-dir/apps/syslog/:/var/log/remote/:rw
+ ports:
+ - "1514:1514"
+ - "1514:1514/udp"
+ networks:
+ - atd_nginx
+ tacacs:
+ container_name: atd-tacacs
+ image: us.gcr.io/atd-testdrivetraining-dev/atddocker_tacacs:1.0.0
+ restart: always
+ environment:
+ - PYTHONUNBUFFERED=1
+ volumes:
+ - /home/arista/arista-dir/apps/tacacs/config:/etc/tac_plus/tac_user.cfg:ro
+ - /home/arista/arista-dir/apps/tacacs/tac.log:/var/log/tac_plus.log:rw
+ ports:
+ - "49:49"
networks:
- atd_nginx
freerad:
@@ -117,7 +146,7 @@ services:
- "1813:1813/udp"
nginx:
container_name: atd-nginx
- image: us.gcr.io/atd-testdrivetraining-dev/atddocker_nginx:1.0.2
+ image: us.gcr.io/atd-testdrivetraining-dev/atddocker_nginx:1.0.5
restart: always
depends_on:
- uilanding
@@ -158,7 +187,7 @@ services:
- ./jenkins/src/groovy/users.groovy.override:/usr/share/jenkins/ref/init.groovy.d/users.groovy.override:rw
coder:
container_name: atd-coder
- image: us.gcr.io/atd-testdrivetraining-dev/atddocker_coder:1.0.1
+ image: us.gcr.io/atd-testdrivetraining-dev/atddocker_coder:1.0.2
restart: always
user: $ArID:$ArGD
command: /home/coder/project
diff --git a/nested-labvm/atd-docker/docker_run.sh b/nested-labvm/atd-docker/docker_run.sh
new file mode 100644
index 000000000..86fed6a48
--- /dev/null
+++ b/nested-labvm/atd-docker/docker_run.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+echo "Starting one-time containers"
+
+docker run -d --rm -e PYTHONUNBUFFERED=1 --name atd-vtepinfo -v /etc/atd:/etc/atd:rw us.gcr.io/atd-testdrivetraining-dev/atddocker_vtepinfo:0.1.9
\ No newline at end of file
diff --git a/nested-labvm/atd-docker/gitConfigletSync/Dockerfile b/nested-labvm/atd-docker/gitConfigletSync/Dockerfile
index 1375f67ff..1290cfc24 100644
--- a/nested-labvm/atd-docker/gitConfigletSync/Dockerfile
+++ b/nested-labvm/atd-docker/gitConfigletSync/Dockerfile
@@ -11,8 +11,9 @@ RUN curl -SsL https://github.com/boxboat/fixuid/releases/download/v0.5/fixuid-0.
RUN pip install rcvpapi \
cvprac \
Pyyaml \
- ruamel.yaml
-
+ ruamel.yaml \
+ paramiko \
+ scp
RUN mkdir -p /home/arista/CVP_DATA
WORKDIR /home/arista
diff --git a/nested-labvm/atd-docker/gitConfigletSync/src/gitConfigletSync.py b/nested-labvm/atd-docker/gitConfigletSync/src/gitConfigletSync.py
index 99d8bdbda..e0248ccfe 100644
--- a/nested-labvm/atd-docker/gitConfigletSync/src/gitConfigletSync.py
+++ b/nested-labvm/atd-docker/gitConfigletSync/src/gitConfigletSync.py
@@ -6,11 +6,18 @@
import yaml
from ruamel.yaml import YAML
from rcvpapi.rcvpapi import *
+from cvprac.cvp_client import CvpClient
+from paramiko import SSHClient
+from paramiko import AutoAddPolicy
+from scp import SCPClient
+from os import path
from datetime import datetime
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
ACCESS = '/etc/atd/ACCESS_INFO.yaml'
+REPO_PATH = '/opt/atd/'
+REPO_TOPO = REPO_PATH + 'topologies/'
CVP_CONFIG_FIILE = os.path.expanduser('~/CVP_DATA/.cvpState.txt')
sleep_delay = 30
@@ -36,6 +43,45 @@ def syncConfiglet(cvpClient,configletName,configletConfig):
##### End of syncConfiglet
+def getTopoInfo(yaml_file):
+ """
+ Function that parses the supplied YAML file to build the CVP topology.
+ """
+ topoInfo = open(yaml_file,'r')
+ topoYaml = YAML().load(topoInfo)
+ topoInfo.close()
+ return(topoYaml)
+
+def checkConnected(cvp_clnt, NODES):
+ """
+ Function to check if all nodes have connected and
+ are reachable via ping
+ Parameters:
+ cvp_clnt = CVP rCVPAPI client (object)
+ NODES = EOS Node yaml (dict)
+ """
+ tmp_device_count = len(cvp_clnt.inventory)
+ while len(NODES) > tmp_device_count:
+ pS("INFO", "Only {0} out of {1} nodes have registered to CVP. Sleeping {2} seconds.".format(tmp_device_count, len(NODES), sleep_delay))
+ time.sleep(sleep_delay)
+ cvp_clnt.getDeviceInventory()
+ tmp_device_count = len(cvp_clnt.inventory)
+ pS("OK", "All {0} out of {1} nodes have registered to CVP.".format(tmp_device_count, len(NODES)))
+ pS("INFO", "Checking to see if all nodes are reachable")
+ # Make sure all nodes are up and reachable
+ for vnode in cvp_clnt.inventory:
+ while True:
+ vresponse = cvp_clnt.ipConnectivityTest(cvp_clnt.inventory[vnode]['ipAddress'])
+ if 'data' in vresponse:
+ if vresponse['data'] == 'success':
+ pS("OK", "{0} is up and reachable at {1}".format(vnode, cvp_clnt.inventory[vnode]['ipAddress']))
+ break
+ else:
+ pS("INFO", "{0} is NOT reachable at {1}. Sleeping {2} seconds.".format(vnode, cvp_clnt.inventory[vnode]['ipAddress'], sleep_delay))
+ time.sleep(sleep_delay)
+ pS("OK", "All Devices are registered and reachable.")
+ return(True)
+
def pS(mstat,mtype):
"""
Function to send output from service file to Syslog
@@ -53,7 +99,7 @@ def main():
break
else:
pS("ERROR", "ACCESS_INFO file is not available...Waiting for {0} seconds".format(sleep_delay))
- sleep(sleep_delay)
+ time.sleep(sleep_delay)
try:
f = open(ACCESS)
accessinfo = yaml.safe_load(f)
@@ -88,6 +134,7 @@ def main():
# rcvpapi clnt var container
cvp_clnt = ""
+ cvprc_clnt = ""
# Adding new connection to CVP via rcvpapi
while not cvp_clnt:
@@ -106,6 +153,49 @@ def main():
else:
pS("INFO", "Local copy is missing....Waiting 1 minute for it to become available")
time.sleep(60)
+ while not cvprc_clnt:
+ try:
+ cvprac_clnt = CvpClient()
+ cvprac_clnt.api.request_timeout = 180
+ cvprac_clnt.connect([accessinfo['nodes']['cvp'][0]['ip']], cvpUsername, cvpPassword)
+ cvprc_clnt = CVPCON(accessinfo['nodes']['cvp'][0]['ip'], cvpUsername, cvpPassword)
+ pS("OK","Connected to CVP at {0}".format(accessinfo['nodes']['cvp'][0]['ip']))
+ except:
+ pS("ERROR","CVP is currently unavailable....Retrying in {0} seconds.".format(sleep_delay))
+ time.sleep(sleep_delay)
+
+ # ==========================================
+ # Check the current version to see if a
+ # token needs to be generated
+ # ==========================================
+ _version = cvprac_clnt.api.get_cvp_info()
+ _version = _version['version'].split('.')
+ _version_major = float(f"{_version[0]}.{_version[1]}")
+ build_yaml = getTopoInfo(REPO_TOPO + accessinfo['topology'] + '/topo_build.yml')
+ # Perform check if it is a cEOS based topo and 2022.2 or later CVP
+ if _version_major >= 2022.2 and (accessinfo['eos_type'] == 'ceos' or accessinfo['eos_type'] == 'container-labs'):
+ pS("INFO", "Generating a token for onboarding...")
+ _token_response = cvprac_clnt.api.create_enroll_token("24h")
+ _token_path = path.expanduser(f"~/token")
+ with open(f"{_token_path}", 'w') as token_out:
+ token_out.write(_token_response['data'])
+ # EOS_DEV = []
+ for dev in build_yaml['nodes']:
+ devn = list(dev.keys())[0]
+ _eos_ip = dev[devn]['ip_addr']
+ with SSHClient() as ssh:
+ ssh.set_missing_host_key_policy(AutoAddPolicy())
+ ssh.connect(_eos_ip, username=cvpUsername, password=cvpPassword,)
+ with SCPClient(ssh.get_transport()) as scp:
+ pS("INFO", f"Transferring token to {devn}")
+ scp.put(f"{_token_path}", "/tmp/token")
+ else:
+ pS("INFO", f"Version does not require a token for onboarding...")
+
+ # ==========================================
+ # Check to see how many nodes have connected
+ # ==========================================
+ checkConnected(cvp_clnt, build_yaml['nodes'])
configlets = os.listdir(gitTempPath + configletPath)
@@ -133,17 +223,17 @@ def main():
res = cvp_clnt.impConfiglet("static",configletName,configletConfig)
pS("OK", "{0} Configlet: {1}".format(res[0],configletName))
# Perform a check to see if there any pending tasks to be executed due to configlet update
- sleep(20)
+ time.sleep(20)
pS("INFO", "Checking for any pending tasks")
cvp_clnt.getAllTasks("pending")
if cvp_clnt.tasks['pending']:
pS("INFO", "{0} Pending tasks found, will be executing".format(len(cvp_clnt.tasks['pending'])))
task_response = cvp_clnt.execAllTasks("pending")
- sleep(10)
+ time.sleep(10)
while len(cvp_clnt.tasks['pending']) > 0:
pS("INFO", "{0} Pending tasks found, will be executing".format(len(cvp_clnt.tasks['pending'])))
_tmp_response = cvp_clnt.execAllTasks("pending")
- sleep(5)
+ time.sleep(5)
cvp_clnt.getAllTasks("pending")
# Perform check to see if there are any existing tasks to be executed
if task_response:
@@ -160,7 +250,27 @@ def main():
break
else:
pS("INFO", "Task ID: {0} Status: {1}, Waiting 10 seconds...".format(task_id, task_status))
- sleep(10)
+ time.sleep(10)
+ # Perform check to see if any tasks failed
+ cvp_clnt.getAllTasks("failed")
+ if len(cvp_clnt.tasks["failed"]) > 0:
+ pS("INFO", "Failed tasks found, will execute tasks...")
+ task_response = cvp_clnt.execAllTasks("failed")
+ if task_response:
+ pS("OK", "All pending tasks are executing")
+ for task_id in task_response['ids']:
+ task_status = cvp_clnt.getTaskStatus(task_id)['taskStatus']
+ while task_status != "Completed":
+ task_status = cvp_clnt.getTaskStatus(task_id)['taskStatus']
+ if task_status == 'Failed':
+ pS("iBerg", "Task ID: {0} Status: {1}".format(task_id, task_status))
+ break
+ elif task_status == 'Completed':
+ pS("INFO", "Task ID: {0} Status: {1}".format(task_id, task_status))
+ break
+ else:
+ pS("INFO", "Task ID: {0} Status: {1}, Waiting 10 seconds...".format(task_id, task_status))
+ time.sleep(10)
else:
pS("INFO", "No pending tasks found to be executed.")
@@ -174,4 +284,4 @@ def main():
else:
pS("INFO", "CVP not provisioned, holding off on configlet sync.")
while True:
- sleep(600)
\ No newline at end of file
+ time.sleep(600)
\ No newline at end of file
diff --git a/nested-labvm/atd-docker/labguides/src/build_labguides.sh b/nested-labvm/atd-docker/labguides/src/build_labguides.sh
index 68a0a7f3a..3bea11217 100644
--- a/nested-labvm/atd-docker/labguides/src/build_labguides.sh
+++ b/nested-labvm/atd-docker/labguides/src/build_labguides.sh
@@ -1,45 +1,45 @@
#!/bin/bash
-while [ $(cat /etc/atd/ACCESS_INFO.yaml | shyaml get-value login_info.jump_host.pw) == 'REPLACE_PWD' ]
-do
- echo "Password has not been updated yet. sleeping..."
- sleep 10
-done
+# while [ $(cat /etc/atd/ACCESS_INFO.yaml | shyaml get-value login_info.jump_host.pw) == 'REPLACE_PWD' ]
+# do
+# echo "Password has not been updated yet. sleeping..."
+# sleep 10
+# done
-TOPO=$(cat /etc/atd/ACCESS_INFO.yaml | shyaml get-value topology)
-ARISTA_PWD=$(cat /etc/atd/ACCESS_INFO.yaml | shyaml get-value login_info.jump_host.pw)
-EOS_TYPE=$(cat /etc/atd/ACCESS_INFO.yaml | python3 -m shyaml get-value eos_type)
+# TOPO=$(cat /etc/atd/ACCESS_INFO.yaml | shyaml get-value topology)
+# ARISTA_PWD=$(cat /etc/atd/ACCESS_INFO.yaml | shyaml get-value login_info.jump_host.pw)
+# EOS_TYPE=$(cat /etc/atd/ACCESS_INFO.yaml | python3 -m shyaml get-value eos_type)
-# Clean up previous stuff to make sure it's current
-#rm -rf /home/arista/labguides/build
+# # Clean up previous stuff to make sure it's current
+# #rm -rf /home/arista/labguides/build
-cp -r /opt/atd/topologies/$TOPO/labguides/* /root/labguides/
+# cp -r /opt/atd/topologies/$TOPO/labguides/* /root/labguides/
-# Update the Arista user password for connecting to the labvm
-find /root/labguides/source/* -type f -print0 | xargs -0 sed -i "s/{REPLACE_PWD}/$ARISTA_PWD/g"
+# # Update the Arista user password for connecting to the labvm
+# find /root/labguides/source/* -type f -print0 | xargs -0 sed -i "s/{REPLACE_PWD}/$ARISTA_PWD/g"
-if [ $EOS_TYPE == 'ceos' ]
-then
- find /root/labguides/source/* -type f -print0 | xargs -0 sed -i "s/Management1/Management0/g"
-fi
+# if [ $EOS_TYPE == 'ceos' ]
+# then
+# find /root/labguides/source/* -type f -print0 | xargs -0 sed -i "s/Management1/Management0/g"
+# fi
-# chown -R arista:arista /home/arista/labguides/src/
+# # chown -R arista:arista /home/arista/labguides/src/
-# Build the lab guides html files
-cd /root/labguides/
-make html
-sphinx-build -b latex source build
+# # Build the lab guides html files
+# cd /root/labguides/
+# make html
+# sphinx-build -b latex source build
-# Build the lab guides PDF
-make latexpdf LATEXOPTS=-interaction=nonstopmode
+# # Build the lab guides PDF
+# make latexpdf LATEXOPTS=-interaction=nonstopmode
-rm -r /root/labguides/web/*
+# rm -r /root/labguides/web/*
-# Put the new HTML and PDF in the proper directories
-mv /root/labguides/build/latex/ATD.pdf /root/labguides/web/
-mv /root/labguides/build/html/* /root/labguides/web/
+# # Put the new HTML and PDF in the proper directories
+# mv /root/labguides/build/latex/ATD.pdf /root/labguides/web/
+# mv /root/labguides/build/html/* /root/labguides/web/
-echo Labguide build complete
+# echo Labguide build complete
cd /root
diff --git a/nested-labvm/atd-docker/login/Dockerfile b/nested-labvm/atd-docker/login/Dockerfile
index 8fb369598..8f5ce9217 100644
--- a/nested-labvm/atd-docker/login/Dockerfile
+++ b/nested-labvm/atd-docker/login/Dockerfile
@@ -31,16 +31,26 @@ RUN mkdir .ssh
COPY src/login.py /usr/local/bin
+COPY src/callConfigTopo.py /usr/local/bin
+
COPY src/resetVMs.py /usr/local/bin
+COPY src/lab_status.py /usr/local/bin
+
COPY src/uploadExam.py /usr/local/bin
COPY src/localGrading.py /usr/local/bin
COPY src/saveRunning.py /usr/local/bin
+COPY src/qa-steps.py /usr/local/bin
+
+RUN chmod +x /usr/local/bin/lab_status.py
+
RUN chmod +x /usr/local/bin/login.py
+RUN chmod +x /usr/local/bin/qa-steps.py
+
RUN chmod +x /usr/local/bin/resetVMs.py
RUN chmod +x /usr/local/bin/uploadExam.py
@@ -67,4 +77,4 @@ EXPOSE 22
USER arista
-CMD ["/usr/local/bin/entrypoint.sh"]
+CMD ["/usr/local/bin/entrypoint.sh"]
\ No newline at end of file
diff --git a/nested-labvm/atd-docker/login/src/ConfigureTopology/ConfigureTopology.py b/nested-labvm/atd-docker/login/src/ConfigureTopology/ConfigureTopology.py
index 1f25038dc..de73e32de 100644
--- a/nested-labvm/atd-docker/login/src/ConfigureTopology/ConfigureTopology.py
+++ b/nested-labvm/atd-docker/login/src/ConfigureTopology/ConfigureTopology.py
@@ -243,6 +243,7 @@ def deploy_lab(self):
input('Lab Setup Completed. Please press Enter to continue...')
self.send_to_syslog("OK", 'Lab Setup Completed.')
else:
+ print('Lab Setup Completed. ')
self.send_to_syslog("OK", 'Lab Setup Completed.')
all_tasks_completed = True
else:
@@ -279,4 +280,5 @@ def deploy_lab(self):
input('Lab Setup Completed. Please press Enter to continue...')
self.send_to_syslog("OK", 'Lab Setup Completed.')
else:
- self.send_to_syslog("OK", 'Lab Setup Completed.')
+ print('Lab Setup Completed. ')
+ self.send_to_syslog("OK", 'Lab Setup Completed.')
\ No newline at end of file
diff --git a/nested-labvm/atd-docker/login/src/callConfigTopo.py b/nested-labvm/atd-docker/login/src/callConfigTopo.py
new file mode 100644
index 000000000..b1a406846
--- /dev/null
+++ b/nested-labvm/atd-docker/login/src/callConfigTopo.py
@@ -0,0 +1,4 @@
+from ConfigureTopology.ConfigureTopology import ConfigureTopology
+import sys
+#ConfigureTopology(selected_menu='training-l3',selected_lab='reset',public_module_flag=True)
+ConfigureTopology(selected_menu=str(sys.argv[1]),selected_lab=str(sys.argv[2]),public_module_flag=True)
\ No newline at end of file
diff --git a/nested-labvm/atd-docker/login/src/lab_status.py b/nested-labvm/atd-docker/login/src/lab_status.py
new file mode 100644
index 000000000..2f48a3b8f
--- /dev/null
+++ b/nested-labvm/atd-docker/login/src/lab_status.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+
+import libvirt
+import time
+import jsonrpclib
+import yaml
+import ssl
+import sys
+
+try:
+ _create_unverified_https_context = ssl._create_unverified_context
+except AttributeError:
+ pass
+else:
+ ssl._create_default_https_context = _create_unverified_https_context
+
+
+labACCESS = '/etc/atd/ACCESS_INFO.yaml'
+
+
+def readLabDetails():
+ # get the lab password and the topolgy in use
+ with open(labACCESS) as f:
+ labDetails = yaml.load(f,Loader=yaml.FullLoader)
+ return labDetails['login_info']['jump_host']['pw'], labDetails['topology']
+
+
+
+def readAtdTopo(labTopology):
+ #get a list of all IP addresses in the topology
+ with open("/opt/atd/topologies/"+ labTopology +"/topo_build.yml") as f:
+ topology = yaml.load(f,Loader=yaml.FullLoader)
+ # print(topology)
+ mylist= topology['nodes']
+ test=[]
+ for item in mylist:
+ test.append(list(item.keys()))
+ hostsName = [item for sublist in test for item in sublist]
+ hostsIP = []
+ for a in topology['nodes']:
+ for key in a.keys():
+ hostsIP.append(a[key]['ip_addr'])
+ return hostsIP, hostsName
+
+
+def _get_libvirt_machine(machine):
+ #libvirt.registerErrorHandler(f=_libvirt_silence_error, ctx=None)
+ try:
+ conn = libvirt.open("qemu:///system")
+ except:
+ print("Unable to connect to local HV. Are you using sudo?")
+ sys.exit()
+ else:
+ libvirt_machine = conn.lookupByName(machine)
+ return libvirt_machine
+
+
+def main():
+ labPassword, labTopology = readLabDetails()
+ allHostsIP, allHostsName = readAtdTopo(labTopology)
+ switch_status=[]
+ for name, ip in zip(allHostsName,allHostsIP):
+ switch = jsonrpclib.Server("https://arista:{password}@{ipaddress}/command-api".format(password = labPassword, ipaddress = ip))
+ try:
+ switch.runCmds(1,["show version"])
+ except:
+ print("{switch},Down".format(switch = name))
+ else:
+ print("{switch},Ok".format(switch = name))
+main()
\ No newline at end of file
diff --git a/nested-labvm/atd-docker/login/src/login.py b/nested-labvm/atd-docker/login/src/login.py
index 8963dc2fb..5f2d3780e 100644
--- a/nested-labvm/atd-docker/login/src/login.py
+++ b/nested-labvm/atd-docker/login/src/login.py
@@ -86,9 +86,9 @@ def device_menu():
# Sort veos instances
veos_info_sorted = sort_veos(veos_info)
- print("\n\n*****************************************")
- print("*****Jump Host for Arista Test Drive*****")
- print("*****************************************")
+ print("\n\n*******************************************")
+ print("*****Jump Host for Arista Training Labs****")
+ print("*******************************************")
print("\n\n==========Device SSH Menu==========\n")
print("Screen Instructions:\n")
@@ -107,6 +107,7 @@ def device_menu():
counter += 1
print("\nOther Options: ")
+ print("95. Upload your exam (exam)")
print("96. Screen (screen) - Opens a screen session to each of the hosts")
print("97. Back to Previous Menu (back)")
print("98. Shell (shell/bash)")
@@ -121,6 +122,8 @@ def device_menu():
os.system('ssh -o StrictHostKeyChecking=no ' + device_dict[user_input])
elif user_input == '96' or user_input.lower() == 'screen':
os.system('/usr/bin/screen')
+ elif user_input == '95' or user_input.lower() == 'exam':
+ os.system('uploadExam.py')
elif user_input == '97' or user_input.lower() == 'back':
if menu_mode == previous_menu:
menu_mode = 'MAIN'
@@ -145,9 +148,9 @@ def lab_options_menu():
global previous_menu
os.system("clear")
- print("\n\n*****************************************")
- print("*****Jump Host for Arista Test Drive*****")
- print("*****************************************")
+ print("\n\n*******************************************")
+ print("*****Jump Host for Arista Training Labs****")
+ print("*******************************************")
if menu_mode == 'LAB_OPTIONS':
# Get Yaml Files in /home/arista/menus
@@ -263,9 +266,9 @@ def main_menu():
global previous_menu
os.system("clear")
- print("\n\n*****************************************")
- print("*****Jump Host for Arista Test Drive*****")
- print("*****************************************")
+ print("\n\n*******************************************")
+ print("*****Jump Host for Arista Training Labs****")
+ print("*******************************************")
print("\n\n==========Main Menu==========\n")
print("Please select from the following options: ")
@@ -369,4 +372,4 @@ def main():
os.system("/bin/bash")
if __name__ == '__main__':
- main()
+ main()
\ No newline at end of file
diff --git a/nested-labvm/atd-docker/login/src/qa-steps.py b/nested-labvm/atd-docker/login/src/qa-steps.py
new file mode 100644
index 000000000..85ffc3d46
--- /dev/null
+++ b/nested-labvm/atd-docker/login/src/qa-steps.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+from base64 import b64decode, b64encode
+import time
+import jsonrpclib
+import yaml
+import ssl
+import sys
+import traceback
+import json
+import requests
+TOPO_API = 'atd-conftopo'
+try:
+ _create_unverified_https_context = ssl._create_unverified_context
+except AttributeError:
+ pass
+else:
+ ssl._create_default_https_context = _create_unverified_https_context
+
+
+labACCESS = '/etc/atd/ACCESS_INFO.yaml'
+
+
+def readLabDetails():
+ # get the lab password and the topolgy in use
+ with open(labACCESS) as f:
+ labDetails = yaml.load(f,Loader=yaml.FullLoader)
+ return labDetails['login_info']['jump_host']['pw'], labDetails['topology']
+
+
+
+def readAtdTopo(labTopology):
+ #get a list of all IP addresses in the topology
+ with open("/opt/atd/topologies/"+ labTopology +"/topo_build.yml") as f:
+ topology = yaml.load(f,Loader=yaml.FullLoader)
+ # print(topology)
+ mylist= topology['nodes']
+ test=[]
+ for item in mylist:
+ test.append(list(item.keys()))
+ hostsName = [item for sublist in test for item in sublist]
+ hostsIP = []
+ for a in topology['nodes']:
+ for key in a.keys():
+ hostsIP.append(a[key]['ip_addr'])
+ return hostsIP, hostsName
+
+
+def encodeID(tmp_data):
+ tmp_str = json.dumps(tmp_data).encode()
+ enc_str = b64encode(tmp_str).decode()
+ return(enc_str)
+
+def getAPI(action):
+ try:
+ _action = encodeID(action)
+ response = requests.get(f"http://{TOPO_API}:50010/td-api/conftopo?action={_action}")
+ return(json.loads(response.text))
+ except Exception as e:
+ print("Error calling backend API.")
+ traceback.print_exc()
+ print("Message: {err}".format(
+ err = str(e),
+ ))
+ return (e)
+
+def main():
+ status = 0
+ switches={}
+ labPassword, labTopology = readLabDetails()
+ allHostsIP, allHostsName = readAtdTopo(labTopology)
+ try:
+ for name, ip in zip(allHostsName,allHostsIP):
+ name=name.replace('-','')
+ switches[name]={}
+ switch = jsonrpclib.Server("https://arista:{password}@{ipaddress}/command-api".format(password = labPassword, ipaddress = ip))
+ switches[name]["hostname"]=switch.runCmds(1,["show hostname"])[0]["hostname"]
+ switches[name]["ztp_mode"]=switch.runCmds(1,["show zerotouch"])[0]['mode']
+ if name != switches[name]['hostname'] or switches[name]['ztp_mode']!='disabled':
+ return("failed")
+ switches["cvp_status"]=getAPI("cvp_tasks")
+ if isinstance(switches["cvp_status"], Exception):
+ return("failed")
+ elif switches["cvp_status"]['status'] == 'Complete':
+ return("success")
+ else:
+ return ("failed")
+ except Exception as e:
+ print(e)
+ return("failed")
+print(main())
\ No newline at end of file
diff --git a/nested-labvm/atd-docker/login/src/resetVMs.py b/nested-labvm/atd-docker/login/src/resetVMs.py
index 7c41a00f3..abe0ebb26 100644
--- a/nested-labvm/atd-docker/login/src/resetVMs.py
+++ b/nested-labvm/atd-docker/login/src/resetVMs.py
@@ -69,7 +69,10 @@ def main():
print("Switch {switch} appears to have no eAPI connectivity".format(switch = name))
machine_to_kill = _get_libvirt_machine(name)
print("Restarting {switch}".format(switch = name))
- machine_to_kill.destroy()
+ try:
+ machine_to_kill.destroy()
+ except:
+ print("Switch does not exists.")
time.sleep(3)
machine_to_kill.create()
print("Restarted {switch}".format(switch = name))
@@ -83,4 +86,4 @@ def main():
print("No problems were detected, please check with your instructor")
-main()
+main()
\ No newline at end of file
diff --git a/nested-labvm/atd-docker/nginx/src/atd.conf b/nested-labvm/atd-docker/nginx/src/atd.conf
index 371e0a5dd..8608d5b26 100644
--- a/nested-labvm/atd-docker/nginx/src/atd.conf
+++ b/nested-labvm/atd-docker/nginx/src/atd.conf
@@ -14,6 +14,7 @@ server {
}
server {
listen 443 ssl;
+ http2 on;
ssl_certificate /etc/nginx/certs/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/privkey.pem;
ssl_session_cache builtin:1000 shared:SSL:10m;
@@ -51,6 +52,35 @@ server {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
+ location /host1 {
+ proxy_pass http://192.168.0.1:6001/;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_ssl_verify off;
+ proxy_hide_header Content-Security-Policy;
+ proxy_buffering off;
+ proxy_read_timeout 90;
+ client_max_body_size 800M;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection $http_connection;
+ }
+ location /host2 {
+ proxy_pass http://192.168.0.1:6002/;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_ssl_verify off;
+ proxy_hide_header Content-Security-Policy;
+ proxy_buffering off;
+ proxy_read_timeout 90;
+ client_max_body_size 800M;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection $http_connection;
+
+ }
location /uptime {
access_log off;
proxy_pass http://atd-uptime:50010;
@@ -94,7 +124,14 @@ server {
proxy_read_timeout 86400;
}
}
- location ~ ^/(cv|static|api|web) {
+ location ~ ^/(grpc-web/arista\..*|arista\..*) {
+ grpc_pass grpcs://192.168.0.5:443;
+ grpc_ssl_verify off;
+ grpc_read_timeout 14400;
+ grpc_send_timeout 14400;
+ client_body_timeout 14400;
+ }
+ location ~ ^/(cv|grpc-web|cvpservice|static|api|web|assets) {
proxy_pass https://192.168.0.5;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
diff --git a/nested-labvm/atd-docker/syslog/Dockerfile b/nested-labvm/atd-docker/syslog/Dockerfile
new file mode 100644
index 000000000..f58930723
--- /dev/null
+++ b/nested-labvm/atd-docker/syslog/Dockerfile
@@ -0,0 +1,19 @@
+FROM ubuntu:14.04
+
+ENV DEBIAN_FRONTEND noninteractive
+
+ADD ./src/rsyslog.list /etc/apt/sources.list.d/rsyslog.list
+RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 0F6DD8135234BF2B
+RUN apt-get update && \
+ apt-get install -y rsyslog
+
+# Create app structure
+RUN mkdir -p /var/log/remote/
+ADD ./src/rsyslog.conf /etc/rsyslog.conf
+VOLUME /var/log/remote/
+# Set the syslog user and group explicitly
+RUN chmod -R 777 /var/log/remote/
+
+EXPOSE 1514
+EXPOSE 1514/udp
+CMD /usr/sbin/rsyslogd -n -f /etc/rsyslog.conf
\ No newline at end of file
diff --git a/nested-labvm/atd-docker/syslog/src/rsyslog.conf b/nested-labvm/atd-docker/syslog/src/rsyslog.conf
new file mode 100644
index 000000000..536ab393b
--- /dev/null
+++ b/nested-labvm/atd-docker/syslog/src/rsyslog.conf
@@ -0,0 +1,68 @@
+# /etc/rsyslog.conf Configuration file for rsyslog.
+#
+# For more information see
+# /usr/share/doc/rsyslog-doc/html/rsyslog_conf.html
+#
+# Default logging rules can be found in /etc/rsyslog.d/50-default.conf
+
+
+#################
+#### MODULES ####
+#################
+
+# provides UDP syslog reception
+$ModLoad imudp
+$UDPServerRun 1514
+
+# provides TCP syslog reception
+$ModLoad imtcp
+$InputTCPServerRun 1514
+
+###########################
+#### GLOBAL DIRECTIVES ####
+###########################
+
+#
+# Use traditional timestamp format.
+# To enable high precision timestamps, comment out the following line.
+#
+$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
+
+# Filter duplicated messages
+$RepeatedMsgReduction on
+
+#
+# Set the default permissions for all log files.
+#
+$FileOwner root
+$FileGroup root
+$FileCreateMode 0777
+$DirCreateMode 0777
+$Umask 0022
+$PrivDropToUser root
+$PrivDropToGroup root
+
+#
+# Where to place spool and state files
+#
+$WorkDirectory /var/spool/rsyslog
+
+#
+# Include all config files in /etc/rsyslog.d/
+#
+$IncludeConfig /etc/rsyslog.d/*.conf
+
+###########################
+#### Central log stuff ####
+###########################
+template (name="HostLogs" type="string" string="/var/log/remote/%FROMHOST%/%programname%.%$YEAR%-%$MONTH%-%$DAY%.log")
+
+ruleset(name="remote"){
+ action(type="omfile" DynaFile="HostLogs")
+}
+
+input(type="imtcp" port="1514" ruleset="remote")
+input(type="imudp" port="1514" ruleset="remote")
+# remote host is: name/ip:port, e.g. 192.168.0.1:514, port optional
+*.* @@192.168.0.24:514
+# ### end of the forwarding rule ###
\ No newline at end of file
diff --git a/nested-labvm/atd-docker/syslog/src/rsyslog.conf.client b/nested-labvm/atd-docker/syslog/src/rsyslog.conf.client
new file mode 100644
index 000000000..317e18130
--- /dev/null
+++ b/nested-labvm/atd-docker/syslog/src/rsyslog.conf.client
@@ -0,0 +1,47 @@
+# /etc/rsyslog.conf Configuration file for rsyslog.
+#
+# For more information see
+# /usr/share/doc/rsyslog-doc/html/rsyslog_conf.html
+#
+# Default logging rules can be found in /etc/rsyslog.d/50-default.conf
+
+
+#################
+#### MODULES ####
+#################
+
+###########################
+#### GLOBAL DIRECTIVES ####
+###########################
+
+#
+# Use traditional timestamp format.
+# To enable high precision timestamps, comment out the following line.
+#
+$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
+
+# Filter duplicated messages
+$RepeatedMsgReduction on
+
+#
+# Set the default permissions for all log files.
+#
+$FileOwner syslog
+$FileGroup adm
+$FileCreateMode 0640
+$DirCreateMode 0755
+$Umask 0022
+$PrivDropToUser syslog
+$PrivDropToGroup syslog
+
+#
+# Where to place spool and state files
+#
+$WorkDirectory /var/spool/rsyslog
+
+#
+# Include all config files in /etc/rsyslog.d/
+#
+#$IncludeConfig /etc/rsyslog.d/*.conf
+
+*.* @@rsyslog.services.thalarion.be:1514
\ No newline at end of file
diff --git a/nested-labvm/atd-docker/syslog/src/rsyslog.list b/nested-labvm/atd-docker/syslog/src/rsyslog.list
new file mode 100644
index 000000000..da5cbeb24
--- /dev/null
+++ b/nested-labvm/atd-docker/syslog/src/rsyslog.list
@@ -0,0 +1,2 @@
+deb http://ppa.launchpad.net/adiscon/v8-stable/ubuntu trusty main
+deb-src http://ppa.launchpad.net/adiscon/v8-stable/ubuntu trusty main
\ No newline at end of file
diff --git a/nested-labvm/atd-docker/tacacs/Dockerfile b/nested-labvm/atd-docker/tacacs/Dockerfile
new file mode 100644
index 000000000..4bff971df
--- /dev/null
+++ b/nested-labvm/atd-docker/tacacs/Dockerfile
@@ -0,0 +1,28 @@
+FROM alpine:latest as base
+ENV VERSION=201712190728
+ENV TAC_PLUS_BIN=/tacacs/sbin/tac_plus
+ENV CONF_FILE=/etc/tac_plus/tac_plus.cfg
+
+
+FROM base as build
+RUN apk add --no-cache \
+ build-base bzip2 perl perl-digest-md5 perl-ldap
+ADD http://www.pro-bono-publico.de/projects/src/DEVEL.$VERSION.tar.bz2 /tac_plus.tar.bz2
+ADD http://www.pro-bono-publico.de/projects/unpacked/mavis/perl/mavis_tacplus_radius.pl /mavis_tacplus_radius.pl
+RUN tar -xjf /tac_plus.tar.bz2 && \
+ cd /PROJECTS && \
+ ./configure --prefix=/tacacs && \
+ make && \
+ make install
+
+
+FROM base
+COPY --from=build /tacacs /tacacs
+COPY --from=build /mavis_tacplus_radius.pl /usr/local/lib/mavis_tacplus_radius.pl
+COPY ./src/tac_base.cfg $CONF_FILE
+COPY ./src/entrypoint.sh /entrypoint.sh
+
+RUN apk add --no-cache perl perl-digest-md5 perl-ldap && \
+ chmod u+x /entrypoint.sh
+EXPOSE 49
+ENTRYPOINT ["/entrypoint.sh"]
\ No newline at end of file
diff --git a/nested-labvm/atd-docker/tacacs/src/config b/nested-labvm/atd-docker/tacacs/src/config
new file mode 100644
index 000000000..8ef85cfa0
--- /dev/null
+++ b/nested-labvm/atd-docker/tacacs/src/config
@@ -0,0 +1,20 @@
+key = "COOKBOOK"
+group = limited {
+ default service = deny
+}
+user = fedexuser {
+ # default service = permit
+ login = clear fedexuser
+ # member = limited
+ service = shell {
+ set priv-lvl = 15
+ cmd = show {
+ deny running-config
+ permit .*
+ }
+ }
+}
+user = fedex {
+ default service = permit
+ login = clear arista
+}
\ No newline at end of file
diff --git a/nested-labvm/atd-docker/tacacs/src/entrypoint.sh b/nested-labvm/atd-docker/tacacs/src/entrypoint.sh
new file mode 100644
index 000000000..b00dc6332
--- /dev/null
+++ b/nested-labvm/atd-docker/tacacs/src/entrypoint.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Check configuration file exists
+if [ ! -f /etc/tac_plus/tac_plus.cfg ]; then
+ echo "No configuration file at ${CONF_FILE}"
+ exit 1
+fi
+
+# Check configuration file for syntax errors
+${TAC_PLUS_BIN} -P ${CONF_FILE}
+if [ $? -ne 0 ]; then
+ echo "Invalid configuration file"
+ exit 1
+fi
+
+# Make the log directories
+mkdir -p /var/log/tac_plus
+
+echo "Starting server..."
+
+# Start the server
+exec ${TAC_PLUS_BIN} -f ${CONF_FILE}
\ No newline at end of file
diff --git a/nested-labvm/atd-docker/tacacs/src/tac_base.cfg b/nested-labvm/atd-docker/tacacs/src/tac_base.cfg
new file mode 100644
index 000000000..0a4b30c48
--- /dev/null
+++ b/nested-labvm/atd-docker/tacacs/src/tac_base.cfg
@@ -0,0 +1,43 @@
+id = spawnd {
+ listen = { port = 49 }
+ spawn = {
+ instances min = 1
+ instances max = 10
+ }
+ background = no
+}
+
+id = tac_plus {
+ debug = AUTHOR AUTHEN
+
+ log = stdout {
+ destination = /proc/1/fd/1
+ }
+
+ log = stderr {
+ destination = /dev/stderr
+ }
+
+ log = file {
+ destination = /var/log/tac_plus.log
+ }
+
+ # Seems to have problems with STDOUT, so we'll log to STDERR as well (this works fine!)
+ authentication log = stderr
+ authorization log = stderr
+ accounting log = stderr
+
+ #authentication log = stdout
+ #authorization log = stdout
+ #accounting log = stdout
+
+ authentication log = file
+ authorization log = file
+ accounting log = file
+
+ user = $enable$ {
+ login = clear enable
+ }
+
+ include = /etc/tac_plus/tac_user.cfg
+}
\ No newline at end of file
diff --git a/nested-labvm/atd-docker/uilanding/Dockerfile b/nested-labvm/atd-docker/uilanding/Dockerfile
index 37dcd1fdf..fb323b25d 100644
--- a/nested-labvm/atd-docker/uilanding/Dockerfile
+++ b/nested-labvm/atd-docker/uilanding/Dockerfile
@@ -3,7 +3,7 @@ FROM python:3.9
RUN pip install --upgrade pip
-RUN pip install tornado requests ruamel.yaml
+RUN pip install tornado requests ruamel.yaml docker
RUN mkdir -p /opt/topo/html
@@ -11,6 +11,12 @@ RUN mkdir -p /root/labguides
WORKDIR /root
+RUN apt-get update && \
+ apt-get -qy full-upgrade && \
+ apt-get install -qy curl && \
+ apt-get install -qy curl && \
+ curl -sSL https://get.docker.com/ | sh
+
COPY ./src/html /opt/topo/html/
COPY ./src/uilanding.py /usr/local/bin/uilanding
@@ -20,4 +26,3 @@ RUN chmod +x /usr/local/bin/uilanding
EXPOSE 80
CMD ["uilanding"]
-
diff --git a/nested-labvm/atd-docker/uilanding/Dockerfile copy b/nested-labvm/atd-docker/uilanding/Dockerfile copy
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/nested-labvm/atd-docker/uilanding/Dockerfile copy
@@ -0,0 +1 @@
+
diff --git a/nested-labvm/atd-docker/uilanding/src/html/css/style.css b/nested-labvm/atd-docker/uilanding/src/html/css/style.css
new file mode 100644
index 000000000..520fd6131
--- /dev/null
+++ b/nested-labvm/atd-docker/uilanding/src/html/css/style.css
@@ -0,0 +1,78 @@
+#spinner {
+ position: fixed;
+ top: 0;
+ left: 0;
+ opacity: 0.5;
+ z-index: 60;
+ width: 100vw;
+ height: 100vh;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ background: white;
+ }
+ #spinner img {
+ height: 100px;
+ width: 100px;
+ }
+ #tooltiptext {
+ visibility: hidden;
+ background-color: black;
+ color: #fff;
+ text-align: center;
+ padding: 5px 0;
+ border-radius: 6px;
+ position: absolute;
+ z-index: 1;
+ text-align: center;
+ display: flex;
+ margin-left: 12px;
+ width: 200px;
+ }
+
+ table {
+ font-family: arial, sans-serif;
+ border-collapse: collapse;
+ width: 100%;
+ }
+
+ td,
+ th {
+ border: 1px solid #dddddd;
+ text-align: left;
+ text-align: center;
+ padding: 8px;
+ }
+
+ .modal {
+ display: none;
+ position: fixed;
+ padding-top: 100px;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ overflow: auto;
+ background-color: rgb(0, 0, 0);
+ background-color: rgba(0, 0, 0, 0.4);
+ }
+ .modal-content {
+ background-color: #fefefe;
+ margin: auto;
+ padding: 20px;
+ border: 1px solid #888;
+ width: 80%;
+ }
+ .close {
+ color: #aaaaaa;
+ float: right;
+ font-size: 28px;
+ font-weight: bold;
+ }
+
+ .close:hover,
+ .close:focus {
+ color: #000;
+ text-decoration: none;
+ cursor: pointer;
+ }
\ No newline at end of file
diff --git a/nested-labvm/atd-docker/uilanding/src/html/index.html b/nested-labvm/atd-docker/uilanding/src/html/index.html
index fa257c69c..a4e6c1a57 100755
--- a/nested-labvm/atd-docker/uilanding/src/html/index.html
+++ b/nested-labvm/atd-docker/uilanding/src/html/index.html
@@ -12,12 +12,18 @@
-
+
+
+
+
+
+
+
@@ -26,14 +32,27 @@
+
+ Home
+
{% if "labguides" not in disable_links %}
- Lab Guides (PDF)
+ Lab Guides
{% end %}
{% if "console" not in disable_links %}
- Console Access
+ Switch Access
+
+
+ {% end %}
+ {% if "cvp" not in disable_links %}
+
+ CVP
+ CVP is Starting, Please wait
+
+
+ CVP
{% end %}
{% if "ide" not in disable_links %}
@@ -46,14 +65,23 @@
WebUI
{% end %}
- {% if "cvp" not in disable_links %}
+
+ {% if "jenkins" not in disable_links %}
- CVP
+ Jenkins
{% end %}
- {% if "jenkins" not in disable_links %}
+ {% if "lab_menu" not in disable_links %}
- Jenkins
+
+
+ {% end %}
+
+ Passwords
+
+ {% if "lab_status" not in disable_links %}
+
+ Lab Status
{% end %}
@@ -63,6 +91,7 @@
+
Arista {{ topo_title }}
Welcome to the Arista {{ topo_title }}! Please use the links on the left to navigate through the lab.
@@ -80,29 +109,122 @@
Topology
{% end %}
{% end %}
+ {% for gui_url in zip(GUI_URLS,SERVERS) %}
+
+ {% end %}
{% if topo_cvp %}
{% end %}
-
Usernames and Passwords
- Use the following usernames and passwords to access the ATD:
-
-
-
- Device Username Password
-
- Lab Credentials arista {{ ARISTA_PWD }}
- Programmability IDE {{ ARISTA_PWD }}
- WebUI @rista1
-
+
+
+
+
+
Lab Status
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Lab
+
+
+ Completed
+
+
+
+ Ip
+ Yes
+
+
+ BGP
+ Yes
+
+
+ VXLAN
+ No
+
+
+ Comments: issues with rm
+
+
+
+
+
+ EVP (L2)
+ Yes
+
+
+
+
+ Grade
+
+
+
+
+
-
+
+
+
+
+
+
Usernames and Passwords
+ Use the following usernames and passwords to access the ATD:
+
+
+
+
+
×
+
+
+ Device Username Password
+
+ Lab Credentials arista {{ ARISTA_PWD }}
+ Programmability IDE {{ ARISTA_PWD }}
+ WebUI @rista1
+
+
+
@@ -110,8 +232,9 @@ Usernames and Passwords
+
-