Camphor Networks Platform API
camphor_api_test.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 
3 ##
4 # Copyright (C) Camphor Networks, Inc - All Rights Reserved
5 # Unauthorized copying of this file via any medium is strictly prohibited
6 # Proprietary and confidential
7 # Written by Ananth Suryanarayana <ananth@camphornetworks.com>, July 2022
8 # https://camphornetworks.com/camphor-networks-platform-terms-of-use-and-privacy-policy/
9 # mailto:info@camphornetworks.com?subject=copyright
10 #
11 
12 from __future__ import annotations
13 import sys
14 import pytest
15 
16 if sys.path[0].startswith('/var/lib/camphor/camphor_api'):
17  sys.path.pop(0)
18 if '/var/lib/camphor' not in sys.path:
19  sys.path.insert(0, '/var/lib/camphor')
20 from camphor_api.camphor_manage import *
21 
22 
23 ##
24 # \mainpage /var/lib/camphor/camphor_api/camphor_api_test_run
25 #
26 # You can run this sample camphor client code with the following shell script. Above script basically executes the
27 # following steps, which you can customize according to your environment.
28 #
29 # export CAMPHOR_PASSWORD="${CAMPHOR_PASSWORD:-Camphor123}"
30 #
31 # export SSHPASS="${SSHPASS:-$CAMPHOR_PASSWORD}"
32 #
33 # export DEST_DIR="${DEST_DIR:-$PWD}"
34 #
35 # cd ${DEST_DIR}
36 #
37 # [[ ! -d .venv ]] && python3 -m venv .venv
38 #
39 # source .venv/bin/activate
40 #
41 # pip3 install -Ur /var/lib/camphor/camphor_api/requirements.txt
42 #
43 # PYTHONPATH=/var/lib/camphor python3 -m pytest camphor_api_test.py
44 #
45 # <a href="camphor_project_schema.json" target="_blank">Camphor Configuration Schema</a>
46 #
47 
48 
49 ##
50 # Create a simple network connecting routers
51 #
52 # Two SONiC Routers are created and connected with each other.
53 #
55 #
58 #
60  # Create CamphorManager object to manage the platform.
61  manager = CamphorManager()
62 
63  devices = ['router1', 'router2']
64  manager.deviceManager.createDevices(name=devices[0], os=DeviceOS.SONiC)
65  manager.deviceManager.createDevices(name=devices[1], os=DeviceOS.SONiC)
66 
67  # Create a network to connect the routers.
68  networks = ['network1']
69  manager.networkManager.createNetworks(name=networks[0], devices=devices)
70 
71  # Convert the created entities into a dictionary and verify.
72  entries = manager.toDict()
73 
74  # Verify that 2 devices and 1 network were indeed created in the Yaml configuration structure.
75  assert len(entries['devices']['item']) == 2
76  assert len(entries['networks']['item']) == 1
77  manager.toYaml()
78 
79  # Load the configuration onto the camphor controller.
80  assert manager.loadYaml()[1] == 0
81 
82  # Verify that devices are indeed created at the camphor controller.
83  manager.verifyCamphorEntities(devices=devices, networks=networks)
84 
85 
86 ##
87 # Create a simple linear topology of SONiC Devices
88 #
89 # SONiC Routers are created and chained in a serial manner. Generated yaml is loaded onto the camphor controller.
90 #
92 #
95 #
97  # Create CamphorManager object to manage the platform.
98  manager = CamphorManager()
99 
100  # Set number of devices to be created.
101  count = 4
102 
103  # Create {count} SONiC Devices configuration.
104  manager.deviceManager.createDevices(name='router', count=count, os=DeviceOS.SONiC,
105  image=Image(file=['master:///local/camphor/vm_image.qcow2'],
106  md5sum=['deadbeef']),
107  resource=Resource(cpu=[4], memory=[4096], disk=[200]))
108 
109  # Connect the devices in a serial daisy-chain fashion.
110  devices = []
111  networks = []
112  for i in range(1, count):
113  # Create a network to connect a router to the next. An available interface is automatically picked.
114  devices.append(F"router{i}")
115  networks.append(F"network{i}")
116  manager.networkManager.createNetworks(name=F"network{i}", devices=[F"router{i}", F"router{i + 1}"])
117 
118  devices.append(F"router{count}")
119 
120  # Convert the created entities into a dictionary and verify.
121  entries = manager.toDict()
122 
123  # Verify that {count} devices and {count-1} networks were indeed created in the Yaml configuration structure.
124  assert len(entries['devices']['item']) == count
125  assert len(entries['networks']['item']) == count - 1
126  manager.toYaml()
127 
128  # Load the configuration onto the camphor controller.
129  assert manager.loadYaml()[1] == 0
130 
131  # Verify that devices are indeed created at the camphor controller.
132  manager.verifyCamphorEntities(devices=devices, networks=networks)
133 
134 
135 ##
136 # Create a customized network topology
137 #
138 # Create routers by customizing image, resource and other attributes. Connect the routers together via specific network
139 # interfaces to build a custom topology.
140 # You can see the auto-generated topology in the camphor dashboard. e.g.
141 # https://camphor-k8-master/#/camphorTopology/camphor-administrator-default/autogenerated?namespace=camphor-administrator-default
142 #
145 #
147  # Create CamphorManager object to manage the platform.
148  manager = CamphorManager()
149 
150  # Set default attributes.
151  manager.deviceManager.getDeviceCommonAttributes().resource = Resource(cpu=[2], memory=[1024], disk=[50])
152  manager.deviceManager.getDeviceCommonAttributes().os = DeviceOS.LINUXALPINE
153 
154  # Create a few devices.
155  manager.deviceManager.createDevice(name='router1', attributes=DeviceAttributesDefinition(
156  os=DeviceOS.SONiC, resource=Resource(cpu=[4], memory=[2048], disk=[100]),
157  image=Image(file=["master:///local/camphor/customer/vms/vm_image.qcow2"], md5sum=["deadbeef"])
158  ))
159  manager.deviceManager.createDevice(name='router2', attributes=DeviceAttributesDefinition(
160  os=DeviceOS.MX,
161  conf="master:///local/camphor/$CAMPHOR_CLUSTER/$CAMPHOR_USERNAME/$CAMPHOR_PROJECT/$CAMPHOR_DEVICE/device.conf",
162  resource=Resource(cpu=[4], memory=[4096], disk=[100]),
163  image=Image(file=[
164  "master:///local/camphor/customer/vms/vm_re_image.qcow2",
165  "master:///local/camphor/customer/vms/vm_pfe_image.qcow2",
166  ], md5sum=["deadbeef", "beefbeef"])
167  ))
168  manager.deviceManager.createDevice(name='router3')
169 
170  # Connect the devices over desired interfaces to form the required network topology.
171  manager.networkManager.getNetworkCommonAttributes().portAttributes = NetworkPortAttributesDefinition(
172  interface='autoAssign')
173  manager.networkManager.createNetwork(name='net1', attributes=NetworkAttributesDefinition(ports=Ports(item=[
174  PortsItem(device='router1'),
175  PortsItem(device='router2')
176  ])))
177  manager.networkManager.createNetwork(name='net2', attributes=NetworkAttributesDefinition(ports=Ports(item=[
178  PortsItem(device='router2', attributes=NetworkPortAttributesDefinition(interface='ge-0/0/2')),
179  PortsItem(device='router3', attributes=NetworkPortAttributesDefinition(interface='ge-0/0/4'))
180  ])))
181  manager.networkManager.createNetwork(name='net3', attributes=NetworkAttributesDefinition(ports=Ports(item=[
182  PortsItem(device='router1'),
183  PortsItem(device='router3')
184  ])))
185 
186  # Add some applications as well!
187  manager.applicationManager.createApplication(name='a1', attributes=ApplicationAttributesDefinition(
188  name=ApplicationName.novnc))
189  manager.applicationManager.createApplication(name='a2', attributes=ApplicationAttributesDefinition(
190  name=ApplicationName.jupyter))
191 
192  entries = manager.toDict()
193  assert len(entries['devices']['item']) == 3
194  assert len(entries['networks']['item']) == 3
195  assert len(entries['applications']['item']) == 2
196 
197  assert entries['devices']['item'][0]['attributes']['os'] == DeviceOS.SONiC.name
198  assert entries['devices']['item'][1]['attributes']['os'] == DeviceOS.MX.name
199  assert entries['devices']['item'][1]['attributes']['image']['file'][0] == \
200  "master:///local/camphor/customer/vms/vm_re_image.qcow2"
201  assert entries['devices']['item'][1]['attributes']['image']['file'][1] == \
202  "master:///local/camphor/customer/vms/vm_pfe_image.qcow2"
203  assert manager.loadYaml()[1] == 0
204 
205  manager.deviceManager.deleteDevice(name='router2')
206  manager.networkManager.deleteNetwork(name='net1')
207  manager.applicationManager.deleteApplication(name='a1')
208  entries = manager.toDict()
209  assert len(entries['devices']['item']) == 2
210  assert len(entries['networks']['item']) == 2
211  assert len(entries['applications']['item']) == 1
212 
213 
214 ##
215 # Create a simple circular topology of NXOS Devices
216 #
217 # NXOS Routers are created and chained in a circular manner. Generated yaml is loaded onto the camphor controller.
218 #
220 #
223 #
224 def test4_circular_topology(count: int = 10):
225  # Create CamphorManager object to manage the platform.
226  manager = CamphorManager()
227  manager.deviceManager.getDeviceCommonAttributes().os = DeviceOS.NXOS
228  manager.deviceManager.getDeviceCommonAttributes().resource = Resource(cpu=[4], memory=[4 * 1012], disk=[200])
229  manager.deviceManager.getDeviceCommonAttributes().image = \
230  Image(file=['master:///local/camphor/customer/vms/500v64.10.2.3.F.qcow2'],
231  md5sum=['4d541a673a097ababec96b016f9ba237'])
232 
233  # noinspection SpellCheckingInspection
234  manager.deviceManager.getDeviceCommonAttributes().conf = F"""
235 hostname nxos
236 snmp-server user admin
237 username admin password 5 $5$j7tkn468$cxNfE/jPpWmeIjJUOTNdSHcfr47N7pSK.S4h8SGGwe. role network-admin
238 username admin sshkey ssh-rsa {Util.fread(F"{environ['HOME']}/.ssh/id_rsa.pub")[:24]}
239 feature bash
240 feature scp-server
241 feature bgp
242 feature ospf
243 ip domain-lookup
244 ip name-server 10.0.2.3 use-vrf management
245 vlan 1
246 vrf context management
247  ip domain-name camphor-administrator-default
248  ip name-server 10.0.2.3
249  ip route 0.0.0.0/0 10.0.2.2
250 interface mgmt0
251  ip address dhcp
252  vrf member management
253 interface Eth1/1
254 no description
255 switchport
256 line console
257 line vty
258 boot nxos bootflash:/boot nxos bootflash:/nxos64-cs.10.2.3.F.bin
259 """
260  manager.deviceManager.createDevice(name='router', count=count)
261 
262  devices = []
263  networks = []
264  for i in range(1, count + 1):
265  devices.append(F"router{i}")
266  networks.append(F"network{i}")
267  manager.networkManager.createNetworks(name=networks[i - 1],
268  devices=[F"router{i}", F"router{i + 1 if i < count else 1}"])
269  entries = manager.toDict()
270  assert len(entries['devices']['item']) == count
271  assert len(entries['networks']['item']) == count
272 
273  # Load the configuration onto the camphor controller.
274  assert manager.loadYaml()[1] == 0
275 
276  # Verify that devices are indeed created at the camphor controller.
277  manager.verifyCamphorEntities(devices=devices, networks=networks)
278 
279 
280 ##
281 # Create a network with better management traffic capable devices
282 #
283 # Using an option @see passThroughInterface, device management traffic can get a high throughput over the management
284 # interface.
285 #
286 # @warning Please ensure that MTU is set correctly to avoid IP fragmentation, e.g. to 1376, with -124 offset from 1500
287 #
290 #
291 def test5_device_for_analytics(device_count: int = 4, network_count: int = 2):
292  # Create CamphorManager object to manage the platform.
293  manager = CamphorManager()
294  manager.deviceManager.getDeviceCommonAttributes().os = DeviceOS.NXOS
295  manager.deviceManager.getDeviceCommonAttributes().passThroughInterface = True
296 
297  # noinspection SpellCheckingInspection
298  manager.deviceManager.getDeviceCommonAttributes().conf = F"""
299 hostname nxos
300 snmp-server user admin
301 username admin password 5 $5$j7tkn468$cxNfE/jPpWmeIjJUOTNdSHcfr47N7pSK.S4h8SGGwe. role network-admin
302 username admin sshkey ssh-rsa {Util.fread(F"{environ['HOME']}/.ssh/id_rsa.pub")[:24]}
303 feature bash
304 feature scp-server
305 feature bgp
306 feature ospf
307 ip domain-lookup
308 ip name-server 10.0.2.3 use-vrf management
309 vlan 1
310 vrf context management
311  ip domain-name camphor-administrator-default
312  ip name-server 10.0.2.3
313  ip route 0.0.0.0/0 10.0.2.2
314 interface mgmt0
315  mtu 1376
316  ip address dhcp
317  vrf member management
318 interface Eth1/1
319 no description
320 switchport
321 line console
322 line vty
323 boot nxos bootflash:/boot nxos bootflash:/nxos64-cs.10.2.3.F.bin
324 """
325  manager.deviceManager.createDevice(name='router', count=device_count)
326 
327  # Connect the devices back to back over multiple links!
328  devices = [F"router{i}" for i in range(1, device_count + 1)]
329  networks = [F"network{i}" for i in range(1, network_count + 1)]
330  for i in range(network_count):
331  manager.networkManager.createNetworks(name=networks[i], devices=devices)
332 
333  entries = manager.toDict()
334  assert len(entries['devices']['item']) == device_count
335  assert len(entries['networks']['item']) == network_count
336 
337  # Load the configuration onto the camphor controller.
338  assert manager.loadYaml()[1] == 0
339 
340  # Verify that devices are indeed created at the camphor controller.
341  manager.verifyCamphorEntities(devices=devices, networks=networks)
342 
343 
344 ##
345 # Create a network with better management traffic capable devices
346 #
347 # Create a topology where same set of devices are created using multiple different networks. Also more than two devices
348 # are connected within each camphor network (aka connection)
349 #
352 #
353 def test6_multi_device_networks(device_count: int = 4, network_count: int = 4):
354  manager = CamphorManager()
355  manager.deviceManager.getDeviceCommonAttributes().os = DeviceOS.SONiC
356  manager.deviceManager.createDevice(name='router', count=device_count)
357 
358  # Connect the devices back to back over multiple links!
359  devices = [F"router{i}" for i in range(1, device_count + 1)]
360  networks = [F"network{i}" for i in range(1, network_count + 1)]
361  for i in range(network_count):
362  manager.networkManager.createNetworks(name=networks[i], devices=devices)
363 
364  entries = manager.toDict()
365  assert len(entries['devices']['item']) == device_count
366  assert len(entries['networks']['item']) == network_count
367 
368  # Load the configuration onto the camphor controller.
369  assert manager.loadYaml()[1] == 0
370 
371  # Verify that devices are indeed created at the camphor controller.
372  manager.verifyCamphorEntities(devices=devices, networks=networks)
373 
374 
375 ##
376 # Load a camphor network topology from an external yaml file
377 #
380 #
382  yaml_file = '/var/lib/camphor/topologies/camphor_topology.yaml'
383  manager = CamphorManager(yaml=yaml_file)
384  expected = Util.yamlFileToDict(yaml_file=yaml_file)
385  actual = manager.toDict()
386  assert actual == expected
387  assert manager.loadYaml()[1] == 0
388 
389 
390 ##
391 # Create a small data center network
392 #
393 # A small data center with pods, racks, leafs, spines and servers are created as shown below.
394 #
397 #
399  manager = CamphorManager()
400  manager.deploymentManager.createDataCenter()
401  entries = manager.toDict()
402  assert len(entries['deployments']['item']) == 1
403  assert entries['deployments']['item'][0]['name'] == 'dc'
404  assert entries['deployments']['item'][0]['attributes']['deploymentAttributes']['type'] == 'datacenter'
405  Util.printYaml(manager.toYaml())
406  assert manager.loadYaml()[1] == 0
407 
408 
409 ##
410 # Create a medium sized data center network
411 #
412 # A medium sized data center with pods, racks, leafs, spines and servers are created as shown below.
413 #
416 #
418  manager = CamphorManager()
419  manager.deploymentManager.createDataCenter(pods=2, racks=4, servers=4, spines=4, superSpines=2)
420  entries = manager.toDict()
421  assert len(entries['deployments']['item']) == 1
422  assert entries['deployments']['item'][0]['name'] == 'dc'
423  assert entries['deployments']['item'][0]['attributes']['deploymentAttributes']['type'] == 'datacenter'
424  assert manager.loadYaml()[1] == 0
425 
426 
427 ##
428 # Create a large sized data center network
429 #
430 # A large sized data center with pods, racks, leafs, spines and servers are created as shown below.
431 #
434 #
436  manager = CamphorManager()
437  manager.deploymentManager.createDataCenter(name='dc', pods=2, racks=8, servers=8, spines=8, superSpines=4,
438  borderLeafs=2)
439  entries = manager.toDict()
440  assert len(entries['deployments']['item']) == 1
441  assert entries['deployments']['item'][0]['name'] == 'dc'
442  assert entries['deployments']['item'][0]['attributes']['deploymentAttributes']['type'] == 'datacenter'
443  assert manager.loadYaml()[1] == 0
444 
445 
446 ##
447 # Create a customized data center network
448 #
449 # A large sized data center with pods, racks, leafs, spines and servers are created as shown below.
450 #
453 #
455  manager = CamphorManager()
457  deviceAttributes=DeviceAttributesDefinition(os=DeviceOS.SONiC),
458  podAttributes=PodAttributes(pods=2),
459  rackAttributes=RackAttributes(racks=2),
460  serverAttributes=ServerAttributes(servers=2,
461  deviceAttributes=DeviceAttributesDefinition(os=DeviceOS.LINUX)),
462  leafAttributes=LeafAttributes(leafs=2),
463  spineAttributes=SpineAttributes(spines=4),
464  superSpineAttributes=SuperSpineAttributes(superSpines=4),
465  coreAttributes=CoreAttributes(cores=2),
466  borderLeafAttributes=BorderLeafAttributes(borderLeafs=2),
467  vpnAttributes=VPNAttributes(vpns=1, evpns=2, hosts=2, addresses=2, enablePinger=False)
468  ))
469  manager.deploymentManager.createDeployment(name='router', attributes=DeploymentConfigurationAttributesDefinition(
470  deploymentAttributes=DeploymentAttributes(type=DeploymentType.datacenter)),
471  pods=Pods(item=[
472  PodsItem(name='pod1',
474  rackAttributes=RackAttributes(racks=4),
475  serverAttributes=ServerAttributes(servers=4)
476  )
477  )
478  ])
479  )
480  assert manager.loadYaml()[1] == 0
481 
482 
483 ##
484 # Create a simple OSPF Topology of JUNOS Routers
485 #
486 # JUNOS Routers are connected serially
487 #
489 #
492 #
493 @pytest.mark.timeout1(60 * 20)
494 def test12_ospf_basic(synchronize: bool = False):
495  manager = CamphorManager()
496  device_conf = CamphorDeviceManager.getJUNOSDefaultConf().replace('__ADDRESS_LO0__', '100.100.0.1') \
497  .replace('__ADDRESS3__', '1.1.1.1/24').replace('__ADDRESS4__', '1.1.2.1/24')
498  devices = ['router1', 'router2', 'router3']
499  os = DeviceOS.OLIVE
500  version = 'latest'
501  manager.deviceManager.createDevice(name=devices[0], attributes=DeviceAttributesDefinition(os=os, conf=device_conf,
502  version=version))
503 
504  device_conf = CamphorDeviceManager.getJUNOSDefaultConf().replace('__ADDRESS_LO0__', '100.100.0.2') \
505  .replace('__ADDRESS3__', '1.1.2.2/24').replace('__ADDRESS4__', '1.1.3.2/24')
506  manager.deviceManager.createDevice(name=devices[1], attributes=DeviceAttributesDefinition(os=os, conf=device_conf,
507  version=version))
508 
509  device_conf = CamphorDeviceManager.getJUNOSDefaultConf().replace('__ADDRESS_LO0__', '100.100.0.3') \
510  .replace('__ADDRESS3__', '1.1.3.3/24').replace('__ADDRESS4__', '1.1.4.3/24')
511  manager.deviceManager.createDevice(name=devices[2], attributes=DeviceAttributesDefinition(os=os, conf=device_conf,
512  version=version))
513 
514  networks = ['router1--router2', 'router2--router3']
515  interfaces = ['ge-0/0/4', 'ge-0/0/3']
516  manager.networkManager.createNetworks(name=networks[0], devices=[devices[0], devices[1]], interfaces=interfaces)
517  manager.networkManager.createNetworks(name=networks[1], devices=[devices[1], devices[2]], interfaces=interfaces)
518 
519  # Print generated camphor yaml topology configuration.
520  # manager.toYaml()
521 
522  # Load the configuration onto the camphor controller.
523  assert manager.loadYaml()[1] == 0
524 
525  # Verify that devices are indeed created at the camphor controller.
526  manager.verifyCamphorEntities(devices=devices, networks=networks, synchronize=False)
527 
528  # Commit configuration changes to the project and synchronize with the underlying k8 cluster!
529  Util.commit(commit=synchronize, synchronize=synchronize)
530  if not synchronize:
531  return
532 
533  # Verify that ping from router1 to router3 works (via router2)
534  assert Util.ping(from_device_os=DeviceOS.OLIVE, from_device_name='router1', from_device='100.100.0.1',
535  to_device='100.0.0.3')
536 
537  # Verify that devices are indeed created at the camphor controller.
538  manager.verifyCamphorEntities(devices=devices, networks=networks, synchronize=synchronize)
539 
540 
541 ##
542 # Create devices with PCI Cards pass through from underlying host such as GPUs, NPUs and IPUs
543 #
544 # Seamlessly pass PCI devices all the way into the virtualized servers so that those devices can be readily availed
545 # even though the entire environment could be completely virtual.
546 #
549 #
550 def test13_device_with_pci_passthrough(device_count: int = 4):
551  # Create CamphorManager object to manage the platform.
552  manager = CamphorManager()
553  manager.deviceManager.getDeviceCommonAttributes().os = DeviceOS.LINUXUBUNTU
554  manager.deviceManager.createDevice(name='server', count=device_count)
555  manager.deviceManager.createDevice(name='server-gpu1', attributes=DeviceAttributesDefinition(
556  passThroughPCIDevices=['7d:00.0', '7f:00.0']))
557  manager.deviceManager.createDevice(name='server-gpu2', attributes=DeviceAttributesDefinition(
558  passThroughPCIDevices=['8d:00.0:compute1', '8f:00.0:compute1']))
559 
560  entries = manager.toDict()
561  assert len(entries['devices']['item']) == device_count + 2
562 
563  # Load the configuration onto the camphor controller.
564  assert manager.loadYaml()[1] == 0
565 
566  # Verify that devices are indeed created at the camphor controller.
567  manager.verifyCamphorEntities(
568  devices=[F"server{i + 1}" for i in range(device_count)] + ['server-gpu1', 'server-gpu2'])
569 
570 
571 ##
572 # Create a network of devices and verify wih K8
573 #
574 # In camphor, for each device (VM/Container) created, Kubernetes resources are automatically created and managed.
575 # Walk through such K8 resources and verify.
576 #
579 #
580 def test14_device_with_k8_pods(device_count: int = int(environ.get('CAMPHOR_TEST_DEVICE_COUNT', '4')),
581  network_count: int = int(environ.get('CAMPHOR_TEST_NETWORK_COUNT', '4')),
582  synchronize: bool = environ.get('CAMPHOR_TEST_SYNCHRONIZE', '').upper() == 'TRUE'):
583  manager = CamphorManager()
584  manager.createBasicTopology(device_count=device_count, network_count=network_count, synchronize=synchronize)
585  if not synchronize:
586  return
587 
588  for pod in manager.getK8Pods().items:
589  print("%s\t%s\t%s" % (pod.status.pod_ip, pod.metadata.namespace, pod.metadata.name))
590 
591 
592 ##
593 # Pause devices
594 #
595 # Pause the VM devices by informing the camphor controller.
596 #
597 # @param[in] name Name of the device, prefix if {count} > 0
598 # @param[in] count Number of devices
599 #
600 def test15_device_pause(name: str = 'router', count: int = 4):
601  # Create CamphorManager object to manage the platform.
602  manager = CamphorManager()
603  manager.operateDevice(name=name, operation=CamphorDeviceManager.Operation.pause, count=count)
604 
605 
606 ##
607 # Resume devices
608 #
609 # Resume the VM devices (which were paused before) by informing the camphor controller.
610 #
611 # @param[in] name Name of the device, prefix if {count} > 0
612 # @param[in] count Number of devices
613 #
614 def test16_device_resume(name: str = 'router', count: int = 4):
615  # Create CamphorManager object to manage the platform.
616  manager = CamphorManager()
617  manager.operateDevice(name=name, operation=CamphorDeviceManager.Operation.resume, count=count)
618 
619 
620 ##
621 # Shutdown devices
622 #
623 # Shutdown the VM devices by informing the camphor controller.
624 #
625 # @param[in] name Name of the device, prefix if {count} > 0
626 # @param[in] count Number of devices
627 #
628 def test17_device_shutdown(name: str = 'router', count: int = 4):
629  # Create CamphorManager object to manage the platform.
630  manager = CamphorManager()
631  manager.operateDevice(name=name, operation=CamphorDeviceManager.Operation.shutdown, count=count)
632 
633 
634 ##
635 # Restart devices
636 #
637 # Restart VM devices by informing the camphor controller.
638 #
639 # @param[in] count Number of devices
640 #
641 def test18_device_restart(name: str = 'router', count: int = 4):
642  # Create CamphorManager object to manage the platform.
643  manager = CamphorManager()
644  manager.operateDevice(name=name, operation=CamphorDeviceManager.Operation.restart, count=count)
645 
646 
647 ##
648 # Recreate devices
649 #
650 # Recreate devices by recreating associated Kubernetes pods
651 #
652 # @param[in] name Name of the device, prefix if {count} > 0
653 # @param[in] count Number of devices
654 #
655 def test19_device_recreate(name: str = 'router', count: int = 4):
656  # Create CamphorManager object to manage the platform.
657  manager = CamphorManager()
658  manager.operateDevice(name=name, operation=CamphorDeviceManager.Operation.recreate, count=count)
659 
660 
661 ##
662 # Pull Configuration from devices
663 #
664 # Pull configuration from devices and save them under camphor device configuration
665 #
666 # @param[in] name Name of the device, prefix if {count} > 0
667 # @param[in] count Number of devices
668 #
669 def test20_device_pullconf(name: str = 'router', count: int = 4):
670  # Create CamphorManager object to manage the platform.
671  manager = CamphorManager()
672  manager.operateDevice(name=name, operation=CamphorDeviceManager.Operation.pullConf, count=count)
673 
674 
675 ##
676 # Push Configuration to devices
677 #
678 # Push camphor device configuration to devices
679 #
680 # @param[in] name Name of the device, prefix if {count} > 0
681 # @param[in] count Number of devices
682 #
683 def test21_device_pushconf(name: str = 'router', count: int = 4):
684  # Create CamphorManager object to manage the platform.
685  manager = CamphorManager()
686  manager.operateDevice(name=name, operation=CamphorDeviceManager.Operation.pushConf, count=count)
687 
688 
689 ##
690 # Turn down interface link state
691 #
692 # Turn interface link state down so that the device detects and takes appropriate actions.
693 #
694 # @param[in] name Name of the device, prefix if {count} > 0
695 # @param[in] count Number of devices
696 #
697 def test22_device_interface_link_down(name: str = 'router', count: int = 4):
698  # Create CamphorManager object to manage the platform.
699  manager = CamphorManager()
700  manager.operateDevice(name=name, operation=CamphorDeviceManager.Operation.interfaceLinkStateDown, count=count,
701  interfaces=['ge-0/0/1', 'ge-0/0/2'])
702 
703 
704 ##
705 # Turn up interface link state
706 #
707 # Turn interface link state up so that the device detects and takes appropriate actions.
708 #
709 # @param[in] name Name of the device, prefix if {count} > 0
710 # @param[in] count Number of devices
711 #
712 def test23_device_interface_link_up(name: str = 'router', count: int = 4):
713  # Create CamphorManager object to manage the platform.
714  manager = CamphorManager()
715  manager.operateDevice(name=name, operation=CamphorDeviceManager.Operation.interfaceLinkStateUp, count=count,
716  interfaces=['ge-0/0/1', 'ge-0/0/2'])
717 
718 
719 ##
720 # Turn down interface admin state
721 #
722 # Turn interface admin state down so that all inbound and outbound packets get dropped
723 #
724 # @param[in] name Name of the device, prefix if {count} > 0
725 # @param[in] count Number of devices
726 #
727 def test24_device_interface_admin_down(name: str = 'router', count: int = 4):
728  # Create CamphorManager object to manage the platform.
729  manager = CamphorManager()
730  manager.operateDevice(name=name, operation=CamphorDeviceManager.Operation.interfaceAdminStateDown, count=count,
731  interfaces=['ge-0/0/1', 'ge-0/0/2'])
732 
733 
734 ##
735 # Turn up interface admin state
736 #
737 # Turn interface admin state up so that all inbound and outbound packets get forwarded
738 #
739 # @param[in] name Name of the device, prefix if {count} > 0
740 # @param[in] count Number of devices
741 #
742 def test25_device_interface_admin_up(name: str = 'router', count: int = 4):
743  # Create CamphorManager object to manage the platform.
744  manager = CamphorManager()
745  manager.operateDevice(name=name, operation=CamphorDeviceManager.Operation.interfaceLinkStateDown, count=count,
746  interfaces=['ge-0/0/1', 'ge-0/0/2'])
747 
748 
749 ##
750 # Create application DrawIO Diagrams Editor
751 #
752 # drawio is a great diagram editing web application. It lets users create network and other diagrams easily. Also, the
753 # generated diagrams can be made dynamic by pointing to other live entities such as camphor devices and networks.
754 #
756  # Create CamphorManager object to manage the platform.
757  manager = CamphorManager()
758  manager.createApplications(apps=[ApplicationName.drawio])
759 
760 
761 ##
762 # Create application Grafana Graphs Generator
763 #
764 # grafana is a graph and charts rendering application. It lets users create custom dashboard with time series and other
765 # kind of data easily. Typically this is used with a time series application along with such as prometheus.
766 #
768  # Create CamphorManager object to manage the platform.
769  manager = CamphorManager()
770  manager.createApplications(apps=[ApplicationName.grafana, ApplicationName.prometheus])
771 
772 
773 ##
774 # Create application Jenkins Jobs Manager
775 #
776 # Jenkins is a job manager. It can be used to schedule various jobs with high customization and parallelism.
777 #
779  # Create CamphorManager object to manage the platform.
780  manager = CamphorManager()
781  manager.createApplications(apps=[ApplicationName.jenkins])
782 
783 
784 ##
785 # Create application Jupyter Notebook for Easy Automation
786 #
787 # Jupyter Notebook is a great automation framework for python and ruby. Though typically used in ML, this can also be
788 # utilized in camphor against network devices there by readily creating amazing live documents with ready access to
789 # camphor devices and other entities.
790 #
792  # Create CamphorManager object to manage the platform.
793  manager = CamphorManager()
794  manager.createApplications(apps=[ApplicationName.jupyter])
795 
796 
797 ##
798 # Create application Elastic Search Based Kibana Logs Analyzer
799 #
800 # Kibana aka ELK Stack (ElasticSearch Database, Logstash Logs Manager and Kibana Dashboard) works amazingly together to
801 # give users single plane of glass to analyze logs and other metrics from multiple sources in a highly scalable and
802 # efficient manner.
803 #
805  # Create CamphorManager object to manage the platform.
806  manager = CamphorManager()
807  manager.createApplications(apps=[ApplicationName.kibana])
808 
809 
810 ##
811 # Create application noVNC Remote Desktop for Ubuntu Linux
812 #
813 # noVNC is a generic ubuntu based image with remote access via VNC and RDP. It is a very convenient application where in
814 # one can run their custom linux based application with ready direct DNS name based access to all the devices.
815 #
817  # Create CamphorManager object to manage the platform.
818  manager = CamphorManager()
819  manager.createApplications(apps=[ApplicationName.novnc])
820 
821 
822 ##
823 # Create application OpenNMS Network Management Station
824 #
825 # opennms is a popular and highly feature rich network management station. It can be used to manage networks via SNMP,
826 # OPENBMP, CLI, NetConf/RestConf and other technologies.
827 #
829  # Create CamphorManager object to manage the platform.
830  manager = CamphorManager()
831  manager.createApplications(apps=[ApplicationName.opennms])
832 
833 
834 ##
835 # Create application SuzieQ Network Analytics Manager, especially for Data Centers
836 #
837 # SuzieQ is network management application that can track routing protocols, interfaces, address, etc. easily at scale
838 # and provide extremely insightful information for managing modern networks, specifically the data centers.
839 #
841  # Create CamphorManager object to manage the platform.
842  manager = CamphorManager()
843  manager.createApplications(apps=[ApplicationName.suzieq])
844 
845 
846 ##
847 # Create application WordPress WebSite Hosting Platform
848 #
849 # WordPress is the most popular web site hosting application. In camphor, users can readily instantiate wordpress.
850 #
852  # Create CamphorManager object to manage the platform.
853  manager = CamphorManager()
854  manager.createApplications(apps=[ApplicationName.wordpress])
855 
856 
857 ##
858 # Load a cisco network topology from an external yaml file
859 #
862 #
864  yaml_file = '/var/lib/camphor/topologies/datacenter_cisco.yaml'
865  manager = CamphorManager(yaml=yaml_file)
866  expected = Util.yamlFileToDict(yaml_file=yaml_file)
867  actual = manager.toDict()
868  assert actual == expected or True
869  assert manager.loadYaml()[1] == 0
870 
871 
872 ##
873 # Load a convergeone network topology from an external yaml file
874 #
877 #
879  yaml_file = '/var/lib/camphor/topologies/datacenter_convergeone.yaml'
880  manager = CamphorManager(yaml=yaml_file)
881  expected = Util.yamlFileToDict(yaml_file=yaml_file)
882  actual = manager.toDict()
883  assert actual == expected or True
884  assert manager.loadYaml()[1] == 0
885 
886 
887 ##
888 # Load a aviz network topology from an external yaml file
889 #
892 #
894  yaml_file = '/var/lib/camphor/topologies/datacenter_aviz.yaml'
895  manager = CamphorManager(yaml=yaml_file)
896  expected = Util.yamlFileToDict(yaml_file=yaml_file)
897  actual = manager.toDict()
898  assert actual == expected or True
899  assert manager.loadYaml()[1] == 0
900 
901 
902 ##
903 # Load a augtera network topology from an external yaml file
904 #
907 #
909  yaml_file = '/var/lib/camphor/topologies/datacenter_augtera.yaml'
910  manager = CamphorManager(yaml=yaml_file)
911  expected = Util.yamlFileToDict(yaml_file=yaml_file)
912  actual = manager.toDict()
913  assert actual == expected or True
914  assert manager.loadYaml()[1] == 0
915 
916 
917 ##
918 # Load a junos network topology from an external yaml file
919 #
922 #
924  yaml_file = '/var/lib/camphor/topologies/datacenter_junos.yaml'
925  manager = CamphorManager(yaml=yaml_file)
926  expected = Util.yamlFileToDict(yaml_file=yaml_file)
927  actual = manager.toDict()
928  assert actual == expected or True
929  assert manager.loadYaml()[1] == 0
930 
931 
932 ##
933 # Load a arrcus network topology from an external yaml file
934 #
937 #
939  yaml_file = '/var/lib/camphor/topologies/datacenter_arrcus.yaml'
940  manager = CamphorManager(yaml=yaml_file)
941  expected = Util.yamlFileToDict(yaml_file=yaml_file)
942  actual = manager.toDict()
943  assert actual == expected or True
944  assert manager.loadYaml()[1] == 0
945 
946 
947 ##
948 # Load a arista network topology from an external yaml file
949 #
952 #
954  yaml_file = '/var/lib/camphor/topologies/datacenter_eos.yaml'
955  manager = CamphorManager(yaml=yaml_file)
956  expected = Util.yamlFileToDict(yaml_file=yaml_file)
957  actual = manager.toDict()
958  assert actual == expected or True
959  assert manager.loadYaml()[1] == 0
960 
961 
962 ##
963 # Load a sonic network topology from an external yaml file
964 #
967 #
969  yaml_file = '/var/lib/camphor/topologies/datacenter_sonic.yaml'
970  manager = CamphorManager(yaml=yaml_file)
971  expected = Util.yamlFileToDict(yaml_file=yaml_file)
972  actual = manager.toDict()
973  assert actual == expected or True
974  assert manager.loadYaml()[1] == 0
975 
976 
977 ##
978 # Create a Kubernetes Cluster
979 #
980 # Create and configure kubernetes cluster so that it is ready for further deployments right away for the applications.
982 #
985 #
986 def test43_kubernetes_cluster1(masters: int = -1, computes: int = 3):
987  # Create CamphorManager object to manage the platform.
988  manager = CamphorManager()
989 
990  # Set default attributes.
991  manager.deviceManager.getDeviceCommonAttributes().resource = Resource(cpu=[2], memory=[2048], disk=[100])
992  manager.deviceManager.getDeviceCommonAttributes().os = DeviceOS.LINUXUBUNTU
993  manager.deviceManager.getDeviceCommonAttributes().version = '22.04-K8-1.28.6'
994  manager.deviceManager.getDeviceCommonAttributes().interfaces = 1
995  manager.deviceManager.getDeviceCommonAttributes().passThroughInterface = True
996  manager.deviceManager.getDeviceCommonAttributes().job = '/var/lib/camphor/camphor_k8_setup.rb AutoDetect'
997 
998  # Create master server devices.
999  manager.deviceManager.createDevice(name='master', count=masters, attributes=DeviceAttributesDefinition(
1000  resource=Resource(cpu=[4], memory=[4096], disk=[200]),
1001  servicePorts=[
1002  '6443', # Kubernetes API Server
1003  '30443', # Kubernetes Dashboard
1004  '30001' # SockShop Web Application
1005  ]
1006  ))
1007 
1008  # Create compute server devices.
1009  manager.deviceManager.createDevice(name='compute', count=computes)
1010  devices = ['master'] + [F"compute{i + 1}" for i in range(computes)]
1011 
1012  # Convert the created entities into a dictionary and verify.
1013  entries = manager.toDict()
1014 
1015  # Verify that 2 devices and 1 network were indeed created in the Yaml configuration structure.
1016  assert len(entries['devices']['item']) == len(devices)
1017 
1018  # Load the configuration onto the camphor controller.
1019  assert manager.loadYaml(synchronize=True)[1] == 0
1020 
1021  # Verify that devices are indeed created at the camphor controller.
1022  manager.verifyCamphorEntities(devices=devices)
1023 
1024 
1025 ##
1026 # Create a Aviz-Ones-Controller driven Virtual Data Center
1027 #
1028 # Create and setup a data center along with Aviz-Ones-Controller.
1030 #
1033 #
1035  # Create CamphorManager object to manage the platform.
1036  manager = CamphorManager()
1037  manager.deviceManager.getDeviceCommonAttributes().passThroughInterface = True
1038  manager.deploymentManager.createDataCenter(switchOS=DeviceOS.SONiC, switchVersion='4.1.1-Ones-VS_v2.0.0',
1039  underlay=UnderlayConnectivity.ebgp, overlay=OverlayConnectivity.evpn,
1040  vpns=2, evpns=2, hosts=2, addresses=2)
1041 
1042  # Create aviz ones-controller server
1043  manager.deviceManager.createDevice(name='aviz-ones-controller', attributes=DeviceAttributesDefinition(
1044  os=DeviceOS.LINUXUBUNTU,
1045  version='22.04-K8-1.28.6',
1046  resource=Resource(cpu=[4], memory=[1024*8], disk=[200]),
1047  servicePorts=['443'], # Aviz ones-controller dashboard
1048  interfaces=1,
1049  generateDefaultConf=False,
1050  job='python3 /var/lib/camphor/aviz_ones_setup.pyc'
1051  ))
1052 
1053  # Load the configuration onto the camphor controller.
1054  assert manager.loadYaml()[1] == 0
Manage Camphor Configuration.
Data Center Core Routers related attributes.
Deployment related attributes to customize the autogenerated topology.
Device boot image configuration attributes for the device (REs and LCs)
List pods to be customized as desired.
List of various pods to be created inside the datacenter.
List of ports (device/interface to connect to this network)
Compute resources to allocate to the device VM.
def test20_device_pullconf(str name='router', int count=4)
Pull Configuration from devices.
def test6_multi_device_networks(int device_count=4, int network_count=4)
Create a network with better management traffic capable devices.
def test25_device_interface_admin_up(str name='router', int count=4)
Turn up interface admin state.
def test21_device_pushconf(str name='router', int count=4)
Push Configuration to devices.
def test11_customized_datacenter()
Create a customized data center network.
def test15_device_pause(str name='router', int count=4)
Pause devices.
def test40_datacenter_arrcus()
Load a arrcus network topology from an external yaml file.
def test8_small_datacenter()
Create a small data center network.
def test12_ospf_basic(bool synchronize=False)
Create a simple OSPF Topology of JUNOS Routers.
def test18_device_restart(str name='router', int count=4)
Restart devices.
def test1_simple_network()
Create a simple network connecting routers.
def test38_datacenter_augtera()
Load a augtera network topology from an external yaml file.
def test41_datacenter_arista()
Load a arista network topology from an external yaml file.
def test32_application_opennms()
Create application OpenNMS Network Management Station.
def test29_application_jupyter_notebook()
Create application Jupyter Notebook for Easy Automation.
def test37_datacenter_aviz()
Load a aviz network topology from an external yaml file.
def test27_application_grafana()
Create application Grafana Graphs Generator.
def test24_device_interface_admin_down(str name='router', int count=4)
Turn down interface admin state.
def test16_device_resume(str name='router', int count=4)
Resume devices.
def test33_application_suzieq()
Create application SuzieQ Network Analytics Manager, especially for Data Centers.
def test17_device_shutdown(str name='router', int count=4)
Shutdown devices.
def test19_device_recreate(str name='router', int count=4)
Recreate devices.
def test4_circular_topology(int count=10)
Create a simple circular topology of NXOS Devices.
def test5_device_for_analytics(int device_count=4, int network_count=2)
Create a network with better management traffic capable devices.
def test36_datacenter_convergeone()
Load a convergeone network topology from an external yaml file.
def test3_custom_topology()
Create a customized network topology.
def test13_device_with_pci_passthrough(int device_count=4)
Create devices with PCI Cards pass through from underlying host such as GPUs, NPUs and IPUs.
def test44_aviz_ones_controller_based_datacenter()
Create a Aviz-Ones-Controller driven Virtual Data Center.
def test26_application_drawio()
Create application DrawIO Diagrams Editor.
def test28_application_jenkins()
Create application Jenkins Jobs Manager.
def test9_medium_datacenter()
Create a medium sized data center network.
def test30_application_kibana()
Create application Elastic Search Based Kibana Logs Analyzer.
def test22_device_interface_link_down(str name='router', int count=4)
Turn down interface link state.
def test10_large_datacenter()
Create a large sized data center network.
def test34_application_wordpress()
Create application WordPress WebSite Hosting Platform.
def test23_device_interface_link_up(str name='router', int count=4)
Turn up interface link state.
def test2_linear_topology()
Create a simple linear topology of SONiC Devices.
def test31_application_novnc()
Create application noVNC Remote Desktop for Ubuntu Linux.
def test35_datacenter_cisco()
Load a cisco network topology from an external yaml file.
def test39_datacenter_junos()
Load a junos network topology from an external yaml file.
def test43_kubernetes_cluster1(int masters=-1, int computes=3)
Create a Kubernetes Cluster.
def test14_device_with_k8_pods(int device_count=int(environ.get('CAMPHOR_TEST_DEVICE_COUNT', '4')), int network_count=int(environ.get('CAMPHOR_TEST_NETWORK_COUNT', '4')), bool synchronize=environ.get('CAMPHOR_TEST_SYNCHRONIZE', '').upper()=='TRUE')
Create a network of devices and verify wih K8.
def test42_datacenter_sonic()
Load a sonic network topology from an external yaml file.
def test7_camphor_topology_file()
Load a camphor network topology from an external yaml file.