2.2 编程语言的选择
NetDevOps中有开发的部分,开发就必然会涉及编程语言。网络工程师在初次接触NetDevOps时,都会遇到编程语言的选择问题。下面我们就来简单讨论一下如何选择编程语言。这里我们将从程序语言的选择和数据描述语言的选择两个部分来进行叙述。
2.2.1 程序语言的选择
在程序员的世界里,讨论哪种编程语言是最好的语言,往往会引起非常激烈的争吵。笔者不敢在这里和大家讨论哪种语言是最好的语言,而是从自己的角度和大家分享一下如何选择适合NetDevOps的编程语言。
众所周知,编程语言既有编译型语言,也有解释型脚本语言。通常来说,编译型程序执行速度快,同等条件下对系统要求相对较低,C、C++、C#就是这类语言。相对于编译型语言的存在方式,解释型语言的源代码不是直接翻译成机器语言,而是先翻译成中间代码,再由解释器对中间代码进行解释运行。例如,Python、Ruby、JavaScript、Perl、Shell等就是解释型语言。
在网络运维和管理中,程序的执行效率也许不是最为关键的。换句话讲,再慢的程序(只要不出错)也会比人工执行效率要高。程序大量的执行过程是需要和网络设备进行交互的。脚本程序在执行过程中很多时候都是在等待网络设备侧返回的数据信息,因此执行效率瓶颈往往并不是语言的代码执行效率。另外,工程师也许更加关心的是程序开发的效率、代码的可读性方面。从这些方面考虑,解释型语言是首选语言。
在众多的解释型语言中,哪些语言更加合适呢?现在程序在开发的时候,通常会采用Web方式进行程序发布。基于Web的程序通常会分为前端和后端两大部分。前端开发主要解决视觉的问题,即如何更好地展现数据。在浏览器中展现数据,JavaScript几乎是唯一的选择,当然还有HTML以及CSS等语言的方式。除了前端,后端的内容也是非常重要的。后端的主要功能是获取、整理以及保存数据。在某些时候,为了简化开发的工作量,只保留后端的部分也是很正常的。对于NetDevOps网络工程师而言,如果只是为了快速地完成工作内容,将需要更多地关注后端的开发。在后端开发中,较常见的语言有Python、Ruby、Bash、Java。其中,Python与Ruby在Web后端开发中非常有优势。另外,NetDevOps工程师还需要和网络设备打交道,网络设备的厂家很多。近几年,网络设备的可编程能力越来越强。基于笔者的观察,大量的网络设备会支持Python与Bash两种语言。
因此,笔者建议NetDevOps可以选择Python与Bash。如果要兼顾前端的开发,那么也需要了解和掌握一些Javascript、HTML、CSS相关知识。在本书的后续章节中,使用的语言主要是Python与Bash,我们会分别介绍一下这两种语言的基本语法,以及在网络运维和管理中基于这两种语言开发的常用一些工具。
2.2.2 数据描述语言的选择
2.2.1节提到了编程语言的选择问题,其选择余地相对较大,并且笔者给出了认为更加适合的语言,以减少初学者在语言选择上的徘徊。但在数据描述型语言的选择方面会少很多,这里笔者给出一些常见的、在NetDevOps开发中通常会用到的格式。这里提到的数据描述型语言,读者最好能较好地掌握(其实掌握这些内容比学一门编程语言要简单很多)。
数据描述型语言主要是为程序提供服务的,也就是说程序能够快速方便地解析它们。部分数据描述型语言还兼顾了人的可读性,让人也能够较为方便地编写和阅读其内容。
下面是常见的数据描述型语言。
1.JSON
JSON(JavaScript Object Notation)是一种轻量级的数据交换语言,以文字为基础,且易于让人阅读。JSON数据格式与编程语言无关,它脱胎于JavaScript,但目前很多编程语言都支持JSON格式数据的生成和解析。JSON用于描述数据结构,其形式如下:
{名称:值}
❑ 对象(object):一个对象以“{”开始,以“}”结束。一个对象包含一组非排序的名称与值对。
❑ 每个对内的名称与值(collection):名称和值之间使用“:”隔开。
❑ 多个对(名称与值对)之间使用“,”分开。
❑ 值的有序列表(array):一个或者多个值用“,”分区后,使用“[]”括起来就形成了列表。
{["hostname": "Router1", "hostname": "Router2"]}
JSON格式表达的是一种树状的数据类型,非常容易被保存到NoSQL数据库中,如MongoDB。在网络编程中,这种结构较为常见,也易于使用。比如在Cisco Nexus系列的交换机上就可以直接输出为JSON格式的数据。
{ "ins_api": { "type": "cli_show", "version": "0.1", "sid": "eoc", "outputs": { "output": { "body": { "hostname": "switch" }, "input": "show switchname", "msg": "Success", "code": "200" } } } }
2.XML
XML(Extensible Markup Language,可扩展标记语言)是一种标记语言,用于传送及携带数据信息,不用于表现或展示数据。这样的结构并不太适合人直接阅读。但XML中的tag是可以携带多个属性的。并且,XML还有namespace等概念。相比JSON, XML能表示更加复杂的数据结构,也比JSON复杂很多。XML格式是NETCONF协议的默认交换数据的格式。比如Juniper的路由器、交换机等网络设备上运行的JUNOS可以直接输出XML格式的数据。XML是一种结构化的文本,非常适合程序进行处理。
user@host> show chassis alarms
No alarms currently active
user@host> show chassis alarms | display xml
<rpc-reply xmlns:junos="http://xml.juniper.net/junos/10.4R1/junos">
<alarm-information xmlns="http://xml.juniper.net/junos/10.4R1/junos-alarm">
<alarm-summary>
<no-active-alarms/>
</alarm-summary>
</alarm-information>
<cli>
<banner></banner>
</cli>
</rpc-reply>
3.YAML
YAML(http://yaml.org)是一种用来表达数据序列的格式,对人而言可读性较高,可以简单表达清单、散列表、标量等数据形态。它采用空白符号缩进的方式,非常适合用来表达或编辑数据结构、配置文件、文件大纲等内容。由于YAML使用空白字符和分行来分隔数据,因此它特别适合用grep、Python、Perl、Ruby等语言进行操作。另外,YAML没有使用各种封闭符号,如引号、各种括号等,这些符号在嵌套结构中会变得复杂并且难以辨认。YAML的语法非常简单,主要注意文本的缩进。读者可以参考如下链接:
❑ http://www.yaml.org/spec/1.2/spec.html;
❑ http://docs.ansible.com/ansible/YAMLSyntax.html。
下面的Ansible的配置文件就采用了YAML格式进行编写。
--- - hosts: "core" connection: local remote_user: "admin" gather_facts: False tasks: - nxos_interface: interface: "{{ item }}" mode: layer3 admin_state: up transport: nxapi host: 10.255.0.75 username: admin password: cisco12345 with_items: - Ethernet1/1 - Ethernet1/2 - Ethernet1/3 - Ethernet1/4
4.YANG
和前面三种语言不同,YANG不是一种数据描述语言,而是一种数据建模语言。也就是说,它是用来定义数据的数据结构的,而不是数据的实体。通过下面这个例子可以很容易理解。
module acme-system { namespace "http://acme.example.com/system"; prefix "acme"; organization "ACME Inc."; contact "joe@acme.example.com"; description "The module for entities implementing the ACME system."; revision 2007-11-05 { description "Initial revision."; } container system { leaf host-name { type string; description "Hostname for this system"; } leaf-list domain-search { type string; description "List of domain names to search"; } list interface { key "name"; description "List of interfaces in the system"; leaf name { type string; } leaf type { type string; } leaf mtu { type int32; } } } }
这个文件使用YANG定义了一个交换机的输出数据结构。system包含host-name、domain-search以及interface三个子内容。下面的输出内容是某一台交换机真实的输出结果。
<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <system xmlns=" http://acme.example.com/system"> <host-name> Swith-1 </host-name> <domain-search> abc.com </domain-search> <domain-search> abc.net </domain-search> <interface> <name> <name> Eth3/1 </name> <type> Ethernet </type> <mtu> 1500 </mtu> </name> <name> <name> Eth3/2 </name> <type> Ethernet </type> <mtu> 1500 </mtu> </name> </interface> </system> </data>
通过这个例子,我们可以看出:YANG文件定义的是一个数据结构,而设备输出的结果使用了这个定义的数据结构,并在结构中相关部分给出了具体的值。关于YANG语言具体的内容,读者可以参考http://www.yang-central.org。
目前,由于各厂家网络设备的输出格式都不一样,并且大量的格式还是非结构化的数据格式,这种非结构化的数据格式对程序的开发并不友好。YANG语言是专门为网络环境而开发的语言,它对网络设备的输出数据进行抽象化并提供了一个通用的语言。Google、AT&T、Microsoft、BT等公司共同参与了OpenConfig(http://openconfig.net)项目,这个开源的项目定义了大量和网络相关的数据结构描述文件。
关于这些数据描述语言,我们在第9章中会进行更加详细的说明,并且会给出使用Python语言如何处理这四种用于数据描述的格式。