COAS:系统管理工具的灵活方法

作者:Olaf Kirch

COAS 代表 Caldera Open Administration System(Caldera 开放管理系统)。它将被整合到未来版本的 OpenLinux 发行版中,作为主要的配置工具。

对于那些从未使用过 OpenLinux 的人来说,我们已经使用了一段时间的工具名为 LISA(Linux Installation and System Administration,Linux 安装和系统管理),它基本上是一个庞大的 shell 脚本,使用修改版的 dialog 工具与用户交互。当我们觉得是时候转向一些新事物时,我们当然会看看当时已有的东西。当时唯一可行的选择似乎是 LinuxConf,但在它变得有用之前还有很长的路要走。从那时起,它已经变得好多了,但是因为我们已经开始了 COAS 的工作,我们决定坚持下去。当然,我们相信我们的概念更好。

COAS 的源代码以 GNU 通用公共许可证发布。我们认为我们的工作可能对整个 Linux 社区有用,我们希望邀请感兴趣的程序员、管理员和用户参与其开发,提供意见、贡献补丁甚至模块。

垂直模块化

COAS 背后的主要思想不是提供另一个管理工具,而是一个用于编写管理工具的完整框架。从一开始,我们就希望它是一个模块化的应用程序,其中关于系统数据表示、文件位置和依赖关系等方面的假设尽可能地与用户对话框分离,反之亦然。尽管这个目标可能显得雄心勃勃,但我们主要感兴趣的是能够轻松地使该工具适应底层平台的变化,并将其移植到其他 Linux 平台。

我喜欢称之为垂直模块化,因为它将系统管理任务分解为三个层次。最底层是原生系统数据文件,例如 /etc/passwd、/etc/hosts 或定义特定网络接口 IP 地址的文件。

在此之上,COAS 将内部表示实现为一种数据库。如果这个术语让您吓了一跳,并大喊“哦不,比尔先生,不是 Linux 注册表!”,请放心,这绝对不是我们想要的那样。COAS 应该是 vi 管理员友好的。我们希望用户能够在 COAS 和 vi(或 Emacs)管理之间切换,因为即使我们希望 COAS 对日常任务有用,它也无法涵盖系统组件的每一个功能。(想想配置怪物化身 sendmail——您可以花和 Eric Allman 不断推出新功能一样多的时间来编写它的配置软件。)

原生系统文件仍将是信息的主要来源。COAS 数据模型严格来说是系统数据的运行时表示,它试图对上层隐藏磁盘上的表示。例如,BIND 服务器的管理模块不应该关心 DNS 区域文件位于何处以及如何解析;它所需要的只是此服务器作为主服务器或辅助名称服务器的 DNS 区域列表以及它们包含的记录。

拥有抽象的数据表示也允许替代数据访问机制。例如,我们的数据库引擎可以将管理会话的更改日志存储到文件中,然后可以将其分发到其他机器,从而实现批量更新。此外,还有一个模糊的想法,即 COAS 有朝一日可能会支持通过 LDAP 或 SNMP 进行远程访问。

最顶层是用户交互代码。此代码驱动与用户的对话,并控制在什么时间向用户显示哪些信息。它使用一组标准的对话框,提供在线帮助等。我们决定在此层使用脚本语言 Python,以便实现快速原型设计。除此之外,将所有底层功能包装在 Python 类和函数中,提供了额外的隔离级别,限制了程序员可以使用的技巧数量。对于你们中的黑客来说,这可能看起来是一个缺点,但当涉及到代码维护时,这确实是一个很大的优点。

水平模块化

您可能从我选择“垂直模块化”这个术语中猜到,还有水平模块化,事实也正是如此。考虑以下场景:一个安全问题或其他缺陷需要您更新系统的组件,例如 BIND 名称服务器。唉,更新是从 4.9 版本到 8.2 版本,后者使用完全不同的配置文件格式。我们现在可能会要求您安装全新版本的管理工具,以适应新的配置文件格式。一方面,这在带宽方面成本很高。另一方面,确保该工具在应用或未应用所有可能的更新组合的情况下都能正常运行,对我们来说将相当耗时。理想的解决方案是将 DNS 服务器管理模块与我们的 BIND 更新一起打包。

我们正在尝试完成以下操作:COAS 允许您删除整个模块,包括数据模型定义、Python 代码、消息目录等,并将其替换为不同的版本。我们给这些模块起了个昵称 CLAM,它是 Caldera Linux Administration Module(Caldera Linux 管理模块)的缩写(如果您好奇的话,我们先发明了首字母缩写词,然后才决定它的含义)。

数据模型

让我们仔细看看内部数据表示。所有信息都存储在一棵树中,每个节点都有一个单独的名称。例如,包含 root 用户密码的节点名为 system.accounts.users.0.password。如果您熟悉 SNMP,请想想 SNMP 变量的命名方式。

节点可以有不同的类型;例如,system 是一个目录,users 是一个列表,而 password 是一个标量。标量节点可以附加各种约束;例如,字符串可能需要匹配正则表达式或仅包含来自预定义选项集的值。您还可以将自己的解析和表示函数(用 C 编写)附加到标量类型,创建自定义类型,这些类型可以执行诸如将日期字符串(例如,Jun 12tomorrow)转换为 UNIX 时间之类的操作。

所有这些信息都由所谓的模式提供。模式充当数据模型的蓝图,就像 SNMP MIB 定义描述 SNMP 实体的类型和组织一样。

例如,鼠标参数的定义可能如下所示

MODULE   "PERIPHERALS/MOUSE"
MSGCATALOG "peripherals/mouse"
TYPEDEF DevicePathName  STRING MATCHES
    "/dev/[a-z0-9]*"
TYPEDEF MouseProtocol  STRING IN CHOICE {
    "Busmouse", "MouseSystems",
    "Mouseman", "Microsoft",
    ...
}
device         RECORD {
    model      STRING
    protocol    MouseProtocol
    deviceFile   DevicePathName DEFAULT
        "/dev/mouse"
    emulate3btn   BOOLEAN DEFAULT "false"
}

这会创建一个名为 mouse 的记录,其中包含五个标量节点。例如,model 是一个普通的字符串变量,而 deviceFile 是一个特殊的字符串类型,其定义显示在记录上方。前两行包含一些语法糖,目前无需关注。

%Those funky strings (|":MOUSE_EMULATE_NONE:"|)
%are tags for the COAS message catalogs.
此定义将存储在名为 peripherals/mouse.schema 的文件中(通常在 /usr/lib/coas/schema 下),以便可以通过名称 peripherals.mouse.device 访问鼠标配置。

当访问数据项时,COAS 从模式定义中实例化实例树的各个部分,并通过调用所谓的“mapper”(映射器)来填充数据。这些映射器负责解析和写回系统文件,并在必要时锁定它们。通常,它们是用 C++ 编写的,并保存在按需加载的共享库中。最新版本还支持用 Python 编写的映射器。

在鼠标设备的情况下,没有存储此信息的标准位置。例如,在 Red Hat 机器上,它保存在 /etc/sysconfig/mouse 中,该文件包含 shell 变量赋值列表。COAS 已经为此类文件提供了一个通用的映射器(事实证明,大约 80% 的系统文件都非常接近四到五种标准格式),因此剩下的就是定义映射。这可以通过所谓的平台存储库来完成,我们可以在其中输入如下代码

peripherals.mouse.device {
    mapper     builtin.sysconfig
    path      /etc/sysconfig/mouse
    relation    MOUSETYPE:model:\
            PROTO:protocol:\
            DEVICE:deviceFile:\
            XEMU3:emulate3btn(map=/no=false,yes=true/)
}

mapper 关键字将指定的映射器与鼠标设备节点关联。首次访问设备节点时,COAS 会检测到这一点并调用映射器,以便填充鼠标设备节点下方的树。映射器检索 path 参数并读取指定的文件。relation 参数告诉映射器文件中哪些 shell 变量对应于哪些数据模型节点。

当您修改了协议(例如,鼠标)并调用设备节点的 commit 函数时,也会发生同样的事情。数据引擎将调用映射器以便将数据写回文件。同样,映射器将使用指定的 relation 来确定哪些数据模型值将被分配给哪些 shell 变量。请注意,为了体现 vi 管理员的友好性,映射器不会触及它不知道的 shell 变量,并会尽力保留注释。

平台信息通常通过将其与主要的 COAS 平台定义合并来安装,后者位于 /usr/lib/coas/repository 中。

用户交互

编写并安装上述文件后,您已经可以使用 COAS 显示和修改鼠标配置。例如,COAS 附带了一些小程序,例如 coas dumpcoas change,它们允许您转储数据树的各个部分或修改单个节点。您甚至可以编写 Python 脚本来对您的数据执行更复杂的操作。

然而,最终目标(至少对我们而言)是一个与用户交互的 Python 模块,引导用户完成管理任务。该模块位于数据库引擎之上,并且完全在抽象数据表示上运行。它向用户显示数据,选择要编辑的项目,提供在线帮助等。

为什么选择 Python?嗯,一个非常早期的原型使用了 Tcl 作为脚本语言,但由于各种原因,它的效果不太好。与 Tcl 相比,Python 具有相当好的对象支持和至少同样好的扩展机制。另一个候选者是 Perl,但我们反对它,因为它很容易用 Perl 编写糟糕的代码。

与用户的通信通过用 C++ 编写的抽象用户界面 API 进行,该 API 目前支持 curses 和 Qt 前端。正在进行一个扩展的 Qt 前端的工作,该前端利用 KDE 提供的功能。当然,为了能够从 Python 使用此 API,提供了 Python 封装器。

用户界面提供了一组有限但有用的对话框:由文本和几个按钮组成的通知/问题对话框;列表对话框(单选和多选,带或不带复选框等);提示对话框(包含一个或多个标量值的编辑字段);以及表格对话框(以表格形式显示数据,允许就地编辑)。

列表 1

例如,用于编辑鼠标配置的最小模块如列表 1 所示(未显示一些 Python 样板代码,例如 import 语句)。对于那些不熟悉 Python 的人来说,这段代码定义了类 Mouse,它派生自模块 clam 中定义的 CLAM 类。{__init__} 方法是 Python 声明构造函数的方式。

run 方法由 COAS 调用。它做的第一件事是查找鼠标设备的数据模型节点。如上所述,此步骤将触发将配置文件解析为内部数据表示。

接下来,创建一个提示对话框,并为鼠标的型号、协议和设备文件添加三个编辑字段。最后几行是有些标准的对话框循环。根据用户是通过按“确定”还是“取消”按钮来终止对话框,将调用 commitcancel 方法(从 CLAM 基类继承),它们会显示一个类似“您真的要保存/取消吗?”的小问题对话框。

标签呢?

关于此示例,可能首先让您感到奇怪的是,它在任何地方都没有标签字符串。然而,对话框应该有一个标题,编辑字段应该在其左侧有一个标签等等。

答案是 COAS 会根据它拥有的信息为您生成 NLS 字符串。例如,在创建提示对话框时,我们不显眼地将字符串 mouse 传递给函数。因此,COAS 将为对话框的标题创建诸如 |":MOUSE_TITLE:"| 之类的标签,并尝试在模块的消息目录中查找它。(消息目录名称在类构造函数中指定。)同样,对于 protocol 编辑字段,它将生成标签 |":MOUSE_PROTOCOL_LABEL:"|。您所需要做的就是编写消息目录,将这些时髦的字符串映射为可理解的英语(或法语、德语等)并安装该文件。

编辑数据

查看上面的示例代码,您可能还会想到:我理解他们将数据放在对话框中的位置,但是他们如何将其放回数据模型中呢?

这是数据编辑过程中有趣的部分。如果您曾经编写过 Motif 程序,您就会知道从数据模型中提取要编辑的值、将其放入对话框并在用户单击“确定”按钮时将结果值写回数据模型是多么乏味。

COAS 采用的方法是将数据模型节点直接绑定到对话框,并让对话框选择适当的小部件类型(字符串、组合框、切换按钮、微调按钮等)。当用户提供新值时,对话框将自动根据数据模型约束检查值的语法,并将其写回数据模型。

在我们的示例中,对话框将为 deviceName 创建一个简单的字符串编辑字段,为 protocol 创建一个弹出列表(因为它被限制为一组选项),并为 emulation 创建一个切换按钮。

更重要的是,这种机制为您提供了易于使用的上下文帮助,用于每个输入字段,绑定到 f2 键。向数据项添加此类帮助就像在模式文件中向数据定义添加 HELP 属性一样容易

device         RECORD {
    model      STRING HELP "HELP_MODEL"
    protocol    MouseProtocol HELP "HELP_PROTOCOL"
    ...
}

这些帮助消息将在与模式文件关联的消息目录中查找(还记得模式文件中的 MSGCATALOG 关键字吗?),并在用户按下 f2 时在弹出对话框中显示。

当然,您设计的每个方案都有一个缺点。在这种情况下,是如何取消在对话框执行期间所做的更改。当用户按下“取消”按钮时,他希望所有更改都消失。

这就是 marker 对象发挥作用的地方。数据节点的 getMarker 方法获取节点更改日志(在 COAS 术语中称为 journal)的标记。当用户请求放弃所有更改时,CLAM 基类调用 self.mouse.cancel(marker),这将还原在获取标记对象后所做的所有更改。

啤酒在哪里?呃,重点是什么?

我不得不承认,上面的例子在其简单性方面有点具有欺骗性。我在这里展示的是对话框的最简单版本。事实上,您在这里看到的只是配置文件的光荣界面,因为它没有为用户提供任何帮助或指导。一个好的对话框会在选择时自动选择适当的设备文件(例如,总线鼠标),并防止用户为已经有三个按钮的鼠标启用三键仿真。因此,您的普通 COAS 模块将比上面示例中的 20 多行代码多得多。

然而,COAS 在这种情况下提供的最大优势是,它让您摆脱了使用 GUI 时的通常麻烦,并让您专注于数据流。

依赖模型

您好奇吗?

如果这篇文章引起了您的兴趣,并且您想仔细了解 COAS,您可以在 http://www.coas.org/ 和 http://developer.coas.org/ 上找到更多信息。如果您想参与 COAS 的开发,请随时与我联系。

本文中引用的所有列表都可以通过匿名下载文件 ftp.linuxjournal.com/pub/lj/listings/issue58/3019.tgz 获取。

COAS: A Flexible Approach to System Administration Tools
Olaf Kirch (okir@caldera.de) 自 MCC Interim 时代以来一直是 Linux 爱好者,并且撰写了 Linux 网络管理员指南 以及各种 Linux 软件。多年来,他一直是 Linux NFS 代码的主要维护者,自 1997 年以来一直在 Caldera 工作。
加载 Disqus 评论