![An introduction to Libral, a systems management library for Linux](https://opensource.com/sites/default/files/styles/image-full-size/public/images/business/yearbook-haff-rx-linux-file-lead_0.png?itok=48iDNoH8 "An introduction to Libral, a systems management library for Linux")
Basing a management API on desired state, i.e., the idea that the user expresses what the system should look like after an operation rather than how to get into that state, is hardly controversial at this point. Bidirectionality makes it possible to use the same API and, more importantly, the same resource abstractions to read existing state and to enforce changes to it. Lightweight abstractions ensure that it is easy to learn the API and make use of it quickly; past attempts at such management APIs have unduly burdened the user with learning a modeling framework, an important factor in their lack of adoption.
建立一个期望状态的管理 API,举个例子来说,用户表示当操作执行后希望系统看起来是什么状态,而不是怎样进入这个状态,是很难引起争议的。双向性使得使用相同的 API 成为可能,更重要的是,相同的资源抽象成读取现有状态和强制修改成这种状态。轻量级的抽象行为确保能容易的学习 API 并能快速的使用;过去尝试管理 API 的方式已经过度加重了学习建模框架的使用者的负担了,一个重要的因素是他们的接受力缺乏。
Finally, it has to be easy to extend Libral's management capabilities so that users can teach Libral how to manage new kinds of resources. This is important both because of the sheer amount of resources that one might want to manage (and that Libral will manage in due time), as well as because even a fully built-out Libral will always fall short of a user's custom management needs.
Currently, the main way to interact with the Libral API is through the**ralsh**command line tool. It exposes the underlying C++ API, which is still in flux, and is mainly geared at simple scripting tasks. The project also provides language bindings for CRuby, with others to follow.
In the future, Libral will also provide a daemon with a remote API, so that it can serve as the basis for management systems that do not need to install additional agents on managed nodes. This, coupled with the ability to tailor the management capabilities of Libral, makes it possible to tightly control which aspects of a system can be managed and which ones are protected from any interference.
For example, a Libral installation that is restricted to managing users and services will be guaranteed to not interfere with the packages installed on a node. Controlling what gets managed in this manner is currently not possible with any of the existing configuration-management systems; in particular, systems that require arbitrary SSH access to a managed node also expose that system to unwanted accidental or malicious interference.
The basis of the Libral API is formed by two very simple operations:**get**to retrieve the current state of resources, and**set**to enforce the state of current resources. Idealizing a little from the actual implementation, they can be thought of as:
The**provider**is the object that knows how to manage a certain kind of resource, like a user, a service, or a package, and the Libral API provides ways to look up the provider for a certain kind of resource.
The**get**operation receives a list of resource names, e.g., usernames, and needs to produce a list of resources, which are essentially hashes listing the attributes of each resource. This list must contain resources with the provided names, but might contain more, so that a naive**get**implementation can simply ignore the names and list all the resources it knows about.
The**set**operation is used to enforce desired state and receives a list of updates. Each update contains**update.is**, a resource representing the current state, and**update.should**, a resource representing the desired state. Calling the**set**method will make sure that the resources mentioned in the update list will be in the state indicated in**update.should**and produces a list of the changes made to each resource.
With**ralsh**, the current state of the**root**user can be retrieved with the command**ralsh user root**; by default, the command produces human-readable output, reminiscent of Puppet, but**ralsh**also supports a**--json**flag to make it produce JSON output for consumption by scripts. The human-readable output is:
在 “ralsh”下,利用“ralsh user root"能够重新获得“root”用户的当前状态;默认情况下,这个命令会产生一个用户可读的输出,就像木偶一样,但是”ralsh“支持”--json“选项,将利用脚本消耗产生 JSON 输出。用户可读输出是:
The output of ralsh lists both the new state of the root user, with the changed comment attribute, and what changes were made (solely to the**comment**attribute in this case). Running the same command a second time will produce much the same output, but without any change indication, as none will be needed.
It is crucially important that writing new providers for ralsh is easy and requires a minimum amount of effort. For this reason, ralsh offers a number of calling conventions that make it possible to trade the complexity of implementing a provider against the power of what the provider can do. Providers can either be external scripts that adhere to a specific calling convention or be implemented in C++ and built into Libral. Currently, there are three calling conventions:
It is highly recommended to start provider development using the**simple**or the**JSON**calling convention. The file[simple.prov][15]on GitHub contains a skeleton for a simple shell provider, and it should be easy to adapt it for one's own provider. The file[python.prov][16]contains the skeleton of a JSON provider written in Python.
One problem with using higher-level scripting languages for providers is that the runtimes, including all supporting libraries, for these languages need to be present on the system on which Libral will run. In some cases, that is not an obstacle; for example, a provider that does package management based on**yum**can expect that Python is present on the system, as**yum**is written in it.
In many other cases though, there's no logical choice for a language beyond Bourne shell (or Bash) that can be expected to be installed on all managed systems. Often, provider writers need a more powerful scripting environment than just that. Unfortunately, bundling a full Ruby or Python interpreter with its runtime would increase Libral's size beyond what can reasonably be
used in resource-constrained environments. On the other hand, the canonical choices of Lua or Javascript as small embeddable scripting languages are not suitable for this context as they are both not familiar to most provider writers, and require quite a bit of work to expose commonly needed facilities for systems management.
Libral bundles a version of[mruby][17], a small, embeddable version of Ruby, to give provider writers a stable foundation, and a powerful programming language for their implementation. mruby is a full implementation of the Ruby language, albeit with a much reduced standard library. The mruby bundled with Libral contains the parts of Ruby's standard library most important for scripting management tasks, which will be enhanced further over time based on the needs of provider writers. Libral's mruby also bundles an API adpater that makes writing providers to the json convention more comfortable, as it contains simple utilities (like[Augeas][18]for modifying structured files) and conveniences around parsing and outputting JSON. The file[mruby.prov][19]contains a skeleton example of a json provider written in mruby.
The most important next steps for Libral are to make it more widely usable—the[precompiled tarball][20]is a great way to get started and sufficient to develop providers, but Libral also needs to be packaged and made available in mainstream distributions. In a similar vein, the utility of Libral strongly depends on the set of providers it ships with and those need to be expanded to cover a core set of management functionality. The Libral site contains[a todo list][21]showing the providers that are most urgently needed.
There are also several ways in which the availability of Libral for different uses can be improved: from writing bindings for additional languages, for example, Python or Go, to making the use of**ralsh**in shell scripts even easier by offering, besides the existing human-readable output and JSON output, an output format that is easy to process in shell scripts. Use of Libral for larger-scale management can also be improved by adding the remote API discussed above, and by better supporting bulk installation of Libral via transports like SSH—that mostly requires providing prebuilt tarballs for more architectures and scripts that can select the right one based on the discovered architecture of the target system.
There are many more ways in which Libral, its API, and its capabilities could evolve; one intriguing possibility is adding notification capabilities to the API so that Libral can report changes to system resources as they happen outside of its purview. The challenge for Libral will be to continue to be a small, lightweight and well-defined tool while covering an ever increasing set of uses and management capabilities—a challenge and a journey that I encourage every reader to become a part of.
Libral 有很多方式方法,如 API ,它的性能在不断地进化发展;一个有趣的可能性是为 API 增加性能的显示,这样做可以向系统报告资源在超出它的范围发生的变化。Libral 面临的挑战将一直持续下去的是小型化,轻量级和良好定义的工具,来替代曾经增加的使用和管理性能-我希望每一个读者都能成为这个挑战和旅行的一部分。
If any of this has made you curious, I would love to hear from you, be it in the form of a pull request, an enhancement request, or just a report of your experience trying out**ralsh**.
David Lutterkort - David is a software engineer at Puppet, where he’s worked on projects such as Direct Puppet and Razor, the best provisioning tool, ever. He was one of the earliest contributors to Puppet and is the main author of Augeas, a configuration editing tool.