Devnet 20201014
Devnet 20201014
Devnet 20201014
1. Cover Page
2. About This eBook
3. Title Page
4. Copyright Page
5. About the Authors
6. About the Technical Reviewers
7. Dedications
8. Acknowledgments
9. Contents at a Glance
10. Reader Services
11. Contents
12. Icons Used in This Book
13. Command Syntax Conventions
14. Introduction
1. Getting Ready
2. Tools for Final Preparation
3. Suggested Plan for Final Review/Study
4. Summary
37. Glossary
38. Index
39. Appendix C. Study Planner
40. Where are the companion content files? - Register
41. Inside Front Cover
42. Inside Back Cover
43. Code Snippets
1. i
2. ii
3. iii
4. iv
5. v
6. vi
7. vii
8. viii
9. ix
10. x
11. xi
12. xii
13. xiii
14. xiv
15. xv
16. xvi
17. xvii
18. xviii
19. xix
20. xx
21. xxi
22. xxii
23. xxiii
24. xxiv
25. xxv
26. xxvi
27. xxvii
28. xxviii
29. xxix
30. xxx
31. xxxi
32. xxxii
33. xxxiii
34. xxxiv
35. xxxv
36. 2
37. 3
38. 4
39. 5
40. 6
41. 7
42. 8
43. 9
44. 10
45. 11
46. 12
47. 13
48. 14
49. 15
50. 16
51. 17
52. 18
53. 19
54. 20
55. 21
56. 22
57. 23
58. 24
59. 25
60. 26
61. 27
62. 28
63. 29
64. 30
65. 31
66. 32
67. 33
68. 34
69. 35
70. 36
71. 37
72. 38
73. 39
74. 40
75. 41
76. 42
77. 43
78. 44
79. 45
80. 46
81. 47
82. 48
83. 49
84. 50
85. 51
86. 52
87. 53
88. 54
89. 55
90. 56
91. 57
92. 58
93. 59
94. 60
95. 61
96. 62
97. 63
98. 64
99. 65
100. 66
101. 67
102. 68
103. 69
104. 70
105. 71
106. 72
107. 73
108. 74
109. 75
110. 76
111. 77
112. 78
113. 79
114. 80
115. 81
116. 82
117. 83
118. 84
119. 85
120. 86
121. 87
122. 88
123. 89
124. 90
125. 91
126. 92
127. 93
128. 94
129. 95
130. 96
131. 97
132. 98
133. 99
134. 100
135. 101
136. 102
137. 103
138. 104
139. 105
140. 106
141. 107
142. 108
143. 109
144. 110
145. 111
146. 112
147. 113
148. 114
149. 115
150. 116
151. 117
152. 118
153. 119
154. 120
155. 121
156. 122
157. 123
158. 124
159. 125
160. 126
161. 127
162. 128
163. 129
164. 130
165. 131
166. 132
167. 133
168. 134
169. 135
170. 136
171. 137
172. 138
173. 139
174. 140
175. 141
176. 142
177. 143
178. 144
179. 145
180. 146
181. 147
182. 148
183. 149
184. 150
185. 151
186. 152
187. 153
188. 154
189. 155
190. 156
191. 157
192. 158
193. 159
194. 160
195. 161
196. 162
197. 163
198. 164
199. 165
200. 166
201. 167
202. 168
203. 169
204. 170
205. 171
206. 172
207. 173
208. 174
209. 175
210. 176
211. 177
212. 178
213. 179
214. 180
215. 181
216. 182
217. 183
218. 184
219. 185
220. 186
221. 187
222. 188
223. 189
224. 190
225. 191
226. 192
227. 193
228. 194
229. 195
230. 196
231. 197
232. 198
233. 199
234. 200
235. 201
236. 202
237. 203
238. 204
239. 205
240. 206
241. 207
242. 208
243. 209
244. 210
245. 211
246. 212
247. 213
248. 214
249. 215
250. 216
251. 217
252. 218
253. 219
254. 220
255. 221
256. 222
257. 223
258. 224
259. 225
260. 226
261. 227
262. 228
263. 229
264. 230
265. 231
266. 232
267. 233
268. 234
269. 235
270. 236
271. 237
272. 238
273. 239
274. 240
275. 241
276. 242
277. 243
278. 244
279. 245
280. 246
281. 247
282. 248
283. 249
284. 250
285. 251
286. 252
287. 253
288. 254
289. 255
290. 256
291. 257
292. 258
293. 259
294. 260
295. 261
296. 262
297. 263
298. 264
299. 265
300. 266
301. 267
302. 268
303. 269
304. 270
305. 271
306. 272
307. 273
308. 274
309. 275
310. 276
311. 277
312. 278
313. 279
314. 280
315. 281
316. 282
317. 283
318. 284
319. 285
320. 286
321. 287
322. 288
323. 289
324. 290
325. 291
326. 292
327. 293
328. 294
329. 295
330. 296
331. 297
332. 298
333. 299
334. 300
335. 301
336. 302
337. 303
338. 304
339. 305
340. 306
341. 307
342. 308
343. 309
344. 310
345. 311
346. 312
347. 313
348. 314
349. 315
350. 316
351. 317
352. 318
353. 319
354. 320
355. 321
356. 322
357. 323
358. 324
359. 325
360. 326
361. 327
362. 328
363. 329
364. 330
365. 331
366. 332
367. 333
368. 334
369. 335
370. 336
371. 337
372. 338
373. 339
374. 340
375. 341
376. 342
377. 343
378. 344
379. 345
380. 346
381. 347
382. 348
383. 349
384. 350
385. 351
386. 352
387. 353
388. 354
389. 355
390. 356
391. 357
392. 358
393. 359
394. 360
395. 361
396. 362
397. 363
398. 364
399. 365
400. 366
401. 367
402. 368
403. 369
404. 370
405. 371
406. 372
407. 373
408. 374
409. 375
410. 376
411. 377
412. 378
413. 379
414. 380
415. 381
416. 382
417. 383
418. 384
419. 385
420. 386
421. 387
422. 388
423. 389
424. 390
425. 391
426. 392
427. 393
428. 394
429. 395
430. 396
431. 397
432. 398
433. 399
434. 400
435. 401
436. 402
437. 403
438. 404
439. 405
440. 406
441. 407
442. 408
443. 409
444. 410
445. 411
446. 412
447. 413
448. 414
449. 415
450. 416
451. 417
452. 418
453. 419
454. 420
455. 421
456. 422
457. 423
458. 424
459. 425
460. 426
461. 427
462. 428
463. 429
464. 430
465. 431
466. 432
467. 433
468. 434
469. 435
470. 436
471. 437
472. 438
473. 439
474. 440
475. 441
476. 442
477. 443
478. 444
479. 445
480. 446
481. 447
482. 448
483. 449
484. 450
485. 451
486. 452
487. 453
488. 454
489. 455
490. 456
491. 457
492. 458
493. 459
494. 460
495. 461
496. 462
497. 463
498. 464
499. 465
500. 466
501. 467
502. 468
503. 469
504. 470
505. 471
506. 472
507. 473
508. 474
509. 475
510. 476
511. 477
512. 478
513. 479
514. 480
515. 481
516. 482
517. 483
518. 484
519. 485
520. 486
521. 487
522. 488
523. 489
524. 490
525. 491
526. 492
527. 493
528. 494
529. 495
530. 496
531. 497
532. 498
533. 499
534. 500
535. 501
536. 502
537. 503
538. 504
539. 505
540. 506
541. 507
542. 508
543. 509
544. 510
545. 511
546. 512
547. 513
548. 514
549. 515
550. 516
551. 517
552. 518
553. 519
554. 520
555. 521
556. 522
557. 523
558. 524
559. 525
560. 526
561. 527
562. 528
563. 529
564. 530
565. 531
566. 532
567. 533
568. 534
569. 535
570. 536
571. 537
572. 538
573. 539
574. 540
575. 541
576. 542
577. 543
578. 544
579. 545
580. 546
581. 547
582. 548
583. 549
584. 550
585. 551
586. 552
587. 553
588. 554
589. 555
590. 556
591. 557
592. 558
593. 559
594. 560
595. 561
596. 562
597. 563
598. 564
599. 565
600. 566
601. 567
602. 568
603. 569
604. 570
605. 571
606. 572
607. 573
608. 574
609. 575
610. 576
611. 577
612. 578
613. 579
614. 580
615. 581
616. 582
617. 583
618. 584
619. 585
620. 586
621. 587
622. 588
623. 589
624. 590
625. 591
626. 592
627. 593
628. 594
629. 595
630. 596
631. 597
632. 598
633. 599
634. 600
635. 601
636. 602
637. 603
638. 604
639. 605
640. 606
641. 607
642. 608
643. 609
644. 610
645. 611
646. 612
647. 613
648. 614
649. 615
650. 616
651. 617
652. 618
653. 619
654. 620
655. 621
656. 622
657. 623
658. 624
659. 625
660. 626
661. 627
662. 628
663. 629
664. 630
665. 631
666. 632
667. 633
668. 634
669. 635
670. 636
671. 637
672. 638
About This eBook
ePUB is an open, industry-standard format for eBooks.
However, support of ePUB and its many features varies
across reading devices and applications. Use your device
or app settings to customize the presentation to your
liking. Settings that you can customize often include font,
font size, single or double column, landscape or portrait
mode, and figures that you can click or tap to enlarge.
For additional information about the settings and
features on your reading device or app, visit the device
manufacturer’s Web site.
Cisco Press
Cisco Certified DevNet Associate DEVASC
200-901 Official Cert Guide
Chris Jackson, Jason Gooley, Adrian Iliesiu, Ashutosh
Malegaonkar
Published by:
Cisco Press
ScoutAutomatedPrintCode
ISBN-13: 978-01-3664296-1
ISBN-10: 01-3664296-9
Trademark Acknowledgments
All terms mentioned in this book that are known to be
trademarks or service marks have been appropriately
capitalized. Cisco Press or Cisco Systems, Inc., cannot
attest to the accuracy of this information. Use of a term
in this book should not be regarded as affecting the
validity of any trademark or service mark.
Special Sales
For information about buying this title in bulk
quantities, or for special sales opportunities (which may
include electronic versions; custom cover designs; and
content particular to your business, training goals,
marketing focus, or branding interests), please contact
our corporate sales department at
corpsales@pearsoned.com or (800) 382-3419.
Feedback Information
At Cisco Press, our goal is to create in-depth technical
books of the highest quality and value. Each book is
crafted with care and precision, undergoing rigorous
development that involves the unique expertise of
members from the professional technical community.
Composition: codeMantra
Americas Headquarters
Cisco Systems, Inc.
San Jose, CA
Europe Headquarters
Cisco Systems International BV Amsterdam,
The Netherlands
Cisco has more than 200 offices worldwide. Addresses, phone numbers, and
fax numbers are listed on the Cisco Website at
www.cisco.com/go/offices.
Cisco and the Cisco logo are trademarks or registered trademarks of
Cisco and/or its affiliates in the U.S. and other countries. To view a list of
Cisco trademarks, go to this URL: www.cisco.com/go/trademarks. Third
party trademarks mentioned are the property of their respective owners.
The use of the word partner does not imply a partnership relationship
between Cisco and any other company. (1110R)
About the Authors
Chris Jackson, CCIE No. 6256 (R&S and SEC), is a
Distinguished Architect and CTO for Global Sales
Training at Cisco. Chris is focused on digital
transformation and showing customers how to leverage
the tremendous business value Cisco technologies can
provide. He is the author of Network Security Auditing
(Cisco Press, 2010), CCNA Cloud CLDADM 210-455
Official Cert Guide (Cisco Press, 2016), and various
online video courses for Cisco Press. He holds dual
CCIEs in security and routing and switching, CISA,
CISSP, ITIL v3, seven SANS certifications, and a
bachelor’s degree in business administration. Residing in
Franklin, Tennessee, Chris enjoys tinkering with
electronics, robotics, and anything else that can be
programmed to do his bidding. In addition, he is a 3rd
Degree Black Belt in Taekwondo, rabid Star Wars fan,
and has a ridiculous collection of Lego. His wife Piper
and three children Caleb, Sydney, and Savannah are the
true joy of his life and proof that not everything has to
plug into a wall outlet to be fun.
Jason Gooley:
Ashutosh Malegaonkar:
Last but not the least, I sincerely thank Susie Wee for
believing in me and letting me be part of DevNet since
the very early days of DevNet.
Acknowledgments
Chris Jackson:
Jason Gooley:
Adrian Iliesiu:
Huge thank-you to Casey Tong, designer in chief, for all
her help with images and graphics for this book. Big
thank-you to Ashutosh for all his support. Thanks to
Chris and Jason for allowing me to embark on this
journey with them; Ellie Bru and James Manly from
Cisco Press for editing and trying to keep the project on
track; and to John and Bryan for their feedback and
insight. I would also like to thank Mike Mackay for
believing in me when it mattered and for giving me a
chance to prove myself.
Ashutosh Malegaonkar:
*Be sure to check the box that you would like to hear from us to receive exclusive discounts on
future editions of this product.
Contents
Introduction
Chapter 1 Introduction to Cisco DevNet Associate
Certification
Technologies
Community
Support
Events
Foundation Topics
Software Development Lifecycle
Waterfall
Lean
Agile
Common Design Patterns
Model-View-Controller (MVC) Pattern
Observer Pattern
Linux BASH
cd
pwd
ls
mkdir
File Management
cp
mv
rm
touch
cat
Environment Variables
Software Version Control
Git
Understanding Git
Using Git
Cloning/Initiating Repositories
Merging Branches
Handling Conflicts
Foundation Topics
Getting Started with Python
Variables
Data Types
Strings
Lists
Tuples
Dictionaries
Sets
Input and Output
For Loops
While Loops
Foundation Topics
Python Functions
Python Classes
Creating a Class
Methods
Inheritance
Foundation Topics
File Input and Output
Parsing Data
Comma-Separated Values (CSV)
Test-Driven Development
Unit Testing
Foundation Topics
Application Programming Interfaces (APIs)
Northbound APIs
Southbound APIs
API Keys
Custom Tokens
HTTP Headers
Request Headers
Response Headers
Response Codes
XML
JSON
YAML
Webhooks
REST Constraints
Client/Server
Stateless
Cache
Uniform Interface
Layered System
Code on Demand
REST API Versioning
Pagination
Rate Limiting and Monetization
Rate Limiting on the Client Side
REST Tools
Postman
curl
HTTPie
Python Requests
Foundation Topics
What Is an SDK?
Cisco Meraki
Cisco DNA Center
Cisco SD-WAN
Exam Preparation Tasks
Foundation Topics
Cisco ACI
UCS Manager
Cisco UCS Director
Cisco Intersight
Bots
Guest Issuer
Dialog APIs
Finesse Gadgets
Webex Devices
xAPI
xAPI Authentication
xAPI Session Authentication
Creating a Session
Getting the Current Device Status
Administrative XML
Cisco AXL Toolkit
Foundation Topics
Cisco’s Security Portfolio
Cisco Umbrella
Understanding Umbrella
Cisco Firepower
Firepower Management Center APIs
API Keys
Who Am I
The Data, Sample, and IOC APIs
Feeds
NETCONF
YANG
RESTCONF
Model-Driven Telemetry
Essential Characteristics
Service Models
Public Cloud
Hybrid Cloud
Community Cloud
Edge and Fog Computing
Cloud-Native Applications
Containerized Applications
Serverless
DevOps
What Is DevOps?
Putting DevOps into Practice: The Three
Ways
Docker
Understanding Docker
Namespaces
Cgroups
Using Docker
Working with Containers
Dockerfiles
Docker Images
Docker Hub
Exam Preparation Tasks
Additional Resources
Chapter 14 Application Security
“Do I Know This Already?” Quiz
Foundation Topics
Protecting Applications
Tiers of Securing and Protecting
Encryption Fundamentals
Public Key Encryption
Data Security
Secure Development Methods
Ansible
Puppet
Chef
Cisco Network Services Orchestrator (NSO)
Ethernet
MAC Addresses
Routing Concepts
IPv4 Addresses
IPv6 Addresses
Routing
Exam Preparation Tasks
Foundation Topics
What Are Networks?
Elements of Networks
Hubs
Bridges
Switches
Routing in Software
Functions of a Router
SDN Controllers
Cisco Software-Defined Networking
(SDN)
Lease Offer
Lease Request
Lease Acknowledgment
Releasing
Getting Ready
Tools for Final Preparation
Glossary
Index
Online Elements
Appendix C Study Planner
Glossary
Icons Used in This Book
Command Syntax Conventions
The conventions used to present command syntax in this
book are the same conventions used in the IOS
Command Reference. The Command Reference
describes these conventions as follows:
Readers of this book can expect that the blueprint for the
DevNet Associate DEVASC 200-901 exam tightly aligns
with the topics contained in this book. This was by
design. Candidates can follow along with the examples in
this book by utilizing the tools and resources found on
the DevNet website and other free utilities such as
Postman and Python.
Helping you discover which test topics you have not mastered
Print book: Look in the cardboard sleeve in the back of the book for a
piece of paper with your book’s unique PTP code.
Note
Do not lose the activation code because it is the only
means with which you can access the QA content with
the book.
If you want to use the web app only at this point, just
navigate to www.pearsontestprep.com, establish a free
login if you do not already have one, and register this
book’s practice tests using the registration code you just
found. The process should take only a couple of minutes.
Note
Amazon eBook (Kindle) customers: It is easy to miss
Amazon’s email that lists your PTP access code. Soon
after you purchase the Kindle eBook, Amazon should
send an email. However, the email uses very generic
text and makes no specific mention of PTP or practice
exams. To find your code, read every email from
Amazon after you purchase the book. Also do the usual
checks for ensuring your email arrives, like checking
your spam folder.
Note
Other eBook customers: As of the time of publication,
only the publisher and Amazon supply PTP access
codes when you purchase their eBook editions of this
book.
1.8.a Clone 2
1.8.b Add/remove 2
1.8.c Commit 2
1.8.d Push/pull 2
1.8.e Branch 2
1.8.g diff 2
2.0 Understanding and Using APIs
4.3.c Containers 1
3
Caution
The goal of self-assessment is to gauge your mastery of
the topics in this chapter. If you do not know the
answer to a question or are only partially sure of the
answer, you should mark that question as wrong for
purposes of self-assessment. Giving yourself credit for
an answer that you correctly guess skews your self-
assessment results and might provide you with a false
sense of security.
FOUNDATION TOPICS
WHY GET CERTIFIED
The IT industry is constantly changing and evolving. As
time goes on, an ever-increasing number of technologies
are putting strain on networks. New paradigms are
formed as others fall out of favor. New advances are
being developed and adopted in the networking realm.
These advances provide faster innovation and the ability
to adopt relevant technologies in a simplified way. We
therefore need more intelligence and the capability to
leverage the data from connected and distributed
environments such as the campus, branch, data center,
and WAN. Data is being used in interesting and more
powerful ways than ever in the past. The following are
some of the advances driving these outcomes:
Cloud services
Virtualization
Providing credibility
Building confidence
Increasing salary
Architect
Expert
Professional
Associate
Entry
Figure 1-2 Cisco Career Certification Levels of
Accreditation
CCNA
Cyber
Ops
CCNA
Industri
al
EntryAssociateProfessionalExpertArchitect
Cisco Cisco
Certified Certified
Design Architect
Expert (CCAr)
(CCDE)
CCIE
Enterprise
Wireless
CCNP CCIE
Collab Collaboratio
oratio n
n
CCNP CCIE
Securi Security
ty
CCNP CCIE
Servic Service
e Provider
Provid
er
300-101 ROUTE
300-115 SWITCH
300-135 TSHOOT
Virtualization
Infrastructure
Network assurance
Security
Automation
TrackDescriptionConcentration Exam
Note
The exams listed in Table 1-4 were available at the time
of publication. Please visit
http://www.cisco.com/go/certifications to keep up on
all the latest available certifications and associated
tracks.
CCIE Collaboration
CCIE Security
Note
The DevNet Expert certification will be announced in
the future. Please visit
http://www.cisco.com/go/certifications to keep up on
all the latest available certifications and associated
tracks.
Cloud developer
Automation engineer
TrackDescriptionSpecialist Exam
DevNet, Cisco Certified DevNet Specialist– 300-
Enterpri Enterprise Automation and 435
se Programmability ENAU
TO
Note
The DevNet Expert certification is a planned offering
that was not available as this book went to press.
Across the top of the main DevNet page, you can see that
the following menu options:
Discover
Technologies
Community
Support
Events
Discover
The Discover page shows the different offerings that
DevNet has available. This page includes the subsection
Learning Tracks; the learning tracks on this page guide
you through various different technologies and
associated API labs. Some of the available labs are
Programming the Cisco Digital Network Architecture
(DNA), ACI Programmability, Getting Started with Cisco
WebEx Teams APIs, and Introduction to DevNet.
Technologies
The Technologies page allows you to pick relevant
content based on the technology you want to study and
dive directly into the associated labs and training for that
technology. Figure 1-7 shows some of the networking
content that is currently available in DevNet.
Note
Available labs may differ from those shown in this
chapter’s figures. Please visit
http://developer.cisco.com to see the latest content
available and to interact with the current learning labs.
Community
Perhaps one of the most important section of DevNet is
the Community page, where you have access to many
different people at various stages of learning. You can
find DevNet ambassadors and evangelists to help at
various stages of your learning journey. The Community
page puts the latest events and news at your fingertips.
This is also the place to read blogs, sign up for developer
forums, and follow DevNet on all major social media
platforms. This is the safe zone for asking any questions,
regardless of how simple or complex they might seem.
Everyone has to start somewhere. The DevNet
Community page is the place to start for all things Cisco
and network programmability. Figure 1-8 shows some of
the options currently available on the Community page.
Support
On the DevNet Support page you can post questions and
get answers from some of the best in the industry.
Technology-focused professionals are available to answer
questions from both technical and theoretical
perspectives. You can ask questions about specific labs or
overarching technologies, such as Python or YANG
models. You can also open a case with the DevNet
Support team, and your questions will be tracked and
answered in a minimal amount of time. This is a great
place to ask the Support team questions and to tap into
the expertise of the Support team engineers. Figure 1-9
shows the DevNet Support page, where you can open a
case. Being familiar with the options available from a
support perspective is key to understanding the types of
information the engineers can help provide.
Events
The Events page, shown in Figure 1-10, provides a list of
all events that have happened in the past and will be
happening in the future. This is where you can find the
upcoming DevNet Express events as well as any
conferences where DevNet will be present or
participating. Be sure to bookmark this page if you plan
on attending any live events. DevNet Express is a one- to
three-day event led by Cisco developers for both
customers and partners. Attending one of these events
can help you with peer learning and confidence as well as
with honing your development skills.
Walk
Run
Fly
Figure 1-11 shows the landing page for the DevNet
Automation Exchange. You can see that you can view the
use case library as well as share any use cases that you
have created.
DayFunctionDescription
0 In Bringing devices into an initial operational state
sta
ll
SUMMARY
This chapter provides a high-level overview of Cisco’s
career certifications and how candidates can choose their
own destiny by picking the areas where they want to
build experience and become certified. This chapter
describes Cisco’s new specialist exams, which focus on
many different technologies, such as Firepower, SD-
WAN, and IoT. This chapter also discusses some of the
benefits of becoming certified, from career advancement
to building confidence to commanding a higher salary in
the workplace. This chapter also details at a high level
the components of Cisco DevNet, the value of the DevNet
community, and DevNet events such as Cisco DevNet
Express. Finally, this chapter introduces DevNet tools
such as DevNet Automation Exchange and DevNet
learning labs.
Chapter 2
Linux BASH: This section covers key aspects of the Linux BASH shell
and how to use it.
Git: This section discusses the use of the Git version control system.
Linux BASH 5, 6
Git 8–10
1. What is Waterfall?
1. A description of how blame flows from management on failed
software projects
2. A type of SDLC
3. A serial approach to software development that relies on a fixed
scope
4. All of the above
2. What is Agile?
1. A form of project management for Lean
2. An implementation of Lean for software development
3. A strategy for passing the CCNA DevNet exam
4. A key benefit of automation in infrastructure
FOUNDATION TOPICS
SOFTWARE DEVELOPMENT
LIFECYCLE
Anyone can program. Once you learn a programming
language’s syntax, it’s just a matter of slapping it all
together to make your application do what you want it to
do, right? The reality is, software needs to be built using
a structure to give it sustainability, manageability, and
coherency. You may have heard the phrase “cowboy
coding” to refer to an unstructured software project,
where there is little formal design work, and the
programmer just sort of “shoots from the hip” and slaps
code in with little or no forethought. This is a path that
leads straight to late-night support calls and constant
bug scrubbing. Heaven forbid if you inherit a ball of
spaghetti like this and you are asked to try to fix, extend,
or modernize it. You will more than likely be updating
your resume or packing your parachute for a quick
escape.
Note
ISO/IEC 12207 is the international standard for
software lifecycle processes, and there are numerous
organizations around the globe that use it for
certification of their software development efforts. It is
compatible with any SDLC models and augments them
from a quality and process assurance standpoint. It
does not, however, replace your chosen SDLC model.
Waterfall
Lean
Agile
Iterative model
Spiral model
V model
Prototyping models
Luckily, you don’t need to know all of these for the 200-
901 DevNet Associate DEVASC exam. The following
sections cover the ones you should know most about:
Waterfall, Lean, and Agile.
Waterfall
Lean
Agile
Note
Numerous web frameworks use MVC concepts across
many programming languages. Angular, Express, and
Backbone are all written in JavaScript. Django and
Flask are two very popular examples written in Python.
View: The view is what the end users see on the devices they are using
to interact with the program. It could be a web page or text from the
command line. The power of the view is that it can be tailored to any
device and any representation without changing any of the business
logic of the model. The view communicates with the controller by
sending data or receiving output from the model through the controller.
The view’s primary function is to render data.
Observer Pattern
Subject: The subject refers to the object state being observed—in other
words, the data that is to be synchronized. The subject has a
registration process that allows other components of an application or
even remote systems to subscribe to the process. Once registered, a
subscriber is sent an update notification whenever there is a change in
the subject’s data so that the remote systems can synchronize.
LINUX BASH
Knowing how to use Linux BASH is a necessary skill for
working with open-source technologies as well as many
of the tools you need to be proficient with to be
successful in the development world. Linux has taken
over the development world, and even Microsoft has
jumped into the game by providing the Windows
Subsystem for Linux for Windows 10 pro. For the
DEVASC exam, you need to know how to use BASH and
be familiar with some of the key commands.
Getting to Know BASH
While there are many shells you can use, BASH, which
stands for Bourne Again Shell, is one of the most
popular. It has been around since 1989 and is the default
shell on most Linux operating systems. Until recently, it
was also the default for the Mac operating system, but
Apple has replaced BASH with Z shell. The commands
and syntax you will learn with BASH are transferable to
Z shell, as it was built to maintain compatibility with
BASH.
$ man man
man(1)
man(1)
NAME
SYNOPSIS
man [-acdfFhkKtwW] [--path] [-m
system] [-p string] [-C config_file]
[-M pathlist] [-P pager] [-B browser] [-
H htmlpager] [-S section_list]
[section] name ...
DESCRIPTION
man formats and displays the on-line
manual pages. If you specify sec-
tion, man only looks in that section of
the manual. name is normally
the name of the manual page, which is
typically the name of a command,
function, or file. However, if name
contains a slash (/) then man
interprets it as a file specification,
so that you can do man ./foo.5
or even man /cd/foo/bar.1.gz.
import json
import urllib.request
from pprint import pprint
def get_local_weather():
weather_base_url =
'http://forecast.weather.gov/MapClick.php?
FcstType=json&'
places = {
'Austin': ['30.3074624',
'-98.0335911'],
'Portland': ['45.542094',
'-122.9346037'],
'NYC': ['40.7053111', '-74.258188']
}
page_response =
urllib.request.urlopen(weather_url).read()
<output cut for brevity>
Directory Navigation
A UNIX-based file system has a directory tree structure.
The top of the tree is called the root (as it’s an upside-
down tree), and you use the forward slash (/) to refer to
root. From root you have numerous directories, and
under each directory you can have more directories or
files. Figure 2-7 shows a UNIX directory structure.
Figure 2-7 UNIX Directory Structure
cd
The cd command is used to change directories and move
around the file system. You can use it as follows:
pwd
If you ever get lost while navigating around the file
system, you can use the pwd command to print out your
current working directory path. You can use it as follows:
ls
Once you have navigated to a directory, you probably
want to know what is in it. The ls command gives you a
list of the current directory. If you execute it without any
parameters, it just displays whatever is in the directory.
It doesn’t show any hidden files (such as configuration
files). Anything that starts with a . does not show up in a
standard directory listing, and you need to use the -a flag
to see all files, including hidden files. By using the -l flag,
you can see permissions and the user and group that own
the file or directory. You can also use the wildcard * to
list specific filename values; for example, to find any files
with test as a part of the name, you can use ls *test*,
which would match both 1test and test1. You can use the
ls command as follows:
mkdir
To create a directory, you use the mkdir command. If
you are in your home directory or in another directory
where you have the appropriate permissions, you can use
this command without sudo. You can use the mkdir
command as follows:
File Management
Working with files is easy with BASH. There are just a
few commands that you will use often, and they are
described in the following sections.
cp
The purpose of the cp command is to copy a file or folder
someplace. It does not delete the source file but instead
makes an identical duplicate. When editing configuration
files or making changes that you may want to roll back,
you can use the cp command to create a copy as a sort of
backup. The command requires several parameters: the
name of the file you want to copy and where you want to
copy it to and the name of the copy. When copying the
contents of a folder, you need to use the -r, or recursive,
flag. You can use the cp command as follows:
mv
The mv command allows you to move a file or folder
from one directory to another, and it is also used to
rename files or folders from the command line, as BASH
does not have a dedicated renaming function. The mv
command takes a source and destination, just as cp
does. You can use the -i flag to create an interactive
option prompt when moving files that exist at the
destination. The -f flag forces the move and overwrites
any files at the destination. Wildcards also work to select
multiple source files or directories. You can use the mv
command as follows:
rm
To delete a file or directory, you use the rm command. If
the item you are deleting is a file or an empty directory,
you just need to supply the name and press Enter. On the
other hand, if you try to delete a directory that has files
in it, rm tells you that the directory is not empty. In that
case, you can use the -rf flag to force the deletion. You
can use the rm command as follows:
touch
The touch command is used to create a file and/or
change the timestamps on a file’s access without opening
it. This command is often used when a developer wants
to create a file but doesn’t want to put any content in it.
You can use the touch command as follows:
Environment Variables
BASH environment variables contain information about
the current session. Environment variables are available
in all operating systems and are typically set when you
open your terminal from a configuration file associated
with your login. You set these variables with similar
syntax to how you set them when programming. You do
not often use these variables directly, but the programs
and applications you launch do. You can view all of your
currently set environment variables by entering the env
command. Since there can be more entries than you have
room to display on a single terminal page, you can pipe
the results to the more command to pause between
pages:
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware
Fusion.app/Contents/Public:/opt/X11/bin
$ export PATH=$PATH:/Home/chrijack/bin
$ source ~/.bashrc
$ . ~/.bashrc
There are many more tricks you can uncover with BASH.
You will get plenty of chances to use it as you study for
the DEVASC exam.
GIT
If you are working with version control software, chances
are it is Git. A staggering number of companies use Git,
which is free and open source. In 2005, Linus Torvalds
(the father of Linux) created Git as an alternative to the
SCM system BitKeeper, when the original owner of
BitKeeper decided to stop allowing free use of the system
for Linux kernel development. With no existing open-
source options that would meet his needs, Torvalds
created a distributed version control system and named
it Git. Git was created to be fast and scalable, with a
distributed workflow that could support the huge
number of contributors to the Linux kernel. His creation
was turned over to Junio Hamano in 2006, and it has
become the most widely used source management
system in the world.
Note
GitHub is not Git. GitHub is a cloud-based social
networking platform for programmers that allows
anyone to share and contribute to software projects
(open source or private). While GitHub uses Git as its
version control system underneath the graphical front
end, it is not directly tied to the Git open-source
project (much as a Linux distribution, such as Ubuntu
or Fedora, uses the Linux kernel but is independently
developed from it).
Understanding Git
Git is a distributed version control system built with
scalability in mind. It uses a multi-tree structure, and if
you look closely at the design, you see that it looks a lot
like a file system. (Linus Torvalds is an operating system
creator after all.) Git keeps track of three main
structures, or trees (see Figure 2-8):
Local workspace: This is where you store source code files, binaries,
images, documentation, and whatever else you need.
Modified: Whenever you add some code or make a change to the file,
Git changes the status of the file to modified. Modified status is where
Git sees that you are working on the file but you are not finished. You
have to tell Git that you are ready to add a changed (modified) file to
the index or staging area by issuing the git add command again.
Staged: Once a changed file is added to the index, Git needs to be able
to bundle up your changes and update the local repository. This process
is called staging and is accomplished through git commit. At this
point, your file status is moved back to the tracked status, and it stays
there until you make changes to the file in the future and kick off the
whole process once again.
Figure 2-9 Git File Status Lifecycle
Using Git
Cloning/Initiating Repositories
Git operates on a number of processes that enable it to
do its magic. The first of these processes involves
defining a local repository by using either git clone or
git init. The git clone command has the following
syntax:
#git clone
https://github.com/CiscoDevNet/pyats-coding-
101.git
Cloning into 'pyats-coding-101'...
remote: Enumerating objects: 71, done.
remote: Total 71 (delta 0), reused 0 (delta 0),
pack-reused 71
Unpacking objects: 100% (71/71), done.
#cd pyats-coding-101
#pyats-coding-101 git:(master) ls
COPYRIGHT coding-102-parsers
LICENSE coding-103-
yaml
README.md coding-201-
advanced-parsers
coding-101-python
git init (directory name)
#newrepo git:(master)
# git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what
will be committed)
newfile
Git is helpful and tells you that it sees the new file, but
you need to do something else to enable version control
and let Git know to start tracking it.
The git add command adds all new or deleted files and
directories to the index. Why select an individual file
instead of everything with the . or -A option? It comes
down to being specific about what you are changing and
adding to the index. If you accidently make a change to
another file and commit everything, you might
unintentionally make a change to your code and then
have to do a rollback. Being specific is always safest. You
can use the following commands to add the file newfile to
the Git index (in a process known as staging):
# touch removeme.py
# git add .
# ls
newfile removeme.py
# git rm -f removeme.py
rm 'removeme.py'
# ls
oldfile.py
# git mv oldfile.py newfile.py
# ls
newfile.py
Committing Files
When you commit a file, you move it from the index or
staging area to the local copy of the repository. Git
doesn’t send entire updates; it sends just changes. The
commit command is used to bundle up those changes to
be synchronized with the local repository. The command
is simple, but you can specify a lot of options and tweaks.
In its simplest form, you just need to type git commit.
This command has the following syntax:
Note
As a good practice, use the first 50 characters of the
commit message as a title for the commit followed by a
blank line and a more detailed explanation of the
commit. This title can be used throughout Git to
automate notifications such as sending an email
update on a new commit with the title as the subject
line and the detailed message as the body.
To https://github.com/chrijack/devnetccna.git
#git log
commit 40aaf1af65ae7226311a01209b62ddf7f4ef88c2
(HEAD -> master, origin/master)
Author: Chris Jackson <chrijack@cisco.com>
Date: Sat Oct 19 00:00:34 2019 -0500
commit 1a9db03479a69209bf722b21d8ec50f94d727e7d
Author: Chris Jackson <chrijack@cisco.com>
Date: Fri Oct 18 23:59:55 2019 -0500
commit 8eb16e3b9122182592815fa1cc029493967c3bca
Author: Chris Jackson <chrijack@me.com>
Date: Fri Oct 18 20:03:32 2019 -0500
first commit
Notice that the first entry is the current commit state, as
it is referenced by HEAD. The other entries show the
chronological history of the commits. Figure 2-11 shows a
visual representation of this simple three-step commit
history; for brevity, only the first four values of the hash
are used.
Merging Branches
The merge process in Git is used to handle the combining
of multiple branches into one. The git merge command
is used to make this easier on the user and provide a
simple way to manage the changes. It has the following
syntax:
#git add .
#git commit -a -m "new feature"
Now the branch is synced with the new changes, and you
can switch back to the master branch with the following
command:
From the master branch, you can then issue the git
merge command and identify the branch to merge with
(in this case, the newfeature branch):
Handling Conflicts
Merging branches is a very useful capability, but what
happens if the same file is edited by two different
developers? You can have a conflict in terms of which
change takes precedence. Git attempts to handle merging
automatically, but where there is conflict, Git relies on
human intervention to decide what to keep. In the
previous example, if there had been changes made to
text1 in both the master branch and the newfeature
branch, you would have seen the following message after
using the command git merge:
git diff --cached: This command shows any changes between the
index and your last commit.
git diff HEAD: This command shows the differences between your
most recent commit and your current working directory. It is very
useful for seeing what will happen with your next commit.
git diff identified the new file addition and shows the
a/b comparison. Since this is a new file, there is nothing
to compare it with, so you see --- /dev/null as the a
comparison. In the b comparison, you see +++ b/text2,
which shows the addition of the new file, followed by
stacks on what was different. Since there was no file
before, you see -0,0 and +1. (The + and - simply denote
which of the two versions you are comparing. It is not
actually a -0, which would be impossible.) The last line
shows the text that was added to the new file. This is a
very simple example with one line of code. In a big file,
you might see a significant amount of text.
It can help you find more defects and inefficient code that unit tests and
functional tests might miss, making your software more reliable.
Review the code, not the person who wrote it. Avoid being robotic and
harsh so you don’t hurt people’s feeling and discourage them. The goal
is better code, not disgruntled employees.
Keep in mind that code review is a gift. No one is calling your baby ugly.
Check your ego at the door and listen; the feedback you receive will
make you a better coder in the long run.
Make sure the changes recommended are committed back into the code
base. You should also share findings back to the organization so that
everyone can learn from mistakes and improve their techniques.
Paragraph Waterfall 27
Paragraph Lean 28
Paragraph Agile 29
Introduction to Python
This chapter covers the following topics:
Getting Started with Python: This section covers what you need to
know when using Python on your local machine.
Data Types and Variables: This section describes the various types
of data you need to interact with when coding.
Input and Output: This section describes how to get input from a
user and print out results to the terminal.
Caution
The goal of self-assessment is to gauge your mastery of
the topics in this chapter. If you do not know the
answer to a question or are only partially sure of the
answer, you should mark that question as wrong for
purposes of self-assessment. Giving yourself credit for
an answer that you correctly guess skews your self-
assessment results and might provide you with a false
sense of security.
1. What is the appropriate way to create a virtual
environment for Python 3?
1. python3 -virtual myvenv
2. python3 virtual myvenv
3. python3 -m vrt myvenv
4. python3 -m venv myvenv
FOUNDATION TOPICS
GETTING STARTED WITH PYTHON
Those from many engineering backgrounds are looking
to integrate programming into their infrastructure.
Maybe you are a hardcore computer science major and
have been programming in multiple languages for years.
You might be an infrastructure engineer who is strong in
the ways of Cisco IOS and looking for new ways to
operate in a diverse environment. You might even be a
server expert who is familiar with Ansible or Terraform
automation and are being asked to bring that automation
knowledge to the networking team. Regardless of your
background or experience level, the DevNet certifications
are designed to help you build the competency needed to
be successful and give you a chance to prove what you
have learned. If you haven’t coded in years, or if the
language that you currently program in isn’t one that is
very popular for infrastructure automation, where do you
start? Python.
The Python language has become the most popular
language in infrastructure automation because it is super
easy to pick up and doesn’t have all of the crazy syntax
and structure that you see in languages like Java or C.
It’s based on the English language and is not only
readable but extendable and powerful enough to be the
one language you can count on to be able to get things
accomplished in your day-to-day life. Those repetitive
tasks that suck your productivity dry can be automated
with just a few lines of code. Plus, due to the popularity
of Python, millions of sample scripts provided by users
like you as well as engineers at Cisco are free on GitHub
for you to use and modify.
Note
Why would a Mac have such an old version of Python?
Well, that’s a question for Apple to answer, but from a
community standpoint, the move to version 3
historically was slow to happen because many of the
Python extensions (modules) where not updated to the
newer version. If you run across code for a 2.x version,
you will find differences in syntax and commands (also
known as the Python standard library) that will
prevent that code from running under 3.x. Python is
not backward compatible without modifications. In
addition, many Python programs require additional
modules that are installed to add functionality to
Python that aren’t available in the standard library. If
you have a program that was written for a specific
module version, but you have the latest version of
Python installed on your machine, the program might
not work properly. You will learn more about common
Python modules and how to use them in Chapter 4,
“Python Functions, Classes, and Modules.”
The use of Python 3 has changed dramatically as support
for the 2.x version ended in January 2020. The 3.x
version came out in 2008 and is the one that you should
be using today. Of course, this version issue is still a
problem even within the 3.x train of Python and the
corresponding modules you may want to use. To address
this compatibility conundrum across different versions
and modules, Python virtual environments have been
created. Such an environment allows you to install a
specific version of Python and packages to a separate
directory structure. This way, you can ensure that the
right modules are loaded, and your applications don’t
break when you upgrade your base Python installation.
As of Python 3.3, there is native support for these virtual
environments built into the Python distribution. You can
code in Python without using virtual environments, but
the minute you update modules or Python itself, you run
the risk of breaking your apps. A virtual environment
allows you to lock in the components and modules you
use for your app into a single “package,” which is a good
practice for building Python apps.
# MacOS or Linux
python3 -m venv myvenv
source myvenv/bin/activate
# Windows
C:\py -3 -m venv myvenv
C:\myvenv\Scripts\activate.bat
(myvenv)$
ansible==2.6.3
black==19.3b0
flake8==3.7.7
genie==19.0.1
ipython==6.5.0
napalm==2.4.0
ncclient==0.6.3
netmiko==2.3.3
pyang==1.7.5
pyats==19.0
PyYAML==5.1
requests==2.21.0
urllib3==1.24.1
virlutils==0.8.4
xmltodict==0.12.0
If you are building your own code and want to save the
current modules configured in your virtual environment,
you can use the freeze command and have it
automatically populate the requirements.txt file:
Readability counts.
Python is a scripted language, which means that any text
editor can become a Python programming environment.
Your choice of editor is completely up to your own
preferences. The easiest way to get started with some
Python code is to just enter python3 at the command
prompt (assuming that Python 3 is installed, of course)
and use the interactive interpreter:
$ python3
>>> print("Savannah rules!")
Savannah rules!
This code will generate a syntax error the minute you try
to run it. Python is expecting to see indentation on the
line after the :. If you insert four spaces before the
print() statement, the code works:
''' This is
line 2
and line 3'''
Variables
Assigning a variable in Python is very straightforward.
Python auto types a variable, and you can reassign that
same variable to another value of a different type in the
future. (Try doing that in C!) You just need to remember
the rules for variable names:
A variable name is case sensitive (so Value and value are two different
variable names).
Data Types
Everything in Python is an object, and depending on the
type of object, there are certain characteristics that you
must be aware of when trying to determine the correct
action you can perform on them. In Python, whenever
you create an object, you are assigning that object an ID
that Python uses to recall what is being stored. This
mechanism is used to point to the memory location of
the object in question and allows you to perform actions
on it, such as printing its value. When the object is
created, it is assigned a type that does not change. This
type is tied to the object and determines whether it is a
string, an integer, or another class.
NameTypeMutableDescription
OperatorDescriptionExampleEvaluates to
* Indicates an exponent 2 ** 2
* 8 5
6
>>> 5 * 6 - 1
29
>>> 5 * (6 - 1)
25
A floating point number is just a whole number with a
decimal point. When you divide in Python, you often get
a remainder that is displayed as a floating point number,
as in this example:
>>> 10 / 7
1.4285714285714286
>>> 10 // 7
1
>>> 10 % 7
3
0b or 0B for binary
0o or 0O for octal
0x or 0X for hex
You can also convert back and forth by using the base
keyword in front of the value you want to exchange, as in
these examples:
>>> hex(195935983)
'0xbadbeef'
>>> bin(195935983)
'0b1011101011011011111011101111'
Booleans
A Boolean has only two possible values, True and False.
You use comparison operators to evaluate between two
Boolean objects in Python. This data type is the
foundation for constructing conditional steps and
decisions within programs. Table 3-4 shows the various
Boolean comparison operators and some examples of
how to use them.
OperatorWhat It DoesExampleEvaluates to
Strings
The string data type is a sequence of characters and uses
quotes to determine which characters are included. The
string ‘Hello’ is just a set of characters that Python
stores in order from left to right. Even if a string contains
a series of numbers, it can still be a string data type. If
you try to add a 1 to a string value, Python gives you an
error, as shown in this example:
>>> '10' + 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to
str
This error tells you that you have to convert the string to
an integer or another data type to be able to use it as a
number (in a math formula, for example). The int()
function can convert a string value into an integer for
you, as shown in this example:
>>> int('10') + 1
11
>>> a='DevNet'
>>> a[0]
'D'
>>> a[0:3]
'Dev'
>>> a[0:6]
'DevNet'
>>> a[:2]
'De'
>>> a[2:]
'vNet'
>>> a[-2:]
'et'
>>> a[:-2]
'DevN'
MethodWhat It Does
Lists
Python, unlike other programming languages, such as
C++ and Java, doesn’t have arrays. If you want to store a
bunch of values, you can use a list. You can use a variable
to store a collection of items in a list. To create a list, you
assign the contents of the list to a variable with the = and
[] and separate the items with commas, as in this
example:
emptylist = []
emptylist2 = list()
Lists are similar to strings in that each is a set of items
indexed by Python that you can interact with and slice
and dice. To pull out values, you just use the variable
name with brackets and the index number, which starts
at 0, as in this example:
>>> print(kids[1])
Sydney
>>> kids
['Caleb', 'Sidney', 'Savannah']
>>> kids[1]="Sydney"
>>> kids
['Caleb', 'Sydney', 'Savannah']
>>>
>>> a = [1, 2, 4]
>>> b = [4, 5, 6]
>>> c = a + b
>>> print(c)
[1, 2, 4, 4, 5, 6]
MethodWhat It Does
Tuples
Tuples and lists are very similar. The biggest difference
between the two comes down to mutability. As discussed
earlier, Python data types are either mutable or
immutable. Lists are mutable, and tuples are immutable.
So why would you need these two types if they are so
similar? It all comes down to how Python accesses
objects and data in memory. When you have a lot of
changes occurring, a mutable data structure is preferred
because you don’t have to create a new object every time
you need to store different values. When you have a value
that is constant and referenced in multiple parts of a
program, an immutable data type (such as a tuple), is
more memory efficient and easier to debug. You don’t
want some other part of your program to make changes
to a crucial piece of data stored in a mutable data type.
>>> person[0]
2012
>>> person[0]=15
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item
assignment
Tuples can, however, be used to assign a set of variables
quickly:
Dictionaries
A dictionary provides another way of creating a
collection of items. Why do you need another way of
storing data when you already have lists and tuples? A
list is an ordered set of items tracked by an index. What
if you need to access data that is tied to a certain value,
such as a person’s name? This capability is exactly why
you need dictionaries in Python. A dictionary saves a ton
of effort by giving you a built-in system for storing data
in a key:value pair. As when you use labels on files in a
filing cabinet, you can assign data to a key and retrieve it
by calling that key as if you are pulling a file from the
cabinet. Dictionaries don’t have any defined order; all
you need is the key—and not some index number—to get
access to your data. There are some rules regarding
dictionaries.
<class 'dict'>
>>> cabinet["scores"]
(98, 76, 95)
>>> cabinet["company"]
'Cisco'
>>> cabinet["address"]
Sets
A set in Python consists of an unordered grouping of
data and is defined by using the curly braces of a
dictionary, without the key:value pairs. Sets are mutable,
and you can add and remove items from the set. You can
create a special case of sets called a frozen set that makes
the set immutable. A frozen set is often used as the
source of keys in a dictionary (which have to be
immutable); it basically creates a template for the
dictionary structure. If you are familiar with how sets
work in mathematics, the various operations you can
perform on mutable sets in Python will make logical
sense. To define a set, do the following:
>>> type(odds)
<class 'set'>
>>> print('Hello\nWorld')
Hello
World
There are numerous codes like this that can control how
text is displayed in a string and how Python interprets
the output. Without them, you would not be able to use,
for example, a backslash in your text output. Here are a
few of the most common ones:
\\: Backslash
\b: Backspace
\t: Tab
\r: Carriage return
for: A for loop is a counting loop that can iterate through data a
specific number of times.
while: The while loop can iterate forever when certain conditions are
met.
If Statements
An if statement starts with an if and then sets up a
comparison to determine the truth of the statement it is
evaluating and ending with a : to tell Python to expect
the clause (the action if the condition is true) block of
code next. As mentioned earlier in this chapter,
whitespace indenting matters very much in Python. The
clause of an if statement must be indented (four spaces
is the standard) from the beginning of the if statement.
The following example looks for a condition where the
variable n is equal to 5 and prints a message to the
console indicating that the number is indeed a 5:
>>> n = 20
>>> if n == 20:
... print('The number is 20')
...
The number is 20
>>> if n == 20:
... print('oops')
File "<stdin>", line 2
print('oops')
^
IndentationError: expected an indented block
>>> n = 3
>>> if n == 17:
... print('Number is 17')
... elif n < 10:
... print('Number is less than 10')
... elif n > 10:
... print('Number is greater than 10')
...
Number is less than 10
For Loops
The for statement allows you to create a loop that
continues to iterate through the code a specific number
of times. It is also referred to as a counting loop and can
work through a sequence of items, such as a list or other
data objects. The for loop is heavily used to parse
through data and is likely to be your go-to tool for
working with data sets. A for loop starts with the for
statement, followed by a variable name (which is a
placeholder used to hold each sequence of data), the in
keyword, some data set to iterate through, and then
finally a closing colon, as shown in this example:
>>> dataset=(1,2,3,4,5)
>>> for variable in dataset:
... print(variable)
...
1
2
3
4
5
The for loop continues through each item in the data set,
and in this example, it prints each item. You can also use
the range() function to iterate a specific number of
times. The range() function can take arguments that let
you choose what number it starts with or stops on and
how it steps through each one. Here is an example:
While Loops
Whereas the for loop counts through data, the while
loop is a conditional loop, and the evaluation of the
condition (as in if statements) being true is what
determines how many times the loop executes. This
difference is huge in that it means you can specify a loop
that could conceivably go on forever, as long as the loop
condition is still true. You can use else with a while
loop. An else statement after a while loop executes
when the condition for the while loop to continue is no
longer met. Example 3-3 shows a count and an else
statement.
>>> count = 1
>>> while (count < 5):
... print("Loop count is:", count)
... count = count + 1
... else:
... print("loop is finished")
...
Loop count is: 1
Loop count is: 2
Loop count is: 3
Loop count is: 4
loop is finished
while True:
string = input('Enter some text to print.
\nType "done" to quit> ')
if string == 'done' :
break
print(string)
print('Done!')
Paragraph Strings 70
ADDITIONAL RESOURCES
Python Syntax:
https://www.w3schools.com/python/python_syntax.a
sp
Caution
The goal of self-assessment is to gauge your mastery of
the topics in this chapter. If you do not know the
answer to a question or are only partially sure of the
answer, you should mark that question as wrong for
purposes of self-assessment. Giving yourself credit for
an answer that you correctly guess skews your self-
assessment results and might provide you with a false
sense of security.
7. What is a method?
1. A variable applied to a class
2. Syntax notation
3. A function within a class or an object
4. Something that is not used in a class
FOUNDATION TOPICS
PYTHON FUNCTIONS
In Python, a function is a named block of code that can
take a wide variety of input parameters (or none at all)
and return some form of output back to the code that
called the function to begin with. It represents a key
concept in programming sometimes referred to as DRY,
which stands for Don’t Repeat Yourself. The idea behind
DRY is that if you perform some particular operations in
your code multiple times, you can simply create a
function to reuse that block of code anywhere you need it
instead of duplicating effort by typing it each time.
Can be any combination of the A–Z, a–z, 0–9 and the underscore (_)
and dash (-)
print('Simple function')
>>> devnet()
Simple function
>>> help(devnet)
Help on function devnet in module __main__:
devnet()
prints simple function
Hello Caleb !
Hello Sydney !
Hello Savannah !
>>> greeting('Caleb')
Hello Caleb, Good morning!
>>> greeting('Sydney', "How are you?")
Hello Sydney, How are you?
OBJECT-ORIENTED PROGRAMMING
AND PYTHON
Python was developed as a modern object-oriented
programming (OOP) language. Object-oriented
programming is a computer programming paradigm that
makes it possible to describe real-world things and their
relationships to each other. If you wanted to describe a
router in the physical world, for example, you would list
all its properties, such as ports, software versions,
names, and IP addresses. In addition, you might list
different capabilities or functions of the router that you
would want to interact with. OOP was intended to model
these types of relationships programmatically, allowing
you to create an object that you can use anywhere in your
code by just assigning it to a variable in order to
instantiate it.
Objects are central to Python; in fact, Python really is
just a collection of objects interacting with each other. An
object is self-contained code or data, and the idea of OOP
is to break up a program into smaller, easier-to-
understand components. Up until now, you have mainly
seen procedural programming techniques, which take a
top-down approach and follow predefined sets of
instructions. While this approach works well for simple
programs, to write more sophisticated applications with
better scalability, OOP is often the preferred method
used by professional programmers. However, Python is
very flexible in that you can mix and match these two
approaches as you build applications.
PYTHON CLASSES
In Python, you use classes to describe objects. Think of a
class as a tool you use to create your own data structures
that contain information about something; you can then
use functions (methods) to perform operations on the
data you describe. A class models how something should
be defined and represents an idea or a blueprint for
creating objects in Python.
Creating a Class
class Router:
'''Router Class'''
def __init__(self, model, swversion, ip_add):
'''initialize values'''
self.model = model
self.swversion = swversion
self.ip_add = ip_add
>>> rtr1.model
'iosV'
class Router:
'''Router Class'''
def __init__(self, model, swversion,
ip_add):
'''initialize values'''
self.model = model
self.swversion = swversion
self.ip_add = ip_add
def getdesc(self):
'''return a formatted description of
the router'''
desc = f'Router Model :
{self.model}\n'\
f'Software Version :
{self.swversion}\n'\
f'Router Management Address:
{self.ip_add}'
return desc
Rtr1
Router Model :iosV
Software Version :15.6.7
Router Management Address:10.10.10.1
Rtr2
Router Model :isr4221
Software Version :16.9.5
Router Management Address:10.10.10.5
Inheritance
class Router:
'''Router Class'''
def __init__(self, model, swversion,
ip_add):
'''initialize values'''
self.model = model
self.swversion = swversion
self.ip_add = ip_add
def getdesc(self):
'''return a formatted description of
the router'''
desc = (f'Router Model :
{self.model}\n'
f'Software Version :
{self.swversion}\n'
f'Router Management Address:
{self.ip_add}')
return desc
class Switch(Router):
def getdesc(self):
'''return a formatted description of
the switch'''
desc = (f'Switch Model :
{self.model}\n'
f'Software Version :
{self.swversion}\n'
f'Switch Management Address:
{self.ip_add}')
return desc
Rtr1
Router Model :iosV
Software Version :15.6.7
Router Management Address:10.10.10.1
Rtr2
Router Model :isr4221
Software Version :16.9.5
Router Management Address:10.10.10.5
Sw1
Switch Model :Cat9300
Software Version :16.9.5
Switch Management Address:10.10.10.8
Importing a Module
All modules are accessed the same way in Python: by
using the import command. Within a program—by
convention at the very beginning of the code—you type
import followed by the module name you want to use.
The following example uses the math module from the
standard library:
>>> dir(math)
NAME
math
MODULE REFERENCE
https://docs.python.org/3.8/library/math
DESCRIPTION
This module provides access to the
mathematical functions
defined by the C standard.
FUNCTIONS
acos(x, /)
Return the arc cosine (measured in
radians) of x.
acosh(x, /)
Return the inverse hyperbolic cosine of
x.
asin(x, /)
Return the arc sine (measured in
radians) of x.
-Snip for brevity-
>>> help(math.sqrt)
Help on built-in function sqrt in module math:
sqrt(x, /)
Return the square root of x.
>>> math.sqrt(15)
3.872983346207417
February 2020
Mo Tu We Th Fr Sa Su
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29
Importing a whole module when you need only a specific
method or function adds unneeded overhead. To help
with this, Python allows you to import specific methods
by using the from syntax. Here is an example of
importing the sqrt() and tan() methods:
As you can see here, you can import more than one
method by separating the methods you want with
commas.
>>> sys.path
['', '/Users/chrijack/Documents',
'/Library/Frameworks/Python.
framework/Versions/3.8/lib/python38.zip',
'/Library/Frameworks/
Python.framework/Versions/3.8/lib/python3.8',
'/Library/Frameworks/
Python.framework/Versions/3.8/lib/python3.8/lib-
dynload', '/
Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/
site-packages']
Rtr1
Router Model :iosV
Software Version :15.6.7
Router Management Address:10.10.10.1
Rtr2
Router Model :isr4221
Software Version :16.9.5
Router Management Address:10.10.10.5
Sw1
Switch Model :Cat9300
Software Version :16.9.5
Router Management Address:10.10.10.8
import sys
import os
import datetime
time: This module allows you to add time-based delays and clock
capabilities to your Python apps. Use the following command to
import this module:
import time
import xmltodict
import csv
import json
import yaml
import requests
import pysnmp
Automation tools:
import napalm
Testing tools:
Paragraph Inheritance 94
Parsing Data: This section discusses how to parse data into native
Python objects.
Unit Testing: This section discusses how to use the internal Python
module unittest to automate Python code testing.
Test-Driven Development 9
Caution
The goal of self-assessment is to gauge your mastery of
the topics in this chapter. If you do not know the
answer to a question or are only partially sure of the
answer, you should mark that question as wrong for
purposes of self-assessment. Giving yourself credit for
an answer that you correctly guess skews your self-
assessment results and might provide you with a false
sense of security.
FOUNDATION TOPICS
FILE INPUT AND OUTPUT
Pulling data from a file in Python is very straightforward.
To extract data from a text file, you can use native
Python capabilities. Binary files, on the other hand, need
to be processed by some module or another external
program before it is possible to extract the data from
them. The vast majority of your needs will be addressed
through text files, so that is what this section focuses on.
readdata.close()
This is much simpler code, and you can use all of the
same methods to interact with the files as before. To
write to a file, you can use the same structure, but in this
case, because you want to append some data to the file,
you need to change how you open the file to allow for
writing. In this example, you can use "a+" to allow
reading and appending to the end of the file. Here is
what the code would look like:
PARSING DATA
Imagine a world where all the data is in nice, neatly
formatted cells, completely structured, and always
consistent. Unfortunately, data is not so easily accessible,
as there are a multitude of types, structures, and formats.
This is why it is essential that you learn how to parse
data in some of the more common forms within your
Python programs.
"router1","192.168.10.1","Nashville"
"router2","192.168.20.1","Tampa"
"router3","192.168.30.1","San Jose"
>>> sampledata
>>> sampledata[0]
['router1', '192.168.10.1', 'Nashville']
>>> sampledata[0][1]
'192.168.10.1'
Using with, you can iterate through the CSV data and
display information in an easier way:
import csv
csv_list = csv.reader(data)
device = row[0]
location = row[2]
ip = row[1]
print(f"{device} is in {location.rstrip()}
and has IP
{ip}.")
If you want to add a fourth device to the CSV file, you can
follow a process very similar to what you did with text
files. Example 5-1 shows how to add a little interaction
from the command line to fill in the fields and create a
Python list with details on the new router. Instead using
of a reader object, this example uses a writer object to
store the formatted CSV data and then write it to the file.
import csv
{
"interface": {
"name": "GigabitEthernet1",
"description": "Router Uplink",
"enabled": true,
"ipv4": {
"address": [
{
"ip": "192.168.1.1",
"netmask": "255.255.255.0"
}
]
}
}
}
loads(): This will import JSON data from a string for parsing and
manipulating within your program.
dump(): This is used to write JSON data from Python objects to a file.
dumps(): This allows you to take JSON dictionary data and convert it
into a serialized string for parsing and manipulating within Python.
import json
json_dict = json.loads(json_data)
>>> type(json_dict)
<class 'dict'>
>>> print(json_dict)
>>> json_dict["interface"]["description"] =
"Backup Link"
>>> print(json_dict)
Now if you load the file again and print, you can see the
stored changes, as shown in Example 5-3.
<device>
<Hostname>Rtr01</Hostname>
<IPv4>192.168.1.5</IP4>
<IPv6> </IPv6>
</device>
To work with this, you can use the native XML library,
but it has a bit of a learning curve and can be a little hard
to use if you just want to convert XML into something
you can work with in Python. To make it easier, you can
use a module called xmltodict to convert XML into an
ordered dictionary in Python. This is a special class of
dictionary that does not allow elements to change order.
Since dictionaries use key/value pairs, where the
key/value pairs are stored is normally not a problem, but
in the case of XML, order matters. Example 5-5 reads in
the XML from Example 5-4 and converts it to an ordered
dictionary.
import xmltodict
xml_dict = xmltodict.parse(xml_example)
>>> print(xml_dict)
OrderedDict([('interface',
OrderedDict([('@xmlns', 'ietf-interfaces'),
('name',
'GigabitEthernet2'), ('description', 'Wide Area
Network'), ('enabled', 'true'),
('ipv4', OrderedDict([('address',
OrderedDict([('ip', '192.168.0.2'), ('netmask',
'255.255.255.0')]))]))]))])
xml_dict["interface"]["ipv4"]["address"]["ip"] =
"192.168.55.3"
>>> print(xmltodict.unparse(xml_dict,
pretty=True))
<?xml version="1.0" encoding="utf-8"?>
<interface xmlns="ietf-interfaces">
<name>GigabitEthernet2</name>
<description>Wide Area
Network</description>
<enabled>true</enabled>
<ipv4>
<address>
<ip>192.168.55.3</ip>
<netmask>255.255.255.0</netmask>
</address>
</ipv4>
</interface>
---
interface:
name: GigabitEthernet2
description: Wide Area Network
enabled: true
ipv4:
address:
- ip: 172.16.0.2
netmask: 255.255.255.0
Notice that a YAML object has minimal syntax, all data
that is related has the same indentation level, and
key/value pairs are used to store data. YAML can also
represent a list by using the - character to identify
elements, as in the following example of IP addresses.
---
addresses:
- ip: 172.16.0.2
netmask: 255.255.255.0
- ip: 172.16.0.3
netmask: 255.255.255.0
- ip: 172.16.0.4
netmask: 255.255.255.0
import yaml
>>> type(yaml_dict)
<class 'dict'>
>>> yaml_dict
>>> yaml_dict["interface"]["name"] =
"GigabitEthernet1"
>>> print(yaml.dump(yaml_dict,
default_flow_style=False))
interface:
description: Wide Area Network
enabled: true
ipv4:
address:
- ip: 192.168.0.2
netmask: 255.255.255.0
name: GigabitEthernet1
To write these changes back to your file, use the
following code.
x = 0
while True:
try:
filename = input("Which file would you
like to open? :")
with open(filename, "r") as fh:
file_data = fh.read()
except FileNotFoundError:
print(f'Sorry, {filename} doesn't
exist! Please try again.')
else:
print(file_data)
x = 0
break
finally:
x += 1
if x == 3:
print('Wrong filename 3
times.\nCheck name and Rerun.')
break
Here is what the output would look like with three wrong
choices:
TEST-DRIVEN DEVELOPMENT
Test-driven development (TDD) is an interesting concept
that at first glance may seem completely backward. The
idea is that you build a test case first, before any software
has been created or modified. The goal is to streamline
the development process by focusing on only making
changes or adding code that satisfies the goal of the test.
In normal testing, you test after the software is written,
which means you spend your time chasing errors and
bugs more than writing code. By writing the test first,
you spend your time focused on writing only what is
needed and making your code simple, easier to
understand, and hopefully bug free. Figure 5-1 shows the
TDD process in action.
UNIT TESTING
Testing your software is not optional. Every script and
application that you create have to go through testing of
some sort. Maybe it’s just testing your syntax in the
interactive interpreter or using an IDE and trying your
code as you write it. While this is software testing, it’s not
structured and often is not repeatable. Did you test all
options? Did you validate your expectations? What
happens if you send unexpected input to a function?
These are some of the reasons using a structured and
automated testing methodology is crucial to creating
resilient software.
There are other types of testing that you may hear about,
such as integration testing and functional testing. The
differences between these types of testing and unit
testing come down to the scope of the test. As
mentioned, a unit test is testing a small piece of code,
such as a method or function. An integration test, on the
other hand, tests how one software component works
with the rest of the application. It is often used when
modules of an application are developed by separate
teams or when a distributed application has multiple
components working together. A functional test (also
called an end-to-end test) is the broadest in scope from a
testing perspective. This is where the entire system is
tested against the functional specifications and
requirements of the software application. Figure 5-2
shows a testing pyramid to put it in perspective.
Figure 5-2 Testing Pyramid
def area_of_circle(r):
return pi*(r**2)
import unittest
from areacircle import area_of_circle
from math import pi
Next, you need to create a class for your test. You can
name it whatever you want, but you need to inherit
unittest.TestCase from the unittest module. This is
what enables the test function methods to be assigned to
your test class. Next, you can define your first test
function. In this case, you can test various inputs to
validate that the math in your function under test is
working as it should. You will notice a new method called
assertAlmostEqual(), which takes the function you
are testing, passes a value to it, and checks the returned
value against an expected value. You can add a number
of tests to this function. This is what the test now looks
like with the additional code:
class
Test_Area_of_Circle_input(unittest.TestCase):
def test_area(self):
# Test radius >= 0
self.assertAlmostEqual(area_of_circle(1),
pi)
self.assertAlmostEqual(area_of_circle(0),
0)
self.assertAlmostEqual(area_of_circle(3.5),
pi * 3.5**2)
if __name__ == '__main__':
unittest.main()
.
--------------------------------------------------
-----------------
Ran 1 test in 0.000s
OK
The dot at the top shows that 1 test ran (even though you
had multiple checks in the same function) to determine
whether the values submitted produced an error. Since
all are valid for the function, the unit test came back
successfully.
Now you can check to see if a negative number causes a
problem. Create a new function under your previous
test_area function. Name this function test_values.
(The test at the beginning is required, or unittest will
ignore the function and not check it.) You can use the
assertRaises check, which will be looking for a
ValueError exception for the function
area_of_circle, and pass it a value of -1. The following
function can be added to your code:
def test_values(self):
# Test that bad values are caught
self.assertRaises(ValueError,
area_of_circle, -1)
.F
=========================================
FAIL: test_values
(__main__.Test_Area_of_Circle_input)
-----------------------------------------------
-----------------------
Traceback (most recent call last):
File
"/Users/chrijack/Documents/ccnadevnet/test_areacircle.py",
line 14, in
test_values
self.assertRaises(ValueError,
area_of_circle, -1)
AssertionError: ValueError not raised by
area_of_circle
-----------------------------------------------
-----------------------
Ran 2 tests in 0.001s
FAILED (failures=1)
The first check is still good, so you see one dot at the top,
but next to it is a big F for fail. You get a message saying
that the test_value function is where it failed, and see
that your original function did not catch this error. This
means that the code is giving bad results. A radius of -1 is
not possible, but the function gives you the following
output:
>>> area_of_circle(-1)
3.141592653589793
def area_of_circle(r):
if r < 0:
raise ValueError('Negative radius value
error')
return pi*(r**2)
Now when you try the test from the interpreter, you see
an error raised:
File
"/Users/chrijack/Documents/ccnadevnet/areacircle.py",
line 5, in area_of_circle
If you rerun the unit test, you see that it now passes the
new check because an error is raised:
..
--------------------------------------------------
-----------------
Ran 2 tests in 0.000s
OK
ADDITIONAL RESOURCES
Reading Data from a File in Python:
https://developer.cisco.com/learning/lab/coding-
204-reading-a-file/step/1
Application Programming
Interfaces (APIs)
This chapter covers the following topics:
Application Programming Interfaces (APIs): This section
describes what APIs are and what they are used for.
Caution
The goal of self-assessment is to gauge your mastery of
the topics in this chapter. If you do not know the
answer to a question or are only partially sure of the
answer, you should mark that question as wrong for
purposes of self-assessment. Giving yourself credit for
an answer that you correctly guess skews your self-
assessment results and might provide you with a false
sense of security.
Note
RESTful APIs are covered in an upcoming section of
this chapter and in depth in Chapter 7, “RESTful API
Requests and Responses.”
Southbound APIs
If a network operator makes a change to a switch’s
configuration in the management software of the
controller, those changes will then be pushed down to
the individual devices using a southbound API. These
devices can be routers, switches, or even wireless access
points. APIs interact with the components of a network
through the use of a programmatic interface.
Southbound APIs can modify more than just the data
plane on a device.
Note
Chapter 7 provides more detail on HTTP and CRUD
functions as well as response codes.
Note
Cisco DevNet is covered in Chapter 1, “Introduction to
Cisco DevNet Associate Certification.”
Basic Authentication
Basic authentication, illustrated in Figure 6-4, is one of
the simplest and most common authentication methods
used in APIs. The downfall of basic authentication is that
the credentials are passed unencrypted. This means that
if the transport is simple HTTP, it is possible to sniff the
traffic and capture the username and password with little
to no effort. The lack of encryption means that the
credentials are in simple plaintext base 64 encoding in
the HTTP header. However, basic authentication is more
commonly used with SSL or TLS to prevent such attacks.
API Keys
Some APIs use API keys for authentication. An API key
is a predetermined string that is passed from the client to
the server. It is intended to be a pre-shared secret and
should not be well known or easy to guess because it
functions just like a password. Anyone with this key can
access the API in question and can potentially cause a
major outage and gain access to critical or sensitive data.
An API key can be passed to the server in three different
ways:
String
Request header
Cookie
GET /something?api_key=abcdef12345
Note
Later chapters provide detailed examples of the
authentication methods introduced in this chapter.
Custom Tokens
A custom token allows a user to enter his or her
username and password once and receive a unique auto-
generated and encrypted token. The user can then use
this token to access protected pages or resources instead
of having to continuously enter the login credentials.
Tokens can be time bound and set to expire after a
specific amount of time has passed, thus forcing users to
reauthenticate by reentering their credentials. A token is
designed to show proof that a user has previously
authenticated. It simplifies the login process and reduces
the number of times a user has to provide login
credentials. A token is stored in the user’s browser and
gets checked each time the user tries to access
information requiring authentication. Once the user logs
out of the web browser or website, the token is destroyed
so it cannot be compromised. Figure 6-5 provides an
overview of token-based authentication between a client
and a server.
Figure 6-5 Token-Based Authentication Example
Envelope
Header
Body
Fault (optional)
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-
envelope" xmlns:m="http://
www.example.org">
<soap:Header>
</soap:Header>
<soap:Body>
<m:GetStockPrice>
<m:StockName>CSCO</m:StockName>
</m:GetStockPrice>
</soap:Body>
</soap:Envelope>
Fault ElementDescriptionOptional
<env:Envelope
xmlns:env="http://www.w3.org/2003/05/soap-
envelope"
xmlns:m="http://www.example.org/timeouts"
xmlns:xml="http://www.w3.org/XML/1998/namespace">
<env:Body>
<env:Fault>
<env:Code>
<env:Value>env:Sender</env:Value>
<env:Subcode>
<env:Value>m:MessageTimeout</env:Value>
</env:Subcode>
</env:Code>
<env:Reason>
<env:Text xml:lang="en">Sender
Timeout</env:Text>
</env:Reason>
<env:Detail>
<m:MaxTime>P5M</m:MaxTime>
</env:Detail>
</env:Fault>
</env:Body>
</env:Envelope>
Note
The examples used in this chapter are all based on
SOAP version 1.2.
<?xml version="1.0"?>
<methodCall>
<methodName>examples.getStateName</methodName>
<params>
<param>
<value><i4>21</i4></value>
</param>
</params>
</methodCall>
REST Tools: This section covers sequence diagrams and tools such as
Postman, curl, HTTPie, and the Python Requests library that are used
to make basic REST calls.
REST Constraints 6, 7
REST Tools 8
Caution
The goal of self-assessment is to gauge your mastery of
the topics in this chapter. If you do not know the
answer to a question or are only partially sure of the
answer, you should mark that question as wrong for
purposes of self-assessment. Giving yourself credit for
an answer that you correctly guess skews your self-
assessment results and might provide you with a false
sense of security.
FOUNDATION TOPICS
RESTFUL API FUNDAMENTALS
An application programming interface (API) is a
set of functions and procedures intended to be used as an
interface for software components to communicate with
each other. An API may be for a web app, an operating
system, a database system, computer hardware, or any
software library. A common example of an API is the
Google Maps API, which lets you interface with Google
Maps so that you can display maps in your application,
query locations, and so on. Figure 7-1 shows a simple
way to visualize an API.
API Types
APIs can be broadly classified into three categories,
based on the type of work that each one provides:
Private: A private API is for internal use only. This access type gives a
company the most control over its API.
HTTP Basics
A web browser is a classic example of an HTTP client.
Communication in HTTP centers around a concept
called the request/response cycle, in which the client
sends the server a request to do something. The server,
in turn, sends the client a response saying whether or not
the server can do what the client asked. Figure 7-5
provides a very simple illustration of how a client
requests data from a server and how the server responds
to the client.
Method
List of headers
Body
Protocol
Server/host address
Resource
Parameters
MethodExplanation
HTTP MethodOperationExplanation
HTTP Headers
The HTTP headers and parameters provide of a lot of
information that can help you trace issues when you
encounter them. HTTP headers are an essential part of
an API request and response as they represent the
metadata associated with the API request and response.
Headers carry information for the following:
Request authorization
Response caching
Response cookies
In addition, HTTP headers have information about
HTTP connection types, proxies, and so on. Most of
these headers are for managing connections between a
client, a server, and proxies.
Request Headers
The request headers appear as name:value pairs.
Multiple values, separated by commas, can be specified
as follows:
request-header-name: request-header-value1,
request-header-value2, ...
Host: myhouse.cisco.com
Connection: Keep-Alive
Accept: image/gif, image/jpeg, */*
Accept-Language: us-en, fr, cn
Response Headers
The response headers also appear as name:value pairs.
As with request headers, multiple values can be specified
as follows:
response-header-name: response-header-value1,
response-header-value2, ...
Content-Type: text/html
Content-Length: 35
Connection: Keep-Alive
Keep-Alive: timeout=15, max=100
The response message body contains the resource
data requested.
Response Codes
The first line of a response message (that is, the status
line) contains the response status code, which the server
generates to indicate the outcome of the request. Each
status code is a three-digit number:
Status CodeMeaningExplanation
XML
Extensible Markup Language (XML) is a markup
language that encodes information between descriptive
tags. XML is a superset of Hypertext Markup Language
(HTML), which was originally designed to describe the
formatting of web pages served by servers through
HTTP. The encoded information is defined within user-
defined schemas that enable any data to be transmitted
between systems. An entire XML document is stored as
text, and it is both machine readable and human
readable.
JSON
JSON, short for JavaScript Object Notation, is
pronounced like the name “Jason.” The JSON format is
derived from JavaScript object syntax, but it is entirely
text based. It is a key: value data format that is typically
rendered in curly braces {} and square brackets []. JSON
is readable and lightweight, and it is easy for humans to
understand.
String
Number
Object
Array
Null
{
"home": [
"this is my house",
"located in San Jose, CA"
],
"rooms": {
"living_room": "true",
"kitchen": "false",
"study_room": [
{
"size": "20x30"
},
{
"desk": true
},
{
"lights": "On"
}
]
}}
YAML
YAML is an acronym that stands for “YAML Ain’t
Markup Language.” According to the official YAML site
(https://yaml.org), “YAML is a human-friendly data
serialization standard for all programming languages.”
---
home:
- this is my house
- located in San Jose, CA
rooms:
living_room: 'true'
kitchen: 'false'
study_room:
- size: 20x30
- desk: true
- lights: 'On'
Webhooks
Webhooks are user-defined HTTP callbacks. A webhook
is triggered by an event, such as pushing code to a
repository or typing a keyword in a chat window. An
application implementing webhooks sends a POST
message to a URL when a specific event happens.
Webhooks are also referred to as reverse APIs, but
perhaps more accurately, a webhook lets you skip the
request step in the request/response cycle. No request is
required for a webhook, and a webhook sends data when
triggered.
Sequence Diagrams
Now that you understand the fundamentals of REST API
(request, response, and webhooks), authentication, data
exchange, and constraints that go with rest APIs, it’s
time to introduce sequence diagrams. A sequence
diagram models the interactions between various objects
in a single use case. It illustrates how the different parts
of a system interact with each other to carry out a
function and the order in which the interactions occur
when a particular use case is executed. In simpler terms,
a sequence diagram shows how different parts of a
system work in a sequence to get something done.
Figure 7-11 is a sequence diagram for the example we’ve
been looking at, where a user wants to get list of all
rooms in the house. For this example, assume that there
is a web application with a user interface that renders the
list of all the rooms and the various attributes of the
rooms.
REST CONSTRAINTS
REST defines six architectural constraints that make any
web service a truly RESTful API. These are constraints
also known as Fielding’s constraints (see
https://www.ics.uci.edu/~fielding/pubs/dissertation/to
p.htm). They generalize the web’s architectural
principles and represent them as a framework of
constraints or an architectural style. These are the REST
constraints:
Client/server
Stateless
Cache
Uniform interface
Layered system
Code on demand
Client/Server
The client and server exist independently. They must
have no dependency of any sort on each other. The only
information needed is for the client to know the resource
URIs on the server. The interaction between them is only
in the form of requests initiated by the client and
responses that the server sends to the client in response
to requests. The client/server constraint encourages
separation of concerns between the client and the server
and allows them to evolve independently.
Stateless
REST services have to be stateless. Each individual
request contains all the information the server needs to
perform the request and return a response, regardless of
other requests made by the same API user. The server
should not need any additional information from
previous requests to fulfill the current request. The URI
identifies the resource, and the body contains the state of
the resource. A stateless service is easy to scale
horizontally, allowing additional servers to be added or
removed as necessary without worry about routing
subsequent requests to the same server. The servers can
be further load balanced as necessary.
Cache
With REST services, response data must be implicitly or
explicitly labeled as cacheable or non-cacheable. The
service indicates the duration for which the response is
valid. Caching helps improve performance on the client
side and scalability on the server side. If the client has
access to a valid cached response for a given request, it
avoids repeating the same request. Instead, it uses its
cached copy. This helps alleviate some of the server’s
work and thus contributes to scalability and
performance.
Note
GET requests should be cacheable by default. Usually
browsers treat all GET requests as cacheable.
POST requests are not cacheable by default but can be
made cacheable by adding either an Expires header or
a Cache-Control header to the response.
PUT and DELETE are not cacheable at all.
Uniform Interface
The uniform interface is a contract for communication
between a client and a server. It is achieved through four
subconstraints:
Layered System
A layered system further builds on the concept of
client/server architecture. A layered system indicates
that there can be more components than just the client
and the server, and each system can have additional
layers in it. These layers should be easy to add, remove,
or change. Proxies, load balancers, and so on are
examples of additional layers.
Code on Demand
Code on demand is an optional constraint that gives the
client flexibility by allowing it to download code. The
client can request code from the server, and then the
response from the server will contain some code, usually
in the form of a script, when the response is in HTML
format. The client can then execute that code.
URI path versioning: In this strategy, the version number of the API
is included in the URL path.
Pagination
Offset-based pagination
GET /devices?offset=100&limit=10
{
"pagination": {
"offset": 100,
"limit": 10,
"total": 220,
},
"device": [
//...
],
"links": {
"next": "http://myhouse.cisco.com/devices?
offset=110&limit=10",
"prev": "http://myhouse.cisco.com/devices?
offset=90&limit=10"
}
}
Do new calls and requests receive a particular error code and, if so,
which one?
Cache your own data when you need to store specialized values or
rapidly review very large data sets.
REST TOOLS
Understanding and testing REST API architecture when
engaging in software development is crucial for any
development process. The following sections explore a
few of the most commonly used tools in REST API
testing and how to use some of their most important
features. Based on this information, you will get a better
idea of how to determine which one suits a particular
development process the best.
Postman
One of the most intuitive and popular HTTP clients is a
tool called Postman
(https://www.getpostman.com/downloads/). It has a
very simple user interface and is very easy to use, even if
you’re just starting out with RESTful APIs. It can handle
the following:
Creating and executing collections (to group together requests and run
those requests in a predetermined sequence)
curl
curl is an extensive command-line tool that can be
downloaded from https://curl.haxx.se. curl can be used
on just about any platform on any hardware that exists
today. Regardless of what you are running and where,
the most basic curl commands just work.
-d: This option allows you to pass data to the remote server. You can
either embed the data in the command or pass the data using a file.
-H: This option allows you to add an HTTP header to the request.
-c: This option stores data received by the server. You can reuse this
data in subsequent commands with the -b option.
-X: This option allows you to specify the HTTP method, which
normally defaults to GET.
{"args":{},"data":"hello DevNet","files":
{},"form":{},"headers":{"x-forwarded-
proto":"https","host":"postman-
echo.com","content-
length":"12","accept":"*/*","ca
che-control":"no-cache","content-
type":"text/plain","user-
agent":"curl/7.54.0","x-
forwarded-
port":"443"},"json":null,"url":"https://postman-
echo.com/post"}
HTTPie
HTTPie is a modern, user-friendly, and cross-platform
command-line HTTP client written in Python. It is
designed to make CLI interaction with web services easy
and user friendly. Its simple HTTP commands enable
users to send HTTP requests using intuitive syntax.
HTTPie is used primarily for testing, trouble-free
debugging, and interacting with HTTP servers, web
services, and RESTful APIs. For further information on
HTTPie documentation, downloading, and installation,
see https://httpie.org/doc:
$ http https://postman-echo.com/get?test=123
HTTP/1.1 200 OK
Connection: keep-alive
Content-Encoding: gzip
Content-Length: 179
Content-Type: application/json; charset=utf-8
Date: Tue, 27 Aug 2019 05:27:17 GMT
ETag: W/"ed-mB0Pm0M3ExozL3fgwq7UlH9aozQ"
Server: nginx
Vary: Accept-Encoding
set-cookie:
sails.sid=s%3AYCeNAWJG7Kap5wvKPg8HYlZI5SHZoqEf.r7Gi96fe5g7%2FSp0jaJk%2Fa
{
"args": {
"test": "123"
},
"headers": {
"accept": "*/*",
"accept-encoding": "gzip, deflate",
"host": "postman-echo.com",
"user-agent": "HTTPie/1.0.2",
"x-forwarded-port": "443",
"x-forwarded-proto": "https"
},
"url": "https://postman-echo.com/get?
test=123"
}
Python Requests
Requests is a Python module that you can use to send
HTTP requests. It is an easy-to-use library with a lot of
possibilities ranging from passing parameters in URLs to
sending custom headers and SSL verification. The
Requests library is a very handy tool you can use
whenever you programmatically start using any APIs.
Here you will see how to use this library to send simple
HTTP requests in Python as way to illustrate its ease of
use.
You can use Requests with Python versions 2.7 and 3.x.
Requests is an external module, so it needs to be
installed before you can use it. Example 7-11 shows the
command you use to install the Requests package for
Python.
import requests
url = "https://postman-echo.com/get"
querystring = {"test":"123"}
headers = {}
response = requests.request("GET", url,
headers=headers, params=querystring)
print(response.text)
import requests
url = "https://postman-echo.com/post"
payload = "hello DevNet"
headers = {'content-type': "text/plain"}
response = requests.request("POST", url,
data=payload, headers=headers)
print(response.text)
import requests
url = "https://postman-echo.com/basic-auth"
headers = {
'authorization': "Basic
cG9zdG1hbjpwYXNzd29yZA=="
}
response = requests.request("GET", url,
headers=headers)
print(response.text)
Paragrap Pagination 16
h 2
API
REST
CRUD
YAML
JSON
webhook
Chapter 8
Cisco Meraki: This section covers the Cisco Meraki platform and the
REST APIs it exposes.
Cisco DNA Center: This section covers Cisco DNA Center and the
REST APIs that it publicly exposes.
Cisco SD-WAN: This section covers Cisco SD-WAN and the REST
APIs exposed through Cisco vManage.
Caution
The goal of self-assessment is to gauge your mastery of
the topics in this chapter. If you do not know the
answer to a question or are only partially sure of the
answer, you should mark that question as wrong for
purposes of self-assessment. Giving yourself credit for
an answer that you correctly guess skews your self-
assessment results and might provide you with a false
sense of security.
FOUNDATION TOPICS
WHAT IS AN SDK?
An SDK (software development kit) or devkit is a set of
software development tools that developers can use to
create software or applications for a certain platform,
operating system, computer system, or device. An SDK
typically contains a set of libraries, APIs, documentation,
tools, sample code, and processes that make it easier for
developers to integrate, develop, and extend the
platform. An SDK is created for a specific programming
language, and it is very common to have the same
functionality exposed through SDKs in different
programming languages.
Is easy to use
Is well documented
Quicker integration
Brand control
Increased security
Metrics
CISCO MERAKI
Meraki became part of Cisco following its acquisition in
2012. The Meraki portfolio is large, comprising wireless,
switching, security, and video surveillance products. The
differentiating factor for Meraki, compared to similar
products from Cisco and other vendors, is that
management is cloud based. Explore all the current Cisco
Meraki products and offerings at
https://meraki.cisco.com.
From a programmability perspective, the Meraki cloud
platform provides several APIs:
Scanning API
Dashboard API
Organizations
Networks
Devices
Uplink
curl -I -X GET \
--url
'https://api.meraki.com/api/v0/organizations' \
-H 'X-Cisco-Meraki-API-Key:
15da0c6ffff295f16267f88f98694cf29a86ed87'
You can see in Example 8-1 that the response code for
the request is 302. This indicates a redirect to the URL
value in the Location header. Redirects like the one in
Example 8-1 can occur with any API call within the
Dashboard API, including POST, PUT, and DELETE. For
GET calls, the redirect is specified through a 302 status
code, and for any non-GET calls, the redirects are
specified with 307 or 308 status codes. When you specify
the -I option for curl, only the headers of the response
are displayed to the user. At this point, you need to run
the curl command again but this time specify the
resource as
https://n149.meraki.com/api/v0/organizations, remove
the -I flag, and add an Accept header to specify that the
response to the call should be in JSON format. The
command should look like this:
curl -X GET \
--url
'https://n149.meraki.com/api/v0/organizations' \
-H 'X-Cisco-Meraki-API-Key:
15da0c6ffff295f16267f88f98694cf29a86ed87'\
-H 'Accept: application/json'
[
{
"name" : "DevNet Sandbox",
"id" : "549236"
}
]
curl -X GET \
--url
'https://n149.meraki.com/api/v0/organizations/549236/
networks' \
-H 'X-Cisco-Meraki-API-Key:
15da0c6ffff295f16267f88f98694c
f29a86ed87'\
-H 'Accept: application/json'
The response from the API should contain a list of all the
networks that are part of the DevNet Sandbox
organization and should look similar to the output in
Example 8-2.
[
{
"timeZone" : "America/Los_Angeles",
"tags" : " Sandbox ",
"organizationId" : "549236",
"name" : "DevNet Always On Read Only",
"type" : "combined",
"disableMyMerakiCom" : false,
"disableRemoteStatusPage" : true,
"id" : "L_646829496481099586"
},
{
"organizationId" : "549236",
"tags" : null,
"timeZone" : "America/Los_Angeles",
"id" : "N_646829496481152899",
"disableRemoteStatusPage" : true,
"name" : "test - mx65",
"disableMyMerakiCom" : false,
"type" : "appliance"
}, ... omitted output
Now you can try to get the same information—a list of all
the networks that are part of the DevNet Sandbox
organization—by using Postman. As you’ve seen,
Postman by default does the redirection automatically,
so you can specify the API endpoint as
https://api.meraki.com/api/v0/organizations/549236/n
etworks. You need to make sure to specify the GET
method, the X-Cisco-Meraki-API-Key header for
authentication, and the Accept header, in which you
specify that you would like the response from the API to
be in JSON format. Figure 8-2 shows the Postman client
interface with all the information needed to obtain a list
of all the networks that belong to the organization with
ID 549236.
Figure 8-2 GET Networks REST API Call in
Postman
Next, you can obtain a list of all devices that are part of
the network that has the name “DevNet Always On Read
Only” and ID L_646829496481099586. Much as in the
previous steps, you start by checking the API
documentation to find the API endpoint that will return
this data to you. The API resource that contains the
information you are looking for is
/networks/{networkId}/devices, as you can see from the
API documentation at the following link:
https://developer.cisco.com/meraki/api/#/rest/api-
endpoints/devices/get-network-devices. You add the
base URL for the DevNet Sandbox account,
https://n149.meraki.com/api/v0, and populate
{networkId} with the value you obtained in the previous
step. Combining all this information, the endpoint that
will return the information you are seeking is
https://n149.meraki.com/api/v0/networks/L_6468294
96481099586/devices. The curl command in this case is
as follows:
curl -X GET \
--url
'https://n149.meraki.com/api/v0/networks/L_646829496481099586/
devices' \
-H 'X-Cisco-Meraki-API-Key:
15da0c6ffff295f16267f88f98694cf29a86ed87'\
-H 'Accept: application/json'
[
{
"wan2Ip" : null,
"networkId" : "L_646829496481099586",
"lanIp" : "10.10.10.106",
"serial" : "QYYY-WWWW-ZZZZ",
"tags" : " recently-added ",
"lat" : 37.7703718,
"lng" : -122.3871248,
"model" : "MX65",
"mac" : "e0:55:3d:17:d4:23",
"wan1Ip" : "10.10.10.106",
"address" : "500 Terry Francois, San
Francisco"
},
{
"switchProfileId" : null,
"address" : "",
"lng" : -122.098531723022,
"model" : "MS220-8P",
"mac" : "88:15:44:df:f3:af",
"tags" : " recently-added ",
"serial" : "QAAA-BBBB-CCCC",
"networkId" : "L_646829496481099586",
"lanIp" : "192.168.128.2",
"lat" : 37.4180951010362
}
]
#! /usr/bin/env python
from meraki_sdk.meraki_sdk_client import
MerakiSdkClient
PARAMS = {}
PARAMS["organization_id"] = "549236" # Demo
Organization "DevNet Sandbox"
Finally, you get the list of devices that are part of the
network and have the ID L_646829496481099586.
Recall from earlier that this ID is for the “DevNet Always
on Read Only” network. In this case, you use the
devices.get_network_devices() method of the
Meraki API client instance and store the result in the
DEVICES variable. You iterate over the DEVICES
variable and, for each device in the list, extract and print
to the console the device model, the serial number, the
MAC address, and the firmware version.
Intent API
Integration API
Multivendor SDK
With the Site Hierarchy Intent API, you can get information about,
create, update, and delete sites as well as assign devices to a
specific site. (Sites within Cisco DNA Center are logical groupings
of network devices based on a geographic location or site.)
The Site Profile Intent API gives you the option to provision NFV
and ENCS devices as well as retrieve the status of the provisioning
activities.
The Plug and Play (PnP) API enables you to manage all PnP-
related workflows. With this API, you can create, update, and
delete PnP workflows and PnP server profiles, claim and unclaim
devices, add and remove virtual accounts, and retrieve information
about all PnP-related tasks.
The Path Trace API provides access to the Path Trace application
in Cisco DNA Center. Path Trace can be used to troubleshoot and
trace application paths throughout the network and provide
statistics at each hop. The API gives you access to initiating,
retrieving, and deleting path traces.
The File API enables you to retrieve files such as digital certificates,
maps, and SWIM files from Cisco DNA Center.
The Task API provides information about the network actions that
are being run asynchronously. Each of these background actions
can take from seconds to minutes to complete, and each has a task
associated with it. You can query the Task API about the
completion status of these tasks, get the task tree, retrieve tasks by
their IDs, and so on.
The Tag API gives you the option of creating, updating, and
deleting tags as well as assigning tags to specific devices. Tags are
very useful in Cisco DNA Center; they are used extensively to group
devices by different criteria. You can then apply policies and
provision and filter these groups of devices based on their tags.
So far in this section, we’ve covered all the APIs and the
multivendor SDK offered by Cisco DNA Center. Next, we
will start exploring the Intent API, using Cisco DNA
Center version 1.3 for the rest of the chapter. As API
resources and endpoints exposed by the Cisco DNA
Center platform might change in future versions of the
software, it is always best to start exploring the API
documentation for any Cisco product at
https://developer.cisco.com/docs/dna-center/api/1-3-0-
x/.
curl -X POST \
https://sandboxdnac2.cisco.com/dna/system/api/v1/auth/token
\
-H 'Authorization: Basic
ZGV2bmV0dXNlcjpDaXNjbzEyMyE='
{"Token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI1Y2U3M-
TJiMDhlZTY2MjAyZmEyZWI4ZjgiLCJhdXRoU291cmNlIjoiaW50ZXJuYWwiL-
CJ0ZW5hbnROYW1lIjoiVE5UMCIsInJvbGVzIjpbIjViNmNmZGZmNDMwOTkwM-
DA4OWYwZmYzNyJdLCJ0ZW5hbnRJZCI6IjViNmNmZGZjNDMwOTkwMDA4OWYwZ-
mYzMCIsImV4cCI6MTU2NjU0Mzk3OCwidXNlcm5hbWUiOiJkZXZuZXR1c2VyIn0.
Qv6vU6d1tqFGx9GETj6SlDa8Ts6uJNk9624onLSNSnU"}
"Token":
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI1
Y2U3MTJiMDhlZ-
TY2MjAyZmEyZWI4ZjgiLCJhdXRoU291cmNlIjoiaW50ZXJuYWw
iLCJ0ZW5hbnROY-
W1lIjoiVE5UMCIsInJvbGVzIjpbIjViNmNmZGZmNDMwOTkwMDA
4OWYwZmYzNyJdL-
CJ0ZW5hbnRJZCI6IjViNmNmZGZjNDMwOTkwMDA4OWYwZmYzMCI
sImV4cCI6MTU2N-
jU5NzE4OCwidXNlcm5hbWUiOiJkZXZuZXR1c2VyIn0.ubXSmZY
rI-yoCWmzCSY486y-
HWhwdTlnrrWqYip5lv6Y"
Let’s now get a list of all the network devices that are
being managed by the instance of Cisco DNA Center that
is running in the always-on DevNet Sandbox you’ve just
authorized with. If you verify the Cisco DNA Center API
documentation on
https://developer.cisco.com/docs/dna-center/api/1-3-0-
x/, you can see that the API resource that will return a
complete list of all network devices managed by Cisco
DNA Center is /dna/intent/api/v1/network-device.
Figure 8-7 shows the online documentation for Cisco
DNA Center version 1.3.
Figure 8-7 Cisco DNA Center Platform API
Documentation (https://developer.cisco.com)
With all this information in mind, you can craft the curl
request to obtain a list of all the network devices
managed by the Cisco DevNet always-on DNA Center
Sandbox. The complete URL is
https://sandboxdnac2.cisco.com/dna/intent/api/v1/net
work-device. You need to retrieve information through
the API, so we need to do a GET request; don’t forget the
X-Auth-Token header containing the authorization
token. The curl command should look as follows, and it
should contain a valid token:
curl -X GET \
https://sandboxdnac2.cisco.com/dna/intent/api/v1/network-
device \
-H 'X-Auth-Token:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJzdWIiOiI1Y2U3MTJiMDhlZTY2MjAyZmEyZWI4ZjgiLCJhdXRoU291c-
mNlIjoiaW50ZXJuYWwiLCJ0ZW5hbnROYW1lIjoiVE5UMCIsInJvbGVzIjpbI-
jViNmNmZGZmNDMwOTkwMDA4OWYwZmYzNyJdLCJ0ZW5hbnRJZCI6IjViNmNmZG-
ZjNDMwOTkwMDA4OWYwZmYzMCIsImV4cCI6MTU2NjYwODAxMSwidXNlcm5hbWUiOi-
JkZXZuZXR1c2VyIn0.YXc_2o8FDzSQ1YBhUxUIoxwzYXXWYeNJRkB0oKBlIHI'
The response to this curl command should look as
shown in Example 8-5.
{
"response" : [
{
"type" : "Cisco 3504 Wireless LAN
Controller",
"roleSource" : "AUTO",
"apManagerInterfaceIp" : "",
"lastUpdateTime" : 1566603156991,
"inventoryStatusDetail" : "<status>
<general code=\"SUCCESS\"/></status>",
"collectionStatus" : "Managed",
"serialNumber" : "FCW2218M0B1",
"location" : null,
"waasDeviceMode" : null,
"tunnelUdpPort" : "16666",
"reachabilityStatus" : "Reachable",
"lastUpdated" : "2019-08-23 23:32:36",
"tagCount" : "0",
"series" : "Cisco 3500 Series Wireless
LAN Controller",
"snmpLocation" : "",
"upTime" : "158 days, 13:59:36.00",
"lineCardId" : null,
"id" : "50c96308-84b5-43dc-ad68-
cda146d80290",
"reachabilityFailureReason" : "",
"lineCardCount" : null,
"managementIpAddress" : "10.10.20.51",
"memorySize" : "3735302144",
"errorDescription" : null,
"snmpContact" : "",
"family" : "Wireless Controller",
"platformId" : "AIR-CT3504-K9",
"role" : "ACCESS",
"softwareVersion" : "8.5.140.0",
"hostname" : "3504_WLC",
"collectionInterval" : "Global
Default",
"bootDateTime" : "2019-01-19
02:33:05",
"instanceTenantId" : "SYS0",
"macAddress" : "50:61:bf:57:2f:00",
"errorCode" : null,
"locationName" : null,
"softwareType" : "Cisco Controller",
"associatedWlcIp" : "",
"instanceUuid" : "50c96308-84b5-43dc-
ad68-cda146d80290",
"interfaceCount" : "8"
},
... omitted output
],
"version" : "1.0"
}
Now you will see how to obtain the same information you
just got with curl but now using Postman. The same API
endpoint URL is used:
https://sandboxdnac2.cisco.com/dna/intent/api/v1/net
work-device. In this case, it is a GET request, and the X-
Auth-Token header is specified under the Headers tab
and populated with a valid token. If you click Send and
there aren’t any mistakes with the request, the status
code should be 200 OK, and the body of the response
should be very similar to that obtained with the curl
request. Figure 8-8 shows how the Postman interface
should look in this case.
Now you can try to obtain some data about the clients
that are connected to the network managed by Cisco
DNA Center. Much like network devices, network clients
have associated health scores, provided through the
Assurance feature to get a quick overview of client
network health. This score is based on several factors,
including onboarding time, association time, SNR
(signal-to-noise ratio), and RSSI (received signal
strength indicator) values for wireless clients,
authentication time, connectivity and traffic patterns,
and number of DNS requests and responses. In the API
documentation, you can see that the resource providing
the health status of all clients connected to the network is
/dna/intent/api/v1/client-health. This API call requires
a parameter to be specified when performing the call.
This parameter, called timestamp, represents the UNIX
epoch time in milliseconds. UNIX epoch time is a system
for describing a point in time since January 1, 1970, not
counting leap seconds. It is extensively used in UNIX
and many other operating systems. The timestamp
provides the point in time for which the client health
information should be returned in the API response. For
example, if I retrieved the health status of all the clients
connected to the network on Thursday, August 22, 2019
8:41:29 PM GMT, the UNIX time, in milliseconds, would
be 1566506489000. Keep in mind that based on the data
retention policy set in Cisco DNA Center, client data
might not be available for past distant timeframes.
With the information you now have, you can build the
API endpoint to process the API call:
https://sandboxdnac2.cisco.com/dna/intent/api/v1/clie
nt-health?timestamp=1566506489000. The
authorization token also needs to be included in the call
as a value in the X-Auth-Token header. The curl
command should look as follows:
curl -X GET \
https://sandboxdnac2.cisco.com/dna/intent/api/v1/client-
health?timestamp=1566506489000 \
-H 'X-Auth-Token:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJzdWIiOiI1Y2U3MTJiMDhlZTY2MjAyZmEyZWI4ZjgiLCJhdXRoU291c
mNlIjoiaW50ZXJuYWwiLCJ0ZW5hbnROYW1lIjoiVE5UMCIsInJvbGVzIjpbI
jViNmNmZGZmNDMwOTkwMDA4OWYwZmYzNyJdLCJ0ZW5hbnRJZCI6IjViNmNmZG-
ZjNDMwOTkwMDA4OWYwZmYzMCIsImV4cCI6MTU2NjYxODkyOCwidXNlcm5hbWUiO
iJkZXZuZXR1c2VyIn0.7JNXdgSMi3Bju8v8QU_L5nmBKYOTivinAjP8ALT_opw'
From this response, you can see that there are a total of
82 clients in the network, and the average health score
for all of them is 27. To further investigate why the
health scores for some of the clients vary, you can look
into the response to the /dna/intent/api/v1/client-detail
call. This API call takes as input parameters the
timestamp and the MAC address of the client, and it
returns extensive data about the status and health of that
specific client at that specific time.
Now you can try to perform the same API call but this
time with Postman. The API endpoint stays the same:
https://sandboxdnac2.cisco.com/dna/intent/api/v1/clie
nt-health?timestamp=1566506489000. In this case, you
are trying to retrieve information from the API, so it will
be a GET call, and the X-Auth-Token header contains a
valid token value. Notice that the Params section of
Postman gets automatically populated with a timestamp
key, with the value specified in the URL:
1566506489000. Click Send, and if there aren’t any
errors with the API call, the body of the response should
be very similar to the one obtained previously with curl.
The Postman window for this example should look as
shown in Figure 8-9.
Figure 8-9 Viewing Client Health in Cisco DNA
Center
{
"response" : [ {
"siteId" : "global",
"scoreDetail" : [ {
"scoreCategory" : {
"scoreCategory" : "CLIENT_TYPE",
"value" : "ALL"
},
"scoreValue" : 27,
"clientCount" : 82,
"clientUniqueCount" : 82,
"starttime" : 1566506189000,
"endtime" : 1566506489000,
"scoreList" : [ ]
}, ... output omitted
}
#! /usr/bin/env python
from dnacentersdk import api
base_url="https://sandboxdnac2.cisco.com")
CISCO SD-WAN
Cisco SD-WAN (Software-Defined Wide Area Network)
is a cloud-first architecture for deploying WAN
connectivity. Wide-area networks have been deployed for
a long time, and many lessons and best practices have
been learned throughout the years. Applying all these
lessons to software-defined networking (SDN) resulted
in the creation of Cisco SD-WAN. An important feature
of SDN is the separation of the control plane from the
data plane.
vSmart: Cisco vSmart is the brains of the centralized control plane for
the overlay SD-WAN network. It maintains a centralized routing table
and centralized routing policy that it propagates to all the network Edge
devices through permanent DTLS tunnels.
vEdge: Cisco vEdge routers, as the name implies, are Edge devices that
are located at the perimeter of the fabric, such as in remote offices, data
centers, branches, and campuses. They represent the data plane and
bring the whole fabric together and route traffic to and from their site
across the overlay network.
curl -c - -X POST -k \
https://sandboxsdwan.cisco.com:8443/j_security_check
\
-H 'Content-Type: application/x-www-form-
urlencoded' \
-d 'j_username=devnetuser&j_password=Cisco123!'
# https://curl.haxx.se/docs/http-cookies.html
https://sandboxsdwan.cisco.com:8443/dataservice/device
\
-H 'Cookie:
JSESSIONID=v9QcTVL_ZBdIQZRsI2V95vBi7Bz47IMxRY3XAYA6.4
854266f-a8ad-4068-9651-d4e834384f51'
{
... omitted output
"data" : [
{
"state" : "green",
"local-system-ip" : "4.4.4.90",
"status" : "normal",
"latitude" : "37.666684",
"version" : "18.3.1.1",
"model_sku" : "None",
"connectedVManages" : [
"\"4.4.4.90\""
],
"statusOrder" : 4,
"uuid" : "4854266f-a8ad-4068-9651-
d4e834384f51",
"deviceId" : "4.4.4.90",
"reachability" : "reachable",
"device-groups" : [
"\"No groups\""
],
"total_cpu_count" : "2",
"certificate-validity" : "Valid",
"board-serial" : "01",
"platform" : "x86_64",
"device-os" : "next",
"timezone" : "UTC",
"uptime-date" : 1567111260000,
"host-name" : "vmanage",
"device-type" : "vmanage",
"personality" : "vmanage",
"domain-id" : "0",
"isDeviceGeoData" : false,
"lastupdated" : 1567470387553,
"site-id" : "100",
"controlConnections" : "5",
"device-model" : "vmanage",
"validity" : "valid",
"system-ip" : "4.4.4.90",
"state_description" : "All daemons
up",
"max-controllers" : "0",
"layoutLevel" : 1,
"longitude" : "-122.777023"
},
... omitted output
]
}
curl -X GET -k \
https://sandboxsdwan.cisco.com:8443/dataservice/template/device
\
-H 'Cookie:
JSESSIONID=v9QcTVL_ZBdIQZRsI2V95vBi7Bz47IMxRY3XAYA6.48
54266f-a8ad-4068-9651-d4e834384f51'
{
"data" : [
{
"templateDescription" : "VEDGE BASIC
TEMPLATE01",
"lastUpdatedOn" : 1538865915509,
"templateAttached" : 15,
"deviceType" : "vedge-cloud",
"templateId" : "72babaf2-68b6-4176-
92d5-fa8de58e19d8",
"configType" : "template",
"devicesAttached" : 0,
"factoryDefault" : false,
"templateName" :
"VEDGE_BASIC_TEMPLATE",
"lastUpdatedBy" : "admin"
}
],
... output omitted
}
#! /usr/bin/env python
import json
import requests
from requests.packages.urllib3.exceptions
import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
BASE_URL_STR =
'https://{}:8443/'.format(VMANAGE_IP)
DEVICE_RESPONSE = SESS.get(DEVICE_URL,
verify=False)
DEVICE_ITEMS =
json.loads(DEVICE_RESPONSE.content)['data']
print('{0:20s}{1:1}{2:12s}{3:1}{4:36s}{5:1}
{6:16s}{7:1}{8:7s}'\
.format("Host-Name", "|", "Device Model",
"|", "Device ID", \
"|", "System IP", "|", "Site ID"))
print('-'*105)
TEMPLATE_RESPONSE = SESS.get(TEMPLATE_URL,
verify=False)
TEMPLATE_ITEMS =
json.loads(TEMPLATE_RESPONSE.content)['data']
print('{0:20s}{1:1}{2:12s}{3:1}{4:36s}{5:1}
{6:16s}{7:1}{8:7s}'\
.format("Template Name", "|", "Device
Model", "|", "Template ID", \
"|", "Attached devices", "|", "Template
Version"))
print('-'*105)
The code specifies the API resource that will return a list
of all the devices in the SD-WAN fabric:
dataservice/device. The complete URL to retrieve the
devices in the fabric is built on the next line by
combining the base URL with the new resource. The
DEVICE_URL variable will look like
https://sandboxsdwan.cisco.com:8443/dataservice/devi
ce. Next, the same session that was established earlier is
used to perform a GET request to the device_url
resource. The result of this request is stored in the
variable aptly named DEVICE_RESPONSE, which
contains the same JSON-formatted data that was
obtained in the previous curl and Postman requests,
with extensive information about all the devices that are
part of the SD-WAN fabric. From that JSON data, only
the list of devices that are values of the data key are
extracted and stored in the DEVICE_ITEMS variable.
L Advantages of SDKs 1
i 7
s 7
t
Cisco UCS Manager: This section covers Cisco UCS Manager and the
public APIs that come with it.
Cisco UCS Director: This section goes over Cisco UCS Director and
its APIs.
Caution
The goal of self-assessment is to gauge your mastery of
the topics in this chapter. If you do not know the
answer to a question or are only partially sure of the
answer, you should mark that question as wrong for
purposes of self-assessment. Giving yourself credit for
an answer that you correctly guess skews your self-
assessment results and might provide you with a false
sense of security.
FOUNDATION TOPICS
CISCO ACI
Cisco Application Centric Infrastructure (ACI) is the
SDN-based solution from Cisco for data center
deployment, management, and monitoring. The solution
is based on two components: the Cisco Nexus family of
switches and Cisco Application Policy Infrastructure
Controller (APIC).
Cloud APIC appliance for Cisco cloud ACI deployments in public cloud
environments
https://APIC_Host:port/api/{mo|class}/{dn|clas
sname}.{xml|json}?[options]
curl -k -X POST \
https://sandboxapicdc.cisco.com/api/aaaLogin.json
\
-d '{
"aaaUser" : {
"attributes" : {
"name" : "admin",
"pwd" : "ciscopsdt"
}
}
}'
{
"totalCount" : "1",
"imdata" : [
{
"aaaLogin" : {
"attributes" : {
"remoteUser" : "false",
"firstLoginTime" : "1572128727",
"version" : "4.1(1k)",
"buildTime" : "Mon May 13
16:27:03 PDT 2019",
"siteFingerprint" :
"Z29SSG/BAVFY04Vv",
"guiIdleTimeoutSeconds" :
"1200",
"firstName" : "",
"userName" : "admin",
"refreshTimeoutSeconds" : "600",
"restTimeoutSeconds" : "90",
"node" : "topology/pod-1/node-
1",
"creationTime" : "1572128727",
"changePassword" : "no",
"token" :
"pRgAAAAAAAAAAAAAAAAAAGNPf39fZd71fV6DJWidJoqxJmHt1Fephm-
w6Q0I5byoafVMZ29a6pL+4u5krJ0G2Jdrvl0l2l9cMx/o0ciIbVRfFZruCEgqsPg8+dbjb8kWX02FJLcw9Qp
sg98s5QfOaMDQWHSyqwOObKOGxxglLeQbkgxM8/fgOAFZxbKHMw0+09ihdiu7jTb7AAJVZEzYzXA==",
"unixUserId" : "15374",
"lastName" : "",
"sessionId" :
"1IZw4uthRVSmyWWH/+S9aA==",
"maximumLifetimeSeconds" :
"86400"
}
...omitted output
}
Next, let’s get a list of all the ACI fabrics that are being
managed by this APIC instance. The URI for this GET
operation is
https://sandboxapicdc.cisco.com/api/node/class/fabric
Pod.json, and the APIC-cookie header, are specified for
authentication purposes. The curl request should look
similar to the one shown in Example 9-3.
https://sandboxapicdc.cisco.com/api/node/class/fabricPod.json
\
-H 'Cookie: APIC-
cookie=pRgAAAAAAAAAAAAAAAAAAGNPf39fZd71fV6DJWidJoqxJmHt1Fephmw6Q0
I5byoafVMZ29a6pL+4u5krJ0G2Jdrvl0l2l9cMx/o0ciIbVRfFZruCEgqsPg8+dbjb8kWX02FJLcw9Qpsg
98s5QfOaMDQWHSyqwOObKOGxxglLeQbkgxM8/fgOAFZxbKHMw0+09ihdiu7jTb7AAJVZEzYzXA=='
{
"totalCount" : "1",
"imdata" : [
{
"fabricPod" : {
"attributes" : {
"id" : "1",
"monPolDn" : "uni/fabric/monfab-
default",
"dn" : "topology/pod-1",
"status" : "",
"childAction" : "",
"modTs" : "2019-10-
26T18:01:13.491+00:00",
"podType" : "physical",
"lcOwn" : "local"
}
}
}
]
}
curl -k -X GET \
https://sandboxapicdc.cisco.com/api/node/class/topology/pod-
1/topSystem.json \
-H 'Cookie: APIC-
cookie=pRgAAAAAAAAAAAAAAAAAAGNPf39fZd71fV6DJWidJoqxJmHt1Fephmw6Q0
I5byoafVMZ29a6pL+4u5krJ0G2Jdrvl0l2l9cMx/o0ciIbVRfFZruCEgqsPg8+dbjb8kWX02FJLcw9Qpsg
98s5QfOaMDQWHSyqwOObKOGxxglLeQbkgxM8/fgOAFZxbKHMw0+09ihdiu7jTb7AAJVZEzYzXA=='
{
"imdata" : [
{
"topSystem" : {
"attributes" : {
"role" : "controller",
"name" : "apic1",
"fabricId" : "1",
"inbMgmtAddr" : "192.168.11.1",
"oobMgmtAddr" : "10.10.20.14",
"systemUpTime" :
"00:04:33:38.000",
"siteId" : "0",
"state" : "in-service",
"fabricDomain" : "ACI Fabric1",
"dn" : "topology/pod-1/node-
1/sys",
"podId" : "1"
}
}
},
{
"topSystem" : {
"attributes" : {
"state" : "in-service",
"siteId" : "0",
"address" : "10.0.80.64",
"fabricDomain" : "ACI Fabric1",
"dn" : "topology/pod-1/node-
101/sys",
"id" : "101",
"podId" : "1",
"role" : "leaf",
"fabricId" : "1",
"name" : "leaf-1"
}
}
},
{
"topSystem" : {
"attributes" : {
"podId" : "1",
"id" : "102",
"dn" : "topology/pod-1/node-
102/sys",
"address" : "10.0.80.66",
"fabricDomain" : "ACI Fabric1",
"siteId" : "0",
"state" : "in-service",
"role" : "leaf",
"name" : "leaf-2",
"fabricId" : "1"
}
}
},
{
"topSystem" : {
"attributes" : {
"fabricId" : "1",
"name" : "spine-1",
"role" : "spine",
"podId" : "1",
"id" : "201",
"dn" : "topology/pod-1/node-
201/sys",
"state" : "in-service",
"siteId" : "0",
"fabricDomain" : "ACI Fabric1",
"address" : "10.0.80.65"
}
}
}
],
"totalCount" : "4"
}
#! /usr/bin/env python
import sys
import acitoolkit.acitoolkit as aci
APIC_URL = 'https://sandboxapicdc.cisco.com'
USERNAME = 'admin'
PASSWORD = 'ciscopsdt'
# Login to APIC
SESSION = aci.Session(APIC_URL, USERNAME,
PASSWORD)
RESP = SESSION.login()
if not RESP.ok:
print('Could not login to APIC')
sys.exit()
ENDPOINTS = aci.Endpoint.get(SESSION)
print('{0:19s}{1:14s}{2:10s}{3:8s}{4:17s}
{5:10s}'.format(
"MAC ADDRESS",
"IP ADDRESS",
"ENCAP",
"TENANT",
"APP PROFILE",
"EPG"))
print('-'*80)
for EP in ENDPOINTS:
epg = EP.get_parent()
app_profile = epg.get_parent()
tenant = app_profile.get_parent()
print('{0:19s}{1:14s}{2:10s}{3:8s}{4:17s}
{5:10s}'.format(
EP.mac,
EP.ip,
EP.encap,
tenant.name,
app_profile.name,
epg.name))
UCS MANAGER
Cisco Unified Computing System (UCS) encompasses
most of the Cisco compute products. The first UCS
products were released in 2009, and they quickly
established themselves as leaders in the data center
compute and server market. Cisco UCS provides a
unified server solution that brings together compute,
storage, and networking into one system. While initially
the UCS solution took advantage of network-attached
storage (NAS) or storage area networks (SANs) in order
to support requirements for large data stores, with the
release of Cisco HyperFlex and hyperconverged servers,
large storage data stores are now included with the UCS
solution.
Cisco UCS B-series blade servers, C-series rack servers,
S-series storage servers, UCS Mini, and Cisco HyperFlex
hyperconverged servers can all be managed through one
interface: UCS Manager. UCS Manager provides unified,
embedded management of all software and hardware
components of Cisco UCS. Cisco UCS Manager software
runs on a pair of hardware appliances called fabric
interconnects. The two fabric interconnects form an
active/standby cluster that provides high availability.
The UCS infrastructure that is being managed by UCS
Manager forms a UCS fabric that can include up to 160
servers. The system can scale to thousands of servers by
integrating individual UCS Manager instances with Cisco
UCS Central in a multidomain Cisco UCS environment.
DN = {RN}/{RN}/{RN}/{RN}...
Classes: Classes define the properties and states of objects in the MIT.
Methods: Methods define the actions that the API performs on one or
more objects.
Types: Types are object properties that map values to the object state.
Since the query methods available with the XML API can
return large sets of data, filters are supported to limit
this output to subsets of information. Four types of filters
are available:
Simple filters: These true/false filters limit the result set of objects
with the Boolean value of True or False.
The whole MIT tree can be explored, and also queries for
specific DNs can be run from this interface. Additional
developer resources regarding Cisco UCS Manager can
be found on the Cisco DevNet website, at
https://developer.cisco.com/site/ucs-dev-center/.
Next, let’s explore the Cisco UCS Manager XML API. The
complete documentation of the Cisco UCS Manager
information model for different releases can be found at
https://developer.cisco.com/site/ucs-mim-ref-api-
picker/. At this site, you can find all the managed objects,
all the methods, all the types, all the fault and FSM rules,
and extensive documentation for each of them.
Next, let’s get a list of all the objects that are part of the
compute class and are being managed by this instance of
Cisco UCS Manager. In order to accomplish this, we can
use the configFindDnsByClassId method. This
method finds distinguished names and returns them
sorted by class ID. The curl command should look
similar to the following one:
<configFindDnsByClassId
cookie="1573019916/7c901636-c461-487e-bbd0-
c74cd68c27be"
response="yes" classId="computeItem">
<outDns>
<dn value="sys/chassis-
4/blade-8"/>
<dn value="sys/chassis-
5/blade-8"/>
<dn value="sys/chassis-
6/blade-8"/>
<dn value="sys/chassis-
6/blade-1"/>
<dn value="sys/chassis-
3/blade-1"/>
... omitted output
<dn value="sys/rack-unit-9"/>
<dn value="sys/rack-unit-8"/>
<dn value="sys/rack-unit-7"/>
<dn value="sys/rack-unit-6"/>
<dn value="sys/rack-unit-5"/>
<dn value="sys/rack-unit-4"/>
<dn value="sys/rack-unit-3"/>
<dn value="sys/rack-unit-2"/>
<dn value="sys/rack-unit-1"/>
</outDns>
</configFindDnsByClassId>
<configResolveDn dn="sys/chassis-4/blade-8"
cookie="1573019916/7c901636-c461-487e-bbd0-
c74cd68c27be" response="yes">
<outConfig>
<computeBlade
adminPower="policy" adminState="in-service"
assetTag=""
assignedToDn=""
association="none"
availability="available"
availableMemory="49152"
chassisId="4"
checkPoint="discovered"
connPath="A,B" connStatus="A,B" descr=""
discovery="complete"
discoveryStatus=""
dn="sys/chassis-4/blade-8" fltAggr="0"
fsmDescr=""
fsmFlags=""
fsmPrev="DiscoverSuccess"
fsmProgr="100" fsmRmtInvErrCode="none"
fsmRmtInvErrDescr=""
fsmRmtInvRslt=""
fsmStageDescr="" fsmStamp="2019-11-
06T04:02:03.896"
fsmStatus="nop"
fsmTry="0" intId="64508"
kmipFault="no" kmipFaultDescription=""
lc="undiscovered"
lcTs="1970-01-01T00:00:00.000"
localId="" lowVoltageMemory="not-applicable"
managingInst="A"
memorySpeed="not-applicable" mfgTime="not-
applicable"
model="UCSB-
B200-M4" name=""
numOf40GAdaptorsWithOldFw="0"
numOf40GAdaptorsWithUnknownFw="0"
numOfAdaptors="1"
numOfCores="8" numOfCoresEnabled="8"
numOfCpus="2"
numOfEthHostIfs="0"
numOfFcHostIfs="0" numOfThreads="16"
operPower="off"
operPwrTransSrc="unknown"
operQualifier="" operSolutionStackType="none"
operState="unassociated"
operability="operable"
originalUuid="1b4e28ba-2fa1-
11d2-
0408-b9a761bde3fb"
partNumber="" policyLevel="0"
policyOwner="local"
presence="equipped"
revision="0" scaledMode="none" serial="SRV137"
serverId="4/8"
slotId="8" totalMemory="49152"
usrLbl=""
uuid="1b4e28ba-2fa1-11d2-0408-
b9a761bde3fb"
vendor="Cisco Systems Inc"
vid=""/>
</outConfig>
</configResolveDn>
Next, let’s explore the Cisco UCS Python SDK and see
how to connect to a Cisco UCS Manager instance,
retrieve a list of all the compute blades in the system, and
extract specific information from the returned data. The
sample Python code is built in Python 3.7.4 using version
0.9.8 of the ucsmsdk module.
#! /usr/bin/env python
from ucsmsdk.ucshandle import UcsHandle
HANDLE = UcsHandle("10.10.20.110", "ucspe",
"ucspe")
print('{0:23s}{1:8s}{2:12s}{3:14s}
{4:6s}'.format(
"DN",
"SERIAL",
"ADMIN STATE",
"MODEL",
"TOTAL MEMORY"))
print('-'*70)
# Extract DN, serial number, admin state,
# model, and total memory for each blade
for BLADE in BLADES:
print('{0:23s}{1:8s}{2:12s}{3:14s}
{4:6s}'.format(
BLADE.dn,
BLADE.serial,
BLADE.admin_state,
BLADE.model,
BLADE.total_memory))
HANDLE.logout()
Create, clone, and deploy service profiles and templates for all Cisco
UCS servers and compute applications.
Adding the ability to control a new type of device with Cisco UCS
Director
https://Cisco_UCS_Director/app/api/rest?
formatType=json&opName=operationName&op
Data=operationData
where
opName: This is the API operation name that is associated with the
request (for example, userAPIGetMyLoginProfile), as explored later in
this chapter.
curl -k -L -X GET \
-g 'https://10.10.10.66/app/api/rest?
formatType=json&opName=userAPIGetMyLoginProfi
le&opData={}' \
-H 'X-Cloupia-Request-Key:
8187C34017C3479089C66678F32775FE'
{
"opName" : "userAPIGetMyLoginProfile",
"serviceName" : "InfraMgr",
"serviceResult" : {
"email" : null,
"groupName" : null,
"role" : "Admin",
"userId" : "admin",
"groupId" : 0,
"firstName" : null,
"lastName" : null
},
"serviceError" : null}
curl -k -L -X GET \
-g 'http://10.10.10.66/app/api/rest?
formatType=json&opName=userAPIGetWorkflowInput
s&opData=
{param0:%22VMware%20OVF%20Deployment%22}' \
-H 'X-Cloupia-Request-Key:
8187C34017C3479089C66678F32775FE'
CISCO INTERSIGHT
The Cisco Intersight platform provides intelligent cloud-
powered infrastructure management for Cisco UCS and
Cisco HyperFlex platforms. Cisco UCS and Cisco
HyperFlex use model-based management to provision
servers and the associated storage and networking
automatically. Cisco Intersight works with Cisco UCS
Manager and Cisco Integrated Management Controller
(IMC) to bring the model-based management of Cisco
compute solutions into one unified management
solution. Cisco Intersight offers flexible deployment
options either as software as a service (SaaS) on
https://intersight.com or running a Cisco Intersight
virtual appliance on premises. Some of the benefits of
using Cisco Intersight are the following:
Property NameDescription
query: An optional query after the question mark and typically used to
limit the output of the response to only specific parameters
https://intersight.com/api/v1/asset/DeviceRegis
trations/48601f85ae74b80001aee589
API keys
Session cookies
#! /usr/bin/env python
from intersight.intersight_api_client import
IntersightApiClient
from intersight.apis import
equipment_device_summary_api
DEVICES =
D_HANDLE.equipment_device_summaries_get().results
print('{0:35s}{1:40s}{2:13s}{3:14s}'.format(
"DN",
"MODEL",
"SERIAL",
"OBJECT TYPE"))
print('-'*105)
host: This parameter specifies the Cisco Intersight REST API base
URI.
Webex Teams API: This section introduces Webex Teams and the
rich API set for managing and creating applications, integrations, and
bots.
Cisco Finesse
Cisco Finesse 5, 6
Webex Devices 8, 9
Caution
The goal of self-assessment is to gauge your mastery of
the topics in this chapter. If you do not know the
answer to a question or are only partially sure of the
answer, you should mark that question as wrong for
purposes of self-assessment. Giving yourself credit for
an answer that you correctly guess skews your self-
assessment results and might provide you with a false
sense of security.
FOUNDATION TOPICS
INTRODUCTION TO THE CISCO
COLLABORATION PORTFOLIO
Cisco’s collaboration portfolio is vast, but it can be
logically broken down into essentially four high-level
components:
Unified Communications
People work together in different ways. And they use a
lot of collaboration tools: IP telephony for voice calling,
web and video conferencing, voicemail, mobility, desktop
sharing, instant messaging and presence, and more.
A rich user experience that includes the CiscoWebex Calling app, for
mobile and desktop users, integrated with the Cisco Webex Teams
collaboration app
Open Web 2.0 APIs that simplify the development and integration of
value-added applications and minimize the need for detailed desktop
development expertise.
Cisco Webex
Cisco Webex is a conferencing solution that allows
people to collaborate more effectively with each other
anytime, anywhere, and from any device. Webex online
meetings are truly engaging with high-definition video.
Webex makes online meetings easy and productive with
features such as document, application, and desktop
sharing; integrated audio/video; active speaker
detection; recording; and machine learning features.
Webex Share: The new Webex Share device allows easy, one-click
wireless screen sharing from the Webex Teams software client to any
external display with an HDMI port.
Webex Teams
Endpoints
Get Webex Teams space history or be notified in real time when new
messages are posted by others
API Authentication
There are four ways to access the Webex Teams APIs:
Integrations
Bots
Guest issuers
Integrations
To perform actions on behalf of someone else, you need a
separate access token that you obtain through an OAuth
authorization grant flow. OAuth is supported directly
into the platform. With a few easy steps, you can have a
Webex Teams user grant permission to your app and
perform actions on that person’s behalf. Figure 10-4
shows how third-party apps can access the platform.
Access Scopes
Scopes define the level of access that an integration
requires. Each integration alerts the end user with the
scope of the integration. Scopes determine what
resources the Access Token has access to. Table 10-2 lists
and describes the scopes.
ScopeDescription
Organizations API
An organization is a set of people in Webex Teams.
Organizations may manage other organizations or may
be managed themselves. The Organizations API can be
accessed only by an administrator. Table 10-3 shows the
methods used with the Organizations API to get details
about organizations.
MethodAPIDescription
Note
The host name https://api.ciscospark.com has now
been changed to https://webexapis.com. The old
https://api.ciscospark.com will continue to work.
Teams API
A team is a group of people with a set of rooms that is
visible to all members of that team. The Teams API is
used to manage teams—to create, delete, and rename
teams. Table 10-4 lists the various operations that can be
performed on the Teams API.
MethodAPIDescription
import json
import requests
URL = "https://webexapis.com/v1/teams"
PAYLOAD = {
"name": "DevNet Associate Certification
Team"
}
HEADERS = {
"Authorization": "Bearer
MDA0Y2VlMzktNDc2Ni00NzI5LWFiNmYtZmNmYzM3OTkyNjMxNmI0ND-
VmNDktNGE1_PF84_consumer",
"Content-Type": "application/json"
}
RESPONSE = requests.request("POST", URL,
data=json.dumps(PAYLOAD), headers=HEADERS)
print(RESPONSE.text)
Rooms API
Rooms are virtual meeting places where people post
messages and collaborate to get work done. The Rooms
API is used to manage rooms—to create, delete, and
rename them. Table 10-5 lists the operations that can be
performed with the Rooms API.
You can use the Rooms API to create a room. When you
do, an authenticated user is automatically added as a
member of the room. To create a room, you can use the
POST method and the
API https://webexapis.com/v1/rooms.
URL = "https://webexapis.com/v1/rooms"
PAYLOAD = {
"title": "DevAsc Team Room"
}
HEADERS = {
"Authorization": "Bearer
MDA0Y2VlMzktNDc2Ni00NzI5LWFiNmYtZmNmYzM3OTkyNjMxNmI0ND-
VmNDktNGE1_PF84_consumer",
"Content-Type": "application/json"
}
RESPONSE = requests.request("POST", URL,
data=json.dumps(PAYLOAD), headers=HEADERS)
pprint.pprint(json.loads(RESPONSE.text))
$ python3 CreateRoom.py
{'created': '2020-02-15T23:13:35.578Z',
'creatorId':
'Y2lzY29zcGFyazovL3VzL1BFT1BMRS8wYWZmMmFhNC1mN2IyLTQ3MWU-
tYTIzMi0xOTEyNDgwYmDEADB',
'id':
'Y2lzY29zcGFyazovL3VzL1JPT00vY2FhMzJiYTAtNTA0OC0xMWVhLWJiZWItYmY1MWQyNGRm
MTU0',
'isLocked': False,
'lastActivity': '2020-02-15T23:13:35.578Z',
'ownerId': 'consumer',
'title': 'DevAsc Team Room',
'type': 'group'}
$
You can use the Rooms API to get a list of all the rooms
that have been created. To do so, you can use the GET
method and the API https://webexapis.com/v1/rooms.
$ curl -X GET \
https://webexapis.com/v1/rooms \
-H 'Authorization: Bearer
DeadBeefMTAtN2UzZi00YjRiLWIzMGEtMThjMzliNWQwZGEyZTljN-
WQxZTktNTRl_PF84_1eb65fdf-9643-417f-9974-
ad72cae0e10f'
Memberships API
A membership represents a person’s relationship to a
room. You can use the Memberships API to list members
of any room that you’re in or create memberships to
invite someone to a room. Memberships can also be
updated to make someone a moderator or deleted to
remove someone from the room. Table 10-6 lists the
operations that can be performed with respect to the
Memberships API, such as listing memberships and
adding a new member.
MethodAPIDescription
GE https://webexapis.com/v1/mem List
T berships memberships
import json
import requests
import pprint
URL = "https://webexapis.com/v1/memberships"
PAYLOAD = {
"roomId" :
"Y2lzY29zcGFyazovL3VzL1JPT00vY2FhMzJiYTAtNTA0OC0xMWVhLWJiZ-
WItYmY1MWQyNGRDEADB",
"personEmail": "newUser@devasc.com",
"personDisplayName": "Cisco DevNet",
"isModerator": "false"
}
HEADERS = {
"Authorization": "Bearer
MDA0Y2VlMzktNDc2Ni00NzI5LWFiNmYtZmNmYzM3OTkyNjMxNmI0ND-
VmNDktNGE1_PF84_consumer",
"Content-Type": "application/json"
}
RESPONSE = requests.request("POST", URL,
data=json.dumps(PAYLOAD), headers=HEADERS)
pprint.pprint(json.loads(RESPONSE.text))
Messages API
Messages are communications that occur in a room. In
Webex Teams, each message is displayed on its own line,
along with a timestamp and sender information. You can
use the Messages API to list, create, and delete messages.
MethodAPIDescription
API https://webexapis.com/v1/messages.
import json
import requests
import pprint
URL = "https://webexapis.com/v1/messages"
PAYLOAD = {
"roomId" :
"Y2lzY29zcGFyazovL3VzL1JPT00vY2FhMzJiYTAtNTA0OC0xMWVhLWJiZ-
WItYmY1MWQyNGRmMTU0",
"text" : "This is a test message"
}
HEADERS = {
"Authorization": "Bearer
NDkzODZkZDUtZDExNC00ODM5LTk0YmYtZmY4NDI0ZTE5ZDA1MGI-
5YTY3OWUtZGYy_PF84_consumer",
"Content-Type": "application/json",
}
RESPONSE = requests.request("POST", URL,
data=json.dumps(PAYLOAD), headers=HEADERS)
pprint.pprint(json.loads(RESPONSE.text))
Bots
A bot (short for chatbot) is a piece of code or an
application that simulates a human conversation. Users
communicate with a bot via the chat interface or by
voice, just as they would talk to a real person. Bots help
users automate tasks, bring external content into the
discussion, and gain efficiencies. Webex Teams has a rich
set of APIs that make it very easy and simple for any
developer to add a bot to any Teams room. In Webex,
bots are similar to regular Webex Teams users. They can
participate in one-to-one and group spaces, and users
can message them directly or add them to a group space.
A special badge is added to a bot’s avatar in the Webex
Teams clients so users know they’re interacting with a
bot instead of a human.
TypeDescription
Guest Issuer
Guest issuer applications give guest users temporary
access to users within the organization. Guest issuers can
be created at https://developer.Webex.com/my-
apps/new/guest-issuer. To create a new guest issuer, the
only thing that is required is the name. A new guest
issuer ID and shared secret will be generated and can be
used subsequently. The main reason to use a guest issuer
is to interact with users who do not have a Webex Teams
account. These users might be visitors to a website who
you’d like to message with over Webex Teams. Or they
might be customers in a store with which you’d like to
have a video call. These guest users can interact with
regular Webex Teams users via tokens generated by a
guest issuer application.
import base64
import time
import math
import jwt
SECRET = base64.b64decode('GUEST_ISSUE_SECRET')
print(TOKEN.decode('utf-8'))
HEADERS = {
'Authorization': 'Bearer ' +
TOKEN.decode('utf-8')
}
Webex Teams SDKs
As of this writing, there is a variety of SDKs available;
some of them are official Webex Teams SDKs, and others
are from the community. The following is a selection of
the Web Teams SDKs that are available:
SDK for iOS: Integrates messaging and calling into iOS apps (by
Cisco Webex)
CISCO FINESSE
The Cisco Finesse desktop is a call agent and supervisor
desktop solution designed to meet the growing needs of
agents, supervisors, and the administrators and
developers who support them. The Cisco Finesse desktop
runs in a browser, which means you install Cisco Unified
Contact Center Express (Unified CCX), and agents start
by simply typing in the URL for the Unified CCX server.
The desktop is more than an agent state and call-control
application. It is an OpenSocial gadget container, built to
include third-party applications in a single agent desktop
experience. Rather than switching between applications,
agents have easy access to all applications and tools from
a single window, which increases their efficiency. Figure
10-9 shows the architecture and high-level flow of
Finesse, which involves the following steps:
StateDescription
User
Dialog
Queue
Team
ClientLog
Single Sign-On
TeamMessage
http://<FQDN>:
<port>/finesse/api/<object>/<objectID>
API Authentication
All Finesse APIs use HTTP BASIC authentication, which
requires the credentials to be sent in the authorization
header. The credentials contain the username and
password, separated by a single colon (:), within a
Base64-encoded string. For example, the authorization
header would contain the following string:
"Basic ZGV2YXNjOnN0cm9uZ3Bhc3N3b3Jk"
"Bearer <authtoken>"
MethodAPIDescription
<User>
<state>LOGIN</st
ate>
<extension>5250001
</extension>
</User>
<User>
NOT_READY
<state>READY</st
ate> LOGOUT
</User>
URL = "http://hq-
uccx.abc.inc:8082/finesse/api/User/Agent001"
PAYLOAD = (
"<User>" +
" <state>LOGIN</state>" +
" <extension>6001</extension>" +
"</User>"
)
HEADERS = {
'authorization': "Basic
QWdlbnQwMDE6Y2lzY29wc2R0",
'content-type': "application/xml",
}
RESPONSE = requests.request("PUT", URL,
data=PAYLOAD, headers=HEADERS)
print(RESPONSE.text)
print(RESPONSE.status_code)
As another example, the User State Change API lets the
users change their state. State changes could be any one
as shown in Table 10-9. Say that you use the following
information with this API:
URL = "http://hq-
uccx.abc.inc:8082/finesse/api/User/Agent001"
PAYLOAD = (
"<User>" +
" <state>READY</state>" +
"</User>"
)
HEADERS = {
'authorization': "Basic
QWdlbnQwMDE6Y2lzY29wc2R0",
'content-type': "application/xml",
}
RESPONSE = requests.request("PUT", URL,
data=PAYLOAD, headers=HEADERS)
print(RESPONSE.text)
print(RESPONSE.status_code)
MethodAPIDescription
import requests
url = "https://hq-
uccx.abc.inc:8445/finesse/api/Team/2"
headers = {
'authorization': "Basic
QWdlbnQwMDE6Y2lzY29wc2R0",
'cache-control': "no-cache",
}
response = requests.request("GET", url,
headers=headers)
print(response.text)
Dialog APIs
The Dialog object represents a dialog (voice or non-
voice) between two or more users. There are many
flavors of dialog APIs. Table 10-12 shows the Finesse
dialog API, which lets two users make a call with each
other.
MethodAPIDescription
<Dialog>
<requestedAction>MAKE_C
ALL</requestedAction>
<fromAddress>6001</fromA
ddress>
<toAddress>6002</toAddres
s>
</Dialog>
<Dialog>
<requestedAction>START_R
ECORDING</requestedAction
>
<targetMediaAddress>6001<
/targetMediaAddress>
</Dialog>
A full list of the Dialog APIs, with details, can be found at
https://developer.cisco.com/docs/finesse/#dialog-apis.
URL = "http://hq-
uccx.abc.inc:8082/finesse/api/User/Agent001/Dialogs"
PAYLOAD = (
"<Dialog>" +
"
<requestedAction>MAKE_CALL</requestedAction>" +
" <fromAddress>6001</fromAddress>" +
" <toAddress>6002</toAddress>" +
"</Dialog>"
)
HEADERS = {
'authorization': "Basic
QWdlbnQwMDE6Y2lzY29wc2R0",
'content-type': "application/xml",
'cache-control': "no-cache",
}
RESPONSE = requests.request("POST", URL,
data=PAYLOAD, headers=HEADERS)
print(RESPONSE.text)
print(RESPONSE.status_code)
Finesse Gadgets
As indicated earlier in this chapter, the Finesse desktop
application is an OpenSocial gadget container. This
means that an agent or anyone else can customize what
is on the desktop. Gadgets are built using HTML, CSS,